]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix and improve behavior of 'eshell/clear'
authorJim Porter <jporterbugs@gmail.com>
Fri, 11 Oct 2024 04:03:45 +0000 (21:03 -0700)
committerEshel Yaron <me@eshelyaron.com>
Fri, 1 Nov 2024 13:21:25 +0000 (14:21 +0100)
* lisp/eshell/esh-mode.el (eshell-clear): New function.
(eshell/clear): Fix incorrect behavior, and do the right thing when
'eshell-scroll-show-maximum-output' is nil.
(eshell/clear-scrollback): Call 'eshell/clear'.

* test/lisp/eshell/esh-mode-tests.el
(esh-mode-test/clear/eshell-command)
(esh-mode-test/clear/eshell-command/erase)
(esh-mode-test/clear/emacs-command)
(esh-mode-test/clear/emacs-command/erase): New tests.

* etc/NEWS: Mention the new 'eshell-command' (bug#73722).

(cherry picked from commit 98e24e369a3f6bed95cdf0b32ee03999f5dfb98b)

etc/NEWS
lisp/eshell/esh-mode.el
test/lisp/eshell/esh-mode-tests.el

index 9f679fc5032326c4a7532c01fc2b1e1b2273c238..744fc429befcabba205c5c99f12980c3803f6a9c 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -192,6 +192,14 @@ It removes all the buttons in the specified region.
 
 ** Eshell
 
+---
+*** New interactive command 'eshell-clear'.
+This command scrolls the screen so that only the current prompt is
+visible, optionally erasing all the previous input/output as well.
+Previously, the Eshell built-in command 'eshell/clear' supported this
+(e.g. to call it via 'M-x'), but this new command behaves more
+consistently if you have a partially-typed command at the Eshell prompt.
+
 ---
 *** New user option 'eshell-command-async-buffer'.
 This option lets you tell 'eshell-command' how to respond if its output
index 37a88fce790a6bf8e4fe759c0d15d0b028276b74..c86e3cc002cfb9152dcdc6691935771de36b4987 100644 (file)
@@ -876,20 +876,61 @@ When run interactively, widen the buffer first."
   (goto-char (point-max))
   (recenter -1))
 
-(defun eshell/clear (&optional scrollback)
-  "Scroll contents of eshell window out of sight, leaving a blank window.
-If SCROLLBACK is non-nil, clear the scrollback contents."
+(defun eshell-clear (&optional clear-scrollback)
+  "Scroll contents of the Eshell window out of sight, leaving a blank window.
+If CLEAR-SCROLLBACK is non-nil (interactively, with the prefix
+argument), clear the scrollback contents.
+
+Otherwise, the behavior depends on `eshell-scroll-show-maximum-output'.
+If non-nil, fill newlines before the current prompt so that the prompt
+is the last line in the window; if nil, just scroll the window so that
+the prompt is the first line in the window."
+  (interactive "P")
+  (cond
+   (clear-scrollback
+    (let ((inhibit-read-only t))
+      (widen)
+      (delete-region (point-min) (eshell-end-of-output))))
+   (eshell-scroll-show-maximum-output
+    (save-excursion
+      (goto-char (eshell-end-of-output))
+      (let ((inhibit-read-only t))
+        (insert-and-inherit (make-string (window-size) ?\n))))
+    (when (< (point) eshell-last-output-end)
+      (goto-char eshell-last-output-end)))
+  (t
+   (when (< (point) eshell-last-output-end)
+     (goto-char eshell-last-output-end))
+   (set-window-start nil (eshell-end-of-output)))))
+
+(defun eshell/clear (&optional clear-scrollback)
+  "Scroll contents of the Eshell window out of sight, leaving a blank window.
+If CLEAR-SCROLLBACK is non-nil, clear the scrollback contents.
+
+Otherwise, the behavior depends on `eshell-scroll-show-maximum-output'.
+If non-nil, fill newlines before the current prompt so that the prompt
+is the last line in the window; if nil, just scroll the window so that
+the prompt is the first line in the window.
+
+This command is for use as an Eshell command (entered at the prompt);
+for clearing the Eshell buffer from elsewhere (e.g. via
+\\[execute-extended-command]), use `eshell-clear'."
   (interactive)
-  (if scrollback
-      (eshell/clear-scrollback)
+  (cond
+   ((null eshell-current-handles)
+    (eshell-clear clear-scrollback))
+   (clear-scrollback
+    (let ((inhibit-read-only t))
+      (erase-buffer)))
+   (eshell-scroll-show-maximum-output
     (let ((eshell-input-filter-functions nil))
-      (insert (make-string (window-size) ?\n))
-      (eshell-send-input))))
+      (ignore (eshell-interactive-print (make-string (window-size) ?\n)))))
+   (t
+    (recenter 0))))
 
 (defun eshell/clear-scrollback ()
-  "Clear the scrollback content of the eshell window."
-  (let ((inhibit-read-only t))
-    (erase-buffer)))
+  "Clear the scrollback content of the Eshell window."
+  (eshell/clear t))
 
 (defun eshell-get-old-input (&optional use-current-region)
   "Return the command input on the current line.
index 306e11ce4455d5ef83f30c37fe7f0021690b65c8..28839eb65cf80efc125a9503a9fc9ff98abf9b9c 100644 (file)
@@ -26,6 +26,8 @@
 (require 'ert)
 (require 'esh-mode)
 (require 'eshell)
+(require 'em-banner)
+(require 'em-prompt)
 
 (require 'eshell-tests-helpers
          (expand-file-name "eshell-tests-helpers"
     (eshell-match-command-output (format "(format \"hello%c%cp\")" ?\C-h ?\C-h)
                                  "\\`help\n")))
 
+(ert-deftest esh-mode-test/clear/eshell-command ()
+  "Test that `eshell/clear' works as an Eshell command."
+  (let ((eshell-banner-message "")
+        (eshell-prompt-function (lambda () "$ ")))
+    (with-temp-eshell
+      (eshell-insert-command "echo hi")
+      (eshell-insert-command "clear")
+      (should (string-match "\\`\\$ echo hi\nhi\n\\$ clear\n+\\$ "
+                            (buffer-string))))))
+
+(ert-deftest esh-mode-test/clear/eshell-command/erase ()
+  "Test that `eshell/clear' can erase the buffer."
+  (let ((eshell-banner-message "")
+        (eshell-prompt-function (lambda () "$ ")))
+    (with-temp-eshell
+      (eshell-insert-command "echo hi")
+      (eshell-insert-command "clear t")
+      (should (string-match "\\`\\$ " (buffer-string))))))
+
+(ert-deftest esh-mode-test/clear/emacs-command ()
+  "Test that `eshell-clear' works as an interactive Emacs command."
+  (let ((eshell-banner-message "")
+        (eshell-prompt-function (lambda () "$ ")))
+    (with-temp-eshell
+      (eshell-insert-command "echo hi")
+      (insert "echo b")
+      (eshell-clear)
+      (should (string-match "\\`\\$ echo hi\nhi\n\n+\\$ echo b"
+                            (buffer-string))))))
+
+(ert-deftest esh-mode-test/clear/emacs-command/erase ()
+  "Test that `eshell-clear' can erase the buffer."
+  (let ((eshell-banner-message "")
+        (eshell-prompt-function (lambda () "$ ")))
+    (with-temp-eshell
+      (eshell-insert-command "echo hi")
+      (insert "echo b")
+      (eshell-clear t)
+      (should (string-match "\\`\\$ echo b" (buffer-string))))))
+
 ;; esh-mode-tests.el ends here