summaryrefslogtreecommitdiff
path: root/lisp/progmodes
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/progmodes')
-rw-r--r--lisp/progmodes/bat-mode.el6
-rw-r--r--lisp/progmodes/bug-reference.el14
-rw-r--r--lisp/progmodes/cc-cmds.el25
-rw-r--r--lisp/progmodes/cc-engine.el109
-rw-r--r--lisp/progmodes/cc-fonts.el51
-rw-r--r--lisp/progmodes/cc-mode.el152
-rw-r--r--lisp/progmodes/cc-styles.el12
-rw-r--r--lisp/progmodes/cc-vars.el2
-rw-r--r--lisp/progmodes/compile.el10
-rw-r--r--lisp/progmodes/cperl-mode.el16
-rw-r--r--lisp/progmodes/cpp.el7
-rw-r--r--lisp/progmodes/ebrowse.el42
-rw-r--r--lisp/progmodes/elisp-mode.el58
-rw-r--r--lisp/progmodes/erts-mode.el225
-rw-r--r--lisp/progmodes/etags.el24
-rw-r--r--lisp/progmodes/executable.el13
-rw-r--r--lisp/progmodes/f90.el7
-rw-r--r--lisp/progmodes/gdb-mi.el82
-rw-r--r--lisp/progmodes/grep.el8
-rw-r--r--lisp/progmodes/gud.el42
-rw-r--r--lisp/progmodes/hideif.el42
-rw-r--r--lisp/progmodes/idlw-shell.el7
-rw-r--r--lisp/progmodes/inf-lisp.el2
-rw-r--r--lisp/progmodes/js.el1179
-rw-r--r--lisp/progmodes/make-mode.el4
-rw-r--r--lisp/progmodes/octave.el11
-rw-r--r--lisp/progmodes/pascal.el4
-rw-r--r--lisp/progmodes/perl-mode.el6
-rw-r--r--lisp/progmodes/prog-mode.el8
-rw-r--r--lisp/progmodes/project.el231
-rw-r--r--lisp/progmodes/prolog.el7
-rw-r--r--lisp/progmodes/python.el394
-rw-r--r--lisp/progmodes/ruby-mode.el22
-rw-r--r--lisp/progmodes/scheme.el54
-rw-r--r--lisp/progmodes/sh-script.el104
-rw-r--r--lisp/progmodes/sql.el71
-rw-r--r--lisp/progmodes/verilog-mode.el34
-rw-r--r--lisp/progmodes/vhdl-mode.el5
-rw-r--r--lisp/progmodes/xref.el238
-rw-r--r--lisp/progmodes/xscheme.el5
40 files changed, 1457 insertions, 1876 deletions
diff --git a/lisp/progmodes/bat-mode.el b/lisp/progmodes/bat-mode.el
index 7ef2500e46b..6bac297a298 100644
--- a/lisp/progmodes/bat-mode.el
+++ b/lisp/progmodes/bat-mode.el
@@ -71,8 +71,8 @@
"doskey" "echo" "endlocal" "erase" "fc" "find" "findstr" "format"
"ftype" "label" "md" "mkdir" "more" "move" "net" "path" "pause"
"popd" "prompt" "pushd" "rd" "ren" "rename" "replace" "rmdir" "set"
- "setlocal" "shift" "sort" "subst" "time" "title" "tree" "type"
- "ver" "vol" "xcopy"))
+ "setlocal" "setx" "shift" "sort" "subst" "time" "title" "tree"
+ "type" "ver" "vol" "xcopy"))
(CONTROLFLOW
'("call" "cmd" "defined" "do" "else" "equ" "exist" "exit" "for" "geq"
"goto" "gtr" "if" "in" "leq" "lss" "neq" "not" "start"))
@@ -82,7 +82,7 @@
(2 font-lock-constant-face t))
("^:[^:].*"
. 'bat-label-face)
- ("\\_<\\(defined\\|set\\)\\_>[ \t]*\\(\\(\\sw\\|\\s_\\)+\\)"
+ ("\\_<\\(defined\\|set\\|setx\\)\\_>[ \t]*\\(\\(\\sw\\|\\s_\\)+\\)"
(2 font-lock-variable-name-face))
("%~\\([0-9]\\)"
(1 font-lock-variable-name-face))
diff --git a/lisp/progmodes/bug-reference.el b/lisp/progmodes/bug-reference.el
index 0a2d5ed796b..06242a4cba8 100644
--- a/lisp/progmodes/bug-reference.el
+++ b/lisp/progmodes/bug-reference.el
@@ -269,9 +269,9 @@ via the internet it might also be http.")
;; pull/17 page if 17 is a PR. Explicit user/project#17 links to
;; possibly different projects are also supported.
(cl-defmethod bug-reference--build-forge-setup-entry
- (host-domain (_forge-type (eql github)) protocol)
+ (host-domain (_forge-type (eql 'github)) protocol)
`(,(concat "[/@]" (regexp-quote host-domain)
- "[/:]\\([.A-Za-z0-9_/-]+\\)\\.git")
+ "[/:]\\([.A-Za-z0-9_/-]+?\\)\\(?:\\.git\\)?/?\\'")
"\\(\\([.A-Za-z0-9_/-]+\\)?\\(?:#\\)\\([0-9]+\\)\\)\\>"
,(lambda (groups)
(let ((ns-project (nth 1 groups)))
@@ -285,9 +285,9 @@ via the internet it might also be http.")
;; namespace/project#18 or namespace/project!17 references to possibly
;; different projects are also supported.
(cl-defmethod bug-reference--build-forge-setup-entry
- (host-domain (_forge-type (eql gitlab)) protocol)
+ (host-domain (_forge-type (eql 'gitlab)) protocol)
`(,(concat "[/@]" (regexp-quote host-domain)
- "[/:]\\([.A-Za-z0-9_/-]+\\)\\.git")
+ "[/:]\\([.A-Za-z0-9_/-]+?\\)\\(?:\\.git\\)?/?\\'")
"\\(\\([.A-Za-z0-9_/-]+\\)?\\([#!]\\)\\([0-9]+\\)\\)\\>"
,(lambda (groups)
(let ((ns-project (nth 1 groups)))
@@ -302,9 +302,9 @@ via the internet it might also be http.")
;; Gitea: The systematics is exactly as for Github projects.
(cl-defmethod bug-reference--build-forge-setup-entry
- (host-domain (_forge-type (eql gitea)) protocol)
+ (host-domain (_forge-type (eql 'gitea)) protocol)
`(,(concat "[/@]" (regexp-quote host-domain)
- "[/:]\\([.A-Za-z0-9_/-]+\\)\\.git")
+ "[/:]\\([.A-Za-z0-9_/-]+?\\)\\(?:\\.git\\)?/?\\'")
"\\(\\([.A-Za-z0-9_/-]+\\)?\\(?:#\\)\\([0-9]+\\)\\)\\>"
,(lambda (groups)
(let ((ns-project (nth 1 groups)))
@@ -323,7 +323,7 @@ via the internet it might also be http.")
;; repo without tracker, or a repo with a tracker using a different
;; name, etc. So we can only try to make a good guess.
(cl-defmethod bug-reference--build-forge-setup-entry
- (host-domain (_forge-type (eql sourcehut)) protocol)
+ (host-domain (_forge-type (eql 'sourcehut)) protocol)
`(,(concat "[/@]\\(?:git\\|hg\\)." (regexp-quote host-domain)
"[/:]\\(~[.A-Za-z0-9_/-]+\\)")
"\\(\\(~[.A-Za-z0-9_/-]+\\)?\\(?:#\\)\\([0-9]+\\)\\)\\>"
diff --git a/lisp/progmodes/cc-cmds.el b/lisp/progmodes/cc-cmds.el
index f42f82e53bb..e9237bb01e2 100644
--- a/lisp/progmodes/cc-cmds.el
+++ b/lisp/progmodes/cc-cmds.el
@@ -1896,16 +1896,18 @@ defun."
(if (< arg 0)
(c-while-widening-to-decl-block
(< (setq arg (- (c-forward-to-nth-EOF-\;-or-} (- arg) where))) 0)))
- ;; Move forward to the next opening brace....
- (when (and (= arg 0)
- (progn
- (c-while-widening-to-decl-block
- (not (c-syntactic-re-search-forward "{" nil 'eob)))
- (eq (char-before) ?{)))
- (backward-char)
- ;; ... and backward to the function header.
- (c-beginning-of-decl-1)
- t))
+ (prog1
+ ;; Move forward to the next opening brace....
+ (when (and (= arg 0)
+ (progn
+ (c-while-widening-to-decl-block
+ (not (c-syntactic-re-search-forward "{" nil 'eob)))
+ (eq (char-before) ?{)))
+ (backward-char)
+ ;; ... and backward to the function header.
+ (c-beginning-of-decl-1)
+ t)
+ (c-keep-region-active)))
;; Move backward to the opening brace of a function, making successively
;; larger portions of the buffer visible as necessary.
@@ -3413,7 +3415,8 @@ to call `c-scan-conditionals' directly instead."
(interactive "p")
(let ((new-point (c-scan-conditionals count target-depth with-else)))
(push-mark)
- (goto-char new-point)))
+ (goto-char new-point))
+ (c-keep-region-active))
(defun c-scan-conditionals (count &optional target-depth with-else)
"Scan forward across COUNT preprocessor conditionals.
diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el
index 3068c41a57e..ebc1ef43010 100644
--- a/lisp/progmodes/cc-engine.el
+++ b/lisp/progmodes/cc-engine.el
@@ -165,12 +165,16 @@
(defvar c-doc-line-join-end-ch)
(defvar c-syntactic-context)
(defvar c-syntactic-element)
+(defvar c-new-id-start)
+(defvar c-new-id-end)
+(defvar c-new-id-is-type)
(cc-bytecomp-defvar c-min-syn-tab-mkr)
(cc-bytecomp-defvar c-max-syn-tab-mkr)
(cc-bytecomp-defun c-clear-syn-tab)
(cc-bytecomp-defun c-clear-string-fences)
(cc-bytecomp-defun c-restore-string-fences)
(cc-bytecomp-defun c-remove-string-fences)
+(cc-bytecomp-defun c-fontify-new-found-type)
;; Make declarations for all the `c-lang-defvar' variables in cc-langs.
@@ -6808,26 +6812,47 @@ comment at the start of cc-engine.el for more info."
(defvar c-found-types nil)
(make-variable-buffer-local 'c-found-types)
+;; Dynamically bound variable that instructs `c-forward-type' to
+;; record the ranges of types that only are found. Behaves otherwise
+;; like `c-record-type-identifiers'. Also when this variable is non-nil,
+;; `c-fontify-new-found-type' doesn't get called (yet) for the purported
+;; type.
+(defvar c-record-found-types nil)
+
(defsubst c-clear-found-types ()
;; Clears `c-found-types'.
(setq c-found-types
(make-hash-table :test #'equal :weakness nil)))
-(defun c-add-type (from to)
- ;; Add the given region as a type in `c-found-types'. If the region
- ;; doesn't match an existing type but there is a type which is equal
- ;; to the given one except that the last character is missing, then
- ;; the shorter type is removed. That's done to avoid adding all
- ;; prefixes of a type as it's being entered and font locked. This
- ;; doesn't cover cases like when characters are removed from a type
- ;; or added in the middle. We'd need the position of point when the
- ;; font locking is invoked to solve this well.
+(defun c-add-type-1 (from to)
+ ;; Add the given region as a type in `c-found-types'. Prepare occurrences
+ ;; of this new type for fontification throughout the buffer.
;;
;; This function might do hidden buffer changes.
(let ((type (c-syntactic-content from to c-recognize-<>-arglists)))
(unless (gethash type c-found-types)
- (remhash (substring type 0 -1) c-found-types)
- (puthash type t c-found-types))))
+ (puthash type t c-found-types)
+ (when (and (not c-record-found-types) ; Only call `c-fontify-new-fount-type'
+ ; when we haven't "bound" c-found-types
+ ; to itself in c-forward-<>-arglist.
+ (eq (string-match c-symbol-key type) 0)
+ (eq (match-end 0) (length type)))
+ (c-fontify-new-found-type type)))))
+
+(defun c-add-type (from to)
+ ;; Add the given region as a type in `c-found-types'. Also perform the
+ ;; actions of `c-add-type-1'. If the region is or overlaps an identifier
+ ;; which might be being typed in, don't record it. This is tested by
+ ;; checking `c-new-id-start' and `c-new-id-end'. That's done to avoid
+ ;; adding all prefixes of a type as it's being entered and font locked.
+ ;; This is a bit rough and ready, but now covers adding characters into the
+ ;; middle of an identifer.
+ ;;
+ ;; This function might do hidden buffer changes.
+ (if (and c-new-id-start c-new-id-end
+ (<= from c-new-id-end) (>= to c-new-id-start))
+ (setq c-new-id-is-type t)
+ (c-add-type-1 from to)))
(defun c-unfind-type (name)
;; Remove the "NAME" from c-found-types, if present.
@@ -8210,11 +8235,6 @@ multi-line strings (but not C++, for example)."
(setq c-record-ref-identifiers
(cons range c-record-ref-identifiers))))))
-;; Dynamically bound variable that instructs `c-forward-type' to
-;; record the ranges of types that only are found. Behaves otherwise
-;; like `c-record-type-identifiers'.
-(defvar c-record-found-types nil)
-
(defmacro c-forward-keyword-prefixed-id (type)
;; Used internally in `c-forward-keyword-clause' to move forward
;; over a type (if TYPE is 'type) or a name (otherwise) which
@@ -8444,6 +8464,11 @@ multi-line strings (but not C++, for example)."
(c-forward-<>-arglist-recur all-types)))
(progn
(when (consp c-record-found-types)
+ (let ((cur c-record-found-types))
+ (while (consp (car-safe cur))
+ (c-fontify-new-found-type
+ (buffer-substring-no-properties (caar cur) (cdar cur)))
+ (setq cur (cdr cur))))
(setq c-record-type-identifiers
;; `nconc' doesn't mind that the tail of
;; `c-record-found-types' is t.
@@ -9169,6 +9194,12 @@ multi-line strings (but not C++, for example)."
(when (and (eq res t)
(consp c-record-found-types))
+ ;; Cause the confirmed types to get fontified.
+ (let ((cur c-record-found-types))
+ (while (consp (car-safe cur))
+ (c-fontify-new-found-type
+ (buffer-substring-no-properties (caar cur) (cdar cur)))
+ (setq cur (cdr cur))))
;; Merge in the ranges of any types found by the second
;; `c-forward-type'.
(setq c-record-type-identifiers
@@ -9906,6 +9937,10 @@ This function might do hidden buffer changes."
;; Set when we have encountered a keyword (e.g. "extern") which
;; causes the following declaration to be treated as though top-level.
make-top
+ ;; A list of found types in this declaration. This is an association
+ ;; list, the car being the buffer position, the cdr being the
+ ;; identifier.
+ found-type-list
;; Save `c-record-type-identifiers' and
;; `c-record-ref-identifiers' since ranges are recorded
;; speculatively and should be thrown away if it turns out
@@ -9975,10 +10010,17 @@ This function might do hidden buffer changes."
;; If the previous identifier is a found type we
;; record it as a real one; it might be some sort of
;; alias for a prefix like "unsigned".
- (save-excursion
- (goto-char type-start)
- (let ((c-promote-possible-types t))
- (c-forward-type))))
+ ;; We postpone entering the new found type into c-found-types
+ ;; until we are sure of it, thus preventing rapid alternation
+ ;; of the fontification of the token throughout the buffer.
+ (push (cons type-start
+ (buffer-substring-no-properties
+ type-start
+ (save-excursion
+ (goto-char type-start)
+ (c-end-of-token)
+ (point))))
+ found-type-list))
;; Signal a type declaration for "struct foo {".
(when (and backup-at-type-decl
@@ -10224,13 +10266,10 @@ This function might do hidden buffer changes."
(when (eq at-type 'found)
;; Remove the ostensible type from the found types list.
(when type-start
- (c-unfind-type
- (buffer-substring-no-properties
- type-start
- (save-excursion
- (goto-char type-start)
- (c-end-of-token)
- (point)))))
+ (let ((discard-t (assq type-start found-type-list)))
+ (when discard-t
+ (setq found-type-list
+ (remq discard-t found-type-list)))))
t))
;; The token which we assumed to be a type is actually the
;; identifier, and we have no explicit type.
@@ -10844,6 +10883,14 @@ This function might do hidden buffer changes."
;; interactive refontification.
(c-put-c-type-property (point) 'c-decl-arg-start))
+ ;; Enter all the found types into `c-found-types'.
+ (when found-type-list
+ (save-excursion
+ (let ((c-promote-possible-types t))
+ (dolist (ft found-type-list)
+ (goto-char (car ft))
+ (c-forward-type)))))
+
;; Record the type's coordinates in `c-record-type-identifiers' for
;; later fontification.
(when (and c-record-type-identifiers at-type ;; (not (eq at-type t))
@@ -12092,7 +12139,10 @@ comment at the start of cc-engine.el for more info."
(and (c-major-mode-is 'pike-mode)
c-decl-block-key)))
(while (eq braceassignp 'dontknow)
- (cond ((eq (char-after) ?\;)
+ (cond ((or (eq (char-after) ?\;)
+ (save-excursion
+ (progn (c-backward-syntactic-ws)
+ (c-at-vsemi-p))))
(setq braceassignp nil))
((and class-key
(looking-at class-key))
@@ -14016,7 +14066,8 @@ comment at the start of cc-engine.el for more info."
;; clause - we assume only C++ needs it.
(c-syntactic-skip-backward "^;,=" lim t))
(setq placeholder (point))
- (memq (char-before) '(?, ?= ?<)))
+ (and (memq (char-before) '(?, ?= ?<))
+ (not (c-crosses-statement-barrier-p (point) indent-point))))
(cond
;; CASE 5D.6: Something like C++11's "using foo = <type-exp>"
diff --git a/lisp/progmodes/cc-fonts.el b/lisp/progmodes/cc-fonts.el
index 63df267b43f..15e3beb8377 100644
--- a/lisp/progmodes/cc-fonts.el
+++ b/lisp/progmodes/cc-fonts.el
@@ -97,6 +97,7 @@
(cc-bytecomp-defun c-font-lock-declarators)
(cc-bytecomp-defun c-font-lock-objc-method)
(cc-bytecomp-defun c-font-lock-invalid-string)
+(cc-bytecomp-defun c-font-lock-fontify-region)
;; Note that font-lock in XEmacs doesn't expand face names as
@@ -919,13 +920,6 @@ casts and declarations are fontified. Used on level 2 and higher."
;; This function does hidden buffer changes.
;;(message "c-font-lock-complex-decl-prepare %s %s" (point) limit)
-
- ;; Clear the list of found types if we start from the start of the
- ;; buffer, to make it easier to get rid of misspelled types and
- ;; variables that have gotten recognized as types in malformed code.
- (when (bobp)
- (c-clear-found-types))
-
(c-skip-comments-and-strings limit)
(when (< (point) limit)
@@ -2255,6 +2249,49 @@ higher."
;; defvar will install its default value later on.
(makunbound def-var)))
+;; `c-re-redisplay-timer' is a timer which, when triggered, causes a
+;; redisplay.
+(defvar c-re-redisplay-timer nil)
+
+(defun c-force-redisplay (buffer start end)
+ ;; Force redisplay immediately. This assumes `font-lock-support-mode' is
+ ;; 'jit-lock-mode. Set the variable `c-re-redisplay-timer' to nil.
+ (with-current-buffer buffer
+ (save-excursion (c-font-lock-fontify-region start end))
+ (jit-lock-force-redisplay (copy-marker start) (copy-marker end))
+ (setq c-re-redisplay-timer nil)))
+
+(defun c-fontify-new-found-type (type)
+ ;; Cause the fontification of TYPE, a string, wherever it occurs in the
+ ;; buffer. If TYPE is currently displayed in a window, cause redisplay to
+ ;; happen "instantaneously". These actions are done only when jit-lock-mode
+ ;; is active.
+ (when (and font-lock-mode
+ (boundp 'font-lock-support-mode)
+ (eq font-lock-support-mode 'jit-lock-mode))
+ (c-save-buffer-state
+ ((window-boundaries
+ (mapcar (lambda (win)
+ (cons (window-start win)
+ (window-end win)))
+ (get-buffer-window-list (current-buffer) 'no-mini t)))
+ (target-re (concat "\\_<" type "\\_>")))
+ (save-excursion
+ (save-restriction
+ (widen)
+ (goto-char (point-min))
+ (while (re-search-forward target-re nil t)
+ (put-text-property (match-beginning 0) (match-end 0)
+ 'fontified nil)
+ (dolist (win-boundary window-boundaries)
+ (when (and (< (match-beginning 0) (cdr win-boundary))
+ (> (match-end 0) (car win-boundary))
+ (not c-re-redisplay-timer))
+ (setq c-re-redisplay-timer
+ (run-with-timer 0 nil #'c-force-redisplay
+ (current-buffer)
+ (match-beginning 0) (match-end 0)))))))))))
+
;;; C.
diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el
index 0aef94a4f2d..957a0b8a7c5 100644
--- a/lisp/progmodes/cc-mode.el
+++ b/lisp/progmodes/cc-mode.el
@@ -179,6 +179,15 @@
(when c-buffer-is-cc-mode
(save-restriction
(widen)
+ (let ((lst (buffer-list)))
+ (catch 'found
+ (dolist (b lst)
+ (if (and (not (eq b (current-buffer)))
+ (with-current-buffer b
+ c-buffer-is-cc-mode))
+ (throw 'found nil)))
+ (remove-hook 'post-command-hook 'c-post-command)
+ (remove-hook 'post-gc-hook 'c-post-gc-hook)))
(c-save-buffer-state ()
(c-clear-char-properties (point-min) (point-max) 'category)
(c-clear-char-properties (point-min) (point-max) 'syntax-table)
@@ -745,6 +754,8 @@ that requires a literal mode spec at compile time."
;; would do since font-lock uses a(n implicit) depth of 0) so we don't need
;; c-after-font-lock-init.
(add-hook 'after-change-functions 'c-after-change nil t)
+ (add-hook 'post-command-hook 'c-post-command)
+
(when (boundp 'font-lock-extend-after-change-region-function)
(set (make-local-variable 'font-lock-extend-after-change-region-function)
'c-extend-after-change-region))) ; Currently (2009-05) used by all
@@ -787,43 +798,44 @@ MODE is the symbol for the mode to initialize, like `c-mode'. See
`c-basic-common-init' for details. It's only optional to be
compatible with old code; callers should always specify it."
- (unless mode
- ;; Called from an old third party package. The fallback is to
- ;; initialize for C.
- (c-init-language-vars-for 'c-mode))
+ (let (case-fold-search)
+ (unless mode
+ ;; Called from an old third party package. The fallback is to
+ ;; initialize for C.
+ (c-init-language-vars-for 'c-mode))
- (c-basic-common-init mode c-default-style)
- (when mode
- ;; Only initialize font locking if we aren't called from an old package.
- (c-font-lock-init))
+ (c-basic-common-init mode c-default-style)
+ (when mode
+ ;; Only initialize font locking if we aren't called from an old package.
+ (c-font-lock-init))
- ;; Starting a mode is a sort of "change". So call the change functions...
- (save-restriction
- (widen)
- (setq c-new-BEG (point-min))
- (setq c-new-END (point-max))
- (save-excursion
- (let (before-change-functions after-change-functions)
- (mapc (lambda (fn)
- (funcall fn (point-min) (point-max)))
- c-get-state-before-change-functions)
- (mapc (lambda (fn)
- (funcall fn (point-min) (point-max)
- (- (point-max) (point-min))))
- c-before-font-lock-functions))))
-
- (set (make-local-variable 'outline-regexp) "[^#\n\^M]")
- (set (make-local-variable 'outline-level) 'c-outline-level)
- (set (make-local-variable 'add-log-current-defun-function)
- (lambda ()
- (or (c-cpp-define-name) (car (c-defun-name-and-limits nil)))))
- (let ((rfn (assq mode c-require-final-newline)))
- (when rfn
- (if (boundp 'mode-require-final-newline)
- (and (cdr rfn)
- (set (make-local-variable 'require-final-newline)
- mode-require-final-newline))
- (set (make-local-variable 'require-final-newline) (cdr rfn))))))
+ ;; Starting a mode is a sort of "change". So call the change functions...
+ (save-restriction
+ (widen)
+ (setq c-new-BEG (point-min))
+ (setq c-new-END (point-max))
+ (save-excursion
+ (let (before-change-functions after-change-functions)
+ (mapc (lambda (fn)
+ (funcall fn (point-min) (point-max)))
+ c-get-state-before-change-functions)
+ (mapc (lambda (fn)
+ (funcall fn (point-min) (point-max)
+ (- (point-max) (point-min))))
+ c-before-font-lock-functions))))
+
+ (set (make-local-variable 'outline-regexp) "[^#\n\^M]")
+ (set (make-local-variable 'outline-level) 'c-outline-level)
+ (set (make-local-variable 'add-log-current-defun-function)
+ (lambda ()
+ (or (c-cpp-define-name) (car (c-defun-name-and-limits nil)))))
+ (let ((rfn (assq mode c-require-final-newline)))
+ (when rfn
+ (if (boundp 'mode-require-final-newline)
+ (and (cdr rfn)
+ (set (make-local-variable 'require-final-newline)
+ mode-require-final-newline))
+ (set (make-local-variable 'require-final-newline) (cdr rfn)))))))
(defun c-count-cfss (lv-alist)
;; LV-ALIST is an alist like `file-local-variables-alist'. Count how many
@@ -1950,6 +1962,43 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".")
;; confused by already processed single quotes.
(narrow-to-region (point) (point-max))))))
+;; The next two variables record the bounds of an identifier currently being
+;; typed in. These are used to prevent such a partial identifier being
+;; recorded as a found type by c-add-type.
+(defvar c-new-id-start nil)
+(make-variable-buffer-local 'c-new-id-start)
+(defvar c-new-id-end nil)
+(make-variable-buffer-local 'c-new-id-end)
+;; The next variable, when non-nil, records that the previous two variables
+;; define a type.
+(defvar c-new-id-is-type nil)
+(make-variable-buffer-local 'c-new-id-is-type)
+
+(defun c-update-new-id (end)
+ ;; Note the bounds of any identifier that END is in or just after, in
+ ;; `c-new-id-start' and `c-new-id-end'. Otherwise set these variables to
+ ;; nil.
+ (save-excursion
+ (goto-char end)
+ (let ((id-beg (c-on-identifier)))
+ (setq c-new-id-start id-beg
+ c-new-id-end (and id-beg
+ (progn (c-end-of-current-token) (point)))))))
+
+
+(defun c-post-command ()
+ ;; If point was inside of a new identifier and no longer is, record that
+ ;; fact.
+ (when (and c-buffer-is-cc-mode
+ c-new-id-start c-new-id-end
+ (or (> (point) c-new-id-end)
+ (< (point) c-new-id-start)))
+ (when c-new-id-is-type
+ (c-add-type-1 c-new-id-start c-new-id-end))
+ (setq c-new-id-start nil
+ c-new-id-end nil
+ c-new-id-is-type nil)))
+
(defun c-before-change (beg end)
;; Function to be put on `before-change-functions'. Primarily, this calls
;; the language dependent `c-get-state-before-change-functions'. It is
@@ -1969,11 +2018,16 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".")
(unless (c-called-from-text-property-change-p)
(save-restriction
(widen)
+ ;; Clear the list of found types if we make a change at the start of the
+ ;; buffer, to make it easier to get rid of misspelled types and
+ ;; variables that have gotten recognized as types in malformed code.
+ (when (eq beg (point-min))
+ (c-clear-found-types))
(if c-just-done-before-change
- ;; We have two consecutive calls to `before-change-functions' without
- ;; an intervening `after-change-functions'. An example of this is bug
- ;; #38691. To protect CC Mode, assume that the entire buffer has
- ;; changed.
+ ;; We have two consecutive calls to `before-change-functions'
+ ;; without an intervening `after-change-functions'. An example of
+ ;; this is bug #38691. To protect CC Mode, assume that the entire
+ ;; buffer has changed.
(setq beg (point-min)
end (point-max)
c-just-done-before-change 'whole-buffer)
@@ -2151,6 +2205,7 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".")
c->-as-paren-syntax)
(c-clear-char-property-with-value beg end 'syntax-table nil)))
+ (c-update-new-id end)
(c-trim-found-types beg end old-len) ; maybe we don't
; need all of these.
(c-invalidate-sws-region-after beg end old-len)
@@ -2549,17 +2604,24 @@ This function is called from `c-common-init', once per mode initialization."
At the time of call, point is just after the newly inserted CHAR.
-When CHAR is \", t will be returned unless the \" is marked with
-a string fence syntax-table text property. For other characters,
-the default value of `electric-pair-inhibit-predicate' is called
-and its value returned.
+When CHAR is \" and not within a comment, t will be returned if
+the quotes on the current line are already balanced (i.e. if the
+last \" is not marked with a string fence syntax-table text
+property). For other cases, the default value of
+`electric-pair-inhibit-predicate' is called and its value
+returned.
This function is the appropriate value of
`electric-pair-inhibit-predicate' for CC Mode modes, which mark
invalid strings with such a syntax table text property on the
opening \" and the next unescaped end of line."
- (if (eq char ?\")
- (not (equal (get-text-property (1- (point)) 'c-fl-syn-tab) '(15)))
+ (if (and (eq char ?\")
+ (not (memq (cadr (c-semi-pp-to-literal (1- (point)))) '(c c++))))
+ (let ((last-quote (save-match-data
+ (save-excursion
+ (goto-char (c-point 'eoll))
+ (search-backward "\"")))))
+ (not (equal (c-get-char-property last-quote 'c-fl-syn-tab) '(15))))
(funcall (default-value 'electric-pair-inhibit-predicate) char)))
diff --git a/lisp/progmodes/cc-styles.el b/lisp/progmodes/cc-styles.el
index a66f91e0eb3..8fe8402b1d8 100644
--- a/lisp/progmodes/cc-styles.el
+++ b/lisp/progmodes/cc-styles.el
@@ -444,17 +444,19 @@ STYLE using `c-set-style' if the optional SET-P flag is non-nil."
defstr))
(prompt (concat symname " offset " defstr))
(keymap (make-sparse-keymap))
- (minibuffer-completion-table obarray)
- (minibuffer-completion-predicate 'fboundp)
offset input)
;; In principle completing-read is used here, but SPC is unbound
;; to make it less annoying to enter lists.
(set-keymap-parent keymap minibuffer-local-completion-map)
(define-key keymap " " 'self-insert-command)
(while (not offset)
- (setq input (read-from-minibuffer prompt nil keymap t
- 'c-read-offset-history
- (format "%s" oldoff)))
+ (minibuffer-with-setup-hook
+ (lambda ()
+ (setq-local minibuffer-completion-table obarray)
+ (setq-local minibuffer-completion-predicate 'fboundp))
+ (setq input (read-from-minibuffer prompt nil keymap t
+ 'c-read-offset-history
+ (format "%s" oldoff))))
(if (c-valid-offset input)
(setq offset input)
;; error, but don't signal one, keep trying
diff --git a/lisp/progmodes/cc-vars.el b/lisp/progmodes/cc-vars.el
index 45521d50218..e0f5a7ee021 100644
--- a/lisp/progmodes/cc-vars.el
+++ b/lisp/progmodes/cc-vars.el
@@ -179,7 +179,7 @@ STYLE stands for the choice where the value is taken from some
style setting. PREAMBLE is optionally prepended to FOO; that is,
if FOO contains :tag or :value, the respective two-element list
component is ignored."
- (declare (debug (symbolp form stringp &rest)))
+ (declare (debug (symbolp form stringp &rest)) (indent defun))
(let* ((expanded-doc (concat doc "
This is a style variable. Apart from the valid values described
diff --git a/lisp/progmodes/compile.el b/lisp/progmodes/compile.el
index 7d4a8ffc6fc..e75a44b6537 100644
--- a/lisp/progmodes/compile.el
+++ b/lisp/progmodes/compile.el
@@ -346,12 +346,9 @@ of[ \t]+\"?\\([a-zA-Z]?:?[^\":\n]+\\)\"?:" 3 2 nil (1))
;; PROGRAM:SOURCE-FILE-NAME:LINENO: MESSAGE
;; which is used for non-interactive programs other than
;; compilers (e.g. the "jade:" entry in compilation.txt).
- (? (| (regexp "[[:alpha:]][-[:alnum:].]+: ?")
- ;; FIXME: This pattern was added for handling messages
- ;; from Ruby, but it is unclear whether it is actually
- ;; used since the gcc-include rule above seems to cover
- ;; it.
- (regexp "[ \t]+\\(?:in \\|from\\)")))
+ (? (| (: alpha (+ (in ?. ?- alnum)) ":" (? " "))
+ ;; Skip indentation generated by GCC's -fanalyzer.
+ (: (+ " ") "|")))
;; File name group.
(group-n 1
@@ -2228,6 +2225,7 @@ The parent is always `compilation-mode' and the customizable `compilation-...'
variables are also set from the name of the mode you have chosen,
by replacing the first word, e.g., `compilation-scroll-output' from
`grep-scroll-output' if that variable exists."
+ (declare (indent defun))
(let ((mode-name (replace-regexp-in-string "-mode\\'" "" (symbol-name mode))))
`(define-derived-mode ,mode compilation-mode ,name
,doc
diff --git a/lisp/progmodes/cperl-mode.el b/lisp/progmodes/cperl-mode.el
index ae36789af82..94ecc45b15f 100644
--- a/lisp/progmodes/cperl-mode.el
+++ b/lisp/progmodes/cperl-mode.el
@@ -1019,15 +1019,9 @@ Unless KEEP, removes the old indentation."
(define-key map [(control ?c) (control ?h) ?v]
;;(concat (char-to-string help-char) "v") ; does not work
'cperl-get-help))
- (substitute-key-definition
- 'indent-sexp 'cperl-indent-exp
- map global-map)
- (substitute-key-definition
- 'indent-region 'cperl-indent-region
- map global-map)
- (substitute-key-definition
- 'indent-for-comment 'cperl-indent-for-comment
- map global-map)
+ (define-key map [remap indent-sexp] #'cperl-indent-exp)
+ (define-key map [remap indent-region] #'cperl-indent-region)
+ (define-key map [remap indent-for-comment] #'cperl-indent-for-comment)
map)
"Keymap used in CPerl mode.")
@@ -3840,7 +3834,7 @@ recursive calls in starting lines of here-documents."
"\\<" cperl-sub-regexp "\\>" ; sub with proto/attr
"\\("
cperl-white-and-comment-rex
- (rx (group (eval cperl--normal-identifier-rx)))
+ (rx (opt (group (eval cperl--normal-identifier-rx))))
"\\)"
"\\("
cperl-maybe-white-and-comment-rex
@@ -5951,7 +5945,7 @@ default function."
(eval cperl--basic-identifier-rx)))
(0+ blank) "(")
;; '("\\<for\\(each\\)?\\([ \t]+\\(state\\|my\\|local\\|our\\)\\)?[ \t]*\\(\\$[a-zA-Z_][a-zA-Z_0-9]*\\)[ \t]*("
- 4 font-lock-variable-name-face)
+ 1 font-lock-variable-name-face)
;; Avoid $!, and s!!, qq!! etc. when not fontifying syntactically
'("\\(?:^\\|[^smywqrx$]\\)\\(!\\)" 1 font-lock-negation-char-face)
'("\\[\\(\\^\\)" 1 font-lock-negation-char-face prepend)))
diff --git a/lisp/progmodes/cpp.el b/lisp/progmodes/cpp.el
index 5cdcd7d32e3..f4584b63113 100644
--- a/lisp/progmodes/cpp.el
+++ b/lisp/progmodes/cpp.el
@@ -702,11 +702,8 @@ BRANCH should be either nil (false branch), t (true branch) or `both'."
(x-popup-menu cpp-button-event
(list prompt (cons prompt cpp-face-default-list)))
(let ((name (car (rassq default cpp-face-default-list))))
- (cdr (assoc (completing-read (if name
- (concat prompt
- " (default " name "): ")
- (concat prompt ": "))
- cpp-face-default-list nil t)
+ (cdr (assoc (completing-read (format-prompt "%s" name prompt)
+ cpp-face-default-list nil t)
cpp-face-all-list))))
default))
diff --git a/lisp/progmodes/ebrowse.el b/lisp/progmodes/ebrowse.el
index 047d43a922b..17cc537e38e 100644
--- a/lisp/progmodes/ebrowse.el
+++ b/lisp/progmodes/ebrowse.el
@@ -1330,9 +1330,9 @@ Pop to member buffer if no prefix ARG, to tree buffer otherwise."
"Set the indentation width of the tree display."
(interactive)
(let ((width (string-to-number (read-string
- (concat "Indentation (default "
- (int-to-string ebrowse--indentation)
- "): ")
+ (format-prompt
+ "Indentation"
+ (int-to-string ebrowse--indentation))
nil nil ebrowse--indentation))))
(when (cl-plusp width)
(setq-local ebrowse--indentation width)
@@ -4045,23 +4045,27 @@ NUMBER-OF-STATIC-VARIABLES:"
(defvar ebrowse-global-map nil
"Keymap for Ebrowse commands.")
-
(defvar ebrowse-global-prefix-key "\C-c\C-m"
"Prefix key for Ebrowse commands.")
-
-(defvar ebrowse-global-submap-4 nil
- "Keymap used for `ebrowse-global-prefix' followed by `4'.")
-
-
-(defvar ebrowse-global-submap-5 nil
- "Keymap used for `ebrowse-global-prefix' followed by `5'.")
-
+(defvar-keymap ebrowse-global-submap-4
+ :doc "Keymap used for `ebrowse-global-prefix' followed by `4'."
+ "." #'ebrowse-tags-find-definition-other-window
+ "f" #'ebrowse-tags-find-definition-other-window
+ "v" #'ebrowse-tags-find-declaration-other-window
+ "F" #'ebrowse-tags-view-definition-other-window
+ "V" #'ebrowse-tags-view-declaration-other-window)
+
+(defvar-keymap ebrowse-global-submap-5
+ :doc "Keymap used for `ebrowse-global-prefix' followed by `5'."
+ "." #'ebrowse-tags-find-definition-other-frame
+ "f" #'ebrowse-tags-find-definition-other-frame
+ "v" #'ebrowse-tags-find-declaration-other-frame
+ "F" #'ebrowse-tags-view-definition-other-frame
+ "V" #'ebrowse-tags-view-declaration-other-frame)
(unless ebrowse-global-map
(setq ebrowse-global-map (make-sparse-keymap))
- (setq ebrowse-global-submap-4 (make-sparse-keymap))
- (setq ebrowse-global-submap-5 (make-sparse-keymap))
(define-key ebrowse-global-map "a" 'ebrowse-tags-apropos)
(define-key ebrowse-global-map "b" 'ebrowse-pop-to-browser-buffer)
(define-key ebrowse-global-map "-" 'ebrowse-back-in-position-stack)
@@ -4082,17 +4086,7 @@ NUMBER-OF-STATIC-VARIABLES:"
(define-key ebrowse-global-map " " 'ebrowse-electric-buffer-list)
(define-key ebrowse-global-map "\t" 'ebrowse-tags-complete-symbol)
(define-key ebrowse-global-map "4" ebrowse-global-submap-4)
- (define-key ebrowse-global-submap-4 "." 'ebrowse-tags-find-definition-other-window)
- (define-key ebrowse-global-submap-4 "f" 'ebrowse-tags-find-definition-other-window)
- (define-key ebrowse-global-submap-4 "v" 'ebrowse-tags-find-declaration-other-window)
- (define-key ebrowse-global-submap-4 "F" 'ebrowse-tags-view-definition-other-window)
- (define-key ebrowse-global-submap-4 "V" 'ebrowse-tags-view-declaration-other-window)
(define-key ebrowse-global-map "5" ebrowse-global-submap-5)
- (define-key ebrowse-global-submap-5 "." 'ebrowse-tags-find-definition-other-frame)
- (define-key ebrowse-global-submap-5 "f" 'ebrowse-tags-find-definition-other-frame)
- (define-key ebrowse-global-submap-5 "v" 'ebrowse-tags-find-declaration-other-frame)
- (define-key ebrowse-global-submap-5 "F" 'ebrowse-tags-view-definition-other-frame)
- (define-key ebrowse-global-submap-5 "V" 'ebrowse-tags-view-declaration-other-frame)
(define-key global-map ebrowse-global-prefix-key ebrowse-global-map))
diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el
index 101c323b132..0dfff32f20d 100644
--- a/lisp/progmodes/elisp-mode.el
+++ b/lisp/progmodes/elisp-mode.el
@@ -45,15 +45,13 @@ It has `lisp-mode-abbrev-table' as its parent."
table)
"Syntax table used in `emacs-lisp-mode'.")
-(defvar emacs-lisp-mode-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map lisp-mode-shared-map)
- (define-key map "\e\t" 'completion-at-point)
- (define-key map "\e\C-x" 'eval-defun)
- (define-key map "\e\C-q" 'indent-pp-sexp)
- map)
- "Keymap for Emacs Lisp mode.
-All commands in `lisp-mode-shared-map' are inherited by this map.")
+(defvar-keymap emacs-lisp-mode-map
+ :doc "Keymap for Emacs Lisp mode.
+All commands in `lisp-mode-shared-map' are inherited by this map."
+ :parent lisp-mode-shared-map
+ "M-TAB" #'completion-at-point
+ "C-M-x" #'eval-defun
+ "C-M-q" #'indent-pp-sexp)
(easy-menu-define emacs-lisp-mode-menu emacs-lisp-mode-map
"Menu for Emacs Lisp mode."
@@ -270,10 +268,8 @@ Comments in the form will be lost."
(setq-local lexical-binding t)
(add-file-local-variable-prop-line 'lexical-binding t interactive))))
-(defvar elisp--dynlex-modeline-map
- (let ((map (make-sparse-keymap)))
- (define-key map [mode-line mouse-1] 'elisp-enable-lexical-binding)
- map))
+(defvar-keymap elisp--dynlex-modeline-map
+ "<mode-line> <mouse-1>" #'elisp-enable-lexical-binding)
;;;###autoload
(define-derived-mode emacs-lisp-mode lisp-data-mode
@@ -636,7 +632,8 @@ functions are annotated with \"<f>\" via the
:company-kind #'elisp--company-kind
:company-doc-buffer #'elisp--company-doc-buffer
:company-docsig #'elisp--company-doc-string
- :company-location #'elisp--company-location))
+ :company-location #'elisp--company-location
+ :company-deprecated #'elisp--company-deprecated))
(quoted
(list nil (elisp--completion-local-symbols)
;; Don't include all symbols (bug#16646).
@@ -652,7 +649,8 @@ functions are annotated with \"<f>\" via the
:company-kind #'elisp--company-kind
:company-doc-buffer #'elisp--company-doc-buffer
:company-docsig #'elisp--company-doc-string
- :company-location #'elisp--company-location))
+ :company-location #'elisp--company-location
+ :company-deprecated #'elisp--company-deprecated))
(t
(list nil (completion-table-merge
elisp--local-variables-completion-table
@@ -667,7 +665,8 @@ functions are annotated with \"<f>\" via the
'variable))
:company-doc-buffer #'elisp--company-doc-buffer
:company-docsig #'elisp--company-doc-string
- :company-location #'elisp--company-location)))
+ :company-location #'elisp--company-location
+ :company-deprecated #'elisp--company-deprecated)))
;; Looks like a funcall position. Let's double check.
(save-excursion
(goto-char (1- beg))
@@ -714,13 +713,15 @@ functions are annotated with \"<f>\" via the
:company-kind (lambda (_) 'variable)
:company-doc-buffer #'elisp--company-doc-buffer
:company-docsig #'elisp--company-doc-string
- :company-location #'elisp--company-location))
+ :company-location #'elisp--company-location
+ :company-deprecated #'elisp--company-deprecated))
(_ (list nil (elisp--completion-local-symbols)
:predicate #'elisp--shorthand-aware-fboundp
:company-kind #'elisp--company-kind
:company-doc-buffer #'elisp--company-doc-buffer
:company-docsig #'elisp--company-doc-string
:company-location #'elisp--company-location
+ :company-deprecated #'elisp--company-deprecated
))))))))
(nconc (list beg end)
(if (null (car table-etc))
@@ -743,6 +744,11 @@ functions are annotated with \"<f>\" via the
((facep sym) 'color)
(t 'text))))
+(defun elisp--company-deprecated (str)
+ (let ((sym (intern-soft str)))
+ (or (get sym 'byte-obsolete-variable)
+ (get sym 'byte-obsolete-info))))
+
(defun lisp-completion-at-point (&optional _predicate)
(declare (obsolete elisp-completion-at-point "25.1"))
(elisp-completion-at-point))
@@ -1190,16 +1196,14 @@ namespace but with lower confidence."
;;; Elisp Interaction mode
-(defvar lisp-interaction-mode-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map lisp-mode-shared-map)
- (define-key map "\e\C-x" 'eval-defun)
- (define-key map "\e\C-q" 'indent-pp-sexp)
- (define-key map "\e\t" 'completion-at-point)
- (define-key map "\n" 'eval-print-last-sexp)
- map)
- "Keymap for Lisp Interaction mode.
-All commands in `lisp-mode-shared-map' are inherited by this map.")
+(defvar-keymap lisp-interaction-mode-map
+ :doc "Keymap for Lisp Interaction mode.
+All commands in `lisp-mode-shared-map' are inherited by this map."
+ :parent lisp-mode-shared-map
+ "C-M-x" #'eval-defun
+ "C-M-q" #'indent-pp-sexp
+ "M-TAB" #'completion-at-point
+ "C-j" #'eval-print-last-sexp)
(easy-menu-define lisp-interaction-mode-menu lisp-interaction-mode-map
"Menu for Lisp Interaction mode."
diff --git a/lisp/progmodes/erts-mode.el b/lisp/progmodes/erts-mode.el
new file mode 100644
index 00000000000..31a8bded8ad
--- /dev/null
+++ b/lisp/progmodes/erts-mode.el
@@ -0,0 +1,225 @@
+;;; erts-mode.el --- major mode to edit erts files -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
+
+;; Keywords: tools
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(eval-when-compile (require 'cl-lib))
+(require 'ert)
+
+(defgroup erts-mode nil
+ "Major mode for editing Emacs test files."
+ :group 'lisp)
+
+(defface erts-mode-specification-name
+ '((((class color)
+ (background dark))
+ :foreground "green")
+ (((class color)
+ (background light))
+ :foreground "cornflower blue")
+ (t
+ :bold t))
+ "Face used for displaying specification names."
+ :group 'erts-mode)
+
+(defface erts-mode-specification-value
+ '((((class color)
+ (background dark))
+ :foreground "DeepSkyBlue1")
+ (((class color)
+ (background light))
+ :foreground "blue")
+ (t
+ :bold t))
+ "Face used for displaying specificaton values."
+ :group 'erts-mode)
+
+(defface erts-mode-start-test
+ '((t :inherit font-lock-keyword-face))
+ "Face used for displaying specificaton test start markers."
+ :group 'erts-mode)
+
+(defface erts-mode-end-test
+ '((t :inherit font-lock-comment-face))
+ "Face used for displaying specificaton test start markers."
+ :group 'erts-mode)
+
+(defvar erts-mode-map
+ (let ((map (make-keymap)))
+ (set-keymap-parent map prog-mode-map)
+ (define-key map "\C-c\C-r" 'erts-tag-region)
+ (define-key map "\C-c\C-c" 'erts-run-test)
+ map))
+
+(defvar erts-mode-font-lock-keywords
+ ;; Specifications.
+ `((erts-mode--match-not-in-test
+ ("^\\([^ \t\n:]+:\\)[ \t]*\\(.*\\(\n[ \t].*\\)*\\)\n?"
+ (progn (goto-char (match-beginning 0)) (match-end 0)) nil
+ (1 'erts-mode-specification-name)
+ (2 'erts-mode-specification-value)))
+ ("^=-=$" 0 'erts-mode-start-test)
+ ("^=-=-=$" 0 'erts-mode-end-test)))
+
+(defun erts-mode--match-not-in-test (_limit)
+ (when (erts-mode--in-test-p (point))
+ (erts-mode--end-of-test))
+ (let ((start (point)))
+ (goto-char
+ (if (re-search-forward "^=-=$" nil t)
+ (match-beginning 0)
+ (point-max)))
+ (if (< (point) start)
+ nil
+ ;; Here we disregard LIMIT so that we may extend the area again.
+ (set-match-data (list start (point)))
+ (point))))
+
+(defun erts-mode--end-of-test ()
+ (search-forward "^=-=-=\n" nil t))
+
+(defun erts-mode--in-test-p (point)
+ "Say whether POINT is in a test."
+ (save-excursion
+ (goto-char point)
+ (beginning-of-line)
+ (if (looking-at "=-=\\(-=\\)?$")
+ t
+ (let ((test-start (save-excursion
+ (re-search-backward "^=-=\n" nil t))))
+ ;; Before the first test.
+ (and test-start
+ (let ((test-end (re-search-backward "^=-=-=\n" nil t)))
+ (or (null test-end)
+ ;; Between tests.
+ (> test-start test-end))))))))
+
+;;;###autoload
+(define-derived-mode erts-mode prog-mode "erts"
+ "Major mode for editing erts (Emacs testing) files.
+This mode mainly provides some font locking.
+
+\\{erts-mode-map}"
+ (setq-local font-lock-defaults '(erts-mode-font-lock-keywords t)))
+
+(defun erts-tag-region (start end name)
+ "Tag the region between START and END as a test.
+Interactively, this is the region.
+
+NAME should be a string appropriate for output by ert if the test fails.
+If NAME is nil or the empty string, a name will be auto-generated."
+ (interactive "r\nsTest name: " erts-mode)
+ ;; Automatically make a name.
+ (when (zerop (length name))
+ (save-excursion
+ (goto-char (point-min))
+ (let ((names nil))
+ (while (re-search-forward "^Name:[ \t]*\\(.*\\)" nil t)
+ (let ((name (match-string 1)))
+ (unless (erts-mode--in-test-p (point))
+ (push name names))))
+ (setq name
+ (cl-loop with base = (file-name-sans-extension (buffer-name))
+ for i from 1
+ for name = (format "%s%d" base i)
+ unless (member name names)
+ return name)))))
+ (save-excursion
+ (goto-char end)
+ (unless (bolp)
+ (insert "\n"))
+ (insert "=-=-=\n")
+ (goto-char start)
+ (insert "Name: " name "\n\n")
+ (insert "=-=\n")))
+
+(defun erts-mode--preceding-spec (name)
+ (save-excursion
+ ;; Find the name, but skip if it's in a test.
+ (while (and (re-search-backward (format "^%s:" name) nil t)
+ (erts-mode--in-test-p (point))))
+ (and (not (erts-mode--in-test-p (point)))
+ (re-search-forward "^=-=$" nil t)
+ (progn
+ (goto-char (match-beginning 0))
+ (cdr (assq (intern (downcase name))
+ (ert--erts-specifications (point))))))))
+
+(defun erts-run-test (test-function &optional verbose)
+ "Run the current test.
+If the current erts file doesn't define a test function, the user
+will be prompted for one.
+
+If VERBOSE (interactively, the prefix), display a diff of the
+expected results and the actual results in a separate buffer."
+ (interactive
+ (list (or (erts-mode--preceding-spec "Code")
+ (read-string "Transformation function: "))
+ current-prefix-arg)
+ erts-mode)
+ (save-excursion
+ (erts-mode--goto-start-of-test)
+ (condition-case arg
+ (ert-test--erts-test
+ (list (cons 'dummy t)
+ (cons 'code (car (read-from-string test-function)))
+ (cons 'point-char (erts-mode--preceding-spec "Point-Char")))
+ (buffer-file-name))
+ (:success (message "Test successful"))
+ (ert-test-failed
+ (if (not verbose)
+ (message "Test failure; result: \n%s"
+ (substring-no-properties (cadr (cadr arg))))
+ (message "Test failure")
+ (let (expected got)
+ (unwind-protect
+ (progn
+ (with-current-buffer
+ (setq expected (generate-new-buffer "erts expected"))
+ (insert (nth 1 (cadr arg))))
+ (with-current-buffer
+ (setq got (generate-new-buffer "erts results"))
+ (insert (nth 2 (cadr arg))))
+ (diff-buffers expected got))
+ (kill-buffer expected)
+ (kill-buffer got))))))))
+
+(defun erts-mode--goto-start-of-test ()
+ (if (not (erts-mode--in-test-p (point)))
+ (re-search-forward "^=-=\n" nil t)
+ (re-search-backward "^=-=\n" nil t)
+ (let ((potential-start (match-end 0)))
+ ;; See if we're in a two-clause ("before" and "after") test or not.
+ (if-let ((start (and (save-excursion (re-search-backward "^=-=\n" nil t))
+ (match-end 0))))
+ (let ((end (save-excursion (re-search-backward "^=-=-=\n" nil t))))
+ (if (or (not end)
+ (> start end))
+ ;; We are, so go to the real start.
+ (goto-char start)
+ (goto-char potential-start)))
+ (goto-char potential-start)))))
+
+(provide 'erts-mode)
+
+;;; erts-mode.el ends here
diff --git a/lisp/progmodes/etags.el b/lisp/progmodes/etags.el
index 3826c1888d8..e1b1e67dbcf 100644
--- a/lisp/progmodes/etags.el
+++ b/lisp/progmodes/etags.el
@@ -145,7 +145,9 @@ Otherwise, `find-tag-default' is used."
:type '(choice (const nil) function))
(define-obsolete-variable-alias 'find-tag-marker-ring-length
- 'xref-marker-ring-length "25.1")
+ 'tags-location-ring-length "25.1")
+
+(defvar tags-location-ring-length 16)
(defcustom tags-tag-face 'default
"Face for tags in the output of `tags-apropos'."
@@ -180,10 +182,11 @@ Example value:
(sexp :tag "Tags to search")))
:version "21.1")
-(defvaralias 'find-tag-marker-ring 'xref--marker-ring)
+;; Obsolete variable kept for compatibility. We don't use it in any way.
+(defvar find-tag-marker-ring (make-ring 16))
(make-obsolete-variable
'find-tag-marker-ring
- "use `xref-push-marker-stack' or `xref-pop-marker-stack' instead."
+ "use `xref-push-marker-stack' or `xref-go-back' instead."
"25.1")
(defvar default-tags-table-function nil
@@ -191,7 +194,7 @@ Example value:
This function receives no arguments and should return the default
tags table file to use for the current buffer.")
-(defvar tags-location-ring (make-ring xref-marker-ring-length)
+(defvar tags-location-ring (make-ring tags-location-ring-length)
"Ring of markers which are locations visited by \\[find-tag].
Pop back to the last location with \\[negative-argument] \\[find-tag].")
@@ -292,7 +295,7 @@ file the tag was in."
(or (locate-dominating-file default-directory "TAGS")
default-directory)))
(list (read-file-name
- "Visit tags table (default TAGS): "
+ (format-prompt "Visit tags table" "TAGS")
;; default to TAGS from default-directory up to root.
default-tag-dir
(expand-file-name "TAGS" default-tag-dir)
@@ -625,7 +628,7 @@ Returns t if it visits a tags table, or nil if there are no more in the list."
(car list))
;; Finally, prompt the user for a file name.
(expand-file-name
- (read-file-name "Visit tags table (default TAGS): "
+ (read-file-name (format-prompt "Visit tags table" "TAGS")
default-directory
"TAGS"
t))))))
@@ -731,13 +734,13 @@ Returns t if it visits a tags table, or nil if there are no more in the list."
(interactive)
;; Clear out the markers we are throwing away.
(let ((i 0))
- (while (< i xref-marker-ring-length)
+ (while (< i tags-location-ring-length)
(if (aref (cddr tags-location-ring) i)
(set-marker (aref (cddr tags-location-ring) i) nil))
(setq i (1+ i))))
(xref-clear-marker-stack)
(setq tags-file-name nil
- tags-location-ring (make-ring xref-marker-ring-length)
+ tags-location-ring (make-ring tags-location-ring-length)
tags-table-list nil
tags-table-computed-list nil
tags-table-computed-list-for nil
@@ -1068,7 +1071,7 @@ See documentation of variable `tags-file-name'."
regexp next-p t))
;;;###autoload
-(defalias 'pop-tag-mark 'xref-pop-marker-stack)
+(defalias 'pop-tag-mark 'xref-go-back)
(defvar tag-lines-already-matched nil
@@ -1989,7 +1992,8 @@ see the doc of that variable if you want to add names to the list."
(setq set-list (delete (car set-list) set-list)))
(goto-char (point-min))
(insert-before-markers
- "Type `t' to select a tags table or set of tags tables:\n\n")
+ (substitute-command-keys
+ "Type \\`t' to select a tags table or set of tags tables:\n\n"))
(if desired-point
(goto-char desired-point))
(set-window-start (selected-window) 1 t))
diff --git a/lisp/progmodes/executable.el b/lisp/progmodes/executable.el
index d7c093444ed..670b6e7e898 100644
--- a/lisp/progmodes/executable.el
+++ b/lisp/progmodes/executable.el
@@ -240,12 +240,13 @@ executable."
(not (string= argument
(buffer-substring (point) (match-end 1))))
(if (or (not executable-query) no-query-flag
- (save-window-excursion
- ;; Make buffer visible before question.
- (switch-to-buffer (current-buffer))
- (y-or-n-p (format-message
- "Replace magic number by `#!%s'? "
- argument))))
+ (save-match-data
+ (save-window-excursion
+ ;; Make buffer visible before question.
+ (switch-to-buffer (current-buffer))
+ (y-or-n-p (format-message
+ "Replace magic number by `#!%s'? "
+ argument)))))
(progn
(replace-match argument t t nil 1)
(message "Magic number changed to `#!%s'" argument))))
diff --git a/lisp/progmodes/f90.el b/lisp/progmodes/f90.el
index 526865e6f61..263cd0ef296 100644
--- a/lisp/progmodes/f90.el
+++ b/lisp/progmodes/f90.el
@@ -345,6 +345,7 @@ The options are `downcase-word', `upcase-word', `capitalize-word' and nil."
;; there are spaces.
"contiguous" "submodule" "concurrent" "codimension"
"sync all" "sync memory" "critical" "image_index" "error stop"
+ "impure"
))
"\\_>")
"Regexp used by the function `f90-change-keywords'.")
@@ -646,7 +647,7 @@ do\\([ \t]*while\\)?\\|select[ \t]*\\(?:case\\|type\\)\\|where\\|\
forall\\|block\\|critical\\)\\)\\_>"
(2 font-lock-constant-face nil t) (3 font-lock-keyword-face))
;; Implicit declaration.
- '("\\_<\\(implicit\\)[ \t]*\\(real\\|integer\\|c\\(haracter\\|omplex\\)\
+ '("\\_<\\(implicit\\)[ \t]+\\(real\\|integer\\|c\\(haracter\\|omplex\\)\
\\|enumerator\\|procedure\\|\
logical\\|double[ \t]*precision\\|type[ \t]*(\\(?:\\sw\\|\\s_\\)+)\\|none\\)[ \t]*"
(1 font-lock-keyword-face) (2 font-lock-type-face))
@@ -656,8 +657,10 @@ logical\\|double[ \t]*precision\\|type[ \t]*(\\(?:\\sw\\|\\s_\\)+)\\|none\\)[ \t
'("\\(&\\)[ \t]*\\(!\\|$\\)" (1 font-lock-keyword-face))
"\\_<\\(then\\|continue\\|format\\|include\\|\\(?:error[ \t]+\\)?stop\\|\
return\\)\\_>"
- '("\\_<\\(exit\\|cycle\\)[ \t]*\\(\\(?:\\sw\\|\\s_\\)+\\)?\\_>"
+ '("\\_<\\(exit\\|cycle\\)[ \t]+\\(\\(?:\\sw\\|\\s_\\)+\\)?\\_>"
(1 font-lock-keyword-face) (2 font-lock-constant-face nil t))
+ '("\\_<\\(exit\\|cycle\\)\\_>"
+ (1 font-lock-keyword-face))
'("\\_<\\(case\\)[ \t]*\\(default\\|(\\)" . 1)
;; F2003 "class default".
'("\\_<\\(class\\)[ \t]*default" . 1)
diff --git a/lisp/progmodes/gdb-mi.el b/lisp/progmodes/gdb-mi.el
index 66fc4b1a4ce..a35a7deb4b1 100644
--- a/lisp/progmodes/gdb-mi.el
+++ b/lisp/progmodes/gdb-mi.el
@@ -90,6 +90,7 @@
(require 'gud)
(require 'cl-lib)
(require 'cl-seq)
+(require 'bindat)
(eval-when-compile (require 'pcase))
(declare-function speedbar-change-initial-expansion-list
@@ -1266,7 +1267,7 @@ Used by Speedbar."
:version "22.1")
(define-key gud-minor-mode-map "\C-c\C-w" 'gud-watch)
-(define-key global-map (vconcat gud-key-prefix "\C-w") 'gud-watch)
+(keymap-set gud-global-map "C-w" 'gud-watch)
(declare-function tooltip-identifier-from-point "tooltip" (point))
@@ -1612,6 +1613,7 @@ this trigger is subscribed to `gdb-buf-publisher' and called with
;; Used to display windows with thread-bound buffers
(defmacro def-gdb-preempt-display-buffer (name buffer &optional doc
split-horizontal)
+ (declare (indent defun))
`(defun ,name (&optional thread)
,(when doc doc)
(message "%s" thread)
@@ -3012,6 +3014,7 @@ calling `gdb-current-context-command').
Triggers defined by this command are meant to be used as a
trigger argument when describing buffer types with
`gdb-set-buffer-rules'."
+ (declare (indent defun))
`(defun ,trigger-name (&optional signal)
(when
(or (not ,signal-list)
@@ -3032,6 +3035,7 @@ Erase current buffer and evaluate CUSTOM-DEFUN.
Then call `gdb-update-buffer-name'.
If NOPRESERVE is non-nil, window point is not restored after CUSTOM-DEFUN."
+ (declare (indent defun))
`(defun ,handler-name ()
(let* ((inhibit-read-only t)
,@(unless nopreserve
@@ -3055,6 +3059,7 @@ See `def-gdb-auto-update-trigger'.
HANDLER-NAME handler uses customization of CUSTOM-DEFUN.
See `def-gdb-auto-update-handler'."
+ (declare (indent defun))
`(progn
(def-gdb-auto-update-trigger ,trigger-name
,gdb-command
@@ -3473,6 +3478,7 @@ corresponding to the mode line clicked."
CUSTOM-DEFUN may use locally bound `thread' variable, which will
be the value of `gdb-thread' property of the current line.
If `gdb-thread' is nil, error is signaled."
+ (declare (indent defun))
`(defun ,name (&optional event)
,(when doc doc)
(interactive (list last-input-event))
@@ -3488,6 +3494,7 @@ If `gdb-thread' is nil, error is signaled."
&optional doc)
"Define a NAME which will call BUFFER-COMMAND with id of thread
on the current line."
+ (declare (indent defun))
`(def-gdb-thread-buffer-command ,name
(,buffer-command (gdb-mi--field thread 'id))
,doc))
@@ -3543,6 +3550,7 @@ on the current line."
"Define a NAME which will execute GUD-COMMAND with
`gdb-thread-number' locally bound to id of thread on the current
line."
+ (declare (indent defun))
`(def-gdb-thread-buffer-command ,name
(if gdb-non-stop
(let ((gdb-thread-number (gdb-mi--field thread 'id))
@@ -3711,6 +3719,7 @@ in `gdb-memory-format'."
(defmacro def-gdb-set-positive-number (name variable echo-string &optional doc)
"Define a function NAME which reads new VAR value from minibuffer."
+ (declare (indent defun))
`(defun ,name (event)
,(when doc doc)
(interactive "e")
@@ -3739,6 +3748,7 @@ in `gdb-memory-format'."
"Define a function NAME to switch memory buffer to use FORMAT.
DOC is an optional documentation string."
+ (declare (indent defun))
`(defun ,name () ,(when doc doc)
(interactive)
(customize-set-variable 'gdb-memory-format ,format)
@@ -3808,6 +3818,7 @@ DOC is an optional documentation string."
"Define a function NAME to switch memory unit size to UNIT-SIZE.
DOC is an optional documentation string."
+ (declare (indent defun))
`(defun ,name () ,(when doc doc)
(interactive)
(customize-set-variable 'gdb-memory-unit ,unit-size)
@@ -3832,6 +3843,7 @@ The defined function switches Memory buffer to show address
stored in ADDRESS-VAR variable.
DOC is an optional documentation string."
+ (declare (indent defun))
`(defun ,name
,(when doc doc)
(interactive)
@@ -4277,7 +4289,7 @@ member."
;; uses "-stack-list-locals --simple-values". Needs GDB 6.1 onwards.
(def-gdb-trigger-and-handler
gdb-invalidate-locals
- (concat (gdb-current-context-command "-stack-list-locals")
+ (concat (gdb-current-context-command "-stack-list-variables")
" --simple-values")
gdb-locals-handler gdb-locals-handler-custom
'(start update))
@@ -4288,6 +4300,48 @@ member."
'gdb-locals-mode
'gdb-invalidate-locals)
+
+;; Retrieve the values of all variables before invalidating locals.
+(def-gdb-trigger-and-handler
+ gdb-locals-values
+ (concat (gdb-current-context-command "-stack-list-variables")
+ " --all-values")
+ gdb-locals-values-handler gdb-locals-values-handler-custom
+ '(start update))
+
+(gdb-set-buffer-rules
+ 'gdb-locals-values-buffer
+ 'gdb-locals-values-buffer-name
+ 'gdb-locals-mode
+ 'gdb-locals-values)
+
+(defun gdb-locals-values-buffer-name ()
+ (gdb-current-context-buffer-name
+ (concat "local values of " (gdb-get-target-string))))
+
+(defcustom gdb-locals-simple-values-only nil
+ "Only display simple values in the Locals buffer."
+ :type 'boolean
+ :group 'gud
+ :version "29.1")
+
+(defcustom gdb-locals-value-limit 100
+ "Maximum length the value of a local variable is allowed to be."
+ :type 'integer
+ :group 'gud
+ :version "29.1")
+
+(defvar gdb-locals-values-table (make-hash-table :test #'equal)
+ "Mapping of local variable names to a string with their value.")
+
+(defun gdb-locals-values-handler-custom ()
+ "Store the values of local variables in `gdb-locals-value-map'."
+ (let ((locals-list (bindat-get-field (gdb-mi--partial-output) 'variables)))
+ (dolist (local locals-list)
+ (let ((name (bindat-get-field local 'name))
+ (value (bindat-get-field local 'value)))
+ (puthash name value gdb-locals-values-table)))))
+
(defvar gdb-locals-watch-map
(let ((map (make-sparse-keymap)))
(suppress-keymap map)
@@ -4304,6 +4358,15 @@ member."
map)
"Keymap to edit value of a simple data type local variable.")
+(defun gdb-locals-value-filter (value)
+ "Filter function for the local variable VALUE."
+ (let* ((no-nl (replace-regexp-in-string "\n" " " value))
+ (str (replace-regexp-in-string "[[:space:]]+" " " no-nl))
+ (limit gdb-locals-value-limit))
+ (if (>= (length str) limit)
+ (concat (substring str 0 limit) "...")
+ str)))
+
(defun gdb-edit-locals-value (&optional event)
"Assign a value to a variable displayed in the locals buffer."
(interactive (list last-input-event))
@@ -4316,17 +4379,22 @@ member."
(gud-basic-call
(concat "-gdb-set variable " var " = " value)))))
-;; Don't display values of arrays or structures.
-;; These can be expanded using gud-watch.
+;; Complex data types are looked up in `gdb-locals-values-table'.
(defun gdb-locals-handler-custom ()
- (let ((locals-list (gdb-mi--field (gdb-mi--partial-output) 'locals))
+ "Handler to rebuild the local variables table buffer."
+ (let ((locals-list (bindat-get-field (gdb-mi--partial-output) 'variables))
(table (make-gdb-table)))
(dolist (local locals-list)
(let ((name (gdb-mi--field local 'name))
(value (gdb-mi--field local 'value))
(type (gdb-mi--field local 'type)))
(when (not value)
- (setq value "<complex data type>"))
+ (setq value
+ (if gdb-locals-simple-values-only
+ "<complex data type>"
+ (gethash name gdb-locals-values-table "<unavailable>"))))
+ (setq value (gdb-locals-value-filter value))
+
(if (or (not value)
(string-match "0x" value))
(add-text-properties 0 (length name)
@@ -4849,6 +4917,8 @@ file\" where the GDB session starts (see `gdb-main-file')."
(expand-file-name gdb-default-window-configuration-file
gdb-window-configuration-directory)))
;; Create default layout as before.
+ ;; Make sure that local values are updated before locals.
+ (gdb-get-buffer-create 'gdb-locals-values-buffer)
(gdb-get-buffer-create 'gdb-locals-buffer)
(gdb-get-buffer-create 'gdb-stack-buffer)
(gdb-get-buffer-create 'gdb-breakpoints-buffer)
diff --git a/lisp/progmodes/grep.el b/lisp/progmodes/grep.el
index bbcb644b73f..ccc58e6773c 100644
--- a/lisp/progmodes/grep.el
+++ b/lisp/progmodes/grep.el
@@ -1057,11 +1057,9 @@ REGEXP is used as a string in the prompt."
default-extension
(car grep-files-history)
(car (car grep-files-aliases))))
- (files (completing-read
- (concat "Search for \"" regexp
- "\" in files matching wildcard"
- (if default (concat " (default " default ")"))
- ": ")
+ (files (completing-read
+ (format-prompt "Search for \"%s\" in files matching wildcard"
+ default regexp)
#'read-file-name-internal
nil nil nil 'grep-files-history
(delete-dups
diff --git a/lisp/progmodes/gud.el b/lisp/progmodes/gud.el
index 085cd9b7e66..7092ca2041f 100644
--- a/lisp/progmodes/gud.el
+++ b/lisp/progmodes/gud.el
@@ -90,8 +90,10 @@ pdb (Python), and jdb."
"Prefix of all GUD commands valid in C buffers."
:type 'key-sequence)
-(global-set-key (vconcat gud-key-prefix "\C-l") #'gud-refresh)
-;; (define-key ctl-x-map " " 'gud-break); backward compatibility hack
+(defvar-keymap gud-global-map
+ "C-l" #'gud-refresh)
+
+(global-set-key gud-key-prefix gud-global-map)
(defvar gud-marker-filter nil)
(put 'gud-marker-filter 'permanent-local t)
@@ -433,7 +435,7 @@ we're in the GUD buffer)."
;; Unused lexical warning if cmd does not use "arg".
cmd))))
,(if key `(local-set-key ,(concat "\C-c" key) #',func))
- ,(if key `(global-set-key (vconcat gud-key-prefix ,key) #',func))))
+ ,(if key `(define-key gud-global-map ,key #',func))))
;; Where gud-display-frame should put the debugging arrow; a cons of
;; (filename . line-number). This is set by the marker-filter, which scans
@@ -742,10 +744,10 @@ The option \"--fullname\" must be included in this value."
output))
-(easy-mmode-defmap gud-minibuffer-local-map
- '(("\C-i" . comint-dynamic-complete-filename))
- "Keymap for minibuffer prompting of gud startup command."
- :inherit minibuffer-local-map)
+(defvar-keymap gud-minibuffer-local-map
+ :doc "Keymap for minibuffer prompting of gud startup command."
+ :parent minibuffer-local-map
+ "C-i" #'comint-dynamic-complete-filename)
(defun gud-query-cmdline (minor-mode &optional init)
(let* ((hist-sym (gud-symbol 'history nil minor-mode))
@@ -757,13 +759,18 @@ The option \"--fullname\" must be included in this value."
(concat (or cmd-name (symbol-name minor-mode))
" "
(or init
- (let ((file nil))
- (dolist (f (directory-files default-directory) file)
- (if (and (file-executable-p f)
- (not (file-directory-p f))
- (or (not file)
- (file-newer-than-file-p f file)))
- (setq file f)))))))
+ (let ((file nil)
+ (files (directory-files default-directory)))
+ ;; On remote systems, this may be slow, so avoid it.
+ (when (or (not (file-remote-p default-directory))
+ (length< files 50))
+ (dolist (f files)
+ (if (and (file-executable-p f)
+ (not (file-directory-p f))
+ (or (not file)
+ (file-newer-than-file-p f file)))
+ (setq file f)))
+ file)))))
gud-minibuffer-local-map nil
hist-sym)))
@@ -867,7 +874,8 @@ the buffer in which this command was invoked."
COMMAND is the prefix for which we seek completion.
CONTEXT is the text before COMMAND on the line."
(let* ((complete-list
- (gud-gdb-run-command-fetch-lines (concat "complete " context command)
+ (gud-gdb-run-command-fetch-lines (concat "server complete "
+ context command)
(current-buffer)
;; From string-match above.
(length context))))
@@ -3539,8 +3547,8 @@ Treats actions as defuns."
#'gdb-script-end-of-defun)
(setq-local font-lock-defaults
'(gdb-script-font-lock-keywords nil nil ((?_ . "w")) nil
- (font-lock-syntactic-face-function
- . gdb-script-font-lock-syntactic-face)))
+ (font-lock-syntactic-face-function
+ . gdb-script-font-lock-syntactic-face)))
;; Recognize docstrings.
(setq-local syntax-propertize-function
gdb-script-syntax-propertize-function)
diff --git a/lisp/progmodes/hideif.el b/lisp/progmodes/hideif.el
index 68b085d42f4..ba2c5737480 100644
--- a/lisp/progmodes/hideif.el
+++ b/lisp/progmodes/hideif.el
@@ -181,30 +181,24 @@ Effective only if `hide-ifdef-expand-reinclusion-guard' is t."
:type 'regexp
:version "25.1")
-(defvar hide-ifdef-mode-submap
+(defvar-keymap hide-ifdef-mode-submap
+ :doc "Keymap used by `hide-ifdef-mode' under `hide-ifdef-mode-prefix-key'."
;; Set up the submap that goes after the prefix key.
- (let ((map (make-sparse-keymap)))
- (define-key map "d" 'hide-ifdef-define)
- (define-key map "u" 'hide-ifdef-undef)
- (define-key map "D" 'hide-ifdef-set-define-alist)
- (define-key map "U" 'hide-ifdef-use-define-alist)
-
- (define-key map "h" 'hide-ifdefs)
- (define-key map "s" 'show-ifdefs)
- (define-key map "\C-d" 'hide-ifdef-block)
- (define-key map "\C-s" 'show-ifdef-block)
- (define-key map "e" 'hif-evaluate-macro)
- (define-key map "C" 'hif-clear-all-ifdef-defined)
-
- (define-key map "\C-q" 'hide-ifdef-toggle-read-only)
- (define-key map "\C-w" 'hide-ifdef-toggle-shadowing)
- (substitute-key-definition
- 'read-only-mode 'hide-ifdef-toggle-outside-read-only map)
- ;; `toggle-read-only' is obsoleted by `read-only-mode'.
- (substitute-key-definition
- 'toggle-read-only 'hide-ifdef-toggle-outside-read-only map)
- map)
- "Keymap used by `hide-ifdef-mode' under `hide-ifdef-mode-prefix-key'.")
+ "d" #'hide-ifdef-define
+ "u" #'hide-ifdef-undef
+ "D" #'hide-ifdef-set-define-alist
+ "U" #'hide-ifdef-use-define-alist
+ "h" #'hide-ifdefs
+ "s" #'show-ifdefs
+ "C-d" #'hide-ifdef-block
+ "C-s" #'show-ifdef-block
+ "e" #'hif-evaluate-macro
+ "C" #'hif-clear-all-ifdef-defined
+ "C-q" #'hide-ifdef-toggle-read-only
+ "C-w" #'hide-ifdef-toggle-shadowing
+ "<remap> <read-only-mode>" #'hide-ifdef-toggle-outside-read-only
+ ;; `toggle-read-only' is obsoleted by `read-only-mode'.
+ "<remap> <toggle-read-only>" #'hide-ifdef-toggle-outside-read-only)
(defcustom hide-ifdef-mode-prefix-key "\C-c@"
"Prefix key for all Hide-Ifdef mode commands."
@@ -2456,7 +2450,7 @@ This allows #ifdef VAR to be hidden."
(t
nil))))
(var (read-minibuffer "Define what? " default))
- (val (read-from-minibuffer (format "Set %s to? (default 1): " var)
+ (val (read-from-minibuffer (format-prompt "Set %s to?" "1" var)
nil nil t nil "1")))
(list var val)))
(hif-set-var var (or val 1))
diff --git a/lisp/progmodes/idlw-shell.el b/lisp/progmodes/idlw-shell.el
index af09cab1258..b6063521365 100644
--- a/lisp/progmodes/idlw-shell.el
+++ b/lisp/progmodes/idlw-shell.el
@@ -817,7 +817,7 @@ IDL has currently stepped.")
Command history, searching of previous commands, command line
editing are available via the comint-mode key bindings, by default
- mostly on the key `C-c'. Command history is also available with
+ mostly on the key \\`C-c'. Command history is also available with
the arrow keys UP and DOWN.
2. Completion
@@ -1327,7 +1327,7 @@ See also the variable `idlwave-shell-input-mode-spells'."
Characters are sent one by one, without newlines. The loop is blocking
and intercepts all input events to Emacs. You can use this command
to interact with the IDL command GET_KBRD.
-The loop can be aborted by typing `C-g'. The loop also exits automatically
+The loop can be aborted by typing \\[keyboard-quit]. The loop also exits automatically
when the IDL prompt gets displayed again after the current IDL command."
(interactive)
@@ -1342,7 +1342,8 @@ when the IDL prompt gets displayed again after the current IDL command."
(funcall errf "No IDL program seems to be waiting for input"))
;; OK, start the loop
- (message "Character mode on: Sending single chars (`C-g' to exit)")
+ (message (substitute-command-keys
+ "Character mode on: Sending single chars (\\[keyboard-quit] to exit)"))
(message
(catch 'exit
(while t
diff --git a/lisp/progmodes/inf-lisp.el b/lisp/progmodes/inf-lisp.el
index c952e449810..b9042e66c6b 100644
--- a/lisp/progmodes/inf-lisp.el
+++ b/lisp/progmodes/inf-lisp.el
@@ -308,7 +308,7 @@ quoted using shell quote syntax.
"inferior-lisp" (car cmdlist) nil (cdr cmdlist)))
(inferior-lisp-mode)))
(setq inferior-lisp-buffer "*inferior-lisp*")
- (pop-to-buffer-same-window "*inferior-lisp*"))
+ (pop-to-buffer "*inferior-lisp*" display-comint-buffer-action))
;;;###autoload
(defalias 'run-lisp 'inferior-lisp)
diff --git a/lisp/progmodes/js.el b/lisp/progmodes/js.el
index 812b3b98e3c..9c1358e466d 100644
--- a/lisp/progmodes/js.el
+++ b/lisp/progmodes/js.el
@@ -33,7 +33,7 @@
;; The main features of this JavaScript mode are syntactic
;; highlighting (enabled with `font-lock-mode' or
;; `global-font-lock-mode'), automatic indentation and filling of
-;; comments, C preprocessor fontification, and MozRepl integration.
+;; comments, and C preprocessor fontification.
;;
;; General Remarks:
;;
@@ -51,7 +51,6 @@
(require 'cc-fonts))
(require 'newcomment)
(require 'imenu)
-(require 'moz nil t)
(require 'json)
(require 'prog-mode)
@@ -59,12 +58,9 @@
(require 'cl-lib)
(require 'ido))
-(defvar inferior-moz-buffer)
-(defvar moz-repl-name)
(defvar ido-cur-list)
(defvar electric-layout-rules)
(declare-function ido-mode "ido" (&optional arg))
-(declare-function inferior-moz-process "ext:mozrepl" ())
;;; Constants
@@ -95,7 +91,7 @@ name.")
(defconst js--plain-method-re
(concat "^\\s-*?\\(" js--dotted-name-re "\\)\\.prototype"
- "\\.\\(" js--name-re "\\)\\s-*?=\\s-*?\\(function\\)\\_>")
+ "\\.\\(" js--name-re "\\)\\s-*?=\\s-*?\\(\\(:?async[ \t\n]+\\)function\\)\\_>")
"Regexp matching an explicit JavaScript prototype \"method\" declaration.
Group 1 is a (possibly-dotted) class name, group 2 is a method name,
and group 3 is the `function' keyword.")
@@ -485,25 +481,22 @@ seldom use, either globally or on a per-buffer basis."
(list 'const x))
js--available-frameworks)))
-(defcustom js-js-switch-tabs
- (and (memq system-type '(darwin)) t)
+(defvar js-js-switch-tabs (and (memq system-type '(darwin)) t)
"Whether `js-mode' should display tabs while selecting them.
This is useful only if the windowing system has a good mechanism
-for preventing Firefox from stealing the keyboard focus."
- :type 'boolean)
+for preventing Firefox from stealing the keyboard focus.")
+(make-obsolete-variable 'js-js-switch-tabs "MozRepl no longer exists" "28.1")
-(defcustom js-js-tmpdir
- (locate-user-emacs-file "js/js")
+(defvar js-js-tmpdir (locate-user-emacs-file "js/js")
"Temporary directory used by `js-mode' to communicate with Mozilla.
-This directory must be readable and writable by both Mozilla and Emacs."
- :type 'directory
- :version "28.1")
+This directory must be readable and writable by both Mozilla and Emacs.")
+(make-obsolete-variable 'js-js-tmpdir "MozRepl no longer exists" "28.1")
-(defcustom js-js-timeout 5
+(defvar js-js-timeout 5
"Reply timeout for executing commands in Mozilla via `js-mode'.
The value is given in seconds. Increase this value if you are
-getting timeout messages."
- :type 'integer)
+getting timeout messages.")
+(make-obsolete-variable 'js-js-timeout "MozRepl no longer exists" "28.1")
(defcustom js-indent-first-init nil
"Non-nil means specially indent the first variable declaration's initializer.
@@ -671,18 +664,7 @@ This variable is like `sgml-attribute-offset'."
(defvar js-mode-map
(let ((keymap (make-sparse-keymap)))
- (define-key keymap [(control ?c) (meta ?:)] #'js-eval)
- (define-key keymap [(control ?c) (control ?j)] #'js-set-js-context)
- (define-key keymap [(control meta ?x)] #'js-eval-defun)
(define-key keymap [(meta ?.)] #'js-find-symbol)
- (easy-menu-define nil keymap "JavaScript Menu"
- '("JavaScript"
- ["Select New Mozilla Context..." js-set-js-context
- (fboundp #'inferior-moz-process)]
- ["Evaluate Expression in Mozilla Context..." js-eval
- (fboundp #'inferior-moz-process)]
- ["Send Current Function to Mozilla..." js-eval-defun
- (fboundp #'inferior-moz-process)]))
keymap)
"Keymap for `js-mode'.")
@@ -932,9 +914,10 @@ This puts point at the `function' keyword.
If this is a syntactically-correct non-expression function,
return the name of the function, or t if the name could not be
determined. Otherwise, return nil."
- (cl-assert (looking-at "\\_<function\\_>"))
+ (unless (looking-at "\\(\\_<async\\_>[ \t\n]+\\)?\\_<function\\_>")
+ (error "Invalid position"))
(let ((name t))
- (forward-word-strictly)
+ (goto-char (match-end 0))
(forward-comment most-positive-fixnum)
(when (eq (char-after) ?*)
(forward-char)
@@ -970,14 +953,17 @@ If POS is not in a function prologue, return nil."
(goto-char (match-end 0))))
(skip-syntax-backward "w_")
- (and (or (looking-at "\\_<function\\_>")
- (js--re-search-backward "\\_<function\\_>" nil t))
-
- (save-match-data (goto-char (match-beginning 0))
- (js--forward-function-decl))
-
- (<= pos (point))
- (or prologue-begin (match-beginning 0))))))
+ (let ((start nil))
+ (and (or (looking-at "\\_<function\\_>")
+ (js--re-search-backward "\\_<function\\_>" nil t))
+ (progn
+ (setq start (match-beginning 0))
+ (goto-char start)
+ (when (looking-back "\\_<async\\_>[ \t\n]+" (- (point) 30))
+ (setq start (match-beginning 0)))
+ (js--forward-function-decl))
+ (<= pos (point))
+ (or prologue-begin start))))))
(defun js--beginning-of-defun-raw ()
"Helper function for `js-beginning-of-defun'.
@@ -1247,7 +1233,6 @@ LIMIT defaults to point."
;; Regular function declaration
((and (looking-at "\\_<function\\_>")
(setq name (js--forward-function-decl)))
-
(when (eq name t)
(setq name (js--guess-function-name orig-match-end))
(if name
@@ -1259,6 +1244,11 @@ LIMIT defaults to point."
(cl-assert (eq (char-after) ?{))
(forward-char)
+ (save-excursion
+ (goto-char orig-match-start)
+ (when (looking-back "\\_<async\\_>[ \t\n]+"
+ (- (point) 30))
+ (setq orig-match-start (match-beginning 0))))
(make-js--pitem
:paren-depth orig-depth
:h-begin orig-match-start
@@ -3308,10 +3298,7 @@ marker."
(setf (car bounds) (point))))
(buffer-substring (car bounds) (cdr bounds)))))
-(defvar find-tag-marker-ring) ; etags
-
-;; etags loads ring.
-(declare-function ring-insert "ring" (ring item))
+(declare-function xref-push-marker-stack "xref" (&optional m))
(defun js-find-symbol (&optional arg)
"Read a JavaScript symbol and jump to it.
@@ -3319,7 +3306,7 @@ With a prefix argument, restrict symbols to those from the
current buffer. Pushes a mark onto the tag ring just like
`find-tag'."
(interactive "P")
- (require 'etags)
+ (require 'xref)
(let (symbols marker)
(if (not arg)
(setq symbols (js--get-all-known-symbols))
@@ -3331,1111 +3318,11 @@ current buffer. Pushes a mark onto the tag ring just like
symbols "Jump to: "
(js--guess-symbol-at-point))))
- (ring-insert find-tag-marker-ring (point-marker))
+ (xref-push-marker-stack)
(switch-to-buffer (marker-buffer marker))
(push-mark)
(goto-char marker)))
-;;; MozRepl integration
-
-(define-error 'js-moz-bad-rpc "Mozilla RPC Error") ;; '(timeout error))
-(define-error 'js-js-error "JavaScript Error") ;; '(js-error error))
-
-(defun js--wait-for-matching-output
- (process regexp timeout &optional start)
- "Wait TIMEOUT seconds for PROCESS to output a match for REGEXP.
-On timeout, return nil. On success, return t with match data
-set. If START is non-nil, look for output starting from START.
-Otherwise, use the current value of `process-mark'."
- (with-current-buffer (process-buffer process)
- (cl-loop with start-pos = (or start
- (marker-position (process-mark process)))
- with end-time = (time-add nil timeout)
- for time-left = (float-time (time-subtract end-time nil))
- do (goto-char (point-max))
- if (looking-back regexp start-pos) return t
- while (> time-left 0)
- do (accept-process-output process time-left nil t)
- do (goto-char (process-mark process))
- finally do (signal
- 'js-moz-bad-rpc
- (list (format "Timed out waiting for output matching %S" regexp))))))
-
-(cl-defstruct js--js-handle
- ;; Integer, mirrors the value we see in JS
- (id nil :read-only t)
-
- ;; Process to which this thing belongs
- (process nil :read-only t))
-
-(defun js--js-handle-expired-p (x)
- (not (eq (js--js-handle-process x)
- (inferior-moz-process))))
-
-(defvar js--js-references nil
- "Maps Elisp JavaScript proxy objects to their JavaScript IDs.")
-
-(defvar js--js-process nil
- "The most recent MozRepl process object.")
-
-(defvar js--js-gc-idle-timer nil
- "Idle timer for cleaning up JS object references.")
-
-(defvar js--js-last-gcs-done nil)
-
-(defconst js--moz-interactor
- (replace-regexp-in-string
- "[ \n]+" " "
- ; */" Make Emacs happy
-"(function(repl) {
- repl.defineInteractor('js', {
- onStart: function onStart(repl) {
- if(!repl._jsObjects) {
- repl._jsObjects = {};
- repl._jsLastID = 0;
- repl._jsGC = this._jsGC;
- }
- this._input = '';
- },
-
- _jsGC: function _jsGC(ids_in_use) {
- var objects = this._jsObjects;
- var keys = [];
- var num_freed = 0;
-
- for(var pn in objects) {
- keys.push(Number(pn));
- }
-
- keys.sort(function(x, y) x - y);
- ids_in_use.sort(function(x, y) x - y);
- var i = 0;
- var j = 0;
-
- while(i < ids_in_use.length && j < keys.length) {
- var id = ids_in_use[i++];
- while(j < keys.length && keys[j] !== id) {
- var k_id = keys[j++];
- delete objects[k_id];
- ++num_freed;
- }
- ++j;
- }
-
- while(j < keys.length) {
- var k_id = keys[j++];
- delete objects[k_id];
- ++num_freed;
- }
-
- return num_freed;
- },
-
- _mkArray: function _mkArray() {
- var result = [];
- for(var i = 0; i < arguments.length; ++i) {
- result.push(arguments[i]);
- }
- return result;
- },
-
- _parsePropDescriptor: function _parsePropDescriptor(parts) {
- if(typeof parts === 'string') {
- parts = [ parts ];
- }
-
- var obj = parts[0];
- var start = 1;
-
- if(typeof obj === 'string') {
- obj = window;
- start = 0;
- } else if(parts.length < 2) {
- throw new Error('expected at least 2 arguments');
- }
-
- for(var i = start; i < parts.length - 1; ++i) {
- obj = obj[parts[i]];
- }
-
- return [obj, parts[parts.length - 1]];
- },
-
- _getProp: function _getProp(/*...*/) {
- if(arguments.length === 0) {
- throw new Error('no arguments supplied to getprop');
- }
-
- if(arguments.length === 1 &&
- (typeof arguments[0]) !== 'string')
- {
- return arguments[0];
- }
-
- var [obj, propname] = this._parsePropDescriptor(arguments);
- return obj[propname];
- },
-
- _putProp: function _putProp(properties, value) {
- var [obj, propname] = this._parsePropDescriptor(properties);
- obj[propname] = value;
- },
-
- _delProp: function _delProp(propname) {
- var [obj, propname] = this._parsePropDescriptor(arguments);
- delete obj[propname];
- },
-
- _typeOf: function _typeOf(thing) {
- return typeof thing;
- },
-
- _callNew: function(constructor) {
- if(typeof constructor === 'string')
- {
- constructor = window[constructor];
- } else if(constructor.length === 1 &&
- typeof constructor[0] !== 'string')
- {
- constructor = constructor[0];
- } else {
- var [obj,propname] = this._parsePropDescriptor(constructor);
- constructor = obj[propname];
- }
-
- /* Hacky, but should be robust */
- var s = 'new constructor(';
- for(var i = 1; i < arguments.length; ++i) {
- if(i != 1) {
- s += ',';
- }
-
- s += 'arguments[' + i + ']';
- }
-
- s += ')';
- return eval(s);
- },
-
- _callEval: function(thisobj, js) {
- return eval.call(thisobj, js);
- },
-
- getPrompt: function getPrompt(repl) {
- return 'EVAL>'
- },
-
- _lookupObject: function _lookupObject(repl, id) {
- if(typeof id === 'string') {
- switch(id) {
- case 'global':
- return window;
- case 'nil':
- return null;
- case 't':
- return true;
- case 'false':
- return false;
- case 'undefined':
- return undefined;
- case 'repl':
- return repl;
- case 'interactor':
- return this;
- case 'NaN':
- return NaN;
- case 'Infinity':
- return Infinity;
- case '-Infinity':
- return -Infinity;
- default:
- throw new Error('No object with special id:' + id);
- }
- }
-
- var ret = repl._jsObjects[id];
- if(ret === undefined) {
- throw new Error('No object with id:' + id + '(' + typeof id + ')');
- }
- return ret;
- },
-
- _findOrAllocateObject: function _findOrAllocateObject(repl, value) {
- if(typeof value !== 'object' && typeof value !== 'function') {
- throw new Error('_findOrAllocateObject called on non-object('
- + typeof(value) + '): '
- + value)
- }
-
- for(var id in repl._jsObjects) {
- id = Number(id);
- var obj = repl._jsObjects[id];
- if(obj === value) {
- return id;
- }
- }
-
- var id = ++repl._jsLastID;
- repl._jsObjects[id] = value;
- return id;
- },
-
- _fixupList: function _fixupList(repl, list) {
- for(var i = 0; i < list.length; ++i) {
- if(list[i] instanceof Array) {
- this._fixupList(repl, list[i]);
- } else if(typeof list[i] === 'object') {
- var obj = list[i];
- if(obj.funcall) {
- var parts = obj.funcall;
- this._fixupList(repl, parts);
- var [thisobj, func] = this._parseFunc(parts[0]);
- list[i] = func.apply(thisobj, parts.slice(1));
- } else if(obj.objid) {
- list[i] = this._lookupObject(repl, obj.objid);
- } else {
- throw new Error('Unknown object type: ' + obj.toSource());
- }
- }
- }
- },
-
- _parseFunc: function(func) {
- var thisobj = null;
-
- if(typeof func === 'string') {
- func = window[func];
- } else if(func instanceof Array) {
- if(func.length === 1 && typeof func[0] !== 'string') {
- func = func[0];
- } else {
- [thisobj, func] = this._parsePropDescriptor(func);
- func = thisobj[func];
- }
- }
-
- return [thisobj,func];
- },
-
- _encodeReturn: function(value, array_as_mv) {
- var ret;
-
- if(value === null) {
- ret = ['special', 'null'];
- } else if(value === true) {
- ret = ['special', 'true'];
- } else if(value === false) {
- ret = ['special', 'false'];
- } else if(value === undefined) {
- ret = ['special', 'undefined'];
- } else if(typeof value === 'number') {
- if(isNaN(value)) {
- ret = ['special', 'NaN'];
- } else if(value === Infinity) {
- ret = ['special', 'Infinity'];
- } else if(value === -Infinity) {
- ret = ['special', '-Infinity'];
- } else {
- ret = ['atom', value];
- }
- } else if(typeof value === 'string') {
- ret = ['atom', value];
- } else if(array_as_mv && value instanceof Array) {
- ret = ['array', value.map(this._encodeReturn, this)];
- } else {
- ret = ['objid', this._findOrAllocateObject(repl, value)];
- }
-
- return ret;
- },
-
- _handleInputLine: function _handleInputLine(repl, line) {
- var ret;
- var array_as_mv = false;
-
- try {
- if(line[0] === '*') {
- array_as_mv = true;
- line = line.substring(1);
- }
- var parts = eval(line);
- this._fixupList(repl, parts);
- var [thisobj, func] = this._parseFunc(parts[0]);
- ret = this._encodeReturn(
- func.apply(thisobj, parts.slice(1)),
- array_as_mv);
- } catch(x) {
- ret = ['error', x.toString() ];
- }
-
- var JSON = Components.classes['@mozilla.org/dom/json;1'].createInstance(Components.interfaces.nsIJSON);
- repl.print(JSON.encode(ret));
- repl._prompt();
- },
-
- handleInput: function handleInput(repl, chunk) {
- this._input += chunk;
- var match, line;
- while(match = this._input.match(/.*\\n/)) {
- line = match[0];
-
- if(line === 'EXIT\\n') {
- repl.popInteractor();
- repl._prompt();
- return;
- }
-
- this._input = this._input.substring(line.length);
- this._handleInputLine(repl, line);
- }
- }
- });
-})
-")
-
- "String to set MozRepl up into a simple-minded evaluation mode.")
-
-(defun js--js-encode-value (x)
- "Marshall the given value for JS.
-Strings and numbers are JSON-encoded. Lists (including nil) are
-made into JavaScript array literals and their contents encoded
-with `js--js-encode-value'."
- (cond ((or (stringp x) (numberp x)) (json-encode x))
- ((symbolp x) (format "{objid:%S}" (symbol-name x)))
- ((js--js-handle-p x)
-
- (when (js--js-handle-expired-p x)
- (error "Stale JS handle"))
-
- (format "{objid:%s}" (js--js-handle-id x)))
-
- ((sequencep x)
- (if (eq (car-safe x) 'js--funcall)
- (format "{funcall:[%s]}"
- (mapconcat #'js--js-encode-value (cdr x) ","))
- (concat
- "[" (mapconcat #'js--js-encode-value x ",") "]")))
- (t
- (error "Unrecognized item: %S" x))))
-
-(defconst js--js-prompt-regexp "\\(repl[0-9]*\\)> $")
-(defconst js--js-repl-prompt-regexp "^EVAL>$")
-(defvar js--js-repl-depth 0)
-
-(defun js--js-wait-for-eval-prompt ()
- (js--wait-for-matching-output
- (inferior-moz-process)
- js--js-repl-prompt-regexp js-js-timeout
-
- ;; start matching against the beginning of the line in
- ;; order to catch a prompt that's only partially arrived
- (save-excursion (forward-line 0) (point))))
-
-;; Presumably "inferior-moz-process" loads comint.
-(declare-function comint-send-string "comint" (process string))
-(declare-function comint-send-input "comint"
- (&optional no-newline artificial))
-
-(defun js--js-enter-repl ()
- (inferior-moz-process) ; called for side-effect
- (with-current-buffer inferior-moz-buffer
- (goto-char (point-max))
-
- ;; Do some initialization the first time we see a process
- (unless (eq (inferior-moz-process) js--js-process)
- (setq js--js-process (inferior-moz-process))
- (setq js--js-references (make-hash-table :test 'eq :weakness t))
- (setq js--js-repl-depth 0)
-
- ;; Send interactor definition
- (comint-send-string js--js-process js--moz-interactor)
- (comint-send-string js--js-process
- (concat "(" moz-repl-name ")\n"))
- (js--wait-for-matching-output
- (inferior-moz-process) js--js-prompt-regexp
- js-js-timeout))
-
- ;; Sanity check
- (when (looking-back js--js-prompt-regexp
- (save-excursion (forward-line 0) (point)))
- (setq js--js-repl-depth 0))
-
- (if (> js--js-repl-depth 0)
- ;; If js--js-repl-depth > 0, we *should* be seeing an
- ;; EVAL> prompt. If we don't, give Mozilla a chance to catch
- ;; up with us.
- (js--js-wait-for-eval-prompt)
-
- ;; Otherwise, tell Mozilla to enter the interactor mode
- (insert (match-string-no-properties 1)
- ".pushInteractor('js')")
- (comint-send-input nil t)
- (js--wait-for-matching-output
- (inferior-moz-process) js--js-repl-prompt-regexp
- js-js-timeout))
-
- (cl-incf js--js-repl-depth)))
-
-(defun js--js-leave-repl ()
- (cl-assert (> js--js-repl-depth 0))
- (when (= 0 (cl-decf js--js-repl-depth))
- (with-current-buffer inferior-moz-buffer
- (goto-char (point-max))
- (js--js-wait-for-eval-prompt)
- (insert "EXIT")
- (comint-send-input nil t)
- (js--wait-for-matching-output
- (inferior-moz-process) js--js-prompt-regexp
- js-js-timeout))))
-
-(defsubst js--js-not (value)
- (memq value '(nil null false undefined)))
-
-(defsubst js--js-true (value)
- (not (js--js-not value)))
-
-(eval-and-compile
- (defun js--optimize-arglist (arglist)
- "Convert immediate js< and js! references to deferred ones."
- (cl-loop for item in arglist
- if (eq (car-safe item) 'js<)
- collect (append (list 'list ''js--funcall
- '(list 'interactor "_getProp"))
- (js--optimize-arglist (cdr item)))
- else if (eq (car-safe item) 'js>)
- collect (append (list 'list ''js--funcall
- '(list 'interactor "_putProp"))
-
- (if (atom (cadr item))
- (list (cadr item))
- (list
- (append
- (list 'list ''js--funcall
- '(list 'interactor "_mkArray"))
- (js--optimize-arglist (cadr item)))))
- (js--optimize-arglist (cddr item)))
- else if (eq (car-safe item) 'js!)
- collect (pcase-let ((`(,_ ,function . ,body) item))
- (append (list 'list ''js--funcall
- (if (consp function)
- (cons 'list
- (js--optimize-arglist function))
- function))
- (js--optimize-arglist body)))
- else
- collect item)))
-
-(defmacro js--js-get-service (class-name interface-name)
- `(js! ("Components" "classes" ,class-name "getService")
- (js< "Components" "interfaces" ,interface-name)))
-
-(defmacro js--js-create-instance (class-name interface-name)
- `(js! ("Components" "classes" ,class-name "createInstance")
- (js< "Components" "interfaces" ,interface-name)))
-
-(defmacro js--js-qi (object interface-name)
- `(js! (,object "QueryInterface")
- (js< "Components" "interfaces" ,interface-name)))
-
-(defmacro with-js (&rest forms)
- "Run FORMS with the Mozilla repl set up for js commands.
-Inside the lexical scope of `with-js', `js?', `js!',
-`js-new', `js-eval', `js-list', `js<', `js>', `js-get-service',
-`js-create-instance', and `js-qi' are defined."
- (declare (indent 0) (debug t))
- `(progn
- (js--js-enter-repl)
- (unwind-protect
- (cl-macrolet ((js? (&rest body) `(js--js-true ,@body))
- (js! (function &rest body)
- `(js--js-funcall
- ,(if (consp function)
- (cons 'list
- (js--optimize-arglist function))
- function)
- ,@(js--optimize-arglist body)))
-
- (js-new (function &rest body)
- `(js--js-new
- ,(if (consp function)
- (cons 'list
- (js--optimize-arglist function))
- function)
- ,@body))
-
- (js-eval (thisobj js)
- `(js--js-eval
- ,@(js--optimize-arglist
- (list thisobj js))))
-
- (js-list (&rest args)
- `(js--js-list
- ,@(js--optimize-arglist args)))
-
- (js-get-service (&rest args)
- `(js--js-get-service
- ,@(js--optimize-arglist args)))
-
- (js-create-instance (&rest args)
- `(js--js-create-instance
- ,@(js--optimize-arglist args)))
-
- (js-qi (&rest args)
- `(js--js-qi
- ,@(js--optimize-arglist args)))
-
- (js< (&rest body) `(js--js-get
- ,@(js--optimize-arglist body)))
- (js> (props value)
- `(js--js-funcall
- '(interactor "_putProp")
- ,(if (consp props)
- (cons 'list
- (js--optimize-arglist props))
- props)
- ,@(js--optimize-arglist (list value))
- ))
- (js-handle? (arg) `(js--js-handle-p ,arg)))
- ,@forms)
- (js--js-leave-repl))))
-
-(defvar js--js-array-as-list nil
- "Whether to listify any Array returned by a Mozilla function.
-If nil, the whole Array is treated as a JS symbol.")
-
-(defun js--js-decode-retval (result)
- (pcase (intern (cl-first result))
- ('atom (cl-second result))
- ('special (intern (cl-second result)))
- ('array
- (mapcar #'js--js-decode-retval (cl-second result)))
- ('objid
- (or (gethash (cl-second result)
- js--js-references)
- (puthash (cl-second result)
- (make-js--js-handle
- :id (cl-second result)
- :process (inferior-moz-process))
- js--js-references)))
-
- ('error (signal 'js-js-error (list (cl-second result))))
- (x (error "Unmatched case in js--js-decode-retval: %S" x))))
-
-(defvar comint-last-input-end)
-
-(defun js--js-funcall (function &rest arguments)
- "Call the Mozilla function FUNCTION with arguments ARGUMENTS.
-If function is a string, look it up as a property on the global
-object and use the global object for `this'.
-If FUNCTION is a list with one element, use that element as the
-function with the global object for `this', except that if that
-single element is a string, look it up on the global object.
-If FUNCTION is a list with more than one argument, use the list
-up to the last value as a property descriptor and the last
-argument as a function."
-
- (with-js
- (let ((argstr (js--js-encode-value
- (cons function arguments))))
-
- (with-current-buffer inferior-moz-buffer
- ;; Actual funcall
- (when js--js-array-as-list
- (insert "*"))
- (insert argstr)
- (comint-send-input nil t)
- (js--wait-for-matching-output
- (inferior-moz-process) "EVAL>"
- js-js-timeout)
- (goto-char comint-last-input-end)
-
- ;; Read the result
- (let* ((json-array-type 'list)
- (result (prog1 (json-read)
- (goto-char (point-max)))))
- (js--js-decode-retval result))))))
-
-(defun js--js-new (constructor &rest arguments)
- "Call CONSTRUCTOR as a constructor, with arguments ARGUMENTS.
-CONSTRUCTOR is a JS handle, a string, or a list of these things."
- (apply #'js--js-funcall
- '(interactor "_callNew")
- constructor arguments))
-
-(defun js--js-eval (thisobj js)
- (js--js-funcall '(interactor "_callEval") thisobj js))
-
-(defun js--js-list (&rest arguments)
- "Return a Lisp array resulting from evaluating each of ARGUMENTS."
- (let ((js--js-array-as-list t))
- (apply #'js--js-funcall '(interactor "_mkArray")
- arguments)))
-
-(defun js--js-get (&rest props)
- (apply #'js--js-funcall '(interactor "_getProp") props))
-
-(defun js--js-put (props value)
- (js--js-funcall '(interactor "_putProp") props value))
-
-(defun js-gc (&optional force)
- "Tell the repl about any objects we don't reference anymore.
-With argument, run even if no intervening GC has happened."
- (interactive)
-
- (when force
- (setq js--js-last-gcs-done nil))
-
- (let ((this-gcs-done gcs-done) keys num)
- (when (and js--js-references
- (boundp 'inferior-moz-buffer)
- (buffer-live-p inferior-moz-buffer)
-
- ;; Don't bother running unless we've had an intervening
- ;; garbage collection; without a gc, nothing is deleted
- ;; from the weak hash table, so it's pointless telling
- ;; MozRepl about that references we still hold
- (not (eq js--js-last-gcs-done this-gcs-done))
-
- ;; Are we looking at a normal prompt? Make sure not to
- ;; interrupt the user if he's doing something
- (with-current-buffer inferior-moz-buffer
- (save-excursion
- (goto-char (point-max))
- (looking-back js--js-prompt-regexp
- (save-excursion (forward-line 0) (point))))))
-
- (setq keys (cl-loop for x being the hash-keys
- of js--js-references
- collect x))
- (setq num (js--js-funcall '(repl "_jsGC") (or keys [])))
-
- (setq js--js-last-gcs-done this-gcs-done)
- (when (called-interactively-p 'interactive)
- (message "Cleaned %s entries" num))
-
- num)))
-
-(run-with-idle-timer 30 t #'js-gc)
-
-(defun js-eval (js)
- "Evaluate the JavaScript in JS and return JSON-decoded result."
- (interactive "MJavaScript to evaluate: ")
- (with-js
- (let* ((content-window (js--js-content-window
- (js--get-js-context)))
- (result (js-eval content-window js)))
- (when (called-interactively-p 'interactive)
- (message "%s" (js! "String" result)))
- result)))
-
-(defun js--get-tabs ()
- "Enumerate all JavaScript contexts available.
-Each context is a list:
- (TITLE URL BROWSER TAB TABBROWSER) for content documents
- (TITLE URL WINDOW) for windows
-
-All tabs of a given window are grouped together. The most recent
-window is first. Within each window, the tabs are returned
-left-to-right."
- (with-js
- (let (windows)
-
- (cl-loop with window-mediator = (js! ("Components" "classes"
- "@mozilla.org/appshell/window-mediator;1"
- "getService")
- (js< "Components" "interfaces"
- "nsIWindowMediator"))
- with enumerator = (js! (window-mediator "getEnumerator") nil)
-
- while (js? (js! (enumerator "hasMoreElements")))
- for window = (js! (enumerator "getNext"))
- for window-info = (js-list window
- (js< window "document" "title")
- (js! (window "location" "toString"))
- (js< window "closed")
- (js< window "windowState"))
-
- unless (or (js? (cl-fourth window-info))
- (eq (cl-fifth window-info) 2))
- do (push window-info windows))
-
- (cl-loop for (window title location) in windows
- collect (list title location window)
-
- for gbrowser = (js< window "gBrowser")
- if (js-handle? gbrowser)
- nconc (cl-loop
- for x below (js< gbrowser "browsers" "length")
- collect (js-list (js< gbrowser
- "browsers"
- x
- "contentDocument"
- "title")
-
- (js! (gbrowser
- "browsers"
- x
- "contentWindow"
- "location"
- "toString"))
- (js< gbrowser
- "browsers"
- x)
-
- (js! (gbrowser
- "tabContainer"
- "childNodes"
- "item")
- x)
-
- gbrowser))))))
-
-(defvar js-read-tab-history nil)
-
-(declare-function ido-chop "ido" (items elem))
-
-(defun js--read-tab (prompt)
- "Read a Mozilla tab with prompt PROMPT.
-Return a cons of (TYPE . OBJECT). TYPE is either `window' or
-`tab', and OBJECT is a JavaScript handle to a ChromeWindow or a
-browser, respectively."
-
- ;; Prime IDO
- (unless ido-mode
- (ido-mode 1)
- (ido-mode -1))
-
- (with-js
- (let ((tabs (js--get-tabs)) selected-tab-cname
- selected-tab prev-hitab)
-
- ;; Disambiguate names
- (setq tabs
- (cl-loop with tab-names = (make-hash-table :test 'equal)
- for tab in tabs
- for cname = (format "%s (%s)"
- (cl-second tab) (cl-first tab))
- for num = (cl-incf (gethash cname tab-names -1))
- if (> num 0)
- do (setq cname (format "%s <%d>" cname num))
- collect (cons cname tab)))
-
- (cl-labels
- ((find-tab-by-cname
- (cname)
- (cl-loop for tab in tabs
- if (equal (car tab) cname)
- return (cdr tab)))
-
- (mogrify-highlighting
- (hitab unhitab)
-
- ;; Hack to reduce the number of
- ;; round-trips to mozilla
- (let (cmds)
- (cond
- ;; Highlighting tab
- ((cl-fourth hitab)
- (push '(js! ((cl-fourth hitab) "setAttribute")
- "style"
- "color: red; font-weight: bold")
- cmds)
-
- ;; Highlight window proper
- (push '(js! ((cl-third hitab)
- "setAttribute")
- "style"
- "border: 8px solid red")
- cmds)
-
- ;; Select tab, when appropriate
- (when js-js-switch-tabs
- (push
- '(js> ((cl-fifth hitab) "selectedTab") (cl-fourth hitab))
- cmds)))
-
- ;; Highlighting whole window
- ((cl-third hitab)
- (push '(js! ((cl-third hitab) "document"
- "documentElement" "setAttribute")
- "style"
- (concat "-moz-appearance: none;"
- "border: 8px solid red;"))
- cmds)))
-
- (cond
- ;; Unhighlighting tab
- ((cl-fourth unhitab)
- (push '(js! ((cl-fourth unhitab) "setAttribute") "style" "")
- cmds)
- (push '(js! ((cl-third unhitab) "setAttribute") "style" "")
- cmds))
-
- ;; Unhighlighting window
- ((cl-third unhitab)
- (push '(js! ((cl-third unhitab) "document"
- "documentElement" "setAttribute")
- "style" "")
- cmds)))
-
- (eval `(with-js
- (js-list ,@(nreverse cmds)))
- t)))
-
- (command-hook
- ()
- (let* ((tab (find-tab-by-cname (car ido-matches))))
- (mogrify-highlighting tab prev-hitab)
- (setq prev-hitab tab)))
-
- (setup-hook
- ()
- ;; Fiddle with the match list a bit: if our first match
- ;; is a tabbrowser window, rotate the match list until
- ;; the active tab comes up
- (let ((matched-tab (find-tab-by-cname (car ido-matches))))
- (when (and matched-tab
- (null (cl-fourth matched-tab))
- (equal "navigator:browser"
- (js! ((cl-third matched-tab)
- "document"
- "documentElement"
- "getAttribute")
- "windowtype")))
-
- (cl-loop with tab-to-match = (js< (cl-third matched-tab)
- "gBrowser"
- "selectedTab")
-
- for match in ido-matches
- for candidate-tab = (find-tab-by-cname match)
- if (eq (cl-fourth candidate-tab) tab-to-match)
- do (setq ido-cur-list
- (ido-chop ido-cur-list match))
- and return t)))
-
- (add-hook 'post-command-hook #'command-hook t t)))
-
-
- (unwind-protect
- ;; FIXME: Don't impose IDO on the user.
- (setq selected-tab-cname
- (let ((ido-minibuffer-setup-hook
- (cons #'setup-hook ido-minibuffer-setup-hook)))
- (ido-completing-read
- prompt
- (mapcar #'car tabs)
- nil t nil
- 'js-read-tab-history)))
-
- (when prev-hitab
- (mogrify-highlighting nil prev-hitab)
- (setq prev-hitab nil)))
-
- (add-to-history 'js-read-tab-history selected-tab-cname)
-
- (setq selected-tab (cl-loop for tab in tabs
- if (equal (car tab) selected-tab-cname)
- return (cdr tab)))
-
- (cons (if (cl-fourth selected-tab) 'browser 'window)
- (cl-third selected-tab))))))
-
-(defun js--guess-eval-defun-info (pstate)
- "Helper function for `js-eval-defun'.
-Return a list (NAME . CLASSPARTS), where CLASSPARTS is a list of
-strings making up the class name and NAME is the name of the
-function part."
- (cond ((and (= (length pstate) 3)
- (eq (js--pitem-type (cl-first pstate)) 'function)
- (= (length (js--pitem-name (cl-first pstate))) 1)
- (consp (js--pitem-type (cl-second pstate))))
-
- (append (js--pitem-name (cl-second pstate))
- (list (cl-first (js--pitem-name (cl-first pstate))))))
-
- ((and (= (length pstate) 2)
- (eq (js--pitem-type (cl-first pstate)) 'function))
-
- (append
- (butlast (js--pitem-name (cl-first pstate)))
- (list (car (last (js--pitem-name (cl-first pstate)))))))
-
- (t (error "Function not a toplevel defun or class member"))))
-
-(defvar js--js-context nil
- "The current JavaScript context.
-This is a cons like the one returned from `js--read-tab'.
-Change with `js-set-js-context'.")
-
-(defconst js--js-inserter
- "(function(func_info,func) {
- func_info.unshift('window');
- var obj = window;
- for(var i = 1; i < func_info.length - 1; ++i) {
- var next = obj[func_info[i]];
- if(typeof next !== 'object' && typeof next !== 'function') {
- next = obj.prototype && obj.prototype[func_info[i]];
- if(typeof next !== 'object' && typeof next !== 'function') {
- alert('Could not find ' + func_info.slice(0, i+1).join('.') +
- ' or ' + func_info.slice(0, i+1).join('.') + '.prototype');
- return;
- }
-
- func_info.splice(i+1, 0, 'prototype');
- ++i;
- }
- }
-
- obj[func_info[i]] = func;
- alert('Successfully updated '+func_info.join('.'));
- })")
-
-(defun js-set-js-context (context)
- "Set the JavaScript context to CONTEXT.
-When called interactively, prompt for CONTEXT."
- (interactive (list (js--read-tab "JavaScript Context: ")))
- (setq js--js-context context))
-
-(defun js--get-js-context ()
- "Return a valid JavaScript context.
-If one hasn't been set, or if it's stale, prompt for a new one."
- (with-js
- (when (or (null js--js-context)
- (js--js-handle-expired-p (cdr js--js-context))
- (pcase (car js--js-context)
- ('window (js? (js< (cdr js--js-context) "closed")))
- ('browser (not (js? (js< (cdr js--js-context)
- "contentDocument"))))
- (x (error "Unmatched case in js--get-js-context: %S" x))))
- (setq js--js-context (js--read-tab "JavaScript Context: ")))
- js--js-context))
-
-(defun js--js-content-window (context)
- (with-js
- (pcase (car context)
- ('window (cdr context))
- ('browser (js< (cdr context)
- "contentWindow" "wrappedJSObject"))
- (x (error "Unmatched case in js--js-content-window: %S" x)))))
-
-(defun js--make-nsilocalfile (path)
- (with-js
- (let ((file (js-create-instance "@mozilla.org/file/local;1"
- "nsILocalFile")))
- (js! (file "initWithPath") path)
- file)))
-
-(defun js--js-add-resource-alias (alias path)
- (with-js
- (let* ((io-service (js-get-service "@mozilla.org/network/io-service;1"
- "nsIIOService"))
- (res-prot (js! (io-service "getProtocolHandler") "resource"))
- (res-prot (js-qi res-prot "nsIResProtocolHandler"))
- (path-file (js--make-nsilocalfile path))
- (path-uri (js! (io-service "newFileURI") path-file)))
- (js! (res-prot "setSubstitution") alias path-uri))))
-
-(cl-defun js-eval-defun ()
- "Update a Mozilla tab using the JavaScript defun at point."
- (interactive)
-
- ;; This function works by generating a temporary file that contains
- ;; the function we'd like to insert. We then use the elisp-js bridge
- ;; to command mozilla to load this file by inserting a script tag
- ;; into the document we set. This way, debuggers and such will have
- ;; a way to find the source of the just-inserted function.
- ;;
- ;; We delete the temporary file if there's an error, but otherwise
- ;; we add an unload event listener on the Mozilla side to delete the
- ;; file.
-
- (save-excursion
- (let (begin end pstate defun-info temp-name defun-body)
- (js-end-of-defun)
- (setq end (point))
- (js--ensure-cache)
- (js-beginning-of-defun)
- (re-search-forward "\\_<function\\_>")
- (setq begin (match-beginning 0))
- (setq pstate (js--forward-pstate))
-
- (when (or (null pstate)
- (> (point) end))
- (error "Could not locate function definition"))
-
- (setq defun-info (js--guess-eval-defun-info pstate))
-
- (let ((overlay (make-overlay begin end)))
- (overlay-put overlay 'face 'highlight)
- (unwind-protect
- (unless (y-or-n-p (format "Send %s to Mozilla? "
- (mapconcat #'identity defun-info ".")))
- (message "") ; question message lingers until next command
- (cl-return-from js-eval-defun))
- (delete-overlay overlay)))
-
- (setq defun-body (buffer-substring-no-properties begin end))
-
- (make-directory js-js-tmpdir t)
-
- ;; (Re)register a Mozilla resource URL to point to the
- ;; temporary directory
- (js--js-add-resource-alias "js" js-js-tmpdir)
-
- (setq temp-name (make-temp-file (concat js-js-tmpdir
- "/js-")
- nil ".js"))
- (unwind-protect
- (with-js
- (with-temp-buffer
- (insert js--js-inserter)
- (insert "(")
- (let ((standard-output (current-buffer)))
- (json--print-list defun-info))
- (insert ",\n")
- (insert defun-body)
- (insert "\n)")
- (write-region (point-min) (point-max) temp-name
- nil 1))
-
- ;; Give Mozilla responsibility for deleting this file
- (let* ((content-window (js--js-content-window
- (js--get-js-context)))
- (content-document (js< content-window "document"))
- (head (if (js? (js< content-document "body"))
- ;; Regular content
- (js< (js! (content-document "getElementsByTagName")
- "head")
- 0)
- ;; Chrome
- (js< content-document "documentElement")))
- (elem (js! (content-document "createElementNS")
- "http://www.w3.org/1999/xhtml" "script")))
-
- (js! (elem "setAttribute") "type" "text/javascript")
- (js! (elem "setAttribute") "src"
- (format "resource://js/%s"
- (file-name-nondirectory temp-name)))
-
- (js! (head "appendChild") elem)
-
- (js! (content-window "addEventListener") "unload"
- (js! ((js-new
- "Function" "file"
- "return function() { file.remove(false) }"))
- (js--make-nsilocalfile temp-name))
- 'false)
- (setq temp-name nil)
-
-
-
- ))
-
- ;; temp-name is set to nil on success
- (when temp-name
- (delete-file temp-name))))))
-
;;; Syntax extensions
(defvar js-syntactic-mode-name t
diff --git a/lisp/progmodes/make-mode.el b/lisp/progmodes/make-mode.el
index 9f08f39e1c0..91307f6c09f 100644
--- a/lisp/progmodes/make-mode.el
+++ b/lisp/progmodes/make-mode.el
@@ -542,8 +542,8 @@ not be enclosed in { } or ( )."
This should identify a `make' command that can handle the `-q' option."
:type 'string)
-(defvaralias 'makefile-query-one-target-method
- 'makefile-query-one-target-method-function)
+(define-obsolete-variable-alias 'makefile-query-one-target-method
+ 'makefile-query-one-target-method-function "29.1")
(defcustom makefile-query-one-target-method-function
'makefile-query-by-make-minus-q
diff --git a/lisp/progmodes/octave.el b/lisp/progmodes/octave.el
index a45909537ad..7b7c675873b 100644
--- a/lisp/progmodes/octave.el
+++ b/lisp/progmodes/octave.el
@@ -879,7 +879,8 @@ startup file, `~/.emacs-octave'."
(set-process-filter proc 'comint-output-filter)
;; Just in case, to be sure a cd in the startup file won't have
;; detrimental effects.
- (with-demoted-errors (inferior-octave-resync-dirs))
+ (with-demoted-errors "Octave resync error: %S"
+ (inferior-octave-resync-dirs))
;; Generate a proper prompt, which is critical to
;; `comint-history-isearch-backward-regexp'. Bug#14433.
(comint-send-string proc "\n")))
@@ -1814,18 +1815,18 @@ If the environment variable OCTAVE_SRCDIR is set, it is searched first."
(user-error "Aborted")))
(_ name)))
-(defvar find-tag-marker-ring)
+(declare-function xref-push-marker-stack "xref" (&optional m))
(defun octave-find-definition (fn)
"Find the definition of FN.
Functions implemented in C++ can be found if
variable `octave-source-directories' is set correctly."
(interactive (list (octave-completing-read)))
- (require 'etags)
+ (require 'xref)
(let ((orig (point)))
(if (and (derived-mode-p 'octave-mode)
(octave-goto-function-definition fn))
- (ring-insert find-tag-marker-ring (copy-marker orig))
+ (xref-push-marker-stack (copy-marker orig))
(inferior-octave-send-list-and-digest
;; help NAME is more verbose
(list (format "\
@@ -1840,7 +1841,7 @@ if iskeyword('%s') disp('`%s'' is a keyword') else which('%s') endif\n"
(setq file (match-string 1 line))))
(if (not file)
(user-error "%s" (or line (format-message "`%s' not found" fn)))
- (ring-insert find-tag-marker-ring (point-marker))
+ (xref-push-marker-stack)
(setq file (funcall octave-find-definition-filename-function file))
(when file
(find-file file)
diff --git a/lisp/progmodes/pascal.el b/lisp/progmodes/pascal.el
index 422ee9bb6bd..8dc03b72b1e 100644
--- a/lisp/progmodes/pascal.el
+++ b/lisp/progmodes/pascal.el
@@ -1357,9 +1357,7 @@ The default is a name found in the buffer around point."
default ""))
(label
;; Do completion with default.
- (completing-read (if (not (string= default ""))
- (concat "Label (default " default "): ")
- "Label: ")
+ (completing-read (format-prompt "Label" default)
;; Complete with the defuns found in the
;; current-buffer.
(let ((buf (current-buffer)))
diff --git a/lisp/progmodes/perl-mode.el b/lisp/progmodes/perl-mode.el
index 6f468192a90..92b47ce88f6 100644
--- a/lisp/progmodes/perl-mode.el
+++ b/lisp/progmodes/perl-mode.el
@@ -191,7 +191,9 @@
,(concat "\\<"
(regexp-opt '("if" "until" "while" "elsif" "else" "unless"
"do" "dump" "for" "foreach" "exit" "die"
- "BEGIN" "END" "return" "exec" "eval") t)
+ "BEGIN" "END" "return" "exec" "eval"
+ "when" "given" "default")
+ t)
"\\>")
;;
;; Fontify declarators and prefixes as types.
@@ -212,7 +214,7 @@
(eval-and-compile
(defconst perl--syntax-exp-intro-keywords
- '("split" "if" "unless" "until" "while" "print"
+ '("split" "if" "unless" "until" "while" "print" "printf"
"grep" "map" "not" "or" "and" "for" "foreach" "return"))
(defconst perl--syntax-exp-intro-regexp
diff --git a/lisp/progmodes/prog-mode.el b/lisp/progmodes/prog-mode.el
index 20685354890..7738de6a745 100644
--- a/lisp/progmodes/prog-mode.el
+++ b/lisp/progmodes/prog-mode.el
@@ -49,9 +49,15 @@
(define-key-after menu [prog-separator] menu-bar-separator
'middle-separator)
+ (unless (xref-forward-history-empty-p)
+ (define-key-after menu [xref-forward]
+ '(menu-item "Go Forward" xref-go-forward
+ :help "Forward to the position gone Back from")
+ 'prog-separator))
+
(unless (xref-marker-stack-empty-p)
(define-key-after menu [xref-pop]
- '(menu-item "Go Back" xref-pop-marker-stack
+ '(menu-item "Go Back" xref-go-back
:help "Back to the position of the last search")
'prog-separator))
diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el
index 1000e8c87f4..daaf86f3277 100644
--- a/lisp/progmodes/project.el
+++ b/lisp/progmodes/project.el
@@ -2,7 +2,7 @@
;; Copyright (C) 2015-2022 Free Software Foundation, Inc.
;; Version: 0.8.1
-;; Package-Requires: ((emacs "26.1") (xref "1.0.2"))
+;; Package-Requires: ((emacs "26.1") (xref "1.4.0"))
;; This is a GNU ELPA :core package. Avoid using functionality that
;; not compatible with the version of Emacs recorded above.
@@ -322,7 +322,15 @@ to find the list of ignores for each directory."
(process-file-shell-command command nil t))
(pt (point-min)))
(unless (zerop status)
- (error "File listing failed: %s" (buffer-string)))
+ (goto-char (point-min))
+ (if (and
+ (not (eql status 127))
+ (search-forward "Permission denied\n" nil t))
+ (let ((end (1- (point))))
+ (re-search-backward "\\`\\|\0")
+ (error "File listing failed: %s"
+ (buffer-substring (1+ (point)) end)))
+ (error "File listing failed: %s" (buffer-string))))
(goto-char pt)
(while (search-forward "\0" nil t)
(push (buffer-substring-no-properties (1+ pt) (1- (point)))
@@ -410,30 +418,33 @@ The directory names should be absolute. Used in the VC project
backend implementation of `project-external-roots'.")
(defun project-try-vc (dir)
- (let* ((backend
- ;; FIXME: This is slow. Cache it.
- (ignore-errors (vc-responsible-backend dir)))
- (root
- (pcase backend
- ('Git
- ;; Don't stop at submodule boundary.
- ;; FIXME: Cache for a shorter time.
- (or (vc-file-getprop dir 'project-git-root)
- (let ((root (vc-call-backend backend 'root dir)))
- (vc-file-setprop
- dir 'project-git-root
- (if (and
- ;; FIXME: Invalidate the cache when the value
- ;; of this variable changes.
- (project--vc-merge-submodules-p root)
- (project--submodule-p root))
- (let* ((parent (file-name-directory
- (directory-file-name root))))
- (vc-call-backend backend 'root parent))
- root)))))
- ('nil nil)
- (_ (ignore-errors (vc-call-backend backend 'root dir))))))
- (and root (cons 'vc root))))
+ (or (vc-file-getprop dir 'project-vc)
+ (let* ((backend (ignore-errors (vc-responsible-backend dir)))
+ (root
+ (pcase backend
+ ('Git
+ ;; Don't stop at submodule boundary.
+ (or (vc-file-getprop dir 'project-git-root)
+ (let ((root (vc-call-backend backend 'root dir)))
+ (vc-file-setprop
+ dir 'project-git-root
+ (if (and
+ ;; FIXME: Invalidate the cache when the value
+ ;; of this variable changes.
+ (project--vc-merge-submodules-p root)
+ (project--submodule-p root))
+ (let* ((parent (file-name-directory
+ (directory-file-name root))))
+ (vc-call-backend backend 'root parent))
+ root)))))
+ ('nil nil)
+ (_ (ignore-errors (vc-call-backend backend 'root dir)))))
+ project)
+ (when root
+ (setq project (list 'vc backend root))
+ ;; FIXME: Cache for a shorter time.
+ (vc-file-setprop dir 'project-vc project)
+ project))))
(defun project--submodule-p (root)
;; XXX: We only support Git submodules for now.
@@ -459,7 +470,7 @@ backend implementation of `project-external-roots'.")
(t nil))))
(cl-defmethod project-root ((project (head vc)))
- (cdr project))
+ (nth 2 project))
(cl-defmethod project-external-roots ((project (head vc)))
(project-subtract-directories
@@ -474,8 +485,8 @@ backend implementation of `project-external-roots'.")
(lambda (dir)
(let ((ignores (project--value-in-dir 'project-vc-ignores dir))
backend)
- (if (and (file-equal-p dir (cdr project))
- (setq backend (vc-responsible-backend dir))
+ (if (and (file-equal-p dir (nth 2 project))
+ (setq backend (cadr project))
(cond
((eq backend 'Hg))
((and (eq backend 'Git)
@@ -587,11 +598,11 @@ backend implementation of `project-external-roots'.")
(file-missing nil)))
(cl-defmethod project-ignores ((project (head vc)) dir)
- (let* ((root (cdr project))
+ (let* ((root (nth 2 project))
backend)
(append
(when (file-equal-p dir root)
- (setq backend (vc-responsible-backend root))
+ (setq backend (cadr project))
(delq
nil
(mapcar
@@ -768,7 +779,6 @@ The following commands are available:
(define-key tab-prefix-map "p" #'project-other-tab-command))
(declare-function grep-read-files "grep")
-(declare-function xref--show-xrefs "xref")
(declare-function xref--find-ignores-arguments "xref")
;;;###autoload
@@ -794,7 +804,7 @@ requires quoting, e.g. `\\[quoted-insert]<space>'."
(project--files-in-directory dir
nil
(grep-read-files regexp))))))
- (xref--show-xrefs
+ (xref-show-xrefs
(apply-partially #'project--find-regexp-in-files regexp files)
nil)))
@@ -822,7 +832,7 @@ pattern to search for."
(project-files pr (cons
(project-root pr)
(project-external-roots pr)))))
- (xref--show-xrefs
+ (xref-show-xrefs
(apply-partially #'project--find-regexp-in-files regexp files)
nil)))
@@ -842,28 +852,36 @@ pattern to search for."
project-regexp-history-variable)))
;;;###autoload
-(defun project-find-file ()
+(defun project-find-file (&optional include-all)
"Visit a file (with completion) in the current project.
The filename at point (determined by `thing-at-point'), if any,
-is available as part of \"future history\"."
- (interactive)
+is available as part of \"future history\".
+
+If INCLUDE-ALL is non-nil, or with prefix argument when called
+interactively, include all files under the project root, except
+for VCS directories listed in `vc-directory-exclusion-list'."
+ (interactive "P")
(let* ((pr (project-current t))
(dirs (list (project-root pr))))
- (project-find-file-in (thing-at-point 'filename) dirs pr)))
+ (project-find-file-in (thing-at-point 'filename) dirs pr include-all)))
;;;###autoload
-(defun project-or-external-find-file ()
+(defun project-or-external-find-file (&optional include-all)
"Visit a file (with completion) in the current project or external roots.
The filename at point (determined by `thing-at-point'), if any,
-is available as part of \"future history\"."
- (interactive)
+is available as part of \"future history\".
+
+If INCLUDE-ALL is non-nil, or with prefix argument when called
+interactively, include all files under the project root, except
+for VCS directories listed in `vc-directory-exclusion-list'."
+ (interactive "P")
(let* ((pr (project-current t))
(dirs (cons
(project-root pr)
(project-external-roots pr))))
- (project-find-file-in (thing-at-point 'filename) dirs pr)))
+ (project-find-file-in (thing-at-point 'filename) dirs pr include-all)))
(defcustom project-read-file-name-function #'project--read-file-cpd-relative
"Function to call to read a file name from a list.
@@ -916,12 +934,25 @@ by the user at will."
predicate
hist mb-default))
-(defun project-find-file-in (suggested-filename dirs project)
+(defun project-find-file-in (suggested-filename dirs project &optional include-all)
"Complete a file name in DIRS in PROJECT and visit the result.
SUGGESTED-FILENAME is a relative file name, or part of it, which
-is used as part of \"future history\"."
- (let* ((all-files (project-files project dirs))
+is used as part of \"future history\".
+
+If INCLUDE-ALL is non-nil, or with prefix argument when called
+interactively, include all files from DIRS, except for VCS
+directories listed in `vc-directory-exclusion-list'."
+ (let* ((vc-dirs-ignores (mapcar
+ (lambda (dir)
+ (concat dir "/"))
+ vc-directory-exclusion-list))
+ (all-files
+ (if include-all
+ (mapcan
+ (lambda (dir) (project--files-in-directory dir vc-dirs-ignores))
+ dirs)
+ (project-files project dirs)))
(completion-ignore-case read-file-name-completion-ignore-case)
(file (funcall project-read-file-name-function
"Find file" all-files nil nil
@@ -976,6 +1007,8 @@ is used as part of \"future history\"."
(interactive)
(vc-dir (project-root (project-current t))))
+(declare-function comint-check-proc "comint")
+
;;;###autoload
(defun project-shell ()
"Start an inferior shell in the current project's root directory.
@@ -984,11 +1017,14 @@ switch to it. Otherwise, create a new shell buffer.
With \\[universal-argument] prefix arg, create a new inferior shell buffer even
if one already exists."
(interactive)
+ (require 'comint)
(let* ((default-directory (project-root (project-current t)))
(default-project-shell-name (project-prefixed-buffer-name "shell"))
(shell-buffer (get-buffer default-project-shell-name)))
(if (and shell-buffer (not current-prefix-arg))
- (pop-to-buffer-same-window shell-buffer)
+ (if (comint-check-proc shell-buffer)
+ (pop-to-buffer shell-buffer (bound-and-true-p display-comint-buffer-action))
+ (shell shell-buffer))
(shell (generate-new-buffer-name default-project-shell-name)))))
;;;###autoload
@@ -1004,7 +1040,7 @@ if one already exists."
(eshell-buffer-name (project-prefixed-buffer-name "eshell"))
(eshell-buffer (get-buffer eshell-buffer-name)))
(if (and eshell-buffer (not current-prefix-arg))
- (pop-to-buffer-same-window eshell-buffer)
+ (pop-to-buffer eshell-buffer (bound-and-true-p display-comint-buffer-action))
(eshell t))))
;;;###autoload
@@ -1043,9 +1079,10 @@ Stops when a match is found and prompts for whether to replace it.
If you exit the `query-replace', you can later continue the
`query-replace' loop using the command \\[fileloop-continue]."
(interactive
- (pcase-let ((`(,from ,to)
- (query-replace-read-args "Query replace (regexp)" t t)))
- (list from to)))
+ (let ((query-replace-read-from-regexp-default 'find-tag-default-as-regexp))
+ (pcase-let ((`(,from ,to)
+ (query-replace-read-args "Query replace (regexp)" t t)))
+ (list from to))))
(fileloop-initialize-replace
from to (project-files (project-current t)) 'default)
(fileloop-continue))
@@ -1083,6 +1120,29 @@ If non-nil, it overrides `compilation-buffer-name-function' for
compilation-buffer-name-function)))
(call-interactively #'compile)))
+(defcustom project-ignore-buffer-conditions nil
+ "List of conditions to filter the buffers to be switched to.
+If any of these conditions are satisfied for a buffer in the
+current project, `project-switch-to-buffer',
+`project-display-buffer' and `project-display-buffer-other-frame'
+ignore it.
+See the doc string of `project-kill-buffer-conditions' for the
+general form of conditions."
+ :type '(repeat (choice regexp function symbol
+ (cons :tag "Major mode"
+ (const major-mode) symbol)
+ (cons :tag "Derived mode"
+ (const derived-mode) symbol)
+ (cons :tag "Negation"
+ (const not) sexp)
+ (cons :tag "Conjunction"
+ (const and) sexp)
+ (cons :tag "Disjunction"
+ (const or) sexp)))
+ :version "29.1"
+ :group 'project
+ :package-version '(project . "0.8.2"))
+
(defun project--read-project-buffer ()
(let* ((pr (project-current t))
(current-buffer (current-buffer))
@@ -1092,7 +1152,10 @@ If non-nil, it overrides `compilation-buffer-name-function' for
(predicate
(lambda (buffer)
;; BUFFER is an entry (BUF-NAME . BUF-OBJ) of Vbuffer_alist.
- (memq (cdr buffer) buffers))))
+ (and (memq (cdr buffer) buffers)
+ (not
+ (project--buffer-check
+ (cdr buffer) project-ignore-buffer-conditions))))))
(read-buffer
"Switch to buffer: "
(when (funcall predicate (cons other-name other-buffer))
@@ -1146,7 +1209,10 @@ displayed."
(not (major-mode . help-mode)))
(derived-mode . compilation-mode)
(derived-mode . dired-mode)
- (derived-mode . diff-mode))
+ (derived-mode . diff-mode)
+ (derived-mode . comint-mode)
+ (derived-mode . eshell-mode)
+ (derived-mode . change-log-mode))
"List of conditions to kill buffers related to a project.
This list is used by `project-kill-buffers'.
Each condition is either:
@@ -1179,9 +1245,18 @@ current project, it will be killed."
(const and) sexp)
(cons :tag "Disjunction"
(const or) sexp)))
- :version "28.1"
+ :version "29.1"
:group 'project
- :package-version '(project . "0.6.0"))
+ :package-version '(project . "0.8.2"))
+
+(defcustom project-kill-buffers-display-buffer-list nil
+ "Non-nil to display list of buffers to kill before killing project buffers.
+Used by `project-kill-buffers'."
+ :type 'boolean
+ :version "29.1"
+ :group 'project
+ :package-version '(project . "0.8.2")
+ :safe #'booleanp)
(defun project--buffer-list (pr)
"Return the list of all buffers in project PR."
@@ -1198,11 +1273,12 @@ current project, it will be killed."
(push buf bufs)))
(nreverse bufs)))
-(defun project--kill-buffer-check (buf conditions)
+(defun project--buffer-check (buf conditions)
"Check if buffer BUF matches any element of the list CONDITIONS.
-See `project-kill-buffer-conditions' for more details on the form
-of CONDITIONS."
- (catch 'kill
+See `project-kill-buffer-conditions' or
+`project-ignore-buffer-conditions' for more details on the
+form of CONDITIONS."
+ (catch 'match
(dolist (c conditions)
(when (cond
((stringp c)
@@ -1217,15 +1293,15 @@ of CONDITIONS."
(buffer-local-value 'major-mode buf)
(cdr c)))
((eq (car-safe c) 'not)
- (not (project--kill-buffer-check buf (cdr c))))
+ (not (project--buffer-check buf (cdr c))))
((eq (car-safe c) 'or)
- (project--kill-buffer-check buf (cdr c)))
+ (project--buffer-check buf (cdr c)))
((eq (car-safe c) 'and)
(seq-every-p
- (apply-partially #'project--kill-buffer-check
+ (apply-partially #'project--buffer-check
buf)
(mapcar #'list (cdr c)))))
- (throw 'kill t)))))
+ (throw 'match t)))))
(defun project--buffers-to-kill (pr)
"Return list of buffers in project PR to kill.
@@ -1233,7 +1309,7 @@ What buffers should or should not be killed is described
in `project-kill-buffer-conditions'."
(let (bufs)
(dolist (buf (project-buffers pr))
- (when (project--kill-buffer-check buf project-kill-buffer-conditions)
+ (when (project--buffer-check buf project-kill-buffer-conditions)
(push buf bufs)))
bufs))
@@ -1249,14 +1325,35 @@ NO-CONFIRM is always nil when the command is invoked
interactively."
(interactive)
(let* ((pr (project-current t))
- (bufs (project--buffers-to-kill pr)))
+ (bufs (project--buffers-to-kill pr))
+ (query-user (lambda ()
+ (yes-or-no-p
+ (format "Kill %d buffers in %s? "
+ (length bufs)
+ (project-root pr))))))
(cond (no-confirm
(mapc #'kill-buffer bufs))
((null bufs)
(message "No buffers to kill"))
- ((yes-or-no-p (format "Kill %d buffers in %s? "
- (length bufs)
- (project-root pr)))
+ (project-kill-buffers-display-buffer-list
+ (when
+ (with-current-buffer-window
+ (get-buffer-create "*Buffer List*")
+ `(display-buffer--maybe-at-bottom
+ (dedicated . t)
+ (window-height . (fit-window-to-buffer))
+ (preserve-size . (nil . t))
+ (body-function
+ . ,#'(lambda (_window)
+ (list-buffers-noselect nil bufs))))
+ #'(lambda (window _value)
+ (with-selected-window window
+ (unwind-protect
+ (funcall query-user)
+ (when (window-live-p window)
+ (quit-restore-window window 'kill))))))
+ (mapc #'kill-buffer bufs)))
+ ((funcall query-user)
(mapc #'kill-buffer bufs)))))
diff --git a/lisp/progmodes/prolog.el b/lisp/progmodes/prolog.el
index 6bc7ee408d5..8382c4bd099 100644
--- a/lisp/progmodes/prolog.el
+++ b/lisp/progmodes/prolog.el
@@ -2484,11 +2484,8 @@ Interaction supports completion."
(if (eq (try-completion default prolog-info-alist) nil)
(setq default nil))
;; Read the PredSpec from the user
- (completing-read
- (if (zerop (length default))
- "Help on predicate: "
- (concat "Help on predicate (default " default "): "))
- prolog-info-alist nil t nil nil default)))
+ (completing-read (format-prompt "Help on predicate" default)
+ prolog-info-alist nil t nil nil default)))
(defun prolog-build-info-alist (&optional verbose)
"Build an alist of all builtins and library predicates.
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index e6e8a37ad57..c4d8b123a86 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -5,7 +5,7 @@
;; Author: Fabián E. Gallina <fgallina@gnu.org>
;; URL: https://github.com/fgallina/python.el
;; Version: 0.28
-;; Package-Requires: ((emacs "24.2") (cl-lib "1.0"))
+;; Package-Requires: ((emacs "24.4") (cl-lib "1.0"))
;; Maintainer: emacs-devel@gnu.org
;; Created: Jul 2010
;; Keywords: languages
@@ -92,7 +92,7 @@
;; Operating Systems' pipe buffering (e.g. CPython 3.3.4 in Windows 7.
;; See URL `https://debbugs.gnu.org/cgi/bugreport.cgi?bug=17304'). To
;; avoid this, the `python-shell-unbuffered' defaults to non-nil and
-;; controls whether `python-shell-calculate-process-environment'
+;; controls whether `python-shell--calculate-process-environment'
;; should set the "PYTHONUNBUFFERED" environment variable on startup:
;; See URL `https://docs.python.org/3/using/cmdline.html#cmdoption-u'.
@@ -149,7 +149,7 @@
;; (setq python-shell-process-environment
;; (list
;; (format "PATH=%s" (mapconcat
-;; 'identity
+;; #'identity
;; (reverse
;; (cons (getenv "PATH")
;; '("/path/to/env/bin/")))
@@ -245,7 +245,7 @@
(require 'ansi-color)
(require 'cl-lib)
(require 'comint)
-(require 'tramp-sh)
+(eval-when-compile (require 'subr-x)) ;For `string-empty-p'.
;; Avoid compiler warnings
(defvar view-return-to-alist)
@@ -273,39 +273,39 @@
(defvar python-mode-map
(let ((map (make-sparse-keymap)))
;; Movement
- (define-key map [remap backward-sentence] 'python-nav-backward-block)
- (define-key map [remap forward-sentence] 'python-nav-forward-block)
- (define-key map [remap backward-up-list] 'python-nav-backward-up-list)
- (define-key map [remap mark-defun] 'python-mark-defun)
- (define-key map "\C-c\C-j" 'imenu)
+ (define-key map [remap backward-sentence] #'python-nav-backward-block)
+ (define-key map [remap forward-sentence] #'python-nav-forward-block)
+ (define-key map [remap backward-up-list] #'python-nav-backward-up-list)
+ (define-key map [remap mark-defun] #'python-mark-defun)
+ (define-key map "\C-c\C-j" #'imenu)
;; Indent specific
- (define-key map "\177" 'python-indent-dedent-line-backspace)
- (define-key map (kbd "<backtab>") 'python-indent-dedent-line)
- (define-key map "\C-c<" 'python-indent-shift-left)
- (define-key map "\C-c>" 'python-indent-shift-right)
+ (define-key map "\177" #'python-indent-dedent-line-backspace)
+ (define-key map (kbd "<backtab>") #'python-indent-dedent-line)
+ (define-key map "\C-c<" #'python-indent-shift-left)
+ (define-key map "\C-c>" #'python-indent-shift-right)
;; Skeletons
- (define-key map "\C-c\C-tc" 'python-skeleton-class)
- (define-key map "\C-c\C-td" 'python-skeleton-def)
- (define-key map "\C-c\C-tf" 'python-skeleton-for)
- (define-key map "\C-c\C-ti" 'python-skeleton-if)
- (define-key map "\C-c\C-tm" 'python-skeleton-import)
- (define-key map "\C-c\C-tt" 'python-skeleton-try)
- (define-key map "\C-c\C-tw" 'python-skeleton-while)
+ (define-key map "\C-c\C-tc" #'python-skeleton-class)
+ (define-key map "\C-c\C-td" #'python-skeleton-def)
+ (define-key map "\C-c\C-tf" #'python-skeleton-for)
+ (define-key map "\C-c\C-ti" #'python-skeleton-if)
+ (define-key map "\C-c\C-tm" #'python-skeleton-import)
+ (define-key map "\C-c\C-tt" #'python-skeleton-try)
+ (define-key map "\C-c\C-tw" #'python-skeleton-while)
;; Shell interaction
- (define-key map "\C-c\C-p" 'run-python)
- (define-key map "\C-c\C-s" 'python-shell-send-string)
- (define-key map "\C-c\C-e" 'python-shell-send-statement)
- (define-key map "\C-c\C-r" 'python-shell-send-region)
- (define-key map "\C-\M-x" 'python-shell-send-defun)
- (define-key map "\C-c\C-c" 'python-shell-send-buffer)
- (define-key map "\C-c\C-l" 'python-shell-send-file)
- (define-key map "\C-c\C-z" 'python-shell-switch-to-shell)
+ (define-key map "\C-c\C-p" #'run-python)
+ (define-key map "\C-c\C-s" #'python-shell-send-string)
+ (define-key map "\C-c\C-e" #'python-shell-send-statement)
+ (define-key map "\C-c\C-r" #'python-shell-send-region)
+ (define-key map "\C-\M-x" #'python-shell-send-defun)
+ (define-key map "\C-c\C-c" #'python-shell-send-buffer)
+ (define-key map "\C-c\C-l" #'python-shell-send-file)
+ (define-key map "\C-c\C-z" #'python-shell-switch-to-shell)
;; Some util commands
- (define-key map "\C-c\C-v" 'python-check)
- (define-key map "\C-c\C-f" 'python-eldoc-at-point)
- (define-key map "\C-c\C-d" 'python-describe-at-point)
+ (define-key map "\C-c\C-v" #'python-check)
+ (define-key map "\C-c\C-f" #'python-eldoc-at-point)
+ (define-key map "\C-c\C-d" #'python-describe-at-point)
;; Utilities
- (substitute-key-definition 'complete-symbol 'completion-at-point
+ (substitute-key-definition #'complete-symbol #'completion-at-point
map global-map)
(easy-menu-define python-menu map "Python Mode menu"
'("Python"
@@ -563,6 +563,8 @@ class declarations.")
;; Python 3.5+ PEP492
(and "async" (+ space) (or "def" "for" "with"))
"await"
+ ;; Python 3.10+
+ "match" "case"
;; Extra:
"self")
symbol-end)
@@ -825,7 +827,6 @@ It makes underscores and dots word constituent chars.")
(defcustom python-indent-offset 4
"Default indentation offset for Python."
- :group 'python
:type 'integer
:safe 'integerp)
@@ -835,21 +836,18 @@ It makes underscores and dots word constituent chars.")
(defcustom python-indent-guess-indent-offset t
"Non-nil tells Python mode to guess `python-indent-offset' value."
:type 'boolean
- :group 'python
:safe 'booleanp)
(defcustom python-indent-guess-indent-offset-verbose t
"Non-nil means to emit a warning when indentation guessing fails."
:version "25.1"
:type 'boolean
- :group 'python
:safe' booleanp)
(defcustom python-indent-trigger-commands
'(indent-for-tab-command yas-expand yas/expand)
"Commands that might trigger a `python-indent-line' call."
- :type '(repeat symbol)
- :group 'python)
+ :type '(repeat symbol))
(defcustom python-indent-def-block-scale 2
"Multiplier applied to indentation inside multi-line def blocks."
@@ -1427,6 +1425,13 @@ marks the next defun after the ones already marked."
;;; Navigation
+(defcustom python-forward-sexp-function #'python-nav-forward-sexp
+ "Function to use when navigating between expressions."
+ :version "28.1"
+ :type '(choice (const :tag "Python blocks" python-nav-forward-sexp)
+ (const :tag "CC-mode like" nil)
+ function))
+
(defvar python-nav-beginning-of-defun-regexp
(python-rx line-start (* space) defun (+ space) (group symbol-name))
"Regexp matching class or function definition.
@@ -1518,7 +1523,10 @@ Returns nil if point is not in a def or class."
(python-util-forward-comment -1)
(forward-line 1)
;; Ensure point moves forward.
- (and (> beg-pos (point)) (goto-char beg-pos)))))
+ (and (> beg-pos (point)) (goto-char beg-pos))
+ ;; Return non-nil if we did something (because then we were in a
+ ;; def/class).
+ (/= beg-pos (point)))))
(defun python-nav--syntactically (fn poscompfn &optional contextfn)
"Move point using FN avoiding places with specific context.
@@ -2021,7 +2029,6 @@ position, else returns nil."
(defcustom python-shell-buffer-name "Python"
"Default buffer name for Python interpreter."
:type 'string
- :group 'python
:safe 'stringp)
(defcustom python-shell-interpreter
@@ -2035,19 +2042,16 @@ Some Python interpreters also require changes to
`python-shell-interpreter' to \"ipython3\" requires setting
`python-shell-interpreter-args' to \"--simple-prompt\"."
:version "28.1"
- :type 'string
- :group 'python)
+ :type 'string)
(defcustom python-shell-internal-buffer-name "Python Internal"
"Default buffer name for the Internal Python interpreter."
:type 'string
- :group 'python
:safe 'stringp)
(defcustom python-shell-interpreter-args "-i"
"Default arguments for the Python interpreter."
- :type 'string
- :group 'python)
+ :type 'string)
(defcustom python-shell-interpreter-interactive-arg "-i"
"Interpreter argument to force it to run interactively."
@@ -2112,7 +2116,6 @@ It should not contain a caret (^) at the beginning."
"Should syntax highlighting be enabled in the Python shell buffer?
Restart the Python shell after changing this variable for it to take effect."
:type 'boolean
- :group 'python
:safe 'booleanp)
(defcustom python-shell-unbuffered t
@@ -2120,7 +2123,6 @@ Restart the Python shell after changing this variable for it to take effect."
When non-nil, this may prevent delayed and missing output in the
Python shell. See commentary for details."
:type 'boolean
- :group 'python
:safe 'booleanp)
(defcustom python-shell-process-environment nil
@@ -2130,8 +2132,7 @@ When this variable is non-nil, values are exported into the
process environment before starting it. Any variables already
present in the current environment are superseded by variables
set here."
- :type '(repeat string)
- :group 'python)
+ :type '(repeat string))
(defcustom python-shell-extra-pythonpaths nil
"List of extra pythonpaths for Python shell.
@@ -2140,8 +2141,7 @@ the PYTHONPATH before starting processes. Any values present
here that already exists in PYTHONPATH are moved to the beginning
of the list so that they are prioritized when looking for
modules."
- :type '(repeat string)
- :group 'python)
+ :type '(repeat string))
(defcustom python-shell-exec-path nil
"List of paths for searching executables.
@@ -2149,8 +2149,7 @@ When this variable is non-nil, values added at the beginning of
the PATH before starting processes. Any values present here that
already exists in PATH are moved to the beginning of the list so
that they are prioritized when looking for executables."
- :type '(repeat string)
- :group 'python)
+ :type '(repeat string))
(defcustom python-shell-remote-exec-path nil
"List of paths to be ensured remotely for searching executables.
@@ -2161,8 +2160,7 @@ here. Normally you won't use this variable directly unless you
plan to ensure a particular set of paths to all Python shell
executed through tramp connections."
:version "25.1"
- :type '(repeat string)
- :group 'python)
+ :type '(repeat string))
(define-obsolete-variable-alias
'python-shell-virtualenv-path 'python-shell-virtualenv-root "25.1")
@@ -2172,13 +2170,11 @@ executed through tramp connections."
This variable, when set to a string, makes the environment to be
modified such that shells are started within the specified
virtualenv."
- :type '(choice (const nil) directory)
- :group 'python)
+ :type '(choice (const nil) directory))
(defcustom python-shell-setup-codes nil
"List of code run by `python-shell-send-setup-code'."
- :type '(repeat symbol)
- :group 'python)
+ :type '(repeat symbol))
(defcustom python-shell-compilation-regexp-alist
`((,(rx line-start (1+ (any " \t")) "File \""
@@ -2192,8 +2188,7 @@ virtualenv."
"(" (group (1+ digit)) ")" (1+ (not (any "("))) "()")
1 2))
"`compilation-error-regexp-alist' for inferior Python."
- :type '(alist regexp)
- :group 'python)
+ :type '(alist regexp))
(defvar python-shell-output-filter-in-progress nil)
(defvar python-shell-output-filter-buffer nil)
@@ -2211,33 +2206,34 @@ virtualenv."
(or (getenv "PYTHONPATH") "") path-separator 'omit)))
(python-shell--add-to-path-with-priority
pythonpath python-shell-extra-pythonpaths)
- (mapconcat 'identity pythonpath path-separator)))
+ (mapconcat #'identity pythonpath path-separator)))
(defun python-shell-calculate-process-environment ()
- "Calculate `process-environment' or `tramp-remote-process-environment'.
+ (declare (obsolete python-shell--calculate-process-environment "29.1"))
+ (defvar tramp-remote-process-environment)
+ (let* ((remote-p (file-remote-p default-directory)))
+ (append (python-shell--calculate-process-environment)
+ (if remote-p
+ tramp-remote-process-environment
+ process-environment))))
+
+(defun python-shell--calculate-process-environment ()
+ "Return a list of entries to add to the `process-environment'.
Prepends `python-shell-process-environment', sets extra
pythonpaths from `python-shell-extra-pythonpaths' and sets a few
-virtualenv related vars. If `default-directory' points to a
-remote host, the returned value is intended for
-`tramp-remote-process-environment'."
- (let* ((remote-p (file-remote-p default-directory))
- (process-environment (if remote-p
- tramp-remote-process-environment
- process-environment))
- (virtualenv (when python-shell-virtualenv-root
- (directory-file-name python-shell-virtualenv-root))))
- (dolist (env python-shell-process-environment)
- (pcase-let ((`(,key ,value) (split-string env "=")))
- (setenv key value)))
+virtualenv related vars."
+ (let* ((virtualenv (when python-shell-virtualenv-root
+ (directory-file-name python-shell-virtualenv-root)))
+ (res python-shell-process-environment))
(when python-shell-unbuffered
- (setenv "PYTHONUNBUFFERED" "1"))
+ (push "PYTHONUNBUFFERED=1" res))
(when python-shell-extra-pythonpaths
- (setenv "PYTHONPATH" (python-shell-calculate-pythonpath)))
+ (push (concat "PYTHONPATH=" (python-shell-calculate-pythonpath)) res))
(if (not virtualenv)
- process-environment
- (setenv "PYTHONHOME" nil)
- (setenv "VIRTUAL_ENV" virtualenv))
- process-environment))
+ nil
+ (push "PYTHONHOME" res)
+ (push (concat "VIRTUAL_ENV=" virtualenv) res))
+ res))
(defun python-shell-calculate-exec-path ()
"Calculate `exec-path'.
@@ -2265,14 +2261,26 @@ of `exec-path'."
(defun python-shell-tramp-refresh-remote-path (vec paths)
"Update VEC's remote-path giving PATHS priority."
+ (cl-assert (featurep 'tramp))
+ (declare-function tramp-set-remote-path "tramp-sh")
+ (declare-function tramp-set-connection-property "tramp-cache")
+ (declare-function tramp-get-connection-property "tramp-cache")
(let ((remote-path (tramp-get-connection-property vec "remote-path" nil)))
(when remote-path
+ ;; FIXME: This part of the Tramp code still knows about Python!
(python-shell--add-to-path-with-priority remote-path paths)
(tramp-set-connection-property vec "remote-path" remote-path)
(tramp-set-remote-path vec))))
+
(defun python-shell-tramp-refresh-process-environment (vec env)
"Update VEC's process environment with ENV."
+ (cl-assert (featurep 'tramp))
+ (defvar tramp-end-of-heredoc)
+ (defvar tramp-end-of-output)
+ ;; Do we even know that `tramp-sh' is loaded at this point?
+ ;; What about files accessed via FTP, sudo, ...?
+ (declare-function tramp-send-command "tramp-sh")
;; Stolen from `tramp-open-connection-setup-interactive-shell'.
(let ((env (append (when (fboundp 'tramp-get-remote-locale)
;; Emacs<24.4 compat.
@@ -2285,7 +2293,7 @@ of `exec-path'."
unset vars item)
(while env
(setq item (split-string (car env) "=" 'omit))
- (setcdr item (mapconcat 'identity (cdr item) "="))
+ (setcdr item (mapconcat #'identity (cdr item) "="))
(if (and (stringp (cdr item)) (not (string-equal (cdr item) "")))
(push (format "%s %s" (car item) (cdr item)) vars)
(push (car item) unset))
@@ -2295,12 +2303,12 @@ of `exec-path'."
vec
(format "while read var val; do export $var=$val; done <<'%s'\n%s\n%s"
tramp-end-of-heredoc
- (mapconcat 'identity vars "\n")
+ (mapconcat #'identity vars "\n")
tramp-end-of-heredoc)
t))
(when unset
(tramp-send-command
- vec (format "unset %s" (mapconcat 'identity unset " ")) t))))
+ vec (format "unset %s" (mapconcat #'identity unset " ")) t))))
(defmacro python-shell-with-environment (&rest body)
"Modify shell environment during execution of BODY.
@@ -2309,41 +2317,49 @@ execution of body. If `default-directory' points to a remote
machine then modifies `tramp-remote-process-environment' and
`python-shell-remote-exec-path' instead."
(declare (indent 0) (debug (body)))
- (let ((vec (make-symbol "vec")))
- `(progn
- (let* ((,vec
- (when (file-remote-p default-directory)
- (ignore-errors
- (tramp-dissect-file-name default-directory 'noexpand))))
- (process-environment
- (if ,vec
- process-environment
- (python-shell-calculate-process-environment)))
- (exec-path
- (if ,vec
- exec-path
- (python-shell-calculate-exec-path)))
- (tramp-remote-process-environment
- (if ,vec
- (python-shell-calculate-process-environment)
- tramp-remote-process-environment)))
- (when (tramp-get-connection-process ,vec)
- ;; For already existing connections, the new exec path must
- ;; be re-set, otherwise it won't take effect. One example
- ;; of such case is when remote dir-locals are read and
- ;; *then* subprocesses are triggered within the same
- ;; connection.
- (python-shell-tramp-refresh-remote-path
- ,vec (python-shell-calculate-exec-path))
- ;; The `tramp-remote-process-environment' variable is only
- ;; effective when the started process is an interactive
- ;; shell, otherwise (like in the case of processes started
- ;; with `process-file') the environment is not changed.
- ;; This makes environment modifications effective
- ;; unconditionally.
- (python-shell-tramp-refresh-process-environment
- ,vec tramp-remote-process-environment))
- ,(macroexp-progn body)))))
+ `(python-shell--with-environment
+ (python-shell--calculate-process-environment)
+ (lambda () ,@body)))
+
+(defun python-shell--with-environment (extraenv bodyfun)
+ ;; FIXME: This is where the generic code delegates to Tramp.
+ (let* ((vec
+ (and (file-remote-p default-directory)
+ (fboundp 'tramp-dissect-file-name)
+ (ignore-errors
+ (tramp-dissect-file-name default-directory 'noexpand)))))
+ (if vec
+ (python-shell--tramp-with-environment vec extraenv bodyfun)
+ (let ((process-environment
+ (append extraenv process-environment))
+ (exec-path
+ ;; FIXME: This is still Python-specific.
+ (python-shell-calculate-exec-path)))
+ (funcall bodyfun)))))
+
+(defun python-shell--tramp-with-environment (vec extraenv bodyfun)
+ (defvar tramp-remote-process-environment)
+ (declare-function tramp-get-connection-process "tramp" (vec))
+ (let* ((tramp-remote-process-environment
+ (append extraenv tramp-remote-process-environment)))
+ (when (tramp-get-connection-process vec)
+ ;; For already existing connections, the new exec path must
+ ;; be re-set, otherwise it won't take effect. One example
+ ;; of such case is when remote dir-locals are read and
+ ;; *then* subprocesses are triggered within the same
+ ;; connection.
+ (python-shell-tramp-refresh-remote-path
+ ;; FIXME: This is still Python-specific.
+ vec (python-shell-calculate-exec-path))
+ ;; The `tramp-remote-process-environment' variable is only
+ ;; effective when the started process is an interactive
+ ;; shell, otherwise (like in the case of processes started
+ ;; with `process-file') the environment is not changed.
+ ;; This makes environment modifications effective
+ ;; unconditionally.
+ (python-shell-tramp-refresh-process-environment
+ vec tramp-remote-process-environment))
+ (funcall bodyfun)))
(defvar python-shell--prompt-calculated-input-regexp nil
"Calculated input prompt regexp for inferior python shell.
@@ -2626,7 +2642,7 @@ banner and the initial prompt are received separately."
(define-obsolete-function-alias
'python-comint-output-filter-function
- 'ansi-color-filter-apply
+ #'ansi-color-filter-apply
"25.1")
(defun python-comint-postoutput-scroll-to-bottom (output)
@@ -2724,20 +2740,12 @@ goes wrong and syntax highlighting in the shell gets messed up."
(deactivate-mark nil)
(start-pos prompt-end)
(buffer-undo-list t)
- (font-lock-buffer-pos nil)
(replacement
(python-shell-font-lock-with-font-lock-buffer
- (delete-region (line-beginning-position)
- (point-max))
- (setq font-lock-buffer-pos (point))
+ (delete-region (point-min) (point-max))
(insert input)
- ;; Ensure buffer is fontified, keeping it
- ;; compatible with Emacs < 24.4.
- (if (fboundp 'font-lock-ensure)
- (funcall 'font-lock-ensure)
- (font-lock-default-fontify-buffer))
- (buffer-substring font-lock-buffer-pos
- (point-max))))
+ (font-lock-ensure)
+ (buffer-string)))
(replacement-length (length replacement))
(i 0))
;; Inject text properties to get input fontified.
@@ -2819,8 +2827,7 @@ current process to not hang while waiting. This is useful to
safely attach setup code for long-running processes that
eventually provide a shell."
:version "25.1"
- :type 'hook
- :group 'python)
+ :type 'hook)
(defconst python-shell-eval-setup-code
"\
@@ -2954,7 +2961,7 @@ variable.
(add-hook 'completion-at-point-functions
#'python-shell-completion-at-point nil 'local)
(define-key inferior-python-mode-map "\t"
- 'python-shell-completion-complete-or-indent)
+ #'python-shell-completion-complete-or-indent)
(make-local-variable 'python-shell-internal-last-output)
(when python-shell-font-lock-enable
(python-shell-font-lock-turn-on))
@@ -2980,7 +2987,8 @@ killed."
(let* ((cmdlist (split-string-and-unquote cmd))
(interpreter (car cmdlist))
(args (cdr cmdlist))
- (buffer (apply #'make-comint-in-buffer proc-name proc-buffer-name
+ (buffer (apply #'make-comint-in-buffer proc-name
+ proc-buffer-name
interpreter nil args))
(python-shell--parent-buffer (current-buffer))
(process (get-buffer-process buffer))
@@ -3129,7 +3137,7 @@ there for compatibility with CEDET.")
(run-python-internal))))
(define-obsolete-function-alias
- 'python-proc 'python-shell-internal-get-or-create-process "24.3")
+ 'python-proc #'python-shell-internal-get-or-create-process "24.3")
(defun python-shell--save-temp-file (string)
(let* ((temporary-file-directory
@@ -3214,11 +3222,13 @@ detecting a prompt at the end of the buffer."
(defun python-shell-send-string-no-output (string &optional process)
"Send STRING to PROCESS and inhibit output.
Return the output."
- (let ((process (or process (python-shell-get-process-or-error)))
- (comint-preoutput-filter-functions
- '(python-shell-output-filter))
- (python-shell-output-filter-in-progress t)
- (inhibit-quit t))
+ (or process (setq process (python-shell-get-process-or-error)))
+ (cl-letf (((process-filter process)
+ (lambda (_proc str)
+ (with-current-buffer (process-buffer process)
+ (python-shell-output-filter str))))
+ (python-shell-output-filter-in-progress t)
+ (inhibit-quit t))
(or
(with-local-quit
(python-shell-send-string string process)
@@ -3246,10 +3256,10 @@ Returns the output. See `python-shell-send-string-no-output'."
(python-shell-internal-get-or-create-process))))
(define-obsolete-function-alias
- 'python-send-receive 'python-shell-internal-send-string "24.3")
+ 'python-send-receive #'python-shell-internal-send-string "24.3")
(define-obsolete-function-alias
- 'python-send-string 'python-shell-internal-send-string "24.3")
+ 'python-send-string #'python-shell-internal-send-string "24.3")
(defun python-shell-buffer-substring (start end &optional nomain no-cookie)
"Send buffer substring from START to END formatted for shell.
@@ -3545,8 +3555,7 @@ def __PYTHON_EL_get_completions(text):
completer.print_mode = True
return completions"
"Code used to setup completion in inferior Python processes."
- :type 'string
- :group 'python)
+ :type 'string)
(define-obsolete-variable-alias
'python-shell-completion-module-string-code
@@ -3763,7 +3772,8 @@ With argument MSG show activation/deactivation message."
(format "was t and %S is not part of the "
(file-name-nondirectory python-shell-interpreter))
"`python-shell-completion-native-disabled-interpreters' "
- "list. Native completions have been disabled locally. "))
+ "list. Native completions have been disabled locally. "
+ "Consider installing the python package \"readline\". "))
(python-shell-completion-native-turn-off msg))))))
(defun python-shell-completion-native-turn-on-maybe-with-msg ()
@@ -3810,7 +3820,7 @@ With argument MSG show activation/deactivation message."
(comint-redirect-perform-sanity-check nil)
(comint-redirect-insert-matching-regexp t)
(comint-redirect-finished-regexp
- "1__dummy_completion__[[:space:]]*\n")
+ "1__dummy_completion__.*\n")
(comint-redirect-output-buffer redirect-buffer))
;; Compatibility with Emacs 24.x. Comint changed and
;; now `comint-redirect-filter' gets 3 args. This
@@ -3818,7 +3828,8 @@ With argument MSG show activation/deactivation message."
;; in use based on its args and uses `apply-partially'
;; to make it up for the 3 args case.
(if (= (length
- (help-function-arglist 'comint-redirect-filter)) 3)
+ (help-function-arglist 'comint-redirect-filter))
+ 3)
(set-process-filter
process (apply-partially
#'comint-redirect-filter original-filter-fn))
@@ -3927,7 +3938,7 @@ using that one instead of current buffer's process."
(define-obsolete-function-alias
'python-shell-completion-complete-at-point
- 'python-shell-completion-at-point
+ #'python-shell-completion-at-point
"25.1")
(defun python-shell-completion-complete-or-indent ()
@@ -3956,7 +3967,6 @@ considered over. The overlay arrow will be removed from the currently tracked
buffer. Additionally, if `python-pdbtrack-kill-buffers' is non-nil, all
files opened by pdbtracking will be killed."
:type 'boolean
- :group 'python
:safe 'booleanp)
(defcustom python-pdbtrack-stacktrace-info-regexp
@@ -4165,7 +4175,7 @@ inferior Python process is updated properly."
(define-obsolete-function-alias
'python-completion-complete-at-point
- 'python-completion-at-point
+ #'python-completion-at-point
"25.1")
@@ -4175,29 +4185,25 @@ inferior Python process is updated properly."
"Function to fill comments.
This is the function used by `python-fill-paragraph' to
fill comments."
- :type 'symbol
- :group 'python)
+ :type 'symbol)
(defcustom python-fill-string-function 'python-fill-string
"Function to fill strings.
This is the function used by `python-fill-paragraph' to
fill strings."
- :type 'symbol
- :group 'python)
+ :type 'symbol)
(defcustom python-fill-decorator-function 'python-fill-decorator
"Function to fill decorators.
This is the function used by `python-fill-paragraph' to
fill decorators."
- :type 'symbol
- :group 'python)
+ :type 'symbol)
(defcustom python-fill-paren-function 'python-fill-paren
"Function to fill parens.
This is the function used by `python-fill-paragraph' to
fill parens."
- :type 'symbol
- :group 'python)
+ :type 'symbol)
(defcustom python-fill-docstring-style 'pep-257
"Style used to fill docstrings.
@@ -4267,7 +4273,6 @@ value may result in one of the following docstring styles:
(const :tag "PEP-257 with 2 newlines at end of string." pep-257)
(const :tag "PEP-257 with 1 newline at end of string." pep-257-nn)
(const :tag "Symmetric style." symmetric))
- :group 'python
:safe (lambda (val)
(memq val '(django onetwo pep-257 pep-257-nn symmetric nil))))
@@ -4426,7 +4431,6 @@ JUSTIFY should be used (if applicable) as in `fill-paragraph'."
This happens when pressing \"if<SPACE>\", for example, to prompt for
the if condition."
:type 'boolean
- :group 'python
:safe 'booleanp)
(defvar python-skeleton-available '()
@@ -4551,7 +4555,7 @@ The skeleton will be bound to python-skeleton-NAME."
(defun python-skeleton-add-menu-items ()
"Add menu items to Python->Skeletons menu."
- (let ((skeletons (sort python-skeleton-available 'string<)))
+ (let ((skeletons (sort python-skeleton-available #'string<)))
(dolist (skeleton skeletons)
(easy-menu-add-item
nil '("Python" "Skeletons")
@@ -4581,8 +4585,7 @@ def __FFAP_get_module_path(objstr):
except:
return ''"
"Python code to get a module path."
- :type 'string
- :group 'python)
+ :type 'string)
(defun python-ffap-module-path (module)
"Function for `ffap-alist' to return path for MODULE."
@@ -4610,14 +4613,12 @@ def __FFAP_get_module_path(objstr):
(executable-find "epylint")
"install pyflakes, pylint or something else")
"Command used to check a Python file."
- :type 'string
- :group 'python)
+ :type 'string)
(defcustom python-check-buffer-name
"*Python check: %s*"
"Buffer name used for check commands."
- :type 'string
- :group 'python)
+ :type 'string)
(defvar python-check-custom-command nil
"Internal use.")
@@ -4670,7 +4671,10 @@ See `python-check-command' for the default."
target = obj
objtype = 'def'
if target:
- args = inspect.formatargspec(*argspec_function(target))
+ if hasattr(inspect, 'signature'):
+ args = str(inspect.signature(target))
+ else:
+ args = inspect.formatargspec(*argspec_function(target))
name = obj.__name__
doc = '{objtype} {name}{args}'.format(
objtype=objtype, name=name, args=args
@@ -4681,8 +4685,7 @@ See `python-check-command' for the default."
doc = ''
return doc"
"Python code to setup documentation retrieval."
- :type 'string
- :group 'python)
+ :type 'string)
(defun python-eldoc--get-symbol-at-point ()
"Get the current symbol for eldoc.
@@ -4729,14 +4732,13 @@ Set to nil by `python-eldoc-function' if
(defcustom python-eldoc-function-timeout 1
"Timeout for `python-eldoc-function' in seconds."
- :group 'python
:type 'integer
:version "25.1")
(defcustom python-eldoc-function-timeout-permanent t
- "Non-nil means that when `python-eldoc-function' times out
-`python-eldoc-get-doc' will be set to nil."
- :group 'python
+ "If non-nil, a timeout in Python-Eldoc will disable it permanently.
+Python-Eldoc can be re-enabled manually by setting `python-eldoc-get-doc'
+back to t in the affected buffer."
:type 'boolean
:version "25.1")
@@ -4769,10 +4771,14 @@ Interactively, prompt for symbol."
(interactive
(let ((symbol (python-eldoc--get-symbol-at-point))
(enable-recursive-minibuffers t))
- (list (read-string (if symbol
- (format "Describe symbol (default %s): " symbol)
- "Describe symbol: ")
- nil nil symbol))))
+ (list (read-string
+ ;; `format-prompt' is new in Emacs 28.1.
+ (if (fboundp 'format-prompt)
+ (format-prompt "Describe symbol" symbol)
+ (if symbol
+ (format "Describe symbol (default %s): " symbol)
+ "Describe symbol: "))
+ nil nil symbol))))
(message (python-eldoc--get-doc-at-point symbol)))
(defun python-describe-at-point (symbol process)
@@ -4924,7 +4930,7 @@ To this:
(\"decorator.wrapped_f\" . 393))"
;; Inspired by imenu--flatten-index-alist removed in revno 21853.
(apply
- 'nconc
+ #'nconc
(mapcar
(lambda (item)
(let ((name (if prefix
@@ -5007,7 +5013,7 @@ since it returns nil if point is not inside a defun."
(and (= (current-indentation) 0) (throw 'exit t))))
(and names
(concat (and type (format "%s " type))
- (mapconcat 'identity names ".")))))))
+ (mapconcat #'identity names ".")))))))
(defun python-info-current-symbol (&optional replace-self)
"Return current symbol using dotty syntax.
@@ -5028,9 +5034,10 @@ parent defun name."
(replace-regexp-in-string
(python-rx line-start word-start "self" word-end ?.)
(concat
- (mapconcat 'identity
+ (mapconcat #'identity
(butlast (split-string current-defun "\\."))
- ".") ".")
+ ".")
+ ".")
name)))))))
(defun python-info-statement-starts-block-p ()
@@ -5072,7 +5079,7 @@ parent defun name."
(define-obsolete-function-alias
'python-info-closing-block
- 'python-info-dedenter-opening-block-position "24.4")
+ #'python-info-dedenter-opening-block-position "24.4")
(defun python-info-dedenter-opening-block-position ()
"Return the point of the closest block the current line closes.
@@ -5117,7 +5124,8 @@ likely an invalid python file."
(let ((indentation (current-indentation)))
(when (and (not (memq indentation collected-indentations))
(or (not collected-indentations)
- (< indentation (apply #'min collected-indentations)))
+ (< indentation
+ (apply #'min collected-indentations)))
;; There must be no line with indentation
;; smaller than `indentation' (except for
;; blank lines) between the found opening
@@ -5145,7 +5153,7 @@ likely an invalid python file."
(define-obsolete-function-alias
'python-info-closing-block-message
- 'python-info-dedenter-opening-block-message "24.4")
+ #'python-info-dedenter-opening-block-message "24.4")
(defun python-info-dedenter-opening-block-message ()
"Message the first line of the block the current statement closes."
@@ -5447,10 +5455,12 @@ allowed files."
(let ((dir-name (file-name-as-directory dir)))
(apply #'nconc
(mapcar (lambda (file-name)
- (let ((full-file-name (expand-file-name file-name dir-name)))
+ (let ((full-file-name
+ (expand-file-name file-name dir-name)))
(when (and
(not (member file-name '("." "..")))
- (funcall (or predicate #'identity) full-file-name))
+ (funcall (or predicate #'identity)
+ full-file-name))
(list full-file-name))))
(directory-files dir-name)))))
@@ -5518,7 +5528,6 @@ required arguments. Once launched it will receive the Python source to be
checked as its standard input.
To use `flake8' you would set this to (\"flake8\" \"-\")."
:version "26.1"
- :group 'python-flymake
:type '(repeat string))
;; The default regexp accommodates for older pyflakes, which did not
@@ -5540,7 +5549,6 @@ If COLUMN or TYPE are nil or that index didn't match, that
information is not present on the matched line and a default will
be used."
:version "26.1"
- :group 'python-flymake
:type '(list regexp
(integer :tag "Line's index")
(choice
@@ -5565,17 +5573,9 @@ configuration could be:
By default messages are considered errors."
:version "26.1"
- :group 'python-flymake
:type '(alist :key-type (regexp)
:value-type (symbol)))
-(defcustom python-forward-sexp-function #'python-nav-forward-sexp
- "Function to use when navigating between expressions."
- :version "28.1"
- :type '(choice (const :tag "Python blocks" python-nav-forward-sexp)
- (const :tag "CC-mode like" nil)
- function))
-
(defvar-local python--flymake-proc nil)
(defun python--flymake-parse-output (source proc report-fn)
diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el
index 72631a6557f..eb54ffe05a8 100644
--- a/lisp/progmodes/ruby-mode.el
+++ b/lisp/progmodes/ruby-mode.el
@@ -325,6 +325,13 @@ It is used when `ruby-encoding-magic-comment-style' is set to `custom'."
"Use `ruby-encoding-map' to set encoding magic comment if this is non-nil."
:type 'boolean :group 'ruby)
+(defcustom ruby-toggle-block-space-before-parameters t
+ "When non-nil, ensure space between the \"toggled\" curly and parameters.
+This only affects the output of the command `ruby-toggle-block'."
+ :type 'boolean
+ :safe 'booleanp
+ :version "29.1")
+
;;; SMIE support
(require 'smie)
@@ -1722,13 +1729,14 @@ See `add-log-current-defun-function'."
(insert "}")
(goto-char orig)
(delete-char 2)
- ;; Maybe this should be customizable, let's see if anyone asks.
- (insert "{ ")
- (setq beg-marker (point-marker))
- (when (looking-at "\\s +|")
- (delete-char (- (match-end 0) (match-beginning 0) 1))
- (forward-char)
- (re-search-forward "|" (line-end-position) t))
+ (insert "{")
+ (if (looking-at "\\s +|")
+ (progn
+ (just-one-space (if ruby-toggle-block-space-before-parameters 1 0))
+ (setq beg-marker (point-marker))
+ (forward-char)
+ (re-search-forward "|" (line-end-position) t))
+ (setq beg-marker (point-marker)))
(save-excursion
(skip-chars-forward " \t\n\r")
(setq beg-pos (point))
diff --git a/lisp/progmodes/scheme.el b/lisp/progmodes/scheme.el
index a2689f17705..592e2d50570 100644
--- a/lisp/progmodes/scheme.el
+++ b/lisp/progmodes/scheme.el
@@ -115,12 +115,53 @@
(define-abbrev-table 'scheme-mode-abbrev-table ())
(defvar scheme-imenu-generic-expression
- '((nil
- "^(define\\(?:-\\(?:generic\\(?:-procedure\\)?\\|method\\)\\)?\\s-+(?\\(\\sw+\\)" 1)
- ("Types"
- "^(define-class\\s-+(?\\(\\sw+\\)" 1)
- ("Macros"
- "^(\\(defmacro\\|define-macro\\|define-syntax\\)\\s-+(?\\(\\sw+\\)" 2))
+ `((nil
+ ,(rx bol "(define"
+ (zero-or-one "*")
+ (zero-or-one "-public")
+ (one-or-more space)
+ (zero-or-one "(")
+ (group (one-or-more (or word (syntax symbol)))))
+ 1)
+ ("Methods"
+ ,(rx bol "(define-"
+ (or "generic" "method" "accessor")
+ (one-or-more space)
+ (zero-or-one "(")
+ (group (one-or-more (or word (syntax symbol)))))
+ 1)
+ ("Classes"
+ ,(rx bol "(define-class"
+ (one-or-more space)
+ (zero-or-one "(")
+ (group (one-or-more (or word (syntax symbol)))))
+ 1)
+ ("Records"
+ ,(rx bol "(define-record-type"
+ (zero-or-one "*")
+ (one-or-more space)
+ (group (one-or-more (or word (syntax symbol)))))
+ 1)
+ ("Conditions"
+ ,(rx bol "(define-condition-type"
+ (one-or-more space)
+ (group (one-or-more (or word (syntax symbol)))))
+ 1)
+ ("Modules"
+ ,(rx bol "(define-module"
+ (one-or-more space)
+ (group "(" (one-or-more any) ")"))
+ 1)
+ ("Macros"
+ ,(rx bol "("
+ (or (and "defmacro"
+ (zero-or-one "*")
+ (zero-or-one "-public"))
+ "define-macro" "define-syntax" "define-syntax-rule")
+ (one-or-more space)
+ (zero-or-one "(")
+ (group (one-or-more (or word (syntax symbol)))))
+ 1))
"Imenu generic expression for Scheme mode. See `imenu-generic-expression'.")
(defun scheme-mode-variables ()
@@ -143,7 +184,6 @@
(setq-local comment-start-skip ";+[ \t]*")
(setq-local comment-use-syntax t)
(setq-local comment-column 40)
- (setq-local parse-sexp-ignore-comments t)
(setq-local lisp-indent-function 'scheme-indent-function)
(setq mode-line-process '("" scheme-mode-line-process))
(setq-local imenu-case-fold-search t)
diff --git a/lisp/progmodes/sh-script.el b/lisp/progmodes/sh-script.el
index 03313033dde..8dc55621438 100644
--- a/lisp/progmodes/sh-script.el
+++ b/lisp/progmodes/sh-script.el
@@ -402,45 +402,42 @@ This is buffer-local in every such buffer.")
(rpm . (,sh-mode-syntax-table ?\' ".")))
"Syntax-table used in Shell-Script mode. See `sh-feature'.")
-(defvar sh-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map "\C-c(" 'sh-function)
- (define-key map "\C-c\C-w" 'sh-while)
- (define-key map "\C-c\C-u" 'sh-until)
- (define-key map "\C-c\C-t" 'sh-tmp-file)
- (define-key map "\C-c\C-s" 'sh-select)
- (define-key map "\C-c\C-r" 'sh-repeat)
- (define-key map "\C-c\C-o" 'sh-while-getopts)
- (define-key map "\C-c\C-l" 'sh-indexed-loop)
- (define-key map "\C-c\C-i" 'sh-if)
- (define-key map "\C-c\C-f" 'sh-for)
- (define-key map "\C-c\C-c" 'sh-case)
- (define-key map "\C-c?" #'smie-config-show-indent)
- (define-key map "\C-c=" #'smie-config-set-indent)
- (define-key map "\C-c<" #'smie-config-set-indent)
- (define-key map "\C-c>" #'smie-config-guess)
- (define-key map "\C-c\C-\\" 'sh-backslash-region)
-
- (define-key map "\C-c+" 'sh-add)
- (define-key map "\C-\M-x" 'sh-execute-region)
- (define-key map "\C-c\C-x" 'executable-interpret)
- (define-key map "\C-c\C-n" 'sh-send-line-or-region-and-step)
- (define-key map "\C-c\C-d" 'sh-cd-here)
- (define-key map "\C-c\C-z" 'sh-show-shell)
-
- (define-key map [remap delete-backward-char]
- 'backward-delete-char-untabify)
- (define-key map "\C-c:" 'sh-set-shell)
- (define-key map [remap backward-sentence] 'sh-beginning-of-command)
- (define-key map [remap forward-sentence] 'sh-end-of-command)
- map)
- "Keymap used in Shell-Script mode.")
+(defvar-keymap sh-mode-map
+ :doc "Keymap used in Shell-Script mode."
+ "C-c (" #'sh-function
+ "C-c C-w" #'sh-while
+ "C-c C-u" #'sh-until
+ "C-c C-t" #'sh-tmp-file
+ "C-c C-s" #'sh-select
+ "C-c C-r" #'sh-repeat
+ "C-c C-o" #'sh-while-getopts
+ "C-c C-l" #'sh-indexed-loop
+ "C-c C-i" #'sh-if
+ "C-c C-f" #'sh-for
+ "C-c C-c" #'sh-case
+ "C-c ?" #'smie-config-show-indent
+ "C-c =" #'smie-config-set-indent
+ "C-c <" #'smie-config-set-indent
+ "C-c >" #'smie-config-guess
+ "C-c C-\\" #'sh-backslash-region
+
+ "C-c +" #'sh-add
+ "C-M-x" #'sh-execute-region
+ "C-c C-x" #'executable-interpret
+ "C-c C-n" #'sh-send-line-or-region-and-step
+ "C-c C-d" #'sh-cd-here
+ "C-c C-z" #'sh-show-shell
+ "C-c :" #'sh-set-shell
+
+ "<remap> <delete-backward-char>" #'backward-delete-char-untabify
+ "<remap> <backward-sentence>" #'sh-beginning-of-command
+ "<remap> <forward-sentence>" #'sh-end-of-command)
(easy-menu-define sh-mode-menu sh-mode-map
"Menu for Shell-Script mode."
'("Sh-Script"
["Backslash region" sh-backslash-region
- :help "Insert, align, or delete end-of-line backslashes on the lines in the region."]
+ :help "Insert, align, or delete end-of-line backslashes on the lines in the region"]
["Set shell type..." sh-set-shell
:help "Set this buffer's shell to SHELL (a string)"]
["Execute script..." executable-interpret
@@ -458,7 +455,7 @@ This is buffer-local in every such buffer.")
["Select Statement" sh-select
:help "Insert a select statement "]
["Indexed Loop" sh-indexed-loop
- :help "Insert an indexed loop from 1 to n."]
+ :help "Insert an indexed loop from 1 to n"]
["Options Loop" sh-while-getopts
:help "Insert a while getopts loop."]
["While Loop" sh-while
@@ -482,7 +479,7 @@ This is buffer-local in every such buffer.")
["Show indentation" smie-config-show-indent
:help "Show the how the current line would be indented"]
["Learn buffer indentation" smie-config-guess
- :help "Learn how to indent the buffer the way it currently is."]))
+ :help "Learn how to indent the buffer the way it currently is"]))
(defvar sh-skeleton-pair-default-alist '((?\( _ ?\)) (?\))
(?\[ ?\s _ ?\s ?\]) (?\])
@@ -628,7 +625,8 @@ removed when closing the here document."
(wksh sh-append ksh88)
(zsh sh-append ksh88
- "autoload" "bindkey" "builtin" "chdir" "compctl" "declare" "dirs"
+ "autoload" "always"
+ "bindkey" "builtin" "chdir" "compctl" "declare" "dirs"
"disable" "disown" "echotc" "enable" "functions" "getln" "hash"
"history" "integer" "limit" "local" "log" "popd" "pushd" "r"
"readonly" "rehash" "sched" "setopt" "source" "suspend" "true"
@@ -866,7 +864,7 @@ See `sh-feature'.")
"\\(?:\\(?:.*[^\\\n]\\)?\\(?:\\\\\\\\\\)*\\\\\n\\)*.*")
(defconst sh-here-doc-open-re
- (concat "[^<]<<-?\\s-*\\\\?\\(\\(?:['\"][^'\"]+['\"]\\|\\sw\\|[-/~._]\\)+\\)"
+ (concat "[^<]<<-?\\s-*\\\\?\\(\\(?:['\"][^'\"]+['\"]\\|\\sw\\|[-/~._@]\\)+\\)"
sh-escaped-line-re "\\(\n\\)")))
(defun sh--inside-noncommand-expression (pos)
@@ -1409,7 +1407,7 @@ If FORCE is non-nil and no process found, create one."
(defun sh-show-shell ()
"Pop the shell interaction buffer."
(interactive)
- (pop-to-buffer (process-buffer (sh-shell-process t))))
+ (pop-to-buffer (process-buffer (sh-shell-process t)) display-comint-buffer-action))
(defun sh-send-text (text)
"Send the text to the `sh-shell-process'."
@@ -1604,7 +1602,7 @@ This adds rules for comments and assignments."
;;; Completion
-(defvar sh--completion-keywords '("if" "while" "until" "for"))
+(defvar sh--completion-keywords '("if" "while" "until" "for" "then"))
(defun sh--vars-before-point ()
(save-excursion
@@ -1776,21 +1774,27 @@ Does not preserve point."
(n (skip-syntax-backward ".")))
(if (or (zerop n)
(and (eq n -1)
+ ;; Skip past quoted white space.
(let ((p (point)))
(if (eq -1 (% (skip-syntax-backward "\\") 2))
t
(goto-char p)
nil))))
(while
- (progn (skip-syntax-backward ".w_'")
- (or (not (zerop (skip-syntax-backward "\\")))
- (when (eq ?\\ (char-before (1- (point))))
- (let ((p (point)))
- (forward-char -1)
- (if (eq -1 (% (skip-syntax-backward "\\") 2))
- t
- (goto-char p)
- nil))))))
+ (progn
+ ;; Skip past words, but stop at semicolons.
+ (while (and (not (zerop (skip-syntax-backward "w_'")))
+ (not (eq (char-before (point)) ?\;))
+ (skip-syntax-backward ".")))
+ (or (not (zerop (skip-syntax-backward "\\")))
+ ;; Skip past quoted white space.
+ (when (eq ?\\ (char-before (1- (point))))
+ (let ((p (point)))
+ (forward-char -1)
+ (if (eq -1 (% (skip-syntax-backward "\\") 2))
+ t
+ (goto-char p)
+ nil))))))
(goto-char (- (point) (% (skip-syntax-backward "\\") 2))))
(buffer-substring-no-properties (point) pos)))
@@ -1975,7 +1979,7 @@ May return nil if the line should not be treated as continued."
(cons 'column (smie-indent-keyword ";"))
(smie-rule-separator kind)))
(`(:after . ,(or ";;" ";&" ";;&"))
- (with-demoted-errors
+ (with-demoted-errors "SMIE rule error: %S"
(smie-backward-sexp token)
(cons 'column
(if (or (smie-rule-bolp)
diff --git a/lisp/progmodes/sql.el b/lisp/progmodes/sql.el
index 6183aee20e3..69d16a4357e 100644
--- a/lisp/progmodes/sql.el
+++ b/lisp/progmodes/sql.el
@@ -481,9 +481,9 @@ file. Since that is a plaintext file, this could be dangerous."
:list-all ("\\d+" . "\\dS+")
:list-table ("\\d+ %s" . "\\dS+ %s")
:completion-object sql-postgres-completion-object
- :prompt-regexp "^[[:alnum:]_]*=[#>] "
+ :prompt-regexp "^[-[:alnum:]_]*[-=][#>] "
:prompt-length 5
- :prompt-cont-regexp "^[[:alnum:]_]*[-(][#>] "
+ :prompt-cont-regexp "^[-[:alnum:]_]*[-'(][#>] "
:statement sql-postgres-statement-starters
:input-filter sql-remove-tabs-filter
:terminator ("\\(^\\s-*\\\\g\\|;\\)" . "\\g"))
@@ -700,8 +700,17 @@ making new SQLi sessions."
(sexp :tag "Value Expression")))))
:version "24.1")
-(defvaralias 'sql-dialect 'sql-product)
+(defun sql-add-connection (connection params)
+ "Add a new connection to `sql-connection-alist'.
+If CONNECTION already exists, it is replaced with PARAMS."
+ (setq sql-connection-alist
+ (assoc-delete-all connection sql-connection-alist))
+ (push
+ (cons connection params)
+ sql-connection-alist))
+
+(defvaralias 'sql-dialect 'sql-product)
(defcustom sql-product 'ansi
"Select the SQL database product used.
This allows highlighting buffers properly when you open them."
@@ -963,12 +972,7 @@ If set to \"\\n\", each line in the history file will be interpreted as
one command. Multi-line commands are split into several commands when
the input ring is initialized from a history file.
-This variable used to initialize `comint-input-ring-separator'.
-`comint-input-ring-separator' is part of Emacs 21; if your Emacs
-does not have it, setting `sql-input-ring-separator' will have no
-effect. In that case multiline commands will be split into several
-commands when the input history is read, as if you had set
-`sql-input-ring-separator' to \"\\n\"."
+This variable used to initialize `comint-input-ring-separator'."
:type 'string)
;; The usual hooks
@@ -1357,8 +1361,6 @@ specified, it's `sql-product' or `sql-connection' must match."
(defvar sql-interactive-mode-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map comint-mode-map)
- (if (fboundp 'set-keymap-name)
- (set-keymap-name map 'sql-interactive-mode-map)); XEmacs
(define-key map (kbd "C-j") 'sql-accumulate-and-indent)
(define-key map (kbd "C-c C-w") 'sql-copy-column)
(define-key map (kbd "O") 'sql-magic-go)
@@ -2832,16 +2834,6 @@ configured."
(font-lock-mode-internal nil)
(font-lock-mode-internal t))
- (add-hook 'font-lock-mode-hook
- (lambda ()
- ;; Provide defaults for new font-lock faces.
- (defvar font-lock-builtin-face
- (if (boundp 'font-lock-preprocessor-face)
- font-lock-preprocessor-face
- font-lock-keyword-face))
- (defvar font-lock-doc-face font-lock-string-face))
- nil t)
-
;; Setup imenu; it needs the same syntax-alist.
(when imenu
(setq imenu-syntax-alist syntax-alist))))
@@ -3219,14 +3211,7 @@ For both `:file' and `:completion', there can also be a
symbol
(let* ((default (plist-get plist :default))
(last-value (sql-default-value symbol))
- (prompt-def
- (if default
- (if (string-match "\\(\\):[ \t]*\\'" prompt)
- (replace-match (format " (default \"%s\")" default) t t prompt 1)
- (replace-regexp-in-string "[ \t]*\\'"
- (format " (default \"%s\") " default)
- prompt t t))
- prompt))
+ (prompt-def (format-prompt prompt default))
(use-dialog-box nil))
(cond
((plist-member plist :file)
@@ -3311,7 +3296,7 @@ function like this: (sql-get-login \\='user \\='password \\='database)."
(let ((plist (cdr-safe w)))
(pcase (or (car-safe w) w)
('user
- (sql-get-login-ext 'sql-user "User: " 'sql-user-history plist))
+ (sql-get-login-ext 'sql-user "User" 'sql-user-history plist))
('password
(setq-default sql-password
@@ -3330,14 +3315,14 @@ function like this: (sql-get-login \\='user \\='password \\='database)."
(read-passwd "Password: " nil (sql-default-value 'sql-password)))))
('server
- (sql-get-login-ext 'sql-server "Server: " 'sql-server-history plist))
+ (sql-get-login-ext 'sql-server "Server" 'sql-server-history plist))
('database
(sql-get-login-ext 'sql-database "Database: "
'sql-database-history plist))
('port
- (sql-get-login-ext 'sql-port "Port: "
+ (sql-get-login-ext 'sql-port "Port"
nil (append '(:number t) plist)))))))
(defun sql-find-sqli-buffer (&optional product connection)
@@ -4182,10 +4167,6 @@ must tell Emacs. Here's how to do that in your init file:
(modify-syntax-entry ?\\\\ \"\\\\\" sql-mode-syntax-table)))"
:abbrev-table sql-mode-abbrev-table
- (when (and (featurep 'xemacs)
- sql-mode-menu)
- (easy-menu-add sql-mode-menu))
-
;; (smie-setup sql-smie-grammar #'sql-smie-rules)
(setq-local comment-start "--")
;; Make each buffer in sql-mode remember the "current" SQLi buffer.
@@ -4308,9 +4289,6 @@ you entered, right above the output it created.
(setq mode-name
(concat "SQLi[" (or (sql-get-product-feature sql-product :name)
(symbol-name sql-product)) "]"))
- (when (and (featurep 'xemacs)
- sql-interactive-mode-menu)
- (easy-menu-add sql-interactive-mode-menu))
;; Note that making KEYWORDS-ONLY nil will cause havoc if you try
;; SELECT 'x' FROM DUAL with SQL*Plus, because the title of the column
@@ -4681,6 +4659,14 @@ the call to \\[sql-product-interactive] with
(get-buffer new-sqli-buffer)))))
(user-error "No default SQL product defined: set `sql-product'")))
+(defun sql-comint-automatic-password (_)
+ "Intercept password prompts when we know the password.
+This must also do the job of detecting password prompts."
+ (when (and
+ sql-password
+ (not (string= "" sql-password)))
+ sql-password))
+
(defun sql-comint (product params &optional buf-name)
"Set up a comint buffer to run the SQL processor.
@@ -4705,6 +4691,13 @@ buffer. If nil, a name is chosen for it."
(setq buf-name (sql-generate-unique-sqli-buffer-name product nil)))
(set-text-properties 0 (length buf-name) nil buf-name)
+ ;; Create the buffer first, because we want to set it up before
+ ;; comint starts to run.
+ (set-buffer (get-buffer-create buf-name))
+ ;; Set up the automatic population of passwords, if supported.
+ (when (sql-get-product-feature product :password-in-comint)
+ (setq comint-password-function #'sql-comint-automatic-password))
+
;; Start the command interpreter in the buffer
;; PROC-NAME is BUF-NAME without enclosing asterisks
(let ((proc-name (replace-regexp-in-string "\\`[*]\\(.*\\)[*]\\'" "\\1" buf-name)))
diff --git a/lisp/progmodes/verilog-mode.el b/lisp/progmodes/verilog-mode.el
index b2ce9140573..edce3fef6cf 100644
--- a/lisp/progmodes/verilog-mode.el
+++ b/lisp/progmodes/verilog-mode.el
@@ -9,7 +9,7 @@
;; Keywords: languages
;; The "Version" is the date followed by the decimal rendition of the Git
;; commit hex.
-;; Version: 2021.09.23.089128420
+;; Version: 2021.10.14.127365406
;; Yoni Rabkin <yoni@rabkins.net> contacted the maintainer of this
;; file on 19/3/2008, and the maintainer agreed that when a bug is
@@ -124,7 +124,7 @@
;;
;; This variable will always hold the version number of the mode
-(defconst verilog-mode-version "2021-09-23-54ffde4-vpo-GNU"
+(defconst verilog-mode-version "2021-10-14-797711e-vpo-GNU"
"Version of this Verilog mode.")
(defconst verilog-mode-release-emacs t
"If non-nil, this version of Verilog mode was released with Emacs itself.")
@@ -1264,7 +1264,9 @@ See `verilog-auto-inst-param-value'."
Also affects AUTOINSTPARAM. Declaration order is the default for
backward compatibility, and as some teams prefer signals that are
declared together to remain together. Sorted order reduces
-changes when declarations are moved around in a file.
+changes when declarations are moved around in a file. Sorting is
+within input/output/inout groupings, there is intentionally no
+option to intermix between input/output/inouts.
See also `verilog-auto-arg-sort'."
:version "24.1" ; rev688
@@ -5478,8 +5480,11 @@ becomes:
(let* ((pop-up-windows t))
(let ((name (expand-file-name
(read-file-name
- (format "Find this error in: (default %s) "
- file)
+ ;; `format-prompt' is new in Emacs 28.1.
+ (if (fboundp 'format-prompt)
+ (format-prompt "Find this error in" file)
+ (format "Find this error in (default %s): "
+ file))
nil ;; dir
file t))))
(setq buffer
@@ -6598,7 +6603,8 @@ Also move point to constraint."
(equal (char-before) ?\;)
(equal (char-before) ?\}))
;; skip what looks like bus repetition operator {#{
- (not (string-match "^{\\s-*[\\(\\)0-9a-zA-Z_]*\\s-*{" (buffer-substring p (point)))))))))
+ (not (string-match "^{\\s-*[()0-9a-zA-Z_\\]*\\s-*{"
+ (buffer-substring p (point)))))))))
(progn
(let ( (pt (point)) (pass 0))
(verilog-backward-ws&directives)
@@ -7863,14 +7869,14 @@ If search fails, other files are checked based on
(let* ((default (verilog-get-default-symbol))
;; The following variable is used in verilog-comp-function
(verilog-buffer-to-use (current-buffer))
- (label (if (not (string= default ""))
- ;; Do completion with default
- (completing-read (concat "Goto-Label: (default "
- default ") ")
- #'verilog-comp-defun nil nil "")
- ;; There is no default value. Complete without it
- (completing-read "Goto-Label: "
- #'verilog-comp-defun nil nil "")))
+ (label
+ (completing-read (cond ((fboundp 'format-prompt)
+ ;; `format-prompt' is new in Emacs 28.1.
+ (format-prompt "Goto-Label" default))
+ ((not (string= default ""))
+ (concat "Goto-Label (default " default "): "))
+ (t "Goto-Label: "))
+ #'verilog-comp-defun nil nil ""))
pt)
;; Make sure library paths are correct, in case need to resolve module
(verilog-auto-reeval-locals)
diff --git a/lisp/progmodes/vhdl-mode.el b/lisp/progmodes/vhdl-mode.el
index 64ebc141670..c6693b4de53 100644
--- a/lisp/progmodes/vhdl-mode.el
+++ b/lisp/progmodes/vhdl-mode.el
@@ -10683,8 +10683,9 @@ Include a library specification, if not already there."
(replace-match "" t t)
(vhdl-template-insert-date))
(goto-char beg)
- (while (search-forward "<year>" end t)
- (replace-match (format-time-string "%Y" nil) t t))
+ (let ((year (format-time-string "%Y")))
+ (while (search-forward "<year>" end t)
+ (replace-match year t t)))
(goto-char beg)
(when file-title
(while (search-forward "<title string>" end t)
diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el
index 2fd5e192376..a5e6edf951d 100644
--- a/lisp/progmodes/xref.el
+++ b/lisp/progmodes/xref.el
@@ -1,7 +1,7 @@
;;; xref.el --- Cross-referencing commands -*-lexical-binding:t-*-
;; Copyright (C) 2014-2022 Free Software Foundation, Inc.
-;; Version: 1.3.0
+;; Version: 1.4.1
;; Package-Requires: ((emacs "26.1"))
;; This is a GNU ELPA :core package. Avoid functionality that is not
@@ -75,7 +75,7 @@
(require 'project)
(eval-and-compile
- (when (version< emacs-version "28")
+ (when (version< emacs-version "28.0.60")
;; etags.el in Emacs 26 and 27 uses EIEIO, and its location type
;; inherits from `xref-location'.
(require 'eieio)
@@ -195,9 +195,16 @@ is not known."
;;; Cross-reference
-(cl-defstruct (xref-item
- (:constructor xref-make (summary location))
- (:noinline t))
+(defmacro xref--defstruct (name &rest fields)
+ (declare (indent 1))
+ `(cl-defstruct ,(if (>= emacs-major-version 27)
+ name
+ (remq (assq :noinline name) name))
+ ,@fields))
+
+(xref--defstruct (xref-item
+ (:constructor xref-make (summary location))
+ (:noinline t))
"An xref item describes a reference to a location somewhere."
(summary nil :documentation "String which describes the location.
@@ -213,10 +220,10 @@ locations point to the same line.
This behavior is new in Emacs 28.")
location)
-(cl-defstruct (xref-match-item
- (:include xref-item)
- (:constructor xref-make-match (summary location length))
- (:noinline t))
+(xref--defstruct (xref-match-item
+ (:include xref-item)
+ (:constructor xref-make-match (summary location length))
+ (:noinline t))
"A match xref item describes a search result."
length)
@@ -346,15 +353,9 @@ backward."
(t (goto-char start) nil))))
-;;; Marker stack (M-. pushes, M-, pops)
-
-(defcustom xref-marker-ring-length 16
- "Length of the xref marker ring.
-If this variable is not set through Customize, you must call
-`xref-set-marker-ring-length' for changes to take effect."
- :type 'integer
- :initialize #'custom-initialize-default
- :set #'xref-set-marker-ring-length)
+;; Dummy variable retained for compatibility.
+(defvar xref-marker-ring-length 16)
+(make-obsolete-variable 'xref-marker-ring-length nil "29.1")
(defcustom xref-prompt-for-identifier '(not xref-find-definitions
xref-find-definitions-other-window
@@ -425,42 +426,77 @@ or earlier: it can break `dired-do-find-regexp-and-replace'."
:version "28.1"
:package-version '(xref . "1.2.0"))
-(defvar xref--marker-ring (make-ring xref-marker-ring-length)
- "Ring of markers to implement the marker stack.")
+(make-obsolete-variable 'xref--marker-ring 'xref--history "29.1")
+
+(defun xref-set-marker-ring-length (_var _val)
+ (declare (obsolete nil "29.1"))
+ nil)
-(defun xref-set-marker-ring-length (var val)
- "Set `xref-marker-ring-length'.
-VAR is the symbol `xref-marker-ring-length' and VAL is the new
-value."
- (set-default var val)
- (if (ring-p xref--marker-ring)
- (ring-resize xref--marker-ring val)))
+(defvar xref--history (cons nil nil)
+ "(BACKWARD-STACK . FORWARD-STACK) of markers to visited Xref locations.")
+
+(defun xref--push-backward (m)
+ "Push marker M onto the backward history stack."
+ (unless (equal m (caar xref--history))
+ (push m (car xref--history))))
+
+(defun xref--push-forward (m)
+ "Push marker M onto the forward history stack."
+ (unless (equal m (cadr xref--history))
+ (push m (cdr xref--history))))
(defun xref-push-marker-stack (&optional m)
- "Add point M (defaults to `point-marker') to the marker stack."
- (ring-insert xref--marker-ring (or m (point-marker))))
+ "Add point M (defaults to `point-marker') to the marker stack.
+The future stack is erased."
+ (xref--push-backward (or m (point-marker)))
+ (dolist (mk (cdr xref--history))
+ (set-marker mk nil nil))
+ (setcdr xref--history nil))
+
+;;;###autoload
+(define-obsolete-function-alias 'xref-pop-marker-stack #'xref-go-back "29.1")
+
+;;;###autoload
+(defun xref-go-back ()
+ "Go back to the previous position in xref history.
+To undo, use \\[xref-go-forward]."
+ (interactive)
+ (if (null (car xref--history))
+ (user-error "At start of xref history")
+ (let ((marker (pop (car xref--history))))
+ (xref--push-forward (point-marker))
+ (switch-to-buffer (or (marker-buffer marker)
+ (user-error "The marked buffer has been deleted")))
+ (goto-char (marker-position marker))
+ (set-marker marker nil nil)
+ (run-hooks 'xref-after-return-hook))))
;;;###autoload
-(defun xref-pop-marker-stack ()
- "Pop back to where \\[xref-find-definitions] was last invoked."
+(defun xref-go-forward ()
+ "Got to the point where a previous \\[xref-go-back] was invoked."
(interactive)
- (let ((ring xref--marker-ring))
- (when (ring-empty-p ring)
- (user-error "Marker stack is empty"))
- (let ((marker (ring-remove ring 0)))
+ (if (null (cdr xref--history))
+ (user-error "At end of xref history")
+ (let ((marker (pop (cdr xref--history))))
+ (xref--push-backward (point-marker))
(switch-to-buffer (or (marker-buffer marker)
(user-error "The marked buffer has been deleted")))
(goto-char (marker-position marker))
(set-marker marker nil nil)
(run-hooks 'xref-after-return-hook))))
-(defvar xref--current-item nil)
+(define-obsolete-variable-alias
+ 'xref--current-item
+ 'xref-current-item
+ "29.1")
+
+(defvar xref-current-item nil)
(defun xref-pulse-momentarily ()
(pcase-let ((`(,beg . ,end)
(save-excursion
(or
- (let ((length (xref-match-length xref--current-item)))
+ (let ((length (xref-match-length xref-current-item)))
(and length (cons (point) (+ (point) length))))
(back-to-indentation)
(if (eolp)
@@ -470,17 +506,23 @@ value."
;; etags.el needs this
(defun xref-clear-marker-stack ()
- "Discard all markers from the marker stack."
- (let ((ring xref--marker-ring))
- (while (not (ring-empty-p ring))
- (let ((marker (ring-remove ring)))
- (set-marker marker nil nil)))))
+ "Discard all markers from the xref history."
+ (dolist (l (list (car xref--history) (cdr xref--history)))
+ (dolist (m l)
+ (set-marker m nil nil)))
+ (setq xref--history (cons nil nil))
+ nil)
;;;###autoload
(defun xref-marker-stack-empty-p ()
- "Return t if the marker stack is empty; nil otherwise."
- (ring-empty-p xref--marker-ring))
+ "Whether the xref back-history is empty."
+ (null (car xref--history)))
+;; FIXME: rename this to `xref-back-history-empty-p'.
+;;;###autoload
+(defun xref-forward-history-empty-p ()
+ "Whether the xref forward-history is empty."
+ (null (cdr xref--history)))
(defun xref--goto-char (pos)
@@ -511,7 +553,7 @@ If SELECT is non-nil, select the target window."
(window (pop-to-buffer buf t))
(frame (let ((pop-up-frames t)) (pop-to-buffer buf t))))
(xref--goto-char marker))
- (let ((xref--current-item item))
+ (let ((xref-current-item item))
(run-hooks 'xref-after-jump-hook)))
@@ -619,7 +661,7 @@ SELECT is `quit', also quit the *xref* window."
"Display the source of xref at point in the appropriate window, if any."
(interactive)
(let* ((xref (xref--item-at-point))
- (xref--current-item xref))
+ (xref-current-item xref))
(when xref
(xref--set-arrow)
(xref--show-location (xref-item-location xref)))))
@@ -678,7 +720,7 @@ quit the *xref* buffer."
(let* ((buffer (current-buffer))
(xref (or (xref--item-at-point)
(user-error "Choose a reference to visit")))
- (xref--current-item xref))
+ (xref-current-item xref))
(xref--set-arrow)
(xref--show-location (xref-item-location xref) (if quit 'quit t))
(if (fboundp 'next-error-found)
@@ -695,17 +737,26 @@ quit the *xref* buffer."
"Quit *xref* buffer, then pop the xref marker stack."
(interactive)
(quit-window)
- (xref-pop-marker-stack))
+ (xref-go-back))
(defun xref-query-replace-in-results (from to)
"Perform interactive replacement of FROM with TO in all displayed xrefs.
This command interactively replaces FROM with TO in the names of the
-references displayed in the current *xref* buffer."
+references displayed in the current *xref* buffer.
+
+When called interactively, it uses '.*' as FROM, which means
+replace the whole name. Unless called with prefix argument, in
+which case the user is prompted for both FROM and TO."
(interactive
- (let ((fr (read-regexp "Xref query-replace (regexp)" ".*")))
- (list fr
- (read-regexp (format "Xref query-replace (regexp) %s with: " fr)))))
+ (let* ((fr
+ (if current-prefix-arg
+ (read-regexp "Query-replace (regexp)" ".*")
+ ".*"))
+ (prompt (if current-prefix-arg
+ (format "Query-replace (regexp) %s with: " fr)
+ "Query-replace all matches with: ")))
+ (list fr (read-regexp prompt))))
(let* (item xrefs iter)
(save-excursion
(while (setq item (xref--search-property 'xref-item))
@@ -899,7 +950,7 @@ beginning of the line."
(let ((win (get-buffer-window (current-buffer))))
(and win (set-window-point win (point))))
(xref--set-arrow)
- (let ((xref--current-item xref))
+ (let ((xref-current-item xref))
(xref--show-location (xref-item-location xref) t)))
(t
(error "No %s xref" (if backward "previous" "next"))))))
@@ -1056,6 +1107,13 @@ Return an alist of the form ((GROUP . (XREF ...)) ...)."
(cdr pair)))
alist)))
+(defun xref--ensure-default-directory (dd buffer)
+ ;; We might be in a let-binding which will restore the current value
+ ;; to a previous one (bug#53626). So do this later.
+ (run-with-timer
+ 0 nil
+ (lambda () (with-current-buffer buffer (setq default-directory dd)))))
+
(defun xref--show-xref-buffer (fetcher alist)
(cl-assert (functionp fetcher))
(let* ((xrefs
@@ -1066,7 +1124,7 @@ Return an alist of the form ((GROUP . (XREF ...)) ...)."
(dd default-directory)
buf)
(with-current-buffer (get-buffer-create xref-buffer-name)
- (setq default-directory dd)
+ (xref--ensure-default-directory dd (current-buffer))
(xref--xref-buffer-mode)
(xref--show-common-initialize xref-alist fetcher alist)
(pop-to-buffer (current-buffer))
@@ -1165,7 +1223,7 @@ local keymap that binds `RET' to `xref-quit-and-goto-xref'."
(assoc-default 'display-action alist)))
(t
(with-current-buffer (get-buffer-create xref-buffer-name)
- (setq default-directory dd)
+ (xref--ensure-default-directory dd (current-buffer))
(xref--transient-buffer-mode)
(xref--show-common-initialize (xref--analyze xrefs) fetcher alist)
(pop-to-buffer (current-buffer)
@@ -1289,6 +1347,13 @@ definitions."
(defvar xref--read-pattern-history nil)
+;;;###autoload
+(defun xref-show-xrefs (fetcher display-action)
+ "Display some Xref values produced by FETCHER using DISPLAY-ACTION.
+The meanings of both arguments are the same as documented in
+`xref-show-xrefs-function'."
+ (xref--show-xrefs fetcher display-action))
+
(defun xref--show-xrefs (fetcher display-action &optional _always-show-list)
(xref--push-markers)
(unless (functionp fetcher)
@@ -1334,12 +1399,17 @@ definitions."
(xref--prompt-p this-command))
(let ((id
(completing-read
- (if def
- (format "%s (default %s): "
- (substring prompt 0 (string-match
- "[ :]+\\'" prompt))
- def)
- prompt)
+ ;; `format-prompt' is new in Emacs 28.1
+ (if (fboundp 'format-prompt)
+ (format-prompt (substring prompt 0 (string-match
+ "[ :]+\\'" prompt))
+ def)
+ (if def
+ (format "%s (default %s): "
+ (substring prompt 0 (string-match
+ "[ :]+\\'" prompt))
+ def)
+ prompt))
(xref-backend-identifier-completion-table backend)
nil nil nil
'xref--read-identifier-history def)))
@@ -1400,7 +1470,7 @@ definition for IDENTIFIER, display it in the selected window.
Otherwise, display the list of the possible definitions in a
buffer where the user can select from the list.
-Use \\[xref-pop-marker-stack] to return back to where you invoked this command."
+Use \\[xref-go-back] to return back to where you invoked this command."
(interactive (list (xref--read-identifier "Find definitions of: ")))
(xref--find-definitions identifier nil))
@@ -1427,6 +1497,23 @@ is nil, prompt only if there's no usable symbol at point."
(interactive (list (xref--read-identifier "Find references of: ")))
(xref--find-xrefs identifier 'references identifier nil))
+(defun xref-find-references-and-replace (from to)
+ "Replace all references to identifier FROM with TO."
+ (interactive
+ (let* ((query-replace-read-from-default 'find-tag-default)
+ (common
+ (query-replace-read-args "Query replace identifier" nil)))
+ (list (nth 0 common) (nth 1 common))))
+ (require 'xref)
+ (with-current-buffer
+ (let ((xref-show-xrefs-function
+ ;; Some future-proofing (bug#44905).
+ (custom--standard-value 'xref-show-xrefs-function))
+ ;; Disable auto-jumping, it will mess up replacement logic.
+ xref-auto-jump-to-first-xref)
+ (xref-find-references from))
+ (xref-query-replace-in-results ".*" to)))
+
;;;###autoload
(defun xref-find-definitions-at-mouse (event)
"Find the definition of identifier at or around mouse click.
@@ -1491,7 +1578,8 @@ output of this command when the backend is etags."
;;; Key bindings
;;;###autoload (define-key esc-map "." #'xref-find-definitions)
-;;;###autoload (define-key esc-map "," #'xref-pop-marker-stack)
+;;;###autoload (define-key esc-map "," #'xref-go-back)
+;;;###autoload (define-key esc-map [?\C-,] #'xref-go-forward)
;;;###autoload (define-key esc-map "?" #'xref-find-references)
;;;###autoload (define-key esc-map [?\C-.] #'xref-find-apropos)
;;;###autoload (define-key ctl-x-4-map "." #'xref-find-definitions-other-window)
@@ -1835,21 +1923,22 @@ Such as the current syntax table and the applied syntax properties."
(defvar xref--last-file-buffer nil)
(defvar xref--temp-buffer-file-name nil)
+(defvar xref--hits-remote-id nil)
(defun xref--convert-hits (hits regexp)
(let (xref--last-file-buffer
(tmp-buffer (generate-new-buffer " *xref-temp*"))
- (remote-id (file-remote-p default-directory))
+ (xref--hits-remote-id (file-remote-p default-directory))
(syntax-needed (xref--regexp-syntax-dependent-p regexp)))
(unwind-protect
(mapcan (lambda (hit)
- (xref--collect-matches hit regexp tmp-buffer remote-id syntax-needed))
+ (xref--collect-matches hit regexp tmp-buffer syntax-needed))
hits)
(kill-buffer tmp-buffer))))
-(defun xref--collect-matches (hit regexp tmp-buffer remote-id syntax-needed)
+(defun xref--collect-matches (hit regexp tmp-buffer syntax-needed)
(pcase-let* ((`(,line ,file ,text) hit)
- (file (and file (concat remote-id file)))
+ (file (and file (concat xref--hits-remote-id file)))
(buf (xref--find-file-buffer file))
(inhibit-modification-hooks t))
(if buf
@@ -1922,10 +2011,17 @@ Such as the current syntax table and the applied syntax properties."
(defun xref--find-file-buffer (file)
(unless (equal (car xref--last-file-buffer) file)
- (setq xref--last-file-buffer
- ;; `find-buffer-visiting' is considerably slower,
- ;; especially on remote files.
- (cons file (get-file-buffer file))))
+ ;; `find-buffer-visiting' is considerably slower,
+ ;; especially on remote files.
+ (let ((buf (get-file-buffer file)))
+ (when (and buf
+ (or
+ (buffer-modified-p buf)
+ (unless xref--hits-remote-id
+ (not (verify-visited-file-modtime (current-buffer))))))
+ ;; We can't use buffers whose contents diverge from disk (bug#54025).
+ (setq buf nil))
+ (setq xref--last-file-buffer (cons file buf))))
(cdr xref--last-file-buffer))
(provide 'xref)
diff --git a/lisp/progmodes/xscheme.el b/lisp/progmodes/xscheme.el
index e6db65aced2..6e21131e4aa 100644
--- a/lisp/progmodes/xscheme.el
+++ b/lisp/progmodes/xscheme.el
@@ -574,9 +574,8 @@ See also the commands \\[xscheme-yank-pop] and \\[xscheme-yank-push]."
(if (consp arg)
(exchange-point-and-mark)))
-;; Old name, to avoid errors in users' init files.
-(fset 'xscheme-yank-previous-send
- 'xscheme-yank)
+(define-obsolete-function-alias 'xscheme-yank-previous-send
+ #'xscheme-yank "29.1")
(defun xscheme-yank-pop (arg)
"Insert or replace a just-yanked expression with an older expression.