summaryrefslogtreecommitdiff
path: root/lisp/simple.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/simple.el')
-rw-r--r--lisp/simple.el119
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.