diff options
Diffstat (limited to 'lisp/simple.el')
-rw-r--r-- | lisp/simple.el | 119 |
1 files changed, 94 insertions, 25 deletions
diff --git a/lisp/simple.el b/lisp/simple.el index e4958de113e..2f92238e640 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -199,7 +199,7 @@ rejected, and the function returns nil." (and extra-test-inclusive (funcall extra-test-inclusive)))))) -(defcustom next-error-find-buffer-function #'next-error-buffer-unnavigated-current +(defcustom next-error-find-buffer-function #'ignore "Function called to find a `next-error' capable buffer. This functions takes the same three arguments as the function `next-error-find-buffer', and should return the buffer to be @@ -215,7 +215,7 @@ all other buffers." next-error-buffer-unnavigated-current) (function :tag "Other function")) :group 'next-error - :version "27.1") + :version "28.1") (defcustom next-error-found-function #'ignore "Function called when a next locus is found and displayed. @@ -1227,6 +1227,10 @@ that uses or sets the mark." ;; Counting lines, one way or another. +(defvar goto-line-history nil + "History of values entered with `goto-line'.") +(make-variable-buffer-local 'goto-line-history) + (defun goto-line (line &optional buffer) "Go to LINE, counting from line 1 at beginning of buffer. If called interactively, a numeric prefix argument specifies @@ -1271,7 +1275,8 @@ rather than line counts." ""))) ;; Read the argument, offering that number (if any) as default. (list (read-number (format "Goto line%s: " buffer-prompt) - (list default (line-number-at-pos))) + (list default (line-number-at-pos)) + 'goto-line-history) buffer)))) ;; Switch to the desired buffer, one way or another. (if buffer @@ -1617,8 +1622,11 @@ display the result of expression evaluation." (let ((minibuffer-completing-symbol t)) (minibuffer-with-setup-hook (lambda () - ;; FIXME: call emacs-lisp-mode (see also - ;; `eldoc--eval-expression-setup')? + ;; FIXME: instead of just applying the syntax table, maybe + ;; use a special major mode tailored to reading Lisp + ;; expressions from the minibuffer? (`emacs-lisp-mode' + ;; doesn't preserve the necessary keybindings.) + (set-syntax-table emacs-lisp-mode-syntax-table) (add-hook 'completion-at-point-functions #'elisp-completion-at-point nil t) (run-hooks 'eval-expression-minibuffer-setup-hook)) @@ -1797,23 +1805,36 @@ to get different commands to edit and resubmit." ;; and it serves as a shorthand for "Extended command: ". "M-x ") (lambda (string pred action) - (let ((pred - (if (memq action '(nil t)) - ;; Exclude obsolete commands from completions. - (lambda (sym) - (and (funcall pred sym) - (or (equal string (symbol-name sym)) - (not (get sym 'byte-obsolete-info))))) - pred))) - (complete-with-action action obarray string pred))) + (if (and suggest-key-bindings (eq action 'metadata)) + '(metadata + (annotation-function . read-extended-command--annotation) + (category . command)) + (let ((pred + (if (memq action '(nil t)) + ;; Exclude obsolete commands from completions. + (lambda (sym) + (and (funcall pred sym) + (or (equal string (symbol-name sym)) + (not (get sym 'byte-obsolete-info))))) + pred))) + (complete-with-action action obarray string pred)))) #'commandp t nil 'extended-command-history))) +(defun read-extended-command--annotation (command-name) + (let* ((function (and (stringp command-name) (intern-soft command-name))) + (binding (where-is-internal function overriding-local-map t))) + (when (and binding (not (stringp binding))) + (format " (%s)" (key-description binding))))) + (defcustom suggest-key-bindings t "Non-nil means show the equivalent key-binding when M-x command has one. The value can be a length of time to show the message for. If the value is non-nil and not a number, we wait 2 seconds. -Also see `extended-command-suggest-shorter'." +Also see `extended-command-suggest-shorter'. + +Equivalent key-bindings are also shown in the completion list of +M-x for all commands that have them." :group 'keyboard :type '(choice (const :tag "off" nil) (integer :tag "time" 2) @@ -2528,6 +2549,11 @@ A redo record for ordinary undo maps to the following (earlier) undo.") "Within a run of consecutive undo commands, list remaining to be undone. If t, we undid all the way to the end of it.") +(defun undo--last-change-was-undo-p (undo-list) + (while (and (consp undo-list) (eq (car undo-list) nil)) + (setq undo-list (cdr undo-list))) + (gethash undo-list undo-equiv-table)) + (defun undo (&optional arg) "Undo some previous changes. Repeat this command to undo more changes. @@ -2563,12 +2589,7 @@ as an argument limits undo to changes within the current region." (or (eq pending-undo-list t) ;; If something (a timer or filter?) changed the buffer ;; since the previous command, don't continue the undo seq. - (let ((list buffer-undo-list)) - (while (eq (car list) nil) - (setq list (cdr list))) - ;; If the last undo record made was made by undo - ;; it shows nothing else happened in between. - (gethash list undo-equiv-table)))) + (undo--last-change-was-undo-p buffer-undo-list))) (setq undo-in-region (and (or (region-active-p) (and arg (not (numberp arg)))) (not inhibit-region))) @@ -2658,6 +2679,25 @@ Contrary to `undo', this will not redo a previous undo." (interactive "*p") (let ((undo-no-redo t)) (undo arg))) +(defun undo-redo (&optional arg) + "Undo the last ARG undos." + (interactive "*p") + (cond + ((not (undo--last-change-was-undo-p buffer-undo-list)) + (user-error "No undo to undo")) + (t + (let* ((ul buffer-undo-list) + (new-ul + (let ((undo-in-progress t)) + (while (and (consp ul) (eq (car ul) nil)) + (setq ul (cdr ul))) + (primitive-undo arg ul))) + (new-pul (undo--last-change-was-undo-p new-ul))) + (message "Redo%s" (if undo-in-region " in region" "")) + (setq this-command 'undo) + (setq pending-undo-list new-pul) + (setq buffer-undo-list new-ul))))) + (defvar undo-in-progress nil "Non-nil while performing an undo. Some change-hooks test this variable to do something different.") @@ -3945,7 +3985,7 @@ characters." exit-status) ;; Unless a single contiguous chunk is selected, operate on multiple chunks. (if region-noncontiguous-p - (let ((input (concat (funcall region-extract-function 'delete) "\n")) + (let ((input (concat (funcall region-extract-function (when replace 'delete)) "\n")) output) (with-temp-buffer (insert input) @@ -3953,9 +3993,24 @@ characters." shell-file-name t t nil shell-command-switch command) - (setq output (split-string (buffer-string) "\n"))) - (goto-char start) - (funcall region-insert-function output)) + (setq output (split-string (buffer-substring + (point-min) + ;; Trim the trailing newline. + (if (eq (char-before (point-max)) ?\n) + (1- (point-max)) + (point-max))) + "\n"))) + (cond + (replace + (goto-char start) + (funcall region-insert-function output)) + (t + (let ((buffer (get-buffer-create + (or output-buffer "*Shell Command Output*")))) + (with-current-buffer buffer + (erase-buffer) + (funcall region-insert-function output)) + (display-message-or-buffer buffer))))) (if (or replace (and output-buffer (not (or (bufferp output-buffer) (stringp output-buffer))))) @@ -4118,6 +4173,20 @@ its behavior with respect to remote file attribute caching. You should only ever change this variable with a let-binding; never with `setq'.") +(defcustom process-file-return-signal-string nil + "Whether to return a string describing the signal interrupting a process. +When a process returns an exit code greater than 128, it is +interpreted as a signal. `process-file' requires to return a +string describing this signal. +Since there are processes violating this rule, returning exit +codes greater than 128 which are not bound to a signal, +`process-file' returns the exit code as natural number also in +this case. Setting this user option to non-nil forces +`process-file' to interpret such exit codes as signals, and to +return a corresponding string." + :version "28.1" + :type 'boolean) + (defun start-file-process (name buffer program &rest program-args) "Start a program in a subprocess. Return the process object for it. |