diff options
author | Stefan Monnier <monnier@iro.umontreal.ca> | 2022-09-25 16:15:16 -0400 |
---|---|---|
committer | Stefan Monnier <monnier@iro.umontreal.ca> | 2022-09-25 16:15:16 -0400 |
commit | 650c20f1ca4e07591a727e1cfcc74b3363d15985 (patch) | |
tree | 85d11f6437cde22f410c25e0e5f71a3131ebd07d /lisp/eshell/esh-mode.el | |
parent | 8869332684c2302b5ba1ead4568bbc7ba1c0183e (diff) | |
parent | 4b85ae6a24380fb67a3315eaec9233f17a872473 (diff) | |
download | emacs-650c20f1ca4e07591a727e1cfcc74b3363d15985.tar.gz emacs-650c20f1ca4e07591a727e1cfcc74b3363d15985.tar.bz2 emacs-650c20f1ca4e07591a727e1cfcc74b3363d15985.zip |
Merge 'master' into noverlay
Diffstat (limited to 'lisp/eshell/esh-mode.el')
-rw-r--r-- | lisp/eshell/esh-mode.el | 439 |
1 files changed, 228 insertions, 211 deletions
diff --git a/lisp/eshell/esh-mode.el b/lisp/eshell/esh-mode.el index ea2fe1a6c26..8f11e6f04a4 100644 --- a/lisp/eshell/esh-mode.el +++ b/lisp/eshell/esh-mode.el @@ -1,6 +1,6 @@ ;;; esh-mode.el --- user interface -*- lexical-binding:t -*- -;; Copyright (C) 1999-2017 Free Software Foundation, Inc. +;; Copyright (C) 1999-2022 Free Software Foundation, Inc. ;; Author: John Wiegley <johnw@gnu.org> @@ -58,13 +58,10 @@ ;;; Code: -(provide 'esh-mode) - (require 'esh-util) (require 'esh-module) (require 'esh-cmd) -(require 'esh-io) -(require 'esh-var) +(require 'esh-arg) ;For eshell-parse-arguments (defgroup eshell-mode nil "This module contains code for handling input from the user." @@ -75,51 +72,43 @@ (defcustom eshell-mode-unload-hook nil "A hook that gets run when `eshell-mode' is unloaded." - :type 'hook - :group 'eshell-mode) + :type 'hook) (defcustom eshell-mode-hook nil "A hook that gets run when `eshell-mode' is entered." - :type 'hook - :group 'eshell-mode) + :type 'hook) (defcustom eshell-first-time-mode-hook nil "A hook that gets run the first time `eshell-mode' is entered. That is to say, the first time during an Emacs session." - :type 'hook - :group 'eshell-mode) + :type 'hook) (defcustom eshell-exit-hook nil "A hook that is run whenever `eshell' is exited. This hook is only run if exiting actually kills the buffer." :version "24.1" ; removed eshell-query-kill-processes - :type 'hook - :group 'eshell-mode) + :type 'hook) (defcustom eshell-kill-on-exit t "If non-nil, kill the Eshell buffer on the `exit' command. Otherwise, the buffer will simply be buried." - :type 'boolean - :group 'eshell-mode) + :type 'boolean) (defcustom eshell-input-filter-functions nil "Functions to call before input is processed. The input is contained in the region from `eshell-last-input-start' to `eshell-last-input-end'." - :type 'hook - :group 'eshell-mode) + :type 'hook) (defcustom eshell-send-direct-to-subprocesses nil "If t, send any input immediately to a subprocess." - :type 'boolean - :group 'eshell-mode) + :type 'boolean) (defcustom eshell-expand-input-functions nil "Functions to call before input is parsed. Each function is passed two arguments, which bounds the region of the current input text." - :type 'hook - :group 'eshell-mode) + :type 'hook) (defcustom eshell-scroll-to-bottom-on-input nil "Controls whether input to interpreter causes window to scroll. @@ -129,8 +118,7 @@ buffer. If `this', scroll only the selected window. See `eshell-preinput-scroll-to-bottom'." :type '(radio (const :tag "Do not scroll Eshell windows" nil) (const :tag "Scroll all windows showing the buffer" all) - (const :tag "Scroll only the selected window" this)) - :group 'eshell-mode) + (const :tag "Scroll only the selected window" this))) (defcustom eshell-scroll-to-bottom-on-output nil "Controls whether interpreter output causes window to scroll. @@ -143,8 +131,7 @@ See variable `eshell-scroll-show-maximum-output' and function :type '(radio (const :tag "Do not scroll Eshell windows" nil) (const :tag "Scroll all windows showing the buffer" all) (const :tag "Scroll only the selected window" this) - (const :tag "Scroll all windows other than selected" others)) - :group 'eshell-mode) + (const :tag "Scroll all windows other than selected" others))) (defcustom eshell-scroll-show-maximum-output t "Controls how interpreter output causes window to scroll. @@ -152,16 +139,14 @@ If non-nil, then show the maximum output when the window is scrolled. See variable `eshell-scroll-to-bottom-on-output' and function `eshell-postoutput-scroll-to-bottom'." - :type 'boolean - :group 'eshell-mode) + :type 'boolean) (defcustom eshell-buffer-maximum-lines 1024 "The maximum size in lines for eshell buffers. Eshell buffers are truncated from the top to be no greater than this number, if the function `eshell-truncate-buffer' is on `eshell-output-filter-functions'." - :type 'integer - :group 'eshell-mode) + :type 'natnum) (defcustom eshell-output-filter-functions '(eshell-postoutput-scroll-to-bottom @@ -171,35 +156,34 @@ number, if the function `eshell-truncate-buffer' is on "Functions to call before output is displayed. These functions are only called for output that is displayed interactively, and not for output which is redirected." - :type 'hook - :group 'eshell-mode) + :type 'hook) (defcustom eshell-preoutput-filter-functions nil "Functions to call before output is inserted into the buffer. These functions get one argument, a string containing the text to be inserted. They return the string as it should be inserted." - :type 'hook - :group 'eshell-mode) + :type 'hook) (defcustom eshell-password-prompt-regexp - (format "\\(%s\\).*:\\s *\\'" (regexp-opt password-word-equivalents)) + (format "\\(%s\\)[^::៖]*[::៖]\\s *\\'" (regexp-opt password-word-equivalents)) "Regexp matching prompts for passwords in the inferior process. This is used by `eshell-watch-for-password-prompt'." :type 'regexp - :group 'eshell-mode) + :version "27.1") (defcustom eshell-skip-prompt-function nil "A function called from beginning of line to skip the prompt." - :type '(choice (const nil) function) - :group 'eshell-mode) - -(define-obsolete-variable-alias 'eshell-status-in-modeline - 'eshell-status-in-mode-line "24.3") + :type '(choice (const nil) function)) (defcustom eshell-status-in-mode-line t "If non-nil, let the user know a command is running in the mode line." - :type 'boolean - :group 'eshell-mode) + :type 'boolean) + +(defcustom eshell-directory-name + (locate-user-emacs-file "eshell/" ".eshell/") + "The directory where Eshell control files should be kept." + :type 'directory + :group 'eshell) (defvar eshell-first-time-p t "A variable which is non-nil the first time Eshell is loaded.") @@ -209,10 +193,7 @@ This is used by `eshell-watch-for-password-prompt'." ;; these are only set to nil initially for the sake of the ;; byte-compiler, when compiling other files which `require' this one (defvar eshell-mode nil) -(defvar eshell-mode-map nil) (defvar eshell-command-running-string "--") -(defvar eshell-command-map nil) -(defvar eshell-command-prefix nil) (defvar eshell-last-input-start nil) (defvar eshell-last-input-end nil) (defvar eshell-last-output-start nil) @@ -266,22 +247,39 @@ This is used by `eshell-watch-for-password-prompt'." (modify-syntax-entry ?\] ")[ " st) ;; All non-word multibyte characters should be `symbol'. (map-char-table - (if (featurep 'xemacs) - (lambda (key _val) - (and (characterp key) - (>= (char-int key) 256) - (/= (char-syntax key) ?w) - (modify-syntax-entry key "_ " st))) - (lambda (key _val) - (and (if (consp key) - (and (>= (car key) 128) - (/= (char-syntax (car key)) ?w)) - (and (>= key 256) - (/= (char-syntax key) ?w))) - (modify-syntax-entry key "_ " st)))) + (lambda (key _val) + (and (if (consp key) + (and (>= (car key) 128) + (/= (char-syntax (car key)) ?w)) + (and (>= key 256) + (/= (char-syntax key) ?w))) + (modify-syntax-entry key "_ " st))) (standard-syntax-table)) st)) +(defvar-keymap eshell-mode-map + "C-c" 'eshell-command-map + "RET" #'eshell-send-input + "M-RET" #'eshell-queue-input + "C-M-l" #'eshell-show-output + "C-a" #'eshell-bol) + +(defvar-keymap eshell-command-map + :prefix 'eshell-command-map + "M-o" #'eshell-mark-output + "M-d" #'eshell-toggle-direct-send + "C-a" #'eshell-bol + "C-b" #'eshell-backward-argument + "C-e" #'eshell-show-maximum-output + "C-f" #'eshell-forward-argument + "C-m" #'eshell-copy-old-input + "C-o" #'eshell-kill-output + "C-r" #'eshell-show-output + "C-t" #'eshell-truncate-buffer + "C-u" #'eshell-kill-input + "C-w" #'backward-kill-word + "C-y" #'eshell-repeat-argument) + ;;; User Functions: (defun eshell-kill-buffer-function () @@ -291,7 +289,7 @@ and the hook `eshell-exit-hook'." ;; It's fine to run this unconditionally since it can be customized ;; via the `eshell-kill-processes-on-exit' variable. (and (fboundp 'eshell-query-kill-processes) - (not (memq 'eshell-query-kill-processes eshell-exit-hook)) + (not (memq #'eshell-query-kill-processes eshell-exit-hook)) (eshell-query-kill-processes)) (run-hooks 'eshell-exit-hook)) @@ -300,85 +298,48 @@ and the hook `eshell-exit-hook'." "Emacs shell interactive mode." (setq-local eshell-mode t) - ;; FIXME: What the hell!? - (setq-local eshell-mode-map (make-sparse-keymap)) - (use-local-map eshell-mode-map) - - (when eshell-status-in-mode-line + (when (and eshell-status-in-mode-line + (listp mode-line-format)) (make-local-variable 'eshell-command-running-string) (let ((fmt (copy-sequence mode-line-format))) (setq-local mode-line-format fmt)) - (let ((mode-line-elt (memq 'mode-line-modified mode-line-format))) + (let ((mode-line-elt (cdr (memq 'mode-line-front-space mode-line-format)))) (if mode-line-elt (setcar mode-line-elt 'eshell-command-running-string)))) - (define-key eshell-mode-map "\r" 'eshell-send-input) - (define-key eshell-mode-map "\M-\r" 'eshell-queue-input) - (define-key eshell-mode-map [(meta control ?l)] 'eshell-show-output) - (define-key eshell-mode-map [(control ?a)] 'eshell-bol) - - (setq-local eshell-command-prefix (make-symbol "eshell-command-prefix")) - (fset eshell-command-prefix (make-sparse-keymap)) - (setq-local eshell-command-map (symbol-function eshell-command-prefix)) - (define-key eshell-mode-map [(control ?c)] eshell-command-prefix) - - ;; without this, find-tag complains about read-only text being - ;; modified - (if (eq (key-binding [(meta ?.)]) 'find-tag) - (define-key eshell-mode-map [(meta ?.)] 'eshell-find-tag)) - (define-key eshell-command-map [(meta ?o)] 'eshell-mark-output) - (define-key eshell-command-map [(meta ?d)] 'eshell-toggle-direct-send) - - (define-key eshell-command-map [(control ?a)] 'eshell-bol) - (define-key eshell-command-map [(control ?b)] 'eshell-backward-argument) - (define-key eshell-command-map [(control ?e)] 'eshell-show-maximum-output) - (define-key eshell-command-map [(control ?f)] 'eshell-forward-argument) - (define-key eshell-command-map [return] 'eshell-copy-old-input) - (define-key eshell-command-map [(control ?m)] 'eshell-copy-old-input) - (define-key eshell-command-map [(control ?o)] 'eshell-kill-output) - (define-key eshell-command-map [(control ?r)] 'eshell-show-output) - (define-key eshell-command-map [(control ?t)] 'eshell-truncate-buffer) - (define-key eshell-command-map [(control ?u)] 'eshell-kill-input) - (define-key eshell-command-map [(control ?w)] 'backward-kill-word) - (define-key eshell-command-map [(control ?y)] 'eshell-repeat-argument) - + (setq-local bookmark-make-record-function #'eshell-bookmark-make-record) (setq local-abbrev-table eshell-mode-abbrev-table) - (set (make-local-variable 'list-buffers-directory) - (expand-file-name default-directory)) + (setq-local window-point-insertion-type t) + + (setq-local list-buffers-directory (expand-file-name default-directory)) ;; always set the tab width to 8 in Eshell buffers, since external ;; commands which do their own formatting almost always expect this - (set (make-local-variable 'tab-width) 8) + (setq-local tab-width 8) ;; don't ever use auto-fill in Eshell buffers (setq auto-fill-function nil) ;; always display everything from a return value - (if (boundp 'print-length) - (set (make-local-variable 'print-length) nil)) - (if (boundp 'print-level) - (set (make-local-variable 'print-level) nil)) + (setq-local print-length nil) + (setq-local print-level nil) ;; set require-final-newline to nil; otherwise, all redirected ;; output will end with a newline, whether or not the source ;; indicated it! - (set (make-local-variable 'require-final-newline) nil) + (setq-local require-final-newline nil) - (set (make-local-variable 'max-lisp-eval-depth) - (max 3000 max-lisp-eval-depth)) - (set (make-local-variable 'max-specpdl-size) - (max 6000 max-lisp-eval-depth)) + (setq-local max-lisp-eval-depth (max 3000 max-lisp-eval-depth)) - (set (make-local-variable 'eshell-last-input-start) (point-marker)) - (set (make-local-variable 'eshell-last-input-end) (point-marker)) - (set (make-local-variable 'eshell-last-output-start) (point-marker)) - (set (make-local-variable 'eshell-last-output-end) (point-marker)) - (set (make-local-variable 'eshell-last-output-block-begin) (point)) + (setq-local eshell-last-input-start (point-marker)) + (setq-local eshell-last-input-end (point-marker)) + (setq-local eshell-last-output-start (point-marker)) + (setq-local eshell-last-output-end (point-marker)) + (setq-local eshell-last-output-block-begin (point)) (let ((modules-list (copy-sequence eshell-modules-list))) - (make-local-variable 'eshell-modules-list) - (setq eshell-modules-list modules-list)) + (setq-local eshell-modules-list modules-list)) ;; This is to avoid making the paragraph base direction ;; right-to-left if the first word just happens to start with a @@ -397,7 +358,11 @@ and the hook `eshell-exit-hook'." (unless module-shortname (error "Invalid Eshell module name: %s" module-fullname)) (unless (featurep (intern module-shortname)) - (load module-shortname)))) + (condition-case nil + (load module-shortname) + (error (lwarn 'eshell :error + "Unable to load module `%s' (defined in `eshell-modules-list')" + module-fullname)))))) (unless (file-exists-p eshell-directory-name) (eshell-make-private-directory eshell-directory-name t)) @@ -409,23 +374,23 @@ and the hook `eshell-exit-hook'." (when (and load-hook (boundp load-hook)) (if (memq initfunc (symbol-value load-hook)) (setq initfunc nil)) (run-hooks load-hook)) - ;; So we don't need the -initialize functions on the hooks (b#5375). + ;; So we don't need the -initialize functions on the hooks (bug#5375). (and initfunc (fboundp initfunc) (funcall initfunc)))) (if eshell-send-direct-to-subprocesses - (add-hook 'pre-command-hook 'eshell-intercept-commands t t)) + (add-hook 'pre-command-hook #'eshell-intercept-commands t t)) (if eshell-scroll-to-bottom-on-input - (add-hook 'pre-command-hook 'eshell-preinput-scroll-to-bottom t t)) + (add-hook 'pre-command-hook #'eshell-preinput-scroll-to-bottom t t)) (when eshell-scroll-show-maximum-output - (set (make-local-variable 'scroll-conservatively) 1000)) + (setq-local scroll-conservatively 1000)) (when eshell-status-in-mode-line - (add-hook 'eshell-pre-command-hook 'eshell-command-started nil t) - (add-hook 'eshell-post-command-hook 'eshell-command-finished nil t)) + (add-hook 'eshell-pre-command-hook #'eshell-command-started nil t) + (add-hook 'eshell-post-command-hook #'eshell-command-finished nil t)) - (add-hook 'kill-buffer-hook 'eshell-kill-buffer-function t t) + (add-hook 'kill-buffer-hook #'eshell-kill-buffer-function t t) (if eshell-first-time-p (run-hooks 'eshell-first-time-mode-hook)) @@ -450,22 +415,22 @@ and the hook `eshell-exit-hook'." (if eshell-send-direct-to-subprocesses (progn (setq eshell-send-direct-to-subprocesses nil) - (remove-hook 'pre-command-hook 'eshell-intercept-commands t) + (remove-hook 'pre-command-hook #'eshell-intercept-commands t) (message "Sending subprocess input on RET")) (setq eshell-send-direct-to-subprocesses t) - (add-hook 'pre-command-hook 'eshell-intercept-commands t t) + (add-hook 'pre-command-hook #'eshell-intercept-commands t t) (message "Sending subprocess input directly"))) (defun eshell-self-insert-command () (interactive) (process-send-string - (eshell-interactive-process) + (eshell-head-process) (char-to-string (if (symbolp last-command-event) (get last-command-event 'ascii-character) last-command-event)))) (defun eshell-intercept-commands () - (when (and (eshell-interactive-process) + (when (and (eshell-interactive-process-p) (not (and (integerp last-input-event) (memq last-input-event '(?\C-x ?\C-c))))) (let ((possible-events (where-is-internal this-command)) @@ -487,13 +452,15 @@ and the hook `eshell-exit-hook'." (defun eshell-find-tag (&optional tagname next-p regexp-p) "A special version of `find-tag' that ignores whether the text is read-only." + (declare (obsolete xref-find-definition "27.1")) (interactive) (require 'etags) (let ((inhibit-read-only t) (no-default (eobp)) (find-tag-default-function 'ignore)) - (setq tagname (car (find-tag-interactive "Find tag: " no-default))) - (find-tag tagname next-p regexp-p))) + (setq tagname (car (find-tag-interactive "Find tag" no-default))) + (with-suppressed-warnings ((obsolete find-tag)) + (find-tag tagname next-p regexp-p)))) (defun eshell-move-argument (limit func property arg) "Move forward ARG arguments." @@ -532,7 +499,7 @@ and the hook `eshell-exit-hook'." (yank))) (defun eshell-bol () - "Goes to the beginning of line, then skips past the prompt, if any." + "Go to the beginning of line, then skip past the prompt, if any." (interactive) (beginning-of-line) (and eshell-skip-prompt-function @@ -542,7 +509,7 @@ and the hook `eshell-exit-hook'." "Push a mark at the end of the last input text." (push-mark (1- eshell-last-input-end) t)) -(custom-add-option 'eshell-pre-command-hook 'eshell-push-command-mark) +(custom-add-option 'eshell-pre-command-hook #'eshell-push-command-mark) (defsubst eshell-goto-input-start () "Goto the start of the last command input. @@ -550,7 +517,7 @@ Putting this function on `eshell-pre-command-hook' will mimic Plan 9's 9term behavior." (goto-char eshell-last-input-start)) -(custom-add-option 'eshell-pre-command-hook 'eshell-push-command-mark) +(custom-add-option 'eshell-pre-command-hook #'eshell-goto-input-start) (defsubst eshell-interactive-print (string) "Print STRING to the eshell display buffer." @@ -629,13 +596,13 @@ If NO-NEWLINE is non-nil, the input is sent without an implied final newline." (interactive "P") ;; Note that the input string does not include its terminal newline. - (let ((proc-running-p (and (eshell-interactive-process) + (let ((proc-running-p (and (eshell-head-process) (not queue-p))) (inhibit-point-motion-hooks t) (inhibit-modification-hooks t)) (unless (and proc-running-p (not (eq (process-status - (eshell-interactive-process)) + (eshell-head-process)) 'run))) (if (or proc-running-p (>= (point) eshell-last-output-end)) @@ -647,14 +614,22 @@ newline." (and eshell-send-direct-to-subprocesses proc-running-p)) (insert-before-markers-and-inherit ?\n)) + ;; Delete and reinsert input. This seems like a no-op, except + ;; for the resulting entries in the undo list: undoing this + ;; insertion will delete the region, moving the process mark + ;; back to its original position. + (let ((text (buffer-substring eshell-last-output-end (point))) + (inhibit-read-only t)) + (delete-region eshell-last-output-end (point)) + (insert text)) (if proc-running-p (progn (eshell-update-markers eshell-last-output-end) (if (or eshell-send-direct-to-subprocesses (= eshell-last-input-start eshell-last-input-end)) (unless no-newline - (process-send-string (eshell-interactive-process) "\n")) - (process-send-region (eshell-interactive-process) + (process-send-string (eshell-head-process) "\n")) + (process-send-region (eshell-head-process) eshell-last-input-start eshell-last-input-end))) (if (= eshell-last-output-end (point)) @@ -691,6 +666,16 @@ newline." (run-hooks 'eshell-post-command-hook) (insert-and-inherit input))))))))) +(defun eshell-send-eof-to-process () + "Send EOF to the currently-running \"head\" process." + (interactive) + (require 'esh-mode) + (declare-function eshell-send-input "esh-mode" + (&optional use-region queue-p no-newline)) + (eshell-send-input nil nil t) + (when (eshell-head-process) + (process-send-eof (eshell-head-process)))) + (defsubst eshell-kill-new () "Add the last input text to the kill ring." (kill-ring-save eshell-last-input-start eshell-last-input-end)) @@ -701,46 +686,44 @@ newline." "Send the output from PROCESS (STRING) to the interactive display. This is done after all necessary filtering has been done." (let ((oprocbuf (if process (process-buffer process) - (current-buffer))) - (inhibit-point-motion-hooks t) - (inhibit-modification-hooks t)) - (let ((functions eshell-preoutput-filter-functions)) - (while (and functions string) - (setq string (funcall (car functions) string)) - (setq functions (cdr functions)))) - (if (and string oprocbuf (buffer-name oprocbuf)) - (let (opoint obeg oend) - (with-current-buffer oprocbuf - (setq opoint (point)) - (setq obeg (point-min)) - (setq oend (point-max)) - (let ((buffer-read-only nil) - (nchars (length string)) - (ostart nil)) - (widen) - (goto-char eshell-last-output-end) - (setq ostart (point)) - (if (<= (point) opoint) - (setq opoint (+ opoint nchars))) - (if (< (point) obeg) - (setq obeg (+ obeg nchars))) - (if (<= (point) oend) - (setq oend (+ oend nchars))) + (current-buffer))) + (inhibit-point-motion-hooks t) + (inhibit-modification-hooks t)) + (when (and string oprocbuf (buffer-name oprocbuf)) + (with-current-buffer oprocbuf + (let ((functions eshell-preoutput-filter-functions)) + (while (and functions string) + (setq string (funcall (car functions) string)) + (setq functions (cdr functions)))) + (when string + (let (opoint obeg oend) + (setq opoint (point)) + (setq obeg (point-min)) + (setq oend (point-max)) + (let ((buffer-read-only nil) + (nchars (length string)) + (ostart nil)) + (widen) + (goto-char eshell-last-output-end) + (setq ostart (point)) + (if (<= (point) opoint) + (setq opoint (+ opoint nchars))) + (if (< (point) obeg) + (setq obeg (+ obeg nchars))) + (if (<= (point) oend) + (setq oend (+ oend nchars))) ;; Let the ansi-color overlay hooks run. (let ((inhibit-modification-hooks nil)) - (insert-before-markers string)) - (if (= (window-start) (point)) - (set-window-start (selected-window) - (- (point) nchars))) - (if (= (point) eshell-last-input-end) - (set-marker eshell-last-input-end - (- eshell-last-input-end nchars))) - (set-marker eshell-last-output-start ostart) - (set-marker eshell-last-output-end (point)) - (force-mode-line-update)) - (narrow-to-region obeg oend) - (goto-char opoint) - (eshell-run-output-filters)))))) + (insert string)) + (if (= (window-start) (point)) + (set-window-start (selected-window) + (- (point) nchars))) + (set-marker eshell-last-output-start ostart) + (set-marker eshell-last-output-end (point)) + (force-mode-line-update)) + (narrow-to-region obeg oend) + (goto-char opoint) + (eshell-run-output-filters))))))) (defun eshell-run-output-filters () "Run the `eshell-output-filter-functions' on the current output." @@ -767,13 +750,12 @@ This function should be a pre-command hook." (if (eq scroll 'this) (goto-char (point-max)) (walk-windows - (function - (lambda (window) - (when (and (eq (window-buffer window) current) - (or (eq scroll t) (eq scroll 'all))) - (select-window window) - (goto-char (point-max)) - (select-window selected)))) + (lambda (window) + (when (and (eq (window-buffer window) current) + (or (eq scroll t) (eq scroll 'all))) + (select-window window) + (goto-char (point-max)) + (select-window selected))) nil t)))))) ;;; jww (1999-10-23): this needs testing @@ -789,29 +771,28 @@ This function should be in the list `eshell-output-filter-functions'." (scroll eshell-scroll-to-bottom-on-output)) (unwind-protect (walk-windows - (function - (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))))) + (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) (set-buffer current)))) @@ -884,8 +865,7 @@ If SCROLLBACK is non-nil, clear the scrollback contents." (interactive) (if scrollback (eshell/clear-scrollback) - (let ((eshell-input-filter-functions - (remq 'eshell-add-to-history eshell-input-filter-functions))) + (let ((eshell-input-filter-functions nil)) (insert (make-string (window-size) ?\n)) (eshell-send-input)))) @@ -955,9 +935,9 @@ Then send it to the process running in the current buffer." (interactive) ; Don't pass str as argument, to avoid snooping via C-x ESC ESC (let ((str (read-passwd (format "%s Password: " - (process-name (eshell-interactive-process)))))) + (process-name (eshell-head-process)))))) (if (stringp str) - (process-send-string (eshell-interactive-process) + (process-send-string (eshell-head-process) (concat str "\n")) (message "Warning: text will be echoed")))) @@ -968,14 +948,21 @@ buffer's process if STRING contains a password prompt defined by `eshell-password-prompt-regexp'. This function could be in the list `eshell-output-filter-functions'." - (when (eshell-interactive-process) + (when (eshell-interactive-process-p) (save-excursion (let ((case-fold-search t)) (goto-char eshell-last-output-block-begin) (beginning-of-line) (if (re-search-forward eshell-password-prompt-regexp eshell-last-output-end t) - (eshell-send-invisible)))))) + ;; Use `run-at-time' in order not to pause execution of + ;; the process filter with a minibuffer + (run-at-time + 0 nil + (lambda (current-buf) + (with-current-buffer current-buf + (eshell-send-invisible))) + (current-buffer))))))) (custom-add-option 'eshell-output-filter-functions 'eshell-watch-for-password-prompt) @@ -1012,13 +999,43 @@ This function could be in the list `eshell-output-filter-functions'." 'eshell-handle-control-codes) (autoload 'ansi-color-apply-on-region "ansi-color") +(defvar ansi-color-apply-face-function) +(declare-function ansi-color-apply-text-property-face "ansi-color" + (BEG END FACE)) (defun eshell-handle-ansi-color () "Handle ANSI color codes." - (ansi-color-apply-on-region eshell-last-output-start - eshell-last-output-end)) + (require 'ansi-color) + (let ((ansi-color-apply-face-function #'ansi-color-apply-text-property-face)) + (ansi-color-apply-on-region eshell-last-output-start + eshell-last-output-end))) (custom-add-option 'eshell-output-filter-functions 'eshell-handle-ansi-color) +;;; Bookmark support: + +(declare-function bookmark-prop-get "bookmark" (bookmark prop)) + +(defun eshell-bookmark-name () + (format "eshell-%s" + (file-name-nondirectory + (directory-file-name + (file-name-directory default-directory))))) + +(defun eshell-bookmark-make-record () + "Create a bookmark for the current Eshell buffer." + `(,(eshell-bookmark-name) + (location . ,default-directory) + (handler . eshell-bookmark-jump))) + +;;;###autoload +(defun eshell-bookmark-jump (bookmark) + "Default bookmark handler for Eshell buffers." + (let ((default-directory (bookmark-prop-get bookmark 'location))) + (eshell))) + +(put 'eshell-bookmark-jump 'bookmark-handler-type "Eshell") + +(provide 'esh-mode) ;;; esh-mode.el ends here |