summaryrefslogtreecommitdiff
path: root/lisp/simple.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/simple.el')
-rw-r--r--lisp/simple.el678
1 files changed, 357 insertions, 321 deletions
diff --git a/lisp/simple.el b/lisp/simple.el
index a0f2da7152c..37f92540dde 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -37,28 +37,6 @@
(defvar compilation-current-error)
(defvar compilation-context-lines)
-(defcustom shell-command-dont-erase-buffer nil
- "If non-nil, output buffer is not erased between shell commands.
-Also, a non-nil value sets the point in the output buffer
-once the command completes.
-The value `beg-last-out' sets point at the beginning of the output,
-`end-last-out' sets point at the end of the buffer, `save-point'
-restores the buffer position before the command."
- :type '(choice
- (const :tag "Erase buffer" nil)
- (const :tag "Set point to beginning of last output" beg-last-out)
- (const :tag "Set point to end of last output" end-last-out)
- (const :tag "Save point" save-point))
- :group 'shell
- :version "26.1")
-
-(defvar shell-command-saved-pos nil
- "Record of point positions in output buffers after command completion.
-The value is an alist whose elements are of the form (BUFFER . POS),
-where BUFFER is the output buffer, and POS is the point position
-in BUFFER once the command finishes.
-This variable is used when `shell-command-dont-erase-buffer' is non-nil.")
-
(defcustom idle-update-delay 0.5
"Idle time delay before updating various things on the screen.
Various Emacs features that update auxiliary information when point moves
@@ -132,6 +110,15 @@ If non-nil, the value is passed directly to `recenter'."
:type 'hook
:group 'next-error)
+(defcustom next-error-verbosity nil
+ "If nil, `next-error' always outputs the current error buffer.
+If non-nil, the message is output only when the error buffer
+changes."
+ :group 'next-error
+ :type 'boolean
+ :safe #'booleanp
+ :version "27.1")
+
(defvar next-error-highlight-timer nil)
(defvar next-error-overlay-arrow-position nil)
@@ -144,6 +131,14 @@ A buffer becomes most recent when its compilation, grep, or
similar mode is started, or when it is used with \\[next-error]
or \\[compile-goto-error].")
+(defvar next-error-buffer nil
+ "The buffer-local value of the most recent `next-error' buffer.")
+;; next-error-buffer is made buffer-local to keep the reference
+;; to the parent buffer used to navigate to the current buffer, so the
+;; next call of next-buffer will use the same parent buffer to
+;; continue navigation from it.
+(make-variable-buffer-local 'next-error-buffer)
+
(defvar next-error-function nil
"Function to use to find the next error in the current buffer.
The function is called with 2 parameters:
@@ -191,6 +186,47 @@ rejected, and the function returns nil."
(and extra-test-inclusive
(funcall extra-test-inclusive))))))
+(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
+used by the subsequent invocation of the command `next-error'
+and `previous-error'.
+If the function returns nil, `next-error-find-buffer' will
+try to use the buffer it used previously, and failing that
+all other buffers."
+ :type '(choice (const :tag "No default" ignore)
+ (const :tag "Single next-error capable buffer on selected frame"
+ next-error-buffer-on-selected-frame)
+ (function :tag "Other function"))
+ :group 'next-error
+ :version "27.1")
+
+(defcustom next-error-found-function #'ignore
+ "Function called when a next locus is found and displayed.
+Function is called with two arguments: a FROM-BUFFER buffer
+from which next-error navigated, and a target buffer TO-BUFFER."
+ :type '(choice (const :tag "No default" ignore)
+ (function :tag "Other function"))
+ :group 'next-error
+ :version "27.1")
+
+(defun next-error-buffer-on-selected-frame (&optional _avoid-current
+ extra-test-inclusive
+ extra-test-exclusive)
+ "Return a single visible next-error buffer on the selected frame."
+ (let ((window-buffers
+ (delete-dups
+ (delq nil (mapcar (lambda (w)
+ (if (next-error-buffer-p
+ (window-buffer w)
+ t
+ extra-test-inclusive extra-test-exclusive)
+ (window-buffer w)))
+ (window-list))))))
+ (if (eq (length window-buffers) 1)
+ (car window-buffers))))
+
(defun next-error-find-buffer (&optional avoid-current
extra-test-inclusive
extra-test-exclusive)
@@ -207,28 +243,28 @@ The function EXTRA-TEST-EXCLUSIVE, if non-nil, is called in each buffer
that would normally be considered usable. If it returns nil,
that buffer is rejected."
(or
- ;; 1. If one window on the selected frame displays such buffer, return it.
- (let ((window-buffers
- (delete-dups
- (delq nil (mapcar (lambda (w)
- (if (next-error-buffer-p
- (window-buffer w)
- avoid-current
- extra-test-inclusive extra-test-exclusive)
- (window-buffer w)))
- (window-list))))))
- (if (eq (length window-buffers) 1)
- (car window-buffers)))
- ;; 2. If next-error-last-buffer is an acceptable buffer, use that.
+ ;; 1. If a customizable function returns a buffer, use it.
+ (funcall next-error-find-buffer-function avoid-current
+ extra-test-inclusive
+ extra-test-exclusive)
+ ;; 2. If next-error-buffer has no buffer-local value
+ ;; (i.e. never navigated to the current buffer from another),
+ ;; and the current buffer is a `next-error' capable buffer,
+ ;; use it unconditionally, so next-error will always use it.
+ (if (and (not (local-variable-p 'next-error-buffer))
+ (next-error-buffer-p (current-buffer) avoid-current
+ extra-test-inclusive extra-test-exclusive))
+ (current-buffer))
+ ;; 3. If next-error-last-buffer is an acceptable buffer, use that.
(if (and next-error-last-buffer
(next-error-buffer-p next-error-last-buffer avoid-current
extra-test-inclusive extra-test-exclusive))
next-error-last-buffer)
- ;; 3. If the current buffer is acceptable, choose it.
+ ;; 4. If the current buffer is acceptable, choose it.
(if (next-error-buffer-p (current-buffer) avoid-current
extra-test-inclusive extra-test-exclusive)
(current-buffer))
- ;; 4. Look for any acceptable buffer.
+ ;; 5. Look for any acceptable buffer.
(let ((buffers (buffer-list)))
(while (and buffers
(not (next-error-buffer-p
@@ -236,7 +272,7 @@ that buffer is rejected."
extra-test-inclusive extra-test-exclusive)))
(setq buffers (cdr buffers)))
(car buffers))
- ;; 5. Use the current buffer as a last resort if it qualifies,
+ ;; 6. Use the current buffer as a last resort if it qualifies,
;; even despite AVOID-CURRENT.
(and avoid-current
(next-error-buffer-p (current-buffer) nil
@@ -244,7 +280,7 @@ that buffer is rejected."
(progn
(message "This is the only buffer with error message locations")
(current-buffer)))
- ;; 6. Give up.
+ ;; 7. Give up.
(error "No buffers contain error message locations")))
(defun next-error (&optional arg reset)
@@ -267,8 +303,9 @@ more generally, on any buffer in Compilation mode or with
Compilation Minor mode enabled, or any buffer in which
`next-error-function' is bound to an appropriate function.
To specify use of a particular buffer for error messages, type
-\\[next-error] in that buffer when it is the only one displayed
-in the current frame.
+\\[next-error] in that buffer. You can also use the command
+`next-error-select-buffer' to select the buffer to use for the subsequent
+invocation of `next-error'.
Once \\[next-error] has chosen the buffer for error messages, it
runs `next-error-hook' with `run-hooks', and stays with that buffer
@@ -279,23 +316,57 @@ To control which errors are matched, customize the variable
`compilation-error-regexp-alist'."
(interactive "P")
(if (consp arg) (setq reset t arg nil))
- (when (setq next-error-last-buffer (next-error-find-buffer))
- ;; we know here that next-error-function is a valid symbol we can funcall
- (with-current-buffer next-error-last-buffer
- (funcall next-error-function (prefix-numeric-value arg) reset)
- (when next-error-recenter
- (recenter next-error-recenter))
- (run-hooks 'next-error-hook))))
+ (let ((buffer (next-error-find-buffer)))
+ (when buffer
+ ;; We know here that next-error-function is a valid symbol we can funcall
+ (with-current-buffer buffer
+ (funcall next-error-function (prefix-numeric-value arg) reset)
+ (let ((prev next-error-last-buffer))
+ (next-error-found buffer (current-buffer))
+ (when (or (not next-error-verbosity)
+ (not (eq prev next-error-last-buffer)))
+ (message "%s locus from %s"
+ (cond (reset "First")
+ ((eq (prefix-numeric-value arg) 0) "Current")
+ ((< (prefix-numeric-value arg) 0) "Previous")
+ (t "Next"))
+ next-error-last-buffer)))))))
(defun next-error-internal ()
"Visit the source code corresponding to the `next-error' message at point."
- (setq next-error-last-buffer (current-buffer))
- ;; we know here that next-error-function is a valid symbol we can funcall
- (with-current-buffer next-error-last-buffer
+ (let ((buffer (current-buffer)))
+ ;; We know here that next-error-function is a valid symbol we can funcall
(funcall next-error-function 0 nil)
- (when next-error-recenter
- (recenter next-error-recenter))
- (run-hooks 'next-error-hook)))
+ (let ((prev next-error-last-buffer))
+ (next-error-found buffer (current-buffer))
+ (when (or (not next-error-verbosity)
+ (not (eq prev next-error-last-buffer)))
+ (message "Current locus from %s" next-error-last-buffer)))))
+
+(defun next-error-found (&optional from-buffer to-buffer)
+ "Function to call when the next locus is found and displayed.
+FROM-BUFFER is a buffer from which next-error navigated,
+and TO-BUFFER is a target buffer."
+ (setq next-error-last-buffer (or from-buffer (current-buffer)))
+ (when to-buffer
+ (with-current-buffer to-buffer
+ (setq next-error-buffer from-buffer)))
+ (when next-error-recenter
+ (recenter next-error-recenter))
+ (funcall next-error-found-function from-buffer to-buffer)
+ (run-hooks 'next-error-hook))
+
+(defun next-error-select-buffer (buffer)
+ "Select a `next-error' capable BUFFER and set it as the last used.
+This means that the selected buffer becomes the source of locations
+for the subsequent invocation of `next-error' or `previous-error'.
+Interactively, this command allows selection only among buffers
+where `next-error-function' is bound to an appropriate function."
+ (interactive
+ (list (get-buffer
+ (read-buffer "Select next-error buffer: " nil nil
+ (lambda (b) (next-error-buffer-p (cdr b)))))))
+ (setq next-error-last-buffer buffer))
(defalias 'goto-next-locus 'next-error)
(defalias 'next-match 'next-error)
@@ -306,7 +377,9 @@ To control which errors are matched, customize the variable
Prefix arg N says how many error messages to move backwards (or
forwards, if negative).
-This operates on the output from the \\[compile] and \\[grep] commands."
+This operates on the output from the \\[compile] and \\[grep] commands.
+
+See `next-error' for the details."
(interactive "p")
(next-error (- (or n 1))))
@@ -325,9 +398,11 @@ backwards, if negative).
Finds and highlights the source line like \\[next-error], but does not
select the source buffer."
(interactive "p")
- (let ((next-error-highlight next-error-highlight-no-select))
- (next-error n))
- (pop-to-buffer next-error-last-buffer))
+ (save-selected-window
+ (let ((next-error-highlight next-error-highlight-no-select)
+ (display-buffer-overriding-action
+ '(nil (inhibit-same-window . t))))
+ (next-error n))))
(defun previous-error-no-select (&optional n)
"Move point to the previous error in the `next-error' buffer and highlight match.
@@ -343,9 +418,7 @@ select the source buffer."
(define-minor-mode next-error-follow-minor-mode
"Minor mode for compilation, occur and diff modes.
-With a prefix argument ARG, enable mode if ARG is positive, and
-disable it otherwise. If called from Lisp, enable mode if ARG is
-omitted or nil.
+
When turned on, cursor motion in the compilation, grep, occur or diff
buffer causes automatic display of the corresponding source code location."
:group 'next-error :init-value nil :lighter " Fol"
@@ -535,25 +608,43 @@ When called from Lisp code, ARG may be a prefix string to copy."
(indent-to col 0)
(goto-char pos)))
-(defun delete-indentation (&optional arg)
+(defun delete-indentation (&optional arg beg end)
"Join this line to previous and fix up whitespace at join.
-If there is a fill prefix, delete it from the beginning of this line.
-With argument, join this line to following line."
- (interactive "*P")
- (beginning-of-line)
- (if arg (forward-line 1))
- (if (eq (preceding-char) ?\n)
- (progn
- (delete-region (point) (1- (point)))
- ;; If the second line started with the fill prefix,
- ;; delete the prefix.
- (if (and fill-prefix
- (<= (+ (point) (length fill-prefix)) (point-max))
- (string= fill-prefix
- (buffer-substring (point)
- (+ (point) (length fill-prefix)))))
- (delete-region (point) (+ (point) (length fill-prefix))))
- (fixup-whitespace))))
+If there is a fill prefix, delete it from the beginning of this
+line.
+With prefix ARG, join the current line to the following line.
+When BEG and END are non-nil, join all lines in the region they
+define. Interactively, BEG and END are, respectively, the start
+and end of the region if it is active, else nil. (The region is
+ignored if prefix ARG is given.)"
+ (interactive
+ (progn (barf-if-buffer-read-only)
+ (cons current-prefix-arg
+ (and (use-region-p)
+ (list (region-beginning) (region-end))))))
+ ;; Consistently deactivate mark even when no text is changed.
+ (setq deactivate-mark t)
+ (if (and beg (not arg))
+ ;; Region is active. Go to END, but only if region spans
+ ;; multiple lines.
+ (and (goto-char beg)
+ (> end (line-end-position))
+ (goto-char end))
+ ;; Region is inactive. Set a loop sentinel
+ ;; (subtracting 1 in order to compare less than BOB).
+ (setq beg (1- (line-beginning-position (and arg 2))))
+ (when arg (forward-line)))
+ (let ((prefix (and (> (length fill-prefix) 0)
+ (regexp-quote fill-prefix))))
+ (while (and (> (line-beginning-position) beg)
+ (forward-line 0)
+ (= (preceding-char) ?\n))
+ (delete-char -1)
+ ;; If the appended line started with the fill prefix,
+ ;; delete the prefix.
+ (if (and prefix (looking-at prefix))
+ (replace-match "" t t))
+ (fixup-whitespace))))
(defalias 'join-line #'delete-indentation) ; easier to find
@@ -1106,6 +1197,7 @@ the actual saved text might be different from what was killed."
(defun mark-whole-buffer ()
"Put point at beginning and mark at end of buffer.
+Also push mark at point before pushing mark at end of buffer.
If narrowing is in effect, only uses the accessible part of the buffer.
You probably should not use this function in Lisp programs;
it is usually a mistake for a Lisp function to use any subroutine
@@ -1356,7 +1448,7 @@ in *Help* buffer. See also the command `describe-char'."
(if (or (not coding)
(eq (coding-system-type coding) t))
(setq coding (default-value 'buffer-file-coding-system)))
- (if (and (>= char #x3fff80) (<= char #x3fffff))
+ (if (eq (char-charset char) 'eight-bit)
(setq encoding-msg
(format "(%d, #o%o, #x%x, raw-byte)" char char char))
;; Check if the character is displayed with some `display'
@@ -1554,7 +1646,7 @@ this command arranges for all errors to enter the debugger."
(eval-expression-get-print-arguments current-prefix-arg)))
(if (null eval-expression-debug-on-error)
- (push (eval exp lexical-binding) values)
+ (push (eval (macroexpand-all exp) lexical-binding) values)
(let ((old-value (make-symbol "t")) new-value)
;; Bind debug-on-error to something unique so that we can
;; detect when evalled code changes it.
@@ -1591,13 +1683,10 @@ the minibuffer, then read and evaluate the result."
'command-history)
;; If command was added to command-history as a string,
;; get rid of that. We want only evaluable expressions there.
- (if (stringp (car command-history))
- (setq command-history (cdr command-history)))))))
+ (when (stringp (car command-history))
+ (pop command-history))))))
- ;; If command to be redone does not match front of history,
- ;; add it to the history.
- (or (equal command (car command-history))
- (setq command-history (cons command command-history)))
+ (add-to-history 'command-history command)
(eval command)))
(defun repeat-complex-command (arg)
@@ -1627,13 +1716,10 @@ to get different commands to edit and resubmit."
;; If command was added to command-history as a
;; string, get rid of that. We want only
;; evaluable expressions there.
- (if (stringp (car command-history))
- (setq command-history (cdr command-history))))))
+ (when (stringp (car command-history))
+ (pop command-history)))))
- ;; If command to be redone does not match front of history,
- ;; add it to the history.
- (or (equal newcmd (car command-history))
- (setq command-history (cons newcmd command-history)))
+ (add-to-history 'command-history newcmd)
(apply #'funcall-interactively
(car newcmd)
(mapcar (lambda (e) (eval e t)) (cdr newcmd))))
@@ -1786,9 +1872,11 @@ invoking, give a prefix argument to `execute-extended-command'."
;; If this command displayed something in the echo area;
;; wait a few seconds, then display our suggestion message.
;; FIXME: Wait *after* running post-command-hook!
- ;; FIXME: Don't wait if execute-extended-command--shorter won't
- ;; find a better answer anyway!
- (when suggest-key-bindings
+ ;; FIXME: If execute-extended-command--shorter were
+ ;; faster, we could compute the result here first too.
+ (when (and suggest-key-bindings
+ (or binding
+ (and extended-command-suggest-shorter typed)))
(sit-for (cond
((zerop (length (current-message))) 0)
((numberp suggest-key-bindings) suggest-key-bindings)
@@ -1850,11 +1938,8 @@ a special event, so ignore the prefix argument and don't clear it."
;; If requested, place the macro in the command history. For
;; other sorts of commands, call-interactively takes care of this.
(when record-flag
- (push `(execute-kbd-macro ,final ,prefixarg) command-history)
- ;; Don't keep command history around forever.
- (when (and (numberp history-length) (> history-length 0))
- (let ((cell (nthcdr history-length command-history)))
- (if (consp cell) (setcdr cell nil)))))
+ (add-to-history
+ 'command-history `(execute-kbd-macro ,final ,prefixarg) nil t))
(execute-kbd-macro final prefixarg))
(t
;; Pass `cmd' rather than `final', for the backtrace's sake.
@@ -2958,7 +3043,7 @@ that calls `undo-auto-amalgamate'."
(defun undo-auto--ensure-boundary (cause)
"Add an `undo-boundary' to the current buffer if needed.
REASON describes the reason that the boundary is being added; see
-`undo-auto--last-boundary' for more information."
+`undo-auto--last-boundary-cause' for more information."
(when (and
(undo-auto--needs-boundary-p))
(let ((last-amalgamating
@@ -3007,10 +3092,10 @@ default values.")
"Add an `undo-boundary' in appropriate buffers."
(undo-auto--boundaries
(let ((amal undo-auto--this-command-amalgamating))
- (setq undo-auto--this-command-amalgamating nil)
- (if amal
- 'amalgamate
- 'command))))
+ (setq undo-auto--this-command-amalgamating nil)
+ (if amal
+ 'amalgamate
+ 'command))))
(defun undo-auto-amalgamate ()
"Amalgamate undo if necessary.
@@ -3023,30 +3108,38 @@ behavior."
(let ((last-amalgamating-count
(undo-auto--last-boundary-amalgamating-number)))
(setq undo-auto--this-command-amalgamating t)
- (when
- last-amalgamating-count
- (if
- (and
- (< last-amalgamating-count 20)
- (eq this-command last-command))
+ (when last-amalgamating-count
+ (if (and (< last-amalgamating-count 20)
+ (eq this-command last-command))
;; Amalgamate all buffers that have changed.
+ ;; This may be needed for example if some *-change-functions
+ ;; reflected these changes in some other buffer.
(dolist (b (cdr undo-auto--last-boundary-cause))
(when (buffer-live-p b)
(with-current-buffer
b
- (when
- ;; The head of `buffer-undo-list' is nil.
- ;; `car-safe' doesn't work because
- ;; `buffer-undo-list' need not be a list!
- (and (listp buffer-undo-list)
- (not (car buffer-undo-list)))
+ (when (and (consp buffer-undo-list)
+ ;; `car-safe' doesn't work because
+ ;; `buffer-undo-list' need not be a list!
+ (null (car buffer-undo-list)))
+ ;; The head of `buffer-undo-list' is nil.
(setq buffer-undo-list
(cdr buffer-undo-list))))))
(setq undo-auto--last-boundary-cause 0)))))
(defun undo-auto--undoable-change ()
"Called after every undoable buffer change."
- (add-to-list 'undo-auto--undoably-changed-buffers (current-buffer))
+ (unless (memq (current-buffer) undo-auto--undoably-changed-buffers)
+ (let ((bufs undo-auto--undoably-changed-buffers))
+ ;; Drop dead buffers from the list, to avoid memory leak in
+ ;; (while t (with-temp-buffer (setq buffer-undo-list nil) (insert "a")))
+ (while bufs
+ (let ((next (cdr bufs)))
+ (if (or (buffer-live-p (car bufs)) (null next))
+ (setq bufs next)
+ (setcar bufs (car next))
+ (setcdr bufs (cdr next))))))
+ (push (current-buffer) undo-auto--undoably-changed-buffers))
(undo-auto--boundary-ensure-timer))
;; End auto-boundary section
@@ -3159,61 +3252,6 @@ which is defined in the `warnings' library.\n")
(setq buffer-undo-list nil)
t))
-(defcustom password-word-equivalents
- '("password" "passcode" "passphrase" "pass phrase"
- ; These are sorted according to the GNU en_US locale.
- "암호" ; ko
- "パスワード" ; ja
- "ପ୍ରବେଶ ସଙ୍କେତ" ; or
- "ពាក្យសម្ងាត់" ; km
- "adgangskode" ; da
- "contraseña" ; es
- "contrasenya" ; ca
- "geslo" ; sl
- "hasło" ; pl
- "heslo" ; cs, sk
- "iphasiwedi" ; zu
- "jelszó" ; hu
- "lösenord" ; sv
- "lozinka" ; hr, sr
- "mật khẩu" ; vi
- "mot de passe" ; fr
- "parola" ; tr
- "pasahitza" ; eu
- "passord" ; nb
- "passwort" ; de
- "pasvorto" ; eo
- "salasana" ; fi
- "senha" ; pt
- "slaptažodis" ; lt
- "wachtwoord" ; nl
- "كلمة السر" ; ar
- "ססמה" ; he
- "лозинка" ; sr
- "пароль" ; kk, ru, uk
- "गुप्तशब्द" ; mr
- "शब्दकूट" ; hi
- "પાસવર્ડ" ; gu
- "సంకేతపదము" ; te
- "ਪਾਸਵਰਡ" ; pa
- "ಗುಪ್ತಪದ" ; kn
- "கடவுச்சொல்" ; ta
- "അടയാളവാക്ക്" ; ml
- "গুপ্তশব্দ" ; as
- "পাসওয়ার্ড" ; bn_IN
- "රහස්පදය" ; si
- "密码" ; zh_CN
- "密碼" ; zh_TW
- )
- "List of words equivalent to \"password\".
-This is used by Shell mode and other parts of Emacs to recognize
-password prompts, including prompts in languages other than
-English. Different case choices should not be assumed to be
-included; callers should bind `case-fold-search' to t."
- :type '(repeat string)
- :version "24.4"
- :group 'processes)
-
(defvar shell-command-history nil
"History list for some commands that read shell commands.
@@ -3313,6 +3351,28 @@ is output."
:group 'shell
:version "26.1")
+(defcustom shell-command-dont-erase-buffer nil
+ "If non-nil, output buffer is not erased between shell commands.
+Also, a non-nil value sets the point in the output buffer
+once the command completes.
+The value `beg-last-out' sets point at the beginning of the output,
+`end-last-out' sets point at the end of the buffer, `save-point'
+restores the buffer position before the command."
+ :type '(choice
+ (const :tag "Erase buffer" nil)
+ (const :tag "Set point to beginning of last output" beg-last-out)
+ (const :tag "Set point to end of last output" end-last-out)
+ (const :tag "Save point" save-point))
+ :group 'shell
+ :version "26.1")
+
+(defvar shell-command-saved-pos nil
+ "Record of point positions in output buffers after command completion.
+The value is an alist whose elements are of the form (BUFFER . POS),
+where BUFFER is the output buffer, and POS is the point position
+in BUFFER once the command finishes.
+This variable is used when `shell-command-dont-erase-buffer' is non-nil.")
+
(defun shell-command--save-pos-or-erase ()
"Store a buffer position or erase the buffer.
See `shell-command-dont-erase-buffer'."
@@ -3393,6 +3453,8 @@ a shell (with its need to quote arguments)."
(setq command (concat command " &")))
(shell-command command output-buffer error-buffer))
+(declare-function comint-output-filter "comint" (process string))
+
(defun shell-command (command &optional output-buffer error-buffer)
"Execute string COMMAND in inferior shell; display output, if any.
With prefix argument, insert the COMMAND's output at point.
@@ -3470,12 +3532,11 @@ impose the use of a shell (with its need to quote arguments)."
(not (or (bufferp output-buffer) (stringp output-buffer))))
;; Output goes in current buffer.
(let ((error-file
- (if error-buffer
- (make-temp-file
- (expand-file-name "scor"
- (or small-temporary-file-directory
- temporary-file-directory)))
- nil)))
+ (and error-buffer
+ (make-temp-file
+ (expand-file-name "scor"
+ (or small-temporary-file-directory
+ temporary-file-directory))))))
(barf-if-buffer-read-only)
(push-mark nil t)
;; We do not use -f for csh; we will not support broken use of
@@ -3483,24 +3544,22 @@ impose the use of a shell (with its need to quote arguments)."
;; "if ($?prompt) exit" before things which are not useful
;; non-interactively. Besides, if someone wants their other
;; aliases for shell commands then they can still have them.
- (call-process shell-file-name nil
- (if error-file
- (list t error-file)
- t)
- nil shell-command-switch command)
+ (call-process-shell-command command nil (if error-file
+ (list t error-file)
+ t))
(when (and error-file (file-exists-p error-file))
- (if (< 0 (nth 7 (file-attributes error-file)))
- (with-current-buffer (get-buffer-create error-buffer)
- (let ((pos-from-end (- (point-max) (point))))
- (or (bobp)
- (insert "\f\n"))
- ;; Do no formatting while reading error file,
- ;; because that can run a shell command, and we
- ;; don't want that to cause an infinite recursion.
- (format-insert-file error-file nil)
- ;; Put point after the inserted errors.
- (goto-char (- (point-max) pos-from-end)))
- (display-buffer (current-buffer))))
+ (when (< 0 (file-attribute-size (file-attributes error-file)))
+ (with-current-buffer (get-buffer-create error-buffer)
+ (let ((pos-from-end (- (point-max) (point))))
+ (or (bobp)
+ (insert "\f\n"))
+ ;; Do no formatting while reading error file,
+ ;; because that can run a shell command, and we
+ ;; don't want that to cause an infinite recursion.
+ (format-insert-file error-file nil)
+ ;; Put point after the inserted errors.
+ (goto-char (- (point-max) pos-from-end)))
+ (display-buffer (current-buffer))))
(delete-file error-file))
;; This is like exchange-point-and-mark, but doesn't
;; activate the mark. It is cleaner to avoid activation,
@@ -3519,12 +3578,11 @@ impose the use of a shell (with its need to quote arguments)."
(let* ((buffer (get-buffer-create
(or output-buffer "*Async Shell Command*")))
(bname (buffer-name buffer))
- (directory default-directory)
- proc)
+ (proc (get-buffer-process buffer))
+ (directory default-directory))
;; Remove the ampersand.
(setq command (substring command 0 (match-beginning 0)))
;; Ask the user what to do with already running process.
- (setq proc (get-buffer-process buffer))
(when proc
(cond
((eq async-shell-command-buffer 'confirm-kill-process)
@@ -3556,14 +3614,14 @@ impose the use of a shell (with its need to quote arguments)."
(with-current-buffer buffer
(shell-command--save-pos-or-erase)
(setq default-directory directory)
- (setq proc (start-process "Shell" buffer shell-file-name
- shell-command-switch command))
+ (setq proc
+ (start-process-shell-command "Shell" buffer command))
(setq mode-line-process '(":%s"))
(require 'shell) (shell-mode)
- (set-process-sentinel proc 'shell-command-sentinel)
+ (set-process-sentinel proc #'shell-command-sentinel)
;; Use the comint filter for proper handling of
;; carriage motion (see comint-inhibit-carriage-motion).
- (set-process-filter proc 'comint-output-filter)
+ (set-process-filter proc #'comint-output-filter)
(if async-shell-command-display-buffer
;; Display buffer immediately.
(display-buffer buffer '(nil (allow-no-window . t)))
@@ -3819,7 +3877,8 @@ interactively, this is t."
;; No output; error?
(let ((output
(if (and error-file
- (< 0 (nth 7 (file-attributes error-file))))
+ (< 0 (file-attribute-size
+ (file-attributes error-file))))
(format "some error output%s"
(if shell-command-default-error-buffer
(format " to the \"%s\" buffer"
@@ -3842,7 +3901,7 @@ interactively, this is t."
)))))
(when (and error-file (file-exists-p error-file))
- (if (< 0 (nth 7 (file-attributes error-file)))
+ (if (< 0 (file-attribute-size (file-attributes error-file)))
(with-current-buffer (get-buffer-create error-buffer)
(let ((pos-from-end (- (point-max) (point))))
(or (bobp)
@@ -3863,11 +3922,11 @@ interactively, this is t."
(with-output-to-string
(with-current-buffer
standard-output
- (process-file shell-file-name nil t nil shell-command-switch command))))
+ (shell-command command t))))
(defun process-file (program &optional infile buffer display &rest args)
"Process files synchronously in a separate process that runs PROGRAM.
-Similar to `call-process', but may invoke a file handler based on
+Similar to `call-process', but may invoke a file name handler based on
`default-directory'. The current working directory of the
subprocess is `default-directory'.
@@ -3877,10 +3936,10 @@ by `file-local-name' before passing it to this function.
File names in INFILE and BUFFER are handled normally, but file
names in ARGS should be relative to `default-directory', as they
are passed to the process verbatim. (This is a difference to
-`call-process' which does not support file handlers for INFILE
+`call-process' which does not support file name handlers for INFILE
and BUFFER.)
-Some file handlers might not support all variants, for example
+Some file name handlers might not support all variants, for example
they might behave as if DISPLAY was nil, regardless of the actual
value passed."
(let ((fh (find-file-name-handler default-directory 'process-file))
@@ -3904,7 +3963,7 @@ value passed."
By default, this variable is always set to t, meaning that a
call of `process-file' could potentially change any file on a
-remote host. When set to nil, a file handler could optimize
+remote host. When set to nil, a file name handler could optimize
its behavior with respect to remote file attribute caching.
You should only ever change this variable with a let-binding;
@@ -3913,7 +3972,7 @@ never with `setq'.")
(defun start-file-process (name buffer program &rest program-args)
"Start a program in a subprocess. Return the process object for it.
-Similar to `start-process', but may invoke a file handler based on
+Similar to `start-process', but may invoke a file name handler based on
`default-directory'. See Info node `(elisp)Magic File Names'.
This handler ought to run PROGRAM, perhaps on the local host,
@@ -3923,10 +3982,10 @@ produced from it by `file-local-name', becomes the working directory
of the process on the remote host.
PROGRAM and PROGRAM-ARGS might be file names. They are not
-objects of file handler invocation, so they need to be obtained
+objects of file name handler invocation, so they need to be obtained
by calling `file-local-name', in case they are remote file names.
-File handlers might not support pty association, if PROGRAM is nil."
+File name handlers might not support pty association, if PROGRAM is nil."
(let ((fh (find-file-name-handler default-directory 'start-file-process)))
(if fh (apply fh 'start-file-process name buffer program program-args)
(apply 'start-process name buffer program program-args))))
@@ -3952,8 +4011,11 @@ File handlers might not support pty association, if PROGRAM is nil."
(setq tabulated-list-format [("Process" 15 t)
("PID" 7 t)
("Status" 7 t)
- ("Buffer" 15 t)
+ ;; 25 is the length of the long standard buffer
+ ;; name "*Async Shell Command*<10>" (bug#30016)
+ ("Buffer" 25 t)
("TTY" 12 t)
+ ("Thread" 12 t)
("Command" 0 t)])
(make-local-variable 'process-menu-query-only)
(setq tabulated-list-sort-key (cons "Process" nil))
@@ -3995,6 +4057,13 @@ Also, delete any process that is exited or signaled."
action process-menu-visit-buffer)
"--"))
(tty (or (process-tty-name p) "--"))
+ (thread
+ (cond
+ ((or
+ (null (process-thread p))
+ (not (fboundp 'thread-name))) "--")
+ ((eq (process-thread p) main-thread) "Main")
+ ((thread-name (process-thread p)))))
(cmd
(if (memq type '(network serial))
(let ((contact (process-contact p t)))
@@ -4017,7 +4086,7 @@ Also, delete any process that is exited or signaled."
(format " at %s b/s" speed)
"")))))
(mapconcat 'identity (process-command p) " "))))
- (push (list p (vector name pid status buf-label tty cmd))
+ (push (list p (vector name pid status buf-label tty thread cmd))
tabulated-list-entries)))))
(tabulated-list-init-header))
@@ -4104,7 +4173,7 @@ Runs `prefix-command-preserve-state-hook'."
(when prefix-arg
(concat "C-u"
(pcase prefix-arg
- (`(-) " -")
+ ('(-) " -")
(`(,(and (pred integerp) n))
(let ((str ""))
(while (and (> n 4) (= (mod n 4) 0))
@@ -4386,7 +4455,8 @@ argument should still be a \"useful\" string for such uses."
(funcall interprogram-paste-function))))
(when interprogram-paste
(dolist (s (if (listp interprogram-paste)
- (nreverse interprogram-paste)
+ ;; Use `reverse' to avoid modifying external data.
+ (reverse interprogram-paste)
(list interprogram-paste)))
(unless (and kill-do-not-save-duplicates
(equal-including-properties s (car kill-ring)))
@@ -4395,9 +4465,8 @@ argument should still be a \"useful\" string for such uses."
(equal-including-properties string (car kill-ring)))
(if (and replace kill-ring)
(setcar kill-ring string)
- (push string kill-ring)
- (if (> (length kill-ring) kill-ring-max)
- (setcdr (nthcdr (1- kill-ring-max) kill-ring) nil))))
+ (let ((history-delete-duplicates nil))
+ (add-to-history 'kill-ring string kill-ring-max t))))
(setq kill-ring-yank-pointer kill-ring)
(if interprogram-cut-function
(funcall interprogram-cut-function string)))
@@ -4420,20 +4489,20 @@ If `interprogram-cut-function' is non-nil, call it with the
resulting kill.
If `kill-append-merge-undo' is non-nil, remove the last undo
boundary in the current buffer."
- (let* ((cur (car kill-ring)))
+ (let ((cur (car kill-ring)))
(kill-new (if before-p (concat string cur) (concat cur string))
- (or (= (length cur) 0)
- (equal nil (get-text-property 0 'yank-handler cur))))
- (when (and kill-append-merge-undo (not buffer-read-only))
- (let ((prev buffer-undo-list)
- (next (cdr buffer-undo-list)))
- ;; find the next undo boundary
- (while (car next)
- (pop next)
- (pop prev))
- ;; remove this undo boundary
- (when prev
- (setcdr prev (cdr next)))))))
+ (or (string= cur "")
+ (null (get-text-property 0 'yank-handler cur)))))
+ (when (and kill-append-merge-undo (not buffer-read-only))
+ (let ((prev buffer-undo-list)
+ (next (cdr buffer-undo-list)))
+ ;; Find the next undo boundary.
+ (while (car next)
+ (pop next)
+ (pop prev))
+ ;; Remove this undo boundary.
+ (when prev
+ (setcdr prev (cdr next))))))
(defcustom yank-pop-change-selection nil
"Whether rotating the kill ring changes the window system selection.
@@ -4467,9 +4536,13 @@ move the yanking point; just return the Nth kill forward."
;; Disable the interprogram cut function when we add the new
;; text to the kill ring, so Emacs doesn't try to own the
;; selection, with identical text.
- (let ((interprogram-cut-function nil))
+ ;; Also disable the interprogram paste function, so that
+ ;; `kill-new' doesn't call it repeatedly.
+ (let ((interprogram-cut-function nil)
+ (interprogram-paste-function nil))
(if (listp interprogram-paste)
- (mapc 'kill-new (nreverse interprogram-paste))
+ ;; Use `reverse' to avoid modifying external data.
+ (mapc #'kill-new (reverse interprogram-paste))
(kill-new interprogram-paste)))
(car kill-ring))
(or kill-ring (error "Kill ring is empty"))
@@ -5708,22 +5781,23 @@ Novice Emacs Lisp programmers often try to use the mark for the wrong
purposes. See the documentation of `set-mark' for more information.
In Transient Mark mode, activate mark if optional third arg ACTIVATE non-nil."
- (unless (null (mark t))
- (setq mark-ring (cons (copy-marker (mark-marker)) mark-ring))
- (when (> (length mark-ring) mark-ring-max)
- (move-marker (car (nthcdr mark-ring-max mark-ring)) nil)
- (setcdr (nthcdr (1- mark-ring-max) mark-ring) nil)))
+ (when (mark t)
+ (let ((old (nth mark-ring-max mark-ring))
+ (history-delete-duplicates nil))
+ (add-to-history 'mark-ring (copy-marker (mark-marker)) mark-ring-max t)
+ (when old
+ (set-marker old nil))))
(set-marker (mark-marker) (or location (point)) (current-buffer))
- ;; Now push the mark on the global mark ring.
- (if (and global-mark-ring
- (eq (marker-buffer (car global-mark-ring)) (current-buffer)))
- ;; The last global mark pushed was in this same buffer.
- ;; Don't push another one.
- nil
- (setq global-mark-ring (cons (copy-marker (mark-marker)) global-mark-ring))
- (when (> (length global-mark-ring) global-mark-ring-max)
- (move-marker (car (nthcdr global-mark-ring-max global-mark-ring)) nil)
- (setcdr (nthcdr (1- global-mark-ring-max) global-mark-ring) nil)))
+ ;; Don't push the mark on the global mark ring if the last global
+ ;; mark pushed was in this same buffer.
+ (unless (and global-mark-ring
+ (eq (marker-buffer (car global-mark-ring)) (current-buffer)))
+ (let ((old (nth global-mark-ring-max global-mark-ring))
+ (history-delete-duplicates nil))
+ (add-to-history
+ 'global-mark-ring (copy-marker (mark-marker)) global-mark-ring-max t)
+ (when old
+ (set-marker old nil))))
(or nomsg executing-kbd-macro (> (minibuffer-depth) 0)
(message "Mark set"))
(if (or activate (not transient-mark-mode))
@@ -5735,10 +5809,10 @@ In Transient Mark mode, activate mark if optional third arg ACTIVATE non-nil."
Does not set point. Does nothing if mark ring is empty."
(when mark-ring
(setq mark-ring (nconc mark-ring (list (copy-marker (mark-marker)))))
- (set-marker (mark-marker) (+ 0 (car mark-ring)) (current-buffer))
- (move-marker (car mark-ring) nil)
- (if (null (mark t)) (ding))
- (setq mark-ring (cdr mark-ring)))
+ (set-marker (mark-marker) (car mark-ring))
+ (set-marker (car mark-ring) nil)
+ (unless (mark t) (ding))
+ (pop mark-ring))
(deactivate-mark))
(define-obsolete-function-alias
@@ -5812,9 +5886,6 @@ its earlier value."
(define-minor-mode transient-mark-mode
"Toggle Transient Mark mode.
-With a prefix argument ARG, enable Transient Mark mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-Transient Mark mode if ARG is omitted or nil.
Transient Mark mode is a global minor mode. When enabled, the
region is highlighted with the `region' face whenever the mark
@@ -6849,12 +6920,6 @@ other purposes."
(define-minor-mode visual-line-mode
"Toggle visual line based editing (Visual Line mode) in the current buffer.
-Interactively, with a prefix argument, enable
-Visual Line mode if the prefix argument is positive,
-and disable it otherwise. If called from Lisp, toggle
-the mode if ARG is `toggle', disable the mode if ARG is
-a non-positive integer, and enable the mode otherwise
-\(including if ARG is omitted or nil or a positive integer).
When Visual Line mode is enabled, `word-wrap' is turned on in
this buffer, and simple editing commands are redefined to act on
@@ -7285,12 +7350,6 @@ Some major modes set this.")
(define-minor-mode auto-fill-mode
"Toggle automatic line breaking (Auto Fill mode).
-Interactively, with a prefix argument, enable
-Auto Fill mode if the prefix argument is positive,
-and disable it otherwise. If called from Lisp, toggle
-the mode if ARG is `toggle', disable the mode if ARG is
-a non-positive integer, and enable the mode otherwise
-\(including if ARG is omitted or nil or a positive integer).
When Auto Fill mode is enabled, inserting a space at a column
beyond `current-fill-column' automatically breaks the line at a
@@ -7405,9 +7464,6 @@ if long lines are truncated."
(define-minor-mode overwrite-mode
"Toggle Overwrite mode.
-With a prefix argument ARG, enable Overwrite mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil.
When Overwrite mode is enabled, printing characters typed in
replace existing text on a one-for-one basis, rather than pushing
@@ -7421,9 +7477,6 @@ characters when necessary."
(define-minor-mode binary-overwrite-mode
"Toggle Binary Overwrite mode.
-With a prefix argument ARG, enable Binary Overwrite mode if ARG
-is positive, and disable it otherwise. If called from Lisp,
-enable the mode if ARG is omitted or nil.
When Binary Overwrite mode is enabled, printing characters typed
in replace existing text. Newlines are not treated specially, so
@@ -7441,9 +7494,6 @@ a specialization of overwrite mode, entered by setting the
(define-minor-mode line-number-mode
"Toggle line number display in the mode line (Line Number mode).
-With a prefix argument ARG, enable Line Number mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil.
Line numbers do not appear for very large buffers and buffers
with very long lines; see variables `line-number-display-limit'
@@ -7451,27 +7501,15 @@ and `line-number-display-limit-width'."
: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).
-With a prefix argument ARG, enable Column Number mode if ARG is
-positive, and disable it otherwise.
-
-If called from Lisp, enable the mode if ARG is omitted or nil."
+ "Toggle column number display in the mode line (Column Number mode)."
:global t :group 'mode-line)
(define-minor-mode size-indication-mode
- "Toggle buffer size display in the mode line (Size Indication mode).
-With a prefix argument ARG, enable Size Indication mode if ARG is
-positive, and disable it otherwise.
-
-If called from Lisp, enable the mode if ARG is omitted or nil."
+ "Toggle buffer size display in the mode line (Size Indication mode)."
:global t :group 'mode-line)
(define-minor-mode auto-save-mode
- "Toggle auto-saving in the current buffer (Auto Save mode).
-With a prefix argument ARG, enable Auto Save mode if ARG is
-positive, and disable it otherwise.
-
-If called from Lisp, enable the mode if ARG is omitted or nil."
+ "Toggle auto-saving in the current buffer (Auto Save mode)."
:variable ((and buffer-auto-save-file-name
;; If auto-save is off because buffer has shrunk,
;; then toggling should turn it on.
@@ -7884,7 +7922,7 @@ buffer buried."
(eq mail-user-agent 'message-user-agent)
(let (warn-vars)
(dolist (var '(mail-mode-hook mail-send-hook mail-setup-hook
- mail-yank-hooks mail-archive-file-name
+ mail-citation-hook mail-archive-file-name
mail-default-reply-to mail-mailing-lists
mail-self-blind))
(and (boundp var)
@@ -7902,6 +7940,8 @@ To disable this warning, set `compose-mail-user-agent-warnings' to nil."
warn-vars " "))))))
(let ((function (get mail-user-agent 'composefunc)))
+ (unless function
+ (error "Invalid value for `mail-user-agent'"))
(funcall function to subject other-headers continue switch-function
yank-action send-actions return-action)))
@@ -8380,20 +8420,18 @@ LSHIFTBY is the numeric value of this modifier, in keyboard events.
PREFIX is the string that represents this modifier in an event type symbol."
(if (numberp event)
(cond ((eq symbol 'control)
- (if (and (<= (downcase event) ?z)
- (>= (downcase event) ?a))
- (- (downcase event) ?a -1)
- (if (and (<= (downcase event) ?Z)
- (>= (downcase event) ?A))
- (- (downcase event) ?A -1)
- (logior (lsh 1 lshiftby) event))))
+ (if (<= 64 (upcase event) 95)
+ (- (upcase event) 64)
+ (logior (ash 1 lshiftby) event)))
((eq symbol 'shift)
+ ;; FIXME: Should we also apply this "upcase" behavior of shift
+ ;; to non-ascii letters?
(if (and (<= (downcase event) ?z)
(>= (downcase event) ?a))
(upcase event)
- (logior (lsh 1 lshiftby) event)))
+ (logior (ash 1 lshiftby) event)))
(t
- (logior (lsh 1 lshiftby) event)))
+ (logior (ash 1 lshiftby) event)))
(if (memq symbol (event-modifiers event))
event
(let ((event-type (if (symbolp event) event (car event))))
@@ -8548,13 +8586,16 @@ after it has been set up properly in other respects."
;; Set up other local variables.
(mapc (lambda (v)
- (condition-case () ;in case var is read-only
+ (condition-case ()
(if (symbolp v)
(makunbound v)
(set (make-local-variable (car v)) (cdr v)))
- (error nil)))
+ (setting-constant nil))) ;E.g. for enable-multibyte-characters.
lvars)
+ (setq mark-ring (mapcar (lambda (mk) (copy-marker (marker-position mk)))
+ mark-ring))
+
;; Run any hooks (typically set up by the major mode
;; for cloning to work properly).
(run-hooks 'clone-buffer-hook))
@@ -8667,7 +8708,7 @@ call `normal-erase-is-backspace-mode' (which see) instead."
(and (not noninteractive)
(or (memq system-type '(ms-dos windows-nt))
(memq window-system '(w32 ns))
- (and (memq window-system '(x))
+ (and (eq window-system 'x)
(fboundp 'x-backspace-delete-keys-p)
(x-backspace-delete-keys-p))
;; If the terminal Emacs is running on has erase char
@@ -8678,11 +8719,10 @@ call `normal-erase-is-backspace-mode' (which see) instead."
normal-erase-is-backspace)
1 0)))))
+(declare-function display-symbol-keys-p "frame" (&optional display))
+
(define-minor-mode normal-erase-is-backspace-mode
"Toggle the Erase and Delete mode of the Backspace and Delete keys.
-With a prefix argument ARG, enable this feature if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil.
On window systems, when this mode is on, Delete is mapped to C-d
and Backspace is mapped to DEL; when this mode is off, both
@@ -8716,10 +8756,9 @@ See also `normal-erase-is-backspace'."
(let ((enabled (eq 1 (terminal-parameter
nil 'normal-erase-is-backspace))))
- (cond ((or (memq window-system '(x w32 ns pc))
- (memq system-type '(ms-dos windows-nt)))
+ (cond ((display-symbol-keys-p)
(let ((bindings
- `(([M-delete] [M-backspace])
+ '(([M-delete] [M-backspace])
([C-M-delete] [C-M-backspace])
([?\e C-delete] [?\e C-backspace]))))
@@ -8759,9 +8798,9 @@ See also `normal-erase-is-backspace'."
(define-minor-mode read-only-mode
"Change whether the current buffer is read-only.
-With prefix argument ARG, make the buffer read-only if ARG is
-positive, otherwise make it writable. If buffer is read-only
-and `view-read-only' is non-nil, enter view mode.
+
+If buffer is read-only and `view-read-only' is non-nil, enter
+view mode.
Do not call this from a Lisp program unless you really intend to
do the same thing as the \\[read-only-mode] command, including
@@ -8785,9 +8824,6 @@ to a non-nil value."
(define-minor-mode visible-mode
"Toggle making all invisible text temporarily visible (Visible mode).
-With a prefix argument ARG, enable Visible mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil.
This mode works by saving the value of `buffer-invisibility-spec'
and setting it to nil."
@@ -8979,7 +9015,7 @@ Otherwise, it calls `upcase-word', with prefix argument passed to it
to upcase ARG words."
(interactive "*p")
(if (use-region-p)
- (upcase-region (region-beginning) (region-end))
+ (upcase-region (region-beginning) (region-end) (region-noncontiguous-p))
(upcase-word arg)))
(defun downcase-dwim (arg)
@@ -8989,7 +9025,7 @@ Otherwise, it calls `downcase-word', with prefix argument passed to it
to downcase ARG words."
(interactive "*p")
(if (use-region-p)
- (downcase-region (region-beginning) (region-end))
+ (downcase-region (region-beginning) (region-end) (region-noncontiguous-p))
(downcase-word arg)))
(defun capitalize-dwim (arg)