From 6f496105e392af45c2248b4523ef19804837a8a6 Mon Sep 17 00:00:00 2001 From: Bob Rogers Date: Fri, 31 Mar 2023 09:57:32 +0200 Subject: [PATCH] Allow old input to include continuation lines in shell-mode * lisp/shell.el (shell-get-old-input-include-continuation-lines): New defcustom (default nil). (shell-get-old-input): New function. Like 'comint-get-old-input-default' but include all continuation lines if 'shell-get-old-input-include-continuation-lines' is non-nil. (shell-mode): Install shell-get-old-input. (Bug#61069) * etc/NEWS: Advertise the new defcustom. --- etc/NEWS | 8 ++++++++ lisp/shell.el | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/etc/NEWS b/etc/NEWS index f27cafb3d41..67e1a02d587 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -174,6 +174,14 @@ correctly unloads Eshell and all of its modules. After manually editing 'eshell-aliases-file', you can use this command to load the edited aliases. +** Shell Mode + ++++ +*** New user option 'shell-get-old-input-include-continuation-lines'. +When this user option is non-nil, 'shell-get-old-input' (C-RET) +includes multiple shell "\" continuation lines from command output. +Default is nil. + ** Prog Mode +++ diff --git a/lisp/shell.el b/lisp/shell.el index 5cf108bfa3b..b74442f1961 100644 --- a/lisp/shell.el +++ b/lisp/shell.el @@ -366,6 +366,12 @@ Useful for shells like zsh that has this feature." :group 'shell-directories :version "28.1") +(defcustom shell-get-old-input-include-continuation-lines nil + "Whether `shell-get-old-input' includes \"\\\" lines." + :type 'boolean + :group 'shell + :version "30.1") + (defcustom shell-kill-buffer-on-exit nil "Kill a shell buffer after the shell process terminates." :type 'boolean @@ -506,6 +512,39 @@ Useful for shells like zsh that has this feature." (push (mapconcat #'identity (nreverse arg) "") args))) (cons (nreverse args) (nreverse begins))))) +(defun shell-get-old-input () + "Default for `comint-get-old-input' in `shell-mode'. +If `comint-use-prompt-regexp' is nil, then either +return the current input field (if point is on an input field), or the +current line (if point is on an output field). +If `comint-use-prompt-regexp' is non-nil, then return +the current line, with any initial string matching the regexp +`comint-prompt-regexp' removed. +In either case, if `shell-get-old-input-include-continuation-lines' +is non-nil and the current line ends with a backslash, the next +line is also included and examined for a backslash, ending with a +final line without a backslash." + (let (field-prop bof) + (if (and (not comint-use-prompt-regexp) + ;; Make sure we're in an input rather than output field. + (not (setq field-prop (get-char-property + (setq bof (field-beginning)) 'field)))) + (field-string-no-properties bof) + (comint-bol) + (let ((start (point))) + (cond ((or comint-use-prompt-regexp + (eq field-prop 'output)) + (goto-char (line-end-position)) + (when shell-get-old-input-include-continuation-lines + ;; Include continuation lines as long as the current + ;; line ends with a backslash. + (while (and (not (eobp)) + (= (char-before) ?\\)) + (goto-char (line-end-position 2))))) + (t + (goto-char (field-end)))) + (buffer-substring-no-properties start (point)))))) + ;;;###autoload (defun split-string-shell-command (string) "Split STRING (a shell command) into a list of strings. @@ -642,6 +681,7 @@ command." (setq-local font-lock-defaults '(shell-font-lock-keywords t)) (setq-local shell-dirstack nil) (setq-local shell-last-dir nil) + (setq-local comint-get-old-input #'shell-get-old-input) ;; People expect Shell mode to keep the last line of output at ;; window bottom. (setq-local scroll-conservatively 101) -- 2.39.2