Fix "C-u M-!" when 'shell-command-dont-erase-buffer' is non-nil

* lisp/simple.el (shell-command-dont-erase-buffer): Clarify the
effect of the various values in the doc string.
(shell-command-save-pos-or-erase, shell-command): Don't move or
push point if the output will go to the current buffer.
(Bug#40690)
(shell-command): Mention 'shell-command-dont-erase-buffer' in the
doc string.

* test/lisp/simple-tests.el
(with-shell-command-dont-erase-buffer): Don't is shell quoting
'like this', as it doesn't work on MS-Windows; quote "like this"
instead.
(simple-tests-shell-command-dont-erase-buffer): Adapt the test to
the new modus operandi.

* doc/emacs/misc.texi (Single Shell): Document the effect of the
various values of 'shell-command-dont-erase-buffer'.

* etc/NEWS: Expand and reword the entry regarding changes in
'shell-command-dont-erase-buffer'.
This commit is contained in:
Eli Zaretskii 2020-04-18 12:01:26 +03:00
parent 6b297519b5
commit 175c61c18b
4 changed files with 51 additions and 26 deletions

View file

@ -740,10 +740,11 @@ creates the file @file{foo} and produces no terminal output.
A numeric argument to @code{shell-command}, e.g., @kbd{M-1 M-!},
causes it to insert terminal output into the current buffer instead of
a separate buffer. It puts point before the output, and sets the mark
after the output. For instance, @kbd{M-1 M-! gunzip < foo.gz
@key{RET}} would insert the uncompressed form of the file
@file{foo.gz} into the current buffer.
a separate buffer. By default, it puts point before the output, and
sets the mark after the output (but a non-default value of
@code{shell-command-dont-erase-buffer} can change that, see below).
For instance, @kbd{M-1 M-! gunzip < foo.gz @key{RET}} would insert the
uncompressed form of the file @file{foo.gz} into the current buffer.
Provided the specified shell command does not end with @samp{&}, it
runs @dfn{synchronously}, and you must wait for it to exit before
@ -829,11 +830,21 @@ inserted into a buffer of that name.
By default, the output buffer is erased between shell commands, except
when the output goes to the current buffer. If you change the value
of the option @code{shell-command-dont-erase-buffer} to @code{erase},
then the output buffer is always erased. Any other non-@code{nil}
value prevents to erase the output buffer.
then the output buffer is always erased. Other non-@code{nil} values
prevent erasing of the output buffer, and---if the output buffer is
not the current buffer---also control where to put point after
inserting the output of the shell command:
This option also controls where to set the point in the output buffer
after the command completes; see the documentation of the option for details.
@table @code
@item beg-last-out
Puts point at the beginning of the last shell-command output.
@item end-last-out
Puts point at the end of the last shell-command output, i.e.@: at the
end of the output buffer.
@item save-point
Restores the position of point as it was before inserting the
shell-command output.
@end table
@node Interactive Shell
@subsection Interactive Subshell

View file

@ -2084,12 +2084,17 @@ variable for remote shells. It still defaults to "/bin/sh".
** Single shell commands
+++
*** 'shell-command-dont-erase-buffer' accepts the value 'erase' to
force to erase the output buffer before execution of the command.
*** New values of 'shell-command-dont-erase-buffer'.
This option can now have the value 'erase' to force to erase the
output buffer before execution of the command, even if the output goes
to the current buffer. Additional values 'beg-last-out',
'end-last-out', and 'save-point' control where to put point in the
output buffer after inserting the shell-command output.
---
*** The new functions 'shell-command-save-pos-or-erase' and
'shell-command-set-point-after-cmd' control how point is handled
between two consecutive shell commands in the same buffer.
between two consecutive shell commands in the same output buffer.
+++
*** 'async-shell-command-width' defines the number of display columns

View file

@ -3437,20 +3437,22 @@ This affects `shell-command' and `async-shell-command'."
:version "27.1")
(defcustom shell-command-dont-erase-buffer nil
"Control if the output buffer is erased before the command.
"Whether to erase the output buffer before executing shell command.
A nil value erases the output buffer before execution of the
shell command, except when the output buffer is the current one.
The value `erase' ensures the output buffer is erased before
execution of the shell command.
execution of the shell command even if it is the current buffer.
Other non-nil values prevent the output buffer from being erased and
set the point after execution of the shell command.
Other non-nil values prevent the output buffer from being erased; they
also reposition point in the shell output buffer after execution of the
shell command, except when the output buffer is the current buffer.
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."
The value `beg-last-out' sets point at the beginning of the last
output, `end-last-out' sets point at the end of the last output,
and `save-point' restores the buffer position as it was before the
shell command."
:type '(choice
(const :tag "Erase output buffer if not the current one" nil)
(const :tag "Always erase output buffer" erase)
@ -3480,9 +3482,12 @@ See `shell-command-dont-erase-buffer'."
;; if some text has a non-nil read-only property,
;; which comint sometimes adds for prompts.
(setq pos
(cond ((eq sym 'save-point) (point))
((eq sym 'beg-last-out) (point-max))
;;((not sym)
(cond ((eq sym 'save-point)
(if (not output-to-current-buffer)
(point)))
((eq sym 'beg-last-out)
(if (not output-to-current-buffer)
(point-max)))
((or (eq sym 'erase)
(and (null sym) (not output-to-current-buffer)))
(let ((inhibit-read-only t))
@ -3597,10 +3602,15 @@ says to put the output in some other buffer.
If OUTPUT-BUFFER is a buffer or buffer name, erase that buffer
and insert the output there; a non-nil value of
`shell-command-dont-erase-buffer' prevents the buffer from being
erased. If OUTPUT-BUFFER is not a buffer and not nil, insert the
erased. If OUTPUT-BUFFER is not a buffer and not nil (which happens
interactively when the prefix argument is given), insert the
output in current buffer after point leaving mark after it. This
cannot be done asynchronously.
The user option `shell-command-dont-erase-buffer', which see, controls
whether the output buffer is erased and where to put point after
the shell command.
If the command terminates without error, but generates output,
and you did not specify \"insert it in the current buffer\",
the output can be displayed in the echo area or in its buffer.
@ -3688,8 +3698,7 @@ impose the use of a shell (with its need to quote arguments)."
;; because we inserted text.
(goto-char (prog1 (mark t)
(set-marker (mark-marker) (point)
(current-buffer))))
(shell-command-set-point-after-cmd))
(current-buffer)))))
;; Output goes in a separate buffer.
;; Preserve the match data in case called from a program.
;; FIXME: It'd be ridiculous for an Elisp function to call

View file

@ -724,7 +724,7 @@ See Bug#21722."
(,output-buf (if ,output-buffer-is-current ,caller-buf
(generate-new-buffer "output-buf")))
(emacs (expand-file-name invocation-name invocation-directory))
(,command (format "%s -Q --batch --eval '(princ \"%s\")'"
(,command (format "%s -Q --batch --eval \"(princ \\\"%s\\\")\""
emacs ,str))
(inhibit-message t))
(unwind-protect
@ -761,7 +761,7 @@ See Bug#21722."
(expected-point `((beg-last-out . ,(1+ (length str)))
(end-last-out . ,(1+ (* 2 (length str))))
(save-point . 1))))
(dolist (output-buffer-is-current '(t ni))
(dolist (output-buffer-is-current '(nil))
(with-shell-command-dont-erase-buffer str output-buffer-is-current
(when (memq shell-command-dont-erase-buffer '(beg-last-out end-last-out save-point))
(should (= (point) (alist-get shell-command-dont-erase-buffer expected-point))))))))