Both Comint and Eshell do this, and it can significantly slow down
commands that write a lot of output (bug#71576).
* lisp/comint.el (comint-password-prompt-max-length): New variable...
(comint-watch-for-password-prompt): ... use it. Additionally, use the
matched result for the Emacs-based password prompt.
* lisp/eshell/esh-mode.el (eshell-password-prompt-max-length): New
variable...
(eshell-watch-for-password-prompt): ... use it.
* etc/NEWS: Announce this change.
(cherry picked from commit
1a55e957ae57ec32ae960eabdb170b5b427392d4)
---
*** Performance improvements for interactive output in Eshell.
Interactive output in Eshell should now be significantly faster,
-especially for built-in commands that can print large amounts of output
-(e.g. "cat"). In addition, these commands can now update the display
-periodically to show their progress.
+especially for commands that can print large amounts of output
+(e.g. "cat"). For external commands, Eshell saves time by only looking
+for password prompts in the last 256 characters of each block of output.
+To restore the previous behavior when checking for password prompts, set
+'eshell-password-prompt-max-length' to 'most-positive-fixnum'.
+
+---
+*** Eshell built-in commands can now display progress.
+Eshell built-in commands like "cat" and "ls" now update the display
+periodically while running to show their progress.
+++
*** New special reference type '#<marker POSITION BUFFER>'.
In a 'shell' buffer, this user option is connection-local.
+---
+*** Performance improvements for interactive output.
+Interactive output in Shell mode now scans more selectively for password
+prompts by only examining the last 256 characters of each block of
+output, reducing the time spent when printing large amounts of output.
+To restore the old behavior, set 'comint-password-prompt-max-length' to
+'most-positive-fixnum'.
+
** Make mode
*** The Makefile browser is now obsolete.
:type 'regexp
:group 'comint)
+(defvar comint-password-prompt-max-length 256
+ "The maximum amount of text to examine when matching password prompts.
+This is used by `comint-watch-for-password-prompt' to reduce the amount
+of time spent searching for password prompts.")
+
;; Here are the per-interpreter hooks.
(defvar comint-get-old-input (function comint-get-old-input-default)
"Function that returns old text in Comint mode.
carriage returns (\\r) in STRING.
This function could be in the list `comint-output-filter-functions'."
- (when (let ((case-fold-search t))
- (string-match comint-password-prompt-regexp
- (string-replace "\r" "" string)))
- ;; 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
- (let ((comint--prompt-recursion-depth
- (1+ comint--prompt-recursion-depth)))
- (if (> comint--prompt-recursion-depth 10)
- (message "Password prompt recursion too deep")
- (when (get-buffer-process (current-buffer))
- (comint-send-invisible
- (string-trim string "[ \n\r\t\v\f\b\a]+" "\n+")))))))
- (current-buffer))))
+ (let ((string (string-limit string comint-password-prompt-max-length t))
+ prompt)
+ (when (let ((case-fold-search t))
+ (string-match comint-password-prompt-regexp
+ (string-replace "\r" "" string)))
+ (setq prompt (string-trim (match-string 0 string)
+ "[ \n\r\t\v\f\b\a]+" "\n+"))
+ ;; 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
+ (let ((comint--prompt-recursion-depth
+ (1+ comint--prompt-recursion-depth)))
+ (if (> comint--prompt-recursion-depth 10)
+ (message "Password prompt recursion too deep")
+ (when (get-buffer-process (current-buffer))
+ (comint-send-invisible prompt))))))
+ (current-buffer)))))
\f
;; Low-level process communication
:type 'directory
:group 'eshell)
+(defvar eshell-password-prompt-max-length 256
+ "The maximum amount of text to examine when matching password prompts.
+This is used by `eshell-watch-for-password-prompt' to reduce the amount
+of time spent searching for password prompts.")
+
(defvar eshell-first-time-p t
"A variable which is non-nil the first time Eshell is loaded.")
This function could be in the list `eshell-output-filter-functions'."
(when (eshell-head-process)
(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)
- ;; 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)))))))
+ (goto-char (max eshell-last-output-block-begin
+ (- eshell-last-output-end
+ eshell-password-prompt-max-length)))
+ (when (let ((case-fold-search t))
+ (re-search-forward eshell-password-prompt-regexp
+ eshell-last-output-end t))
+ ;; 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)