(current (current-buffer))
(scroll eshell-scroll-to-bottom-on-output))
(unwind-protect
- (walk-windows
- (lambda (window)
- (if (eq (window-buffer window) current)
- (progn
- (select-window window)
- (if (and (< (point) eshell-last-output-end)
- (or (eq scroll t) (eq scroll 'all)
- ;; Maybe user wants point to jump to end.
- (and (eq scroll 'this)
- (eq selected window))
- (and (eq scroll 'others)
- (not (eq selected window)))
- ;; If point was at the end, keep it at end.
- (>= (point) eshell-last-output-start)))
- (goto-char eshell-last-output-end))
- ;; Optionally scroll so that the text
- ;; ends at the bottom of the window.
- (if (and eshell-scroll-show-maximum-output
- (>= (point) eshell-last-output-end))
- (save-excursion
- (goto-char (point-max))
- (recenter -1)))
- (select-window selected))))
- nil t)
+ (dolist (window (get-buffer-window-list current nil t))
+ (with-selected-window window
+ (when (and (< (point) eshell-last-output-end)
+ (or (eq scroll t) (eq scroll 'all)
+ ;; Maybe user wants point to jump to end.
+ (and (eq scroll 'this)
+ (eq selected window))
+ (and (eq scroll 'others)
+ (not (eq selected window)))
+ ;; If point was at the end, keep it at end.
+ (>= (point) eshell-last-output-start)))
+ (goto-char eshell-last-output-end))
+ ;; Optionally scroll so that the text ends at the bottom of
+ ;; the window.
+ (when (and eshell-scroll-show-maximum-output
+ (>= (point) eshell-last-output-end))
+ (save-excursion
+ (goto-char (point-max))
+ (recenter -1)))))
(set-buffer current))))
(defun eshell-beginning-of-input ()
(goto-char eshell-last-output-block-begin)
(unless (eolp)
(beginning-of-line))
- (while (< (point) eshell-last-output-end)
- (let ((char (char-after)))
+ (while (re-search-forward (rx (any ?\r ?\a ?\C-h))
+ eshell-last-output-end t)
+ (let ((char (char-before)))
(cond
((eq char ?\r)
- (if (< (1+ (point)) eshell-last-output-end)
- (if (memq (char-after (1+ (point)))
- '(?\n ?\r))
- (delete-char 1)
- (let ((end (1+ (point))))
+ (if (< (point) eshell-last-output-end)
+ (if (memq (char-after (point)) '(?\n ?\r))
+ (delete-char -1)
+ (let ((end (point)))
(beginning-of-line)
(delete-region (point) end)))
- (add-text-properties (point) (1+ (point))
- '(invisible t))
- (forward-char)))
+ (add-text-properties (1- (point)) (point)
+ '(invisible t))))
((eq char ?\a)
- (delete-char 1)
+ (delete-char -1)
(beep))
((eq char ?\C-h)
- (delete-region (1- (point)) (1+ (point))))
- (t
- (forward-char)))))))
+ (delete-region (- (point) 2) (point))))))))
(custom-add-option 'eshell-output-filter-functions
'eshell-handle-control-codes)
--- /dev/null
+;;; esh-mode-tests.el --- esh-mode test suite -*- lexical-binding:t -*-
+
+;; Copyright (C) 2022-2024 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Tests for Eshell's command invocation.
+
+;;; Code:
+
+(require 'ert)
+(require 'esh-mode)
+(require 'eshell)
+
+(require 'eshell-tests-helpers
+ (expand-file-name "eshell-tests-helpers"
+ (file-name-directory (or load-file-name
+ default-directory))))
+
+;;; Tests:
+
+(ert-deftest esh-mode-test/handle-control-codes/carriage-return ()
+ "Test that Eshell handles carriage returns properly."
+ (with-temp-eshell
+ (eshell-match-command-output "(format \"hello\r\ngoodbye\")"
+ "\\`hello\ngoodbye\n")
+ (eshell-match-command-output "(format \"hello\rgoodbye\")"
+ "\\`goodbye\n")
+ (eshell-match-command-output "(format \"hello\r\")"
+ "\\`hello")))
+
+(ert-deftest esh-mode-test/handle-control-codes/bell ()
+ "Test that Eshell handles bells properly."
+ (cl-letf* ((beep-called nil)
+ ((symbol-function 'beep) (lambda () (setq beep-called t))))
+ (with-temp-eshell
+ (eshell-match-command-output "(format \"hello\athere\")"
+ "\\`hellothere\n")
+ (should beep-called))))
+
+(ert-deftest esh-mode-test/handle-control-codes/backspace ()
+ "Test that Eshell handles backspaces properly."
+ (with-temp-eshell
+ (eshell-match-command-output (format "(format \"hello%c%cp\")" ?\C-h ?\C-h)
+ "\\`help\n")))
+
+;; esh-mode-tests.el ends here