diff options
Diffstat (limited to 'lisp/simple.el')
-rw-r--r-- | lisp/simple.el | 525 |
1 files changed, 349 insertions, 176 deletions
diff --git a/lisp/simple.el b/lisp/simple.el index 3ea00d44a03..b6d4e0603ee 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. @@ -516,7 +516,7 @@ This hook is run by `delete-selection-uses-region-p', which see.") "Propertized string representing a hard newline character.") (defun newline (&optional arg interactive) - "Insert a newline, and move to left margin of the new line if it's blank. + "Insert a newline, and move to left margin of the new line. With prefix argument ARG, insert that many newlines. If `electric-indent-mode' is enabled, this indents the final new line @@ -553,7 +553,7 @@ A non-nil INTERACTIVE argument means to run the `post-self-insert-hook'." (save-excursion (goto-char beforepos) (beginning-of-line) - (and (looking-at "[ \t]$") + (and (looking-at "[ \t]+$") (> (current-left-margin) 0) (delete-region (point) (line-end-position)))) @@ -1227,7 +1227,47 @@ that uses or sets the mark." ;; Counting lines, one way or another. -(defun goto-line (line &optional buffer) +(defvar goto-line-history nil + "History of values entered with `goto-line'.") +(make-variable-buffer-local 'goto-line-history) + +(defun goto-line-read-args (&optional relative) + "Read arguments for `goto-line' related commands." + (if (and current-prefix-arg (not (consp current-prefix-arg))) + (list (prefix-numeric-value current-prefix-arg)) + ;; Look for a default, a number in the buffer at point. + (let* ((default + (save-excursion + (skip-chars-backward "0-9") + (if (looking-at "[0-9]") + (string-to-number + (buffer-substring-no-properties + (point) + (progn (skip-chars-forward "0-9") + (point))))))) + ;; Decide if we're switching buffers. + (buffer + (if (consp current-prefix-arg) + (other-buffer (current-buffer) t))) + (buffer-prompt + (if buffer + (concat " in " (buffer-name buffer)) + ""))) + ;; Read the argument, offering that number (if any) as default. + (list (read-number (format "Goto%s line%s: " + (if (= (point-min) 1) "" + ;; In a narrowed buffer. + (if relative " relative" " absolute")) + buffer-prompt) + (list default (if (or relative (= (point-min) 1)) + (line-number-at-pos) + (save-restriction + (widen) + (line-number-at-pos)))) + 'goto-line-history) + buffer)))) + +(defun goto-line (line &optional buffer relative) "Go to LINE, counting from line 1 at beginning of buffer. If called interactively, a numeric prefix argument specifies LINE; without a numeric prefix argument, read LINE from the @@ -1237,6 +1277,13 @@ If optional argument BUFFER is non-nil, switch to that buffer and move to line LINE there. If called interactively with \\[universal-argument] as argument, BUFFER is the most recently selected other buffer. +If optional argument RELATIVE is non-nil, counting starts at the beginning +of the accessible portion of the (potentially narrowed) buffer. + +If the variable `widen-automatically' is non-nil, cancel narrowing and +leave all lines accessible. If `widen-automatically' is nil, just move +point to the edge of visible portion and don't change the buffer bounds. + Prior to moving point, this function sets the mark (without activating it), unless Transient Mark mode is enabled and the mark is already active. @@ -1248,31 +1295,7 @@ What you probably want instead is something like: If at all possible, an even better solution is to use char counts rather than line counts." (declare (interactive-only forward-line)) - (interactive - (if (and current-prefix-arg (not (consp current-prefix-arg))) - (list (prefix-numeric-value current-prefix-arg)) - ;; Look for a default, a number in the buffer at point. - (let* ((default - (save-excursion - (skip-chars-backward "0-9") - (if (looking-at "[0-9]") - (string-to-number - (buffer-substring-no-properties - (point) - (progn (skip-chars-forward "0-9") - (point))))))) - ;; Decide if we're switching buffers. - (buffer - (if (consp current-prefix-arg) - (other-buffer (current-buffer) t))) - (buffer-prompt - (if buffer - (concat " in " (buffer-name buffer)) - ""))) - ;; 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))) - buffer)))) + (interactive (goto-line-read-args)) ;; Switch to the desired buffer, one way or another. (if buffer (let ((window (get-buffer-window buffer))) @@ -1281,13 +1304,28 @@ rather than line counts." ;; Leave mark at previous position (or (region-active-p) (push-mark)) ;; Move to the specified line number in that buffer. - (save-restriction - (widen) + (if (and (not relative) (not widen-automatically)) + (save-restriction + (widen) + (goto-char (point-min)) + (if (eq selective-display t) + (re-search-forward "[\n\C-m]" nil 'end (1- line)) + (forward-line (1- line)))) + (unless relative (widen)) (goto-char (point-min)) (if (eq selective-display t) (re-search-forward "[\n\C-m]" nil 'end (1- line)) (forward-line (1- line))))) +(defun goto-line-relative (line &optional buffer) + "Go to LINE, counting from line at (point-min). +The line number is relative to the accessible portion of the narrowed +buffer. The argument BUFFER is the same as in the function `goto-line'." + (declare (interactive-only forward-line)) + (interactive (goto-line-read-args t)) + (with-suppressed-warnings ((interactive-only goto-line)) + (goto-line line buffer t))) + (defun count-words-region (start end &optional arg) "Count the number of words in the region. If called interactively, print a message reporting the number of @@ -1318,7 +1356,9 @@ If called from Lisp, return the number of words between START and END, without printing any message." (interactive (list nil nil)) (cond ((not (called-interactively-p 'any)) - (let ((words 0)) + (let ((words 0) + ;; Count across field boundaries. (Bug#41761) + (inhibit-field-text-motion t)) (save-excursion (save-restriction (narrow-to-region start end) @@ -1361,28 +1401,47 @@ END, without printing any message." (message "line %d (narrowed line %d)" (+ n (line-number-at-pos start) -1) n)))))) -(defun count-lines (start end) +(defun count-lines (start end &optional ignore-invisible-lines) "Return number of lines between START and END. -This is usually the number of newlines between them, -but can be one more if START is not equal to END -and the greater of them is not at the start of a line." +This is usually the number of newlines between them, but can be +one more if START is not equal to END and the greater of them is +not at the start of a line. + +When IGNORE-INVISIBLE-LINES is non-nil, invisible lines are not +included in the count." (save-excursion (save-restriction (narrow-to-region start end) (goto-char (point-min)) - (if (eq selective-display t) - (save-match-data - (let ((done 0)) - (while (re-search-forward "[\n\C-m]" nil t 40) - (setq done (+ 40 done))) - (while (re-search-forward "[\n\C-m]" nil t 1) - (setq done (+ 1 done))) - (goto-char (point-max)) - (if (and (/= start end) - (not (bolp))) - (1+ done) - done))) - (- (buffer-size) (forward-line (buffer-size))))))) + (cond ((and (not ignore-invisible-lines) + (eq selective-display t)) + (save-match-data + (let ((done 0)) + (while (re-search-forward "\n\\|\r[^\n]" nil t 40) + (setq done (+ 40 done))) + (while (re-search-forward "\n\\|\r[^\n]" nil t 1) + (setq done (+ 1 done))) + (goto-char (point-max)) + (if (and (/= start end) + (not (bolp))) + (1+ done) + done)))) + (ignore-invisible-lines + (save-match-data + (- (buffer-size) + (forward-line (buffer-size)) + (let ((invisible-count 0) + prop) + (goto-char (point-min)) + (while (re-search-forward "\n\\|\r[^\n]" nil t) + (setq prop (get-char-property (1- (point)) 'invisible)) + (if (if (eq buffer-invisibility-spec t) + prop + (or (memq prop buffer-invisibility-spec) + (assq prop buffer-invisibility-spec))) + (setq invisible-count (1+ invisible-count)))) + invisible-count)))) + (t (- (buffer-size) (forward-line (buffer-size)))))))) (defun line-number-at-pos (&optional pos absolute) "Return buffer line number at position POS. @@ -1474,7 +1533,11 @@ in *Help* buffer. See also the command `describe-char'." encoded encoding-msg display-prop under-display) (if (or (not coding) (eq (coding-system-type coding) t)) - (setq coding (default-value 'buffer-file-coding-system))) + (setq coding (or (default-value 'buffer-file-coding-system) + ;; A nil value of `buffer-file-coding-system' + ;; means "no conversion" which means each byte + ;; is a char and vice versa. + 'binary))) (if (eq (char-charset char) 'eight-bit) (setq encoding-msg (format "(%d, #o%o, #x%x%s, raw-byte)" char char char char-name-fmt)) @@ -1532,6 +1595,8 @@ in *Help* buffer. See also the command `describe-char'." ;; Might as well bind TAB to completion, since inserting a TAB char is ;; much too rarely useful. (define-key m "\t" 'completion-at-point) + (define-key m "\r" 'read--expression-try-read) + (define-key m "\n" 'read--expression-try-read) (set-keymap-parent m minibuffer-local-map) m)) @@ -1614,11 +1679,18 @@ display the result of expression evaluation." "Hook run by `eval-expression' when entering the minibuffer.") (defun read--expression (prompt &optional initial-contents) + "Read an Emacs Lisp expression from the minibuffer. + +PROMPT and optional argument INITIAL-CONTENTS do the same as in +function `read-from-minibuffer'." (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)) @@ -1626,6 +1698,45 @@ display the result of expression evaluation." read-expression-map t 'read-expression-history)))) +(defun read--expression-try-read () + "Try to read an Emacs Lisp expression in the minibuffer. + +Exit the minibuffer if successful, else report the error to the +user and move point to the location of the error. If point is +not already at the location of the error, push a mark before +moving point." + (interactive) + (unless (> (minibuffer-depth) 0) + (error "Minibuffer must be active")) + (if (let* ((contents (minibuffer-contents)) + (error-point nil)) + (with-temp-buffer + (condition-case err + (progn + (insert contents) + (goto-char (point-min)) + ;; `read' will signal errors like "End of file during + ;; parsing" and "Invalid read syntax". + (read (current-buffer)) + ;; Since `read' does not signal the "Trailing garbage + ;; following expression" error, we check for trailing + ;; garbage ourselves. + (or (progn + ;; This check is similar to what `string_to_object' + ;; does in minibuf.c. + (skip-chars-forward " \t\n") + (= (point) (point-max))) + (error "Trailing garbage following expression"))) + (error + (setq error-point (+ (length (minibuffer-prompt)) (point))) + (with-current-buffer (window-buffer (minibuffer-window)) + (unless (= (point) error-point) + (push-mark)) + (goto-char error-point) + (minibuffer-message (error-message-string err))) + nil)))) + (exit-minibuffer))) + (defun eval-expression-get-print-arguments (prefix-argument) "Get arguments for commands that print an expression result. Returns a list (INSERT-VALUE NO-TRUNCATE CHAR-PRINT-LIMIT) @@ -1773,9 +1884,15 @@ to get different commands to edit and resubmit." (lambda () ;; Get a command name at point in the original buffer ;; to propose it after M-n. - (with-current-buffer (window-buffer (minibuffer-selected-window)) - (and (commandp (function-called-at-point)) - (format "%S" (function-called-at-point))))))) + (let ((def (with-current-buffer + (window-buffer (minibuffer-selected-window)) + (and (commandp (function-called-at-point)) + (format "%S" (function-called-at-point))))) + (all (sort (minibuffer-default-add-completions) + #'string<))) + (if def + (cons def (delete def all)) + all))))) ;; Read a string, completing from and restricting to the set of ;; all defined commands. Don't provide any initial input. ;; Save the command read on the extended-command history list. @@ -1797,23 +1914,34 @@ 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))) + (if (and suggest-key-bindings (eq action 'metadata)) + '(metadata + (annotation-function . read-extended-command--annotation) + (category . command)) (complete-with-action action obarray string pred))) #'commandp t nil 'extended-command-history))) +(defun read-extended-command--annotation (command-name) + (let* ((fun (and (stringp command-name) (intern-soft command-name))) + (binding (where-is-internal fun overriding-local-map t)) + (obsolete (get fun 'byte-obsolete-info)) + (alias (symbol-function fun))) + (cond ((symbolp alias) + (format " (%s)" alias)) + (obsolete + (format " (%s)" (car obsolete))) + ((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) @@ -1939,13 +2067,18 @@ invoking, give a prefix argument to `execute-extended-command'." ;; BEWARE: Called directly from the C code. "Execute CMD as an editor command. CMD must be a symbol that satisfies the `commandp' predicate. -Optional second arg RECORD-FLAG non-nil -means unconditionally put this command in the variable `command-history'. -Otherwise, that is done only if an arg is read using the minibuffer. -The argument KEYS specifies the value to use instead of (this-command-keys) -when reading the arguments; if it is nil, (this-command-keys) is used. -The argument SPECIAL, if non-nil, means that this command is executing -a special event, so ignore the prefix argument and don't clear it." + +Optional second arg RECORD-FLAG non-nil means unconditionally put +this command in the variable `command-history'. Otherwise, that +is done only if an arg is read using the minibuffer. + +The argument KEYS specifies the value to use instead of the +return value of the `this-command-keys' function when reading the +arguments; if it is nil, `this-command-keys' is used. + +The argument SPECIAL, if non-nil, means that this command is +executing a special event, so ignore the prefix argument and +don't clear it." (setq debug-on-next-call nil) (let ((prefixarg (unless special ;; FIXME: This should probably be done around @@ -2036,11 +2169,9 @@ See also `minibuffer-history-case-insensitive-variables'." (interactive (let* ((enable-recursive-minibuffers t) (regexp (read-from-minibuffer - (format "Previous element matching regexp%s: " - (if minibuffer-history-search-history - (format " (default %s)" - (car minibuffer-history-search-history)) - "")) + (format-prompt "Previous element matching regexp" + (and minibuffer-history-search-history + (car minibuffer-history-search-history))) nil minibuffer-local-map nil 'minibuffer-history-search-history (car minibuffer-history-search-history)))) @@ -2323,15 +2454,17 @@ previous element of the minibuffer history in the minibuffer." (goto-char (1- (minibuffer-prompt-end))) (current-column)))) (move-to-column old-column)) - ;; Put the cursor at the end of the visual line instead of the - ;; logical line, so the next `previous-line-or-history-element' - ;; would move to the previous history element, not to a possible upper - ;; visual line from the end of logical line in `line-move-visual' mode. - (end-of-visual-line) - ;; Since `end-of-visual-line' puts the cursor at the beginning - ;; of the next visual line, move it one char back to the end - ;; of the first visual line (bug#22544). - (unless (eolp) (backward-char 1))))))) + (if (not line-move-visual) ; Handle logical lines (bug#42862) + (end-of-line) + ;; Put the cursor at the end of the visual line instead of the + ;; logical line, so the next `previous-line-or-history-element' + ;; would move to the previous history element, not to a possible upper + ;; visual line from the end of logical line in `line-move-visual' mode. + (end-of-visual-line) + ;; Since `end-of-visual-line' puts the cursor at the beginning + ;; of the next visual line, move it one char back to the end + ;; of the first visual line (bug#22544). + (unless (eolp) (backward-char 1)))))))) (defun next-complete-history-element (n) "Get next history element that completes the minibuffer before the point. @@ -2528,6 +2661,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 +2701,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 +2791,26 @@ 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, i.e., redo the last ARG changes. +Interactively, ARG is the prefix numeric argument and defaults to 1." + (interactive "*p") + (cond + ((not (undo--last-change-was-undo-p buffer-undo-list)) + (user-error "No undone changes to redo")) + (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.") @@ -3329,6 +3482,14 @@ which is defined in the `warnings' library.\n") (setq buffer-undo-list nil) t)) +;;;; Shell commands + +(defconst shell-command-buffer-name "*Shell Command Output*" + "Name of the output buffer for shell commands.") + +(defconst shell-command-buffer-name-async "*Async Shell Command*" + "Name of the output buffer for asynchronous shell commands.") + (defvar shell-command-history nil "History list for some commands that read shell commands. @@ -3393,8 +3554,9 @@ to `shell-command-history'." (defcustom async-shell-command-buffer 'confirm-new-buffer "What to do when the output buffer is used by another shell command. This option specifies how to resolve the conflict where a new command -wants to direct its output to the buffer `*Async Shell Command*', -but this buffer is already taken by another running shell command. +wants to direct its output to the buffer whose name is stored +in `shell-command-buffer-name-async', but that buffer is already +taken by another running shell command. The value `confirm-kill-process' is used to ask for confirmation before killing the already running process and running a new process @@ -3545,14 +3707,18 @@ whose `car' is BUFFER." Like `shell-command', but adds `&' at the end of COMMAND to execute it asynchronously. -The output appears in the buffer `*Async Shell Command*'. -That buffer is in shell mode. +The output appears in the buffer whose name is stored in the +variable `shell-command-buffer-name-async'. That buffer is in +shell mode. You can configure `async-shell-command-buffer' to specify what to do -when the `*Async Shell Command*' buffer is already taken by another -running shell command. To run COMMAND without displaying the output -in a window you can configure `display-buffer-alist' to use the action -`display-buffer-no-window' for the buffer `*Async Shell Command*'. +when the buffer specified by `shell-command-buffer-name-async' is +already taken by another running shell command. + +To run COMMAND without displaying the output in a window you can +configure `display-buffer-alist' to use the action +`display-buffer-no-window' for the buffer given by +`shell-command-buffer-name-async'. In Elisp, you will often be better served by calling `start-process' directly, since it offers more control and does not impose the use of @@ -3588,16 +3754,18 @@ If `shell-command-prompt-show-cwd' is non-nil, show the current directory in the prompt. If COMMAND ends in `&', execute it asynchronously. -The output appears in the buffer `*Async Shell Command*'. -That buffer is in shell mode. You can also use -`async-shell-command' that automatically adds `&'. +The output appears in the buffer whose name is specified +by `shell-command-buffer-name-async'. That buffer is in shell +mode. You can also use `async-shell-command' that automatically +adds `&'. Otherwise, COMMAND is executed synchronously. The output appears in -the buffer `*Shell Command Output*'. If the output is short enough to -display in the echo area (which is determined by the variables -`resize-mini-windows' and `max-mini-window-height'), it is shown -there, but it is nonetheless available in buffer `*Shell Command -Output*' even though that buffer is not automatically displayed. +the buffer named by `shell-command-buffer-name'. If the output is +short enough to display in the echo area (which is determined by the +variables `resize-mini-windows' and `max-mini-window-height'), it is +shown there, but it is nonetheless available in buffer named by +`shell-command-buffer-name' even though that buffer is not +automatically displayed. To specify a coding system for converting non-ASCII characters in the shell command output, use \\[universal-coding-system-argument] \ @@ -3716,7 +3884,7 @@ impose the use of a shell (with its need to quote arguments)." (if (string-match "[ \t]*&[ \t]*\\'" command) ;; Command ending with ampersand means asynchronous. (let* ((buffer (get-buffer-create - (or output-buffer "*Async Shell Command*"))) + (or output-buffer shell-command-buffer-name-async))) (bname (buffer-name buffer)) (proc (get-buffer-process buffer)) (directory default-directory)) @@ -3868,9 +4036,9 @@ and are used only if a pop-up buffer is displayed." error-buffer display-error-buffer region-noncontiguous-p) "Execute string COMMAND in inferior shell with region as input. -Normally display output (if any) in temp buffer `*Shell Command Output*'; -Prefix arg means replace the region with it. Return the exit code of -COMMAND. +Normally display output (if any) in temp buffer specified +by `shell-command-buffer-name'; prefix arg means replace the region +with it. Return the exit code of COMMAND. To specify a coding system for converting non-ASCII characters in the input and output to the shell command, use \\[universal-coding-system-argument] @@ -3887,7 +4055,7 @@ in the echo area or in a buffer. If the output is short enough to display in the echo area \(determined by the variable `max-mini-window-height' if `resize-mini-windows' is non-nil), it is shown there. -Otherwise it is displayed in the buffer `*Shell Command Output*'. +Otherwise it is displayed in the buffer named by `shell-command-buffer-name'. The output is available in that buffer in both cases. If there is output and an error, a message about the error @@ -3897,7 +4065,7 @@ Optional fourth arg OUTPUT-BUFFER specifies where to put the command's output. If the value is a buffer or buffer name, erase that buffer and insert the output there; a non-nil value of `shell-command-dont-erase-buffer' prevent to erase the buffer. -If the value is nil, use the buffer `*Shell Command Output*'. +If the value is nil, use the buffer specified by `shell-command-buffer-name'. Any other non-nil value means to insert the output in the current buffer after START. @@ -3945,7 +4113,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 +4121,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-buffer-name)))) + (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))))) @@ -3970,7 +4153,7 @@ characters." (list t error-file) t))) ;; It is rude to delete a buffer that the command is not using. - ;; (let ((shell-buffer (get-buffer "*Shell Command Output*"))) + ;; (let ((shell-buffer (get-buffer shell-command-buffer-name))) ;; (and shell-buffer (not (eq shell-buffer (current-buffer))) ;; (kill-buffer shell-buffer))) ;; Don't muck with mark unless REPLACE says we should. @@ -3978,12 +4161,13 @@ characters." ;; No prefix argument: put the output in a temp buffer, ;; replacing its entire contents. (let ((buffer (get-buffer-create - (or output-buffer "*Shell Command Output*")))) + (or output-buffer shell-command-buffer-name)))) (set-buffer-major-mode buffer) ; Enable globalized modes (bug#38111) (unwind-protect (if (and (eq buffer (current-buffer)) (or (memq shell-command-dont-erase-buffer '(nil erase)) - (and (not (eq buffer (get-buffer "*Shell Command Output*"))) + (and (not (eq buffer (get-buffer + shell-command-buffer-name))) (not (region-active-p))))) ;; If the input is the same buffer as the output, ;; delete everything but the specified region, @@ -4118,6 +4302,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. @@ -4215,7 +4413,7 @@ Also, delete any process that is exited or signaled." ((thread-name (process-thread p))) (t "--"))) (cmd - (if (memq type '(network serial)) + (if (memq type '(network serial pipe)) (let ((contact (process-contact p t t))) (if (eq type 'network) (format "(%s %s)" @@ -5963,8 +6161,6 @@ Does not set point. Does nothing if mark ring is empty." (pop mark-ring)) (deactivate-mark)) -(define-obsolete-function-alias - 'exchange-dot-and-mark 'exchange-point-and-mark "23.3") (defun exchange-point-and-mark (&optional arg) "Put the mark where point is now, and point where the mark is now. This command works even when the mark is not active, @@ -6862,15 +7058,16 @@ rests." (setq done t))))))) (defun move-beginning-of-line (arg) - "Move point to beginning of current line as displayed. -\(If there's an image in the line, this disregards newlines -that are part of the text that the image rests on.) + "Move point to visible beginning of current logical line. +This disregards any invisible newline characters. With argument ARG not nil or 1, move forward ARG - 1 lines first. If point reaches the beginning or end of buffer, it stops there. \(But if the buffer doesn't end in a newline, it stops at the beginning of the last line.) -To ignore intangibility, bind `inhibit-point-motion-hooks' to t." + +To ignore intangibility, bind `inhibit-point-motion-hooks' to t. +For motion by visual lines, see `beginning-of-visual-line'." (interactive "^p") (or arg (setq arg 1)) @@ -7083,15 +7280,16 @@ Mode' for details." :lighter " Wrap" (if visual-line-mode (progn - (set (make-local-variable 'visual-line--saved-state) nil) - ;; Save the local values of some variables, to be restored if - ;; visual-line-mode is turned off. - (dolist (var '(line-move-visual truncate-lines - truncate-partial-width-windows - word-wrap fringe-indicator-alist)) - (if (local-variable-p var) - (push (cons var (symbol-value var)) - visual-line--saved-state))) + (unless visual-line--saved-state + (setq-local visual-line--saved-state (list nil)) + ;; Save the local values of some variables, to be restored if + ;; visual-line-mode is turned off. + (dolist (var '(line-move-visual truncate-lines + truncate-partial-width-windows + word-wrap fringe-indicator-alist)) + (if (local-variable-p var) + (push (cons var (symbol-value var)) + visual-line--saved-state)))) (set (make-local-variable 'line-move-visual) t) (set (make-local-variable 'truncate-partial-width-windows) nil) (setq truncate-lines nil @@ -7105,7 +7303,8 @@ Mode' for details." (kill-local-variable 'truncate-partial-width-windows) (kill-local-variable 'fringe-indicator-alist) (dolist (saved visual-line--saved-state) - (set (make-local-variable (car saved)) (cdr saved))) + (when (car saved) + (set (make-local-variable (car saved)) (cdr saved)))) (kill-local-variable 'visual-line--saved-state))) (defun turn-on-visual-line-mode () @@ -7650,11 +7849,17 @@ a specialization of overwrite mode, entered by setting the Line numbers do not appear for very large buffers and buffers with very long lines; see variables `line-number-display-limit' -and `line-number-display-limit-width'." +and `line-number-display-limit-width'. + +See `mode-line-position-line-format' for how this number is +presented." :init-value t :global t :group 'mode-line) (define-minor-mode column-number-mode - "Toggle column number display in the mode line (Column Number mode)." + "Toggle column number display in the mode line (Column Number mode). + +See `mode-line-position-column-format' for how this number is +presented." :global t :group 'mode-line) (define-minor-mode size-indication-mode @@ -8154,7 +8359,7 @@ makes it easier to edit it." (interactive (let* ((default-var (variable-at-point)) (var (if (custom-variable-p default-var) - (read-variable (format "Set variable (default %s): " default-var) + (read-variable (format-prompt "Set variable" default-var) default-var) (read-variable "Set variable: "))) (minibuffer-help-form `(describe-variable ',var)) @@ -8249,18 +8454,6 @@ Called with three arguments (BEG END TEXT), it should replace the text between BEG and END with TEXT. Expected to be set buffer-locally in the *Completions* buffer.") -(defvar completion-base-size nil - "Number of chars before point not involved in completion. -This is a local variable in the completion list buffer. -It refers to the chars in the minibuffer if completing in the -minibuffer, or in `completion-reference-buffer' otherwise. -Only characters in the field at point are included. - -If nil, Emacs determines which part of the tail end of the -buffer's text is involved in completion by comparing the text -directly.") -(make-obsolete-variable 'completion-base-size 'completion-base-position "23.2") - (defun delete-completion-window () "Delete the completion list window. Go to the window from which completion was requested." @@ -8314,7 +8507,6 @@ If EVENT, use EVENT's position to determine the starting position." (run-hooks 'mouse-leave-buffer-hook) (with-current-buffer (window-buffer (posn-window (event-start event))) (let ((buffer completion-reference-buffer) - (base-size completion-base-size) (base-position completion-base-position) (insert-function completion-list-insert-choice-function) (choice @@ -8341,10 +8533,6 @@ If EVENT, use EVENT's position to determine the starting position." (choose-completion-string choice buffer (or base-position - (when base-size - ;; Someone's using old completion code that doesn't know - ;; about base-position yet. - (list (+ base-size (field-beginning)))) ;; If all else fails, just guess. (list (choose-completion-guess-base-position choice))) insert-function))))) @@ -8372,10 +8560,6 @@ If EVENT, use EVENT's position to determine the starting position." (forward-char 1)) (point)))) -(defun choose-completion-delete-max-match (string) - (declare (obsolete choose-completion-guess-base-position "23.2")) - (delete-region (choose-completion-guess-base-position string) (point))) - (defvar choose-completion-string-functions nil "Functions that may override the normal insertion of a completion choice. These functions are called in order with three arguments: @@ -8404,13 +8588,6 @@ back on `completion-list-insert-choice-function' when nil." ;; unless it is reading a file name and CHOICE is a directory, ;; or completion-no-auto-exit is non-nil. - ;; Some older code may call us passing `base-size' instead of - ;; `base-position'. It's difficult to make any use of `base-size', - ;; so we just ignore it. - (unless (consp base-position) - (message "Obsolete `base-size' passed to choose-completion-string") - (setq base-position nil)) - (let* ((buffer (or buffer completion-reference-buffer)) (mini-p (minibufferp buffer))) ;; If BUFFER is a minibuffer, barf unless it's the currently @@ -8466,8 +8643,7 @@ Type \\<completion-list-mode-map>\\[choose-completion] in the completion list\ to select the completion near point. Or click to select one with the mouse. -\\{completion-list-mode-map}" - (set (make-local-variable 'completion-base-size) nil)) +\\{completion-list-mode-map}") (defun completion-list-mode-finish () "Finish setup of the completions buffer. @@ -8504,14 +8680,11 @@ Called from `temp-buffer-show-hook'." (if minibuffer-completing-file-name (file-name-as-directory (expand-file-name - (buffer-substring (minibuffer-prompt-end) - (- (point) (or completion-base-size 0)))))))) + (buffer-substring (minibuffer-prompt-end) (point))))))) (with-current-buffer standard-output - (let ((base-size completion-base-size) ;Read before killing localvars. - (base-position completion-base-position) + (let ((base-position completion-base-position) (insert-fun completion-list-insert-choice-function)) (completion-list-mode) - (set (make-local-variable 'completion-base-size) base-size) (set (make-local-variable 'completion-base-position) base-position) (set (make-local-variable 'completion-list-insert-choice-function) insert-fun)) |