diff options
| author | Pengji Zhang | 2024-12-10 18:55:36 +0800 |
|---|---|---|
| committer | Jim Porter | 2024-12-11 11:56:45 -0800 |
| commit | 3959ea66448fb371cdc67bd963cd539a90f99ee5 (patch) | |
| tree | 8f4094a990a4eda26381e5cc7ece15365d17db04 | |
| parent | 6a07dc19ac65eaa3ee1eeb814af85bde7fd2c509 (diff) | |
| download | emacs-3959ea66448fb371cdc67bd963cd539a90f99ee5.tar.gz emacs-3959ea66448fb371cdc67bd963cd539a90f99ee5.zip | |
Rework history Isearch for Eshell
This is to make history Isearch for Eshell similar to that of
'comint-mode', by hooking into Isearch properly instead of
defining new commands to emulate Isearch (bug#74287).
* lisp/eshell/em-hist.el (eshell-history-isearch): New user
option.
(eshell-goto-history, eshell--isearch-setup)
(eshell-history-isearch-end, eshell-history-isearch-search)
(eshell-history-isearch-message, eshell-history-isearch-wrap)
(eshell-history-isearch-push-state): New functions.
(eshell-isearch-backward-regexp, eshell-isearch-forward-regexp):
New commands.
(eshell--history-isearch-message-overlay)
(eshell--stored-incomplete-input, eshell--force-history-isearch):
New internal variables.
(eshell-hist-mode-map): Bind 'M-r' to
'eshell-isearch-backward-regexp' and free 'M-s' binding for
normal in-buffer search commands.
(eshell-isearch-backward, eshell-isearch-forward): Use the new
way to start searching.
(eshell-hist-initialize): Use the new Isearch setup function.
(eshell-previous-matching-input): Use 'eshell-goto-history'.
Also inhibit messages when searching.
(eshell-isearch-map, eshell-isearch-repeat-backward)
(eshell-isearch-abort, eshell-isearch-delete-char)
(eshell-isearch-return, eshell-isearch-cancel)
(eshell-isearch-repeat-forward, eshell-test-imatch)
(eshell-return-to-prompt, eshell-prepare-for-search): Remove.
These are for the old history Isearch implementation.
* doc/misc/eshell.texi (History): Document changes.
* etc/NEWS: Annouce changes.
| -rw-r--r-- | doc/misc/eshell.texi | 15 | ||||
| -rw-r--r-- | etc/NEWS | 23 | ||||
| -rw-r--r-- | lisp/eshell/em-hist.el | 326 |
3 files changed, 227 insertions, 137 deletions
diff --git a/doc/misc/eshell.texi b/doc/misc/eshell.texi index 709417a7efb..264bb655e5e 100644 --- a/doc/misc/eshell.texi +++ b/doc/misc/eshell.texi | |||
| @@ -2660,10 +2660,10 @@ navigation and searching are bound to different keys: | |||
| 2660 | 2660 | ||
| 2661 | @table @kbd | 2661 | @table @kbd |
| 2662 | @kindex M-r | 2662 | @kindex M-r |
| 2663 | @kindex M-s | ||
| 2664 | @item M-r | 2663 | @item M-r |
| 2665 | @itemx M-s | 2664 | History I-search. @kbd{M-r} starts an incremental search in input |
| 2666 | History I-search. | 2665 | history. While searching, type @kbd{C-r} to move to the previous match, |
| 2666 | and @kbd{C-s} to move to the next match in the input history. | ||
| 2667 | 2667 | ||
| 2668 | @kindex M-p | 2668 | @kindex M-p |
| 2669 | @kindex M-n | 2669 | @kindex M-n |
| @@ -2674,6 +2674,15 @@ line when you run these commands, they will instead jump to the | |||
| 2674 | previous or next line that begins with that string. | 2674 | previous or next line that begins with that string. |
| 2675 | @end table | 2675 | @end table |
| 2676 | 2676 | ||
| 2677 | @vindex eshell-history-isearch | ||
| 2678 | If you would like to use the default Isearch key-bindings to search | ||
| 2679 | through input history, you may customize @code{eshell-history-isearch} | ||
| 2680 | to @code{t}. That makes, for example, @kbd{C-r} and @kbd{C-M-r} in an | ||
| 2681 | Eshell buffer search in input history only. In addition, if the value | ||
| 2682 | of @code{eshell-history-isearch} is @code{dwim}, those commands search | ||
| 2683 | in the history when the point is after the last prompt, and search in | ||
| 2684 | the buffer when the point is before or within the last prompt. | ||
| 2685 | |||
| 2677 | @node Extension modules | 2686 | @node Extension modules |
| 2678 | @chapter Extension modules | 2687 | @chapter Extension modules |
| 2679 | Eshell provides a facility for defining extension modules so that they | 2688 | Eshell provides a facility for defining extension modules so that they |
| @@ -380,6 +380,29 @@ This hook runs after an Eshell session has been fully initialized, | |||
| 380 | immediately before running 'eshell-post-command-hook' for the first | 380 | immediately before running 'eshell-post-command-hook' for the first |
| 381 | time. | 381 | time. |
| 382 | 382 | ||
| 383 | +++ | ||
| 384 | *** Improved history Isearch. | ||
| 385 | History Isearch in Eshell is reworked. Two new commands | ||
| 386 | 'eshell-isearch-backward-regexp' and 'eshell-isearch-forward-regexp' are | ||
| 387 | added for incrementally searching through the input history. | ||
| 388 | 'eshell-isearch-backward-regexp' is bound to 'M-r' by default, and 'M-s' | ||
| 389 | is freed for normal search commands. If you would like to restore the | ||
| 390 | previous key-bindings for the non-incremental search commands, put in | ||
| 391 | your configuration: | ||
| 392 | |||
| 393 | (keymap-set eshell-hist-mode-map "M-r" | ||
| 394 | #'eshell-previous-matching-input) | ||
| 395 | (keymap-set eshell-hist-mode-map "M-s" | ||
| 396 | #'eshell-next-matching-input) | ||
| 397 | |||
| 398 | +++ | ||
| 399 | *** New user option 'eshell-history-isearch' | ||
| 400 | When 'eshell-history-isearch' is nil (the default), Isearch commands | ||
| 401 | search in the buffer contents. If you customize it to t, those commands | ||
| 402 | only search in input history. If you customize it to the symbol 'dwim', | ||
| 403 | those commands search in input history only when the point is after the | ||
| 404 | last prompt. | ||
| 405 | |||
| 383 | ** SHR | 406 | ** SHR |
| 384 | 407 | ||
| 385 | +++ | 408 | +++ |
diff --git a/lisp/eshell/em-hist.el b/lisp/eshell/em-hist.el index fffd611c06f..4bcf434f6e4 100644 --- a/lisp/eshell/em-hist.el +++ b/lisp/eshell/em-hist.el | |||
| @@ -34,7 +34,6 @@ | |||
| 34 | ;; Also, most of `comint-mode's keybindings are accepted: | 34 | ;; Also, most of `comint-mode's keybindings are accepted: |
| 35 | ;; | 35 | ;; |
| 36 | ;; M-r ; search backward for a previous command by regexp | 36 | ;; M-r ; search backward for a previous command by regexp |
| 37 | ;; M-s ; search forward for a previous command by regexp | ||
| 38 | ;; M-p ; access the last command entered, repeatable | 37 | ;; M-p ; access the last command entered, repeatable |
| 39 | ;; M-n ; access the first command entered, repeatable | 38 | ;; M-n ; access the first command entered, repeatable |
| 40 | ;; | 39 | ;; |
| @@ -132,6 +131,17 @@ whitespace." | |||
| 132 | (function :tag "Other function")) | 131 | (function :tag "Other function")) |
| 133 | :risky t) | 132 | :risky t) |
| 134 | 133 | ||
| 134 | (defcustom eshell-history-isearch nil | ||
| 135 | "Non-nil to Isearch in input history only. | ||
| 136 | If t, usual Isearch keys like \\[isearch-forward] in Eshell search in | ||
| 137 | the input history only. If `dwim', Isearch in the input history when | ||
| 138 | point is at the command line, otherwise search in the current Eshell | ||
| 139 | buffer." | ||
| 140 | :type '(choice (const :tag "Don't search in input history" nil) | ||
| 141 | (const :tag "Search histroy when point is on command line" dwim) | ||
| 142 | (const :tag "Always search in input history" t)) | ||
| 143 | :version "31.1") | ||
| 144 | |||
| 135 | (defun eshell-hist--update-keymap (symbol value) | 145 | (defun eshell-hist--update-keymap (symbol value) |
| 136 | "Update `eshell-hist-mode-map' for `eshell-hist-match-partial'." | 146 | "Update `eshell-hist-mode-map' for `eshell-hist-match-partial'." |
| 137 | ;; Don't try to set this before it is bound. See below. | 147 | ;; Don't try to set this before it is bound. See below. |
| @@ -204,25 +214,20 @@ element, regardless of any text on the command line. In that case, | |||
| 204 | (defvar eshell-hist--new-items nil | 214 | (defvar eshell-hist--new-items nil |
| 205 | "The number of new history items that have not been written to | 215 | "The number of new history items that have not been written to |
| 206 | file. This variable is local in each eshell buffer.") | 216 | file. This variable is local in each eshell buffer.") |
| 207 | 217 | (defvar-local eshell--history-isearch-message-overlay nil | |
| 208 | (defvar-keymap eshell-isearch-map | 218 | "Overlay for Isearch message when searching through input history.") |
| 209 | :doc "Keymap used in isearch in Eshell." | 219 | (defvar-local eshell--stored-incomplete-input nil |
| 210 | :parent isearch-mode-map | 220 | "Stored input for history cycling.") |
| 211 | "C-m" #'eshell-isearch-return | 221 | (defvar eshell--force-history-isearch nil |
| 212 | "C-r" #'eshell-isearch-repeat-backward | 222 | "Non-nil means to force searching in input history. |
| 213 | "C-s" #'eshell-isearch-repeat-forward | 223 | If nil, respect the option `eshell-history-isearch'.") |
| 214 | "C-g" #'eshell-isearch-abort | ||
| 215 | "<backspace>" #'eshell-isearch-delete-char | ||
| 216 | "<delete>" #'eshell-isearch-delete-char | ||
| 217 | "C-c C-c" #'eshell-isearch-cancel) | ||
| 218 | 224 | ||
| 219 | (defvar-keymap eshell-hist-mode-map | 225 | (defvar-keymap eshell-hist-mode-map |
| 220 | "<up>" #'eshell-previous-matching-input-from-input | 226 | "<up>" #'eshell-previous-matching-input-from-input |
| 221 | "<down>" #'eshell-next-matching-input-from-input | 227 | "<down>" #'eshell-next-matching-input-from-input |
| 222 | "C-<up>" #'eshell-previous-input | 228 | "C-<up>" #'eshell-previous-input |
| 223 | "C-<down>" #'eshell-next-input | 229 | "C-<down>" #'eshell-next-input |
| 224 | "M-r" #'eshell-previous-matching-input | 230 | "M-r" #'eshell-isearch-backward-regexp |
| 225 | "M-s" #'eshell-next-matching-input | ||
| 226 | "C-c M-r" #'eshell-previous-matching-input-from-input | 231 | "C-c M-r" #'eshell-previous-matching-input-from-input |
| 227 | "C-c M-s" #'eshell-next-matching-input-from-input | 232 | "C-c M-s" #'eshell-next-matching-input-from-input |
| 228 | "C-c C-l" #'eshell-list-history | 233 | "C-c C-l" #'eshell-list-history |
| @@ -261,20 +266,9 @@ Returns nil if INPUT is prepended by blank space, otherwise non-nil." | |||
| 261 | (not eshell-non-interactive-p)) | 266 | (not eshell-non-interactive-p)) |
| 262 | (let ((rebind-alist eshell-rebind-keys-alist)) | 267 | (let ((rebind-alist eshell-rebind-keys-alist)) |
| 263 | (setq-local eshell-rebind-keys-alist | 268 | (setq-local eshell-rebind-keys-alist |
| 264 | (append rebind-alist eshell-hist-rebind-keys-alist)) | 269 | (append rebind-alist eshell-hist-rebind-keys-alist))) |
| 265 | (setq-local search-invisible t) | ||
| 266 | (setq-local search-exit-option t) | ||
| 267 | (add-hook 'isearch-mode-hook | ||
| 268 | (lambda () | ||
| 269 | (if (>= (point) eshell-last-output-end) | ||
| 270 | (setq overriding-terminal-local-map | ||
| 271 | eshell-isearch-map))) | ||
| 272 | nil t) | ||
| 273 | (add-hook 'isearch-mode-end-hook | ||
| 274 | (lambda () | ||
| 275 | (setq overriding-terminal-local-map nil)) | ||
| 276 | nil t)) | ||
| 277 | (eshell-hist-mode)) | 270 | (eshell-hist-mode)) |
| 271 | (add-hook 'isearch-mode-hook #'eshell--isearch-setup nil t) | ||
| 278 | 272 | ||
| 279 | (make-local-variable 'eshell-history-size) | 273 | (make-local-variable 'eshell-history-size) |
| 280 | (or eshell-history-size | 274 | (or eshell-history-size |
| @@ -384,6 +378,23 @@ unless a different file is specified on the command line.") | |||
| 384 | "Get an input line from the history ring." | 378 | "Get an input line from the history ring." |
| 385 | (ring-ref (or ring eshell-history-ring) index)) | 379 | (ring-ref (or ring eshell-history-ring) index)) |
| 386 | 380 | ||
| 381 | (defun eshell-goto-history (pos) | ||
| 382 | "Replace command line with the element at POS of history ring. | ||
| 383 | Also update `eshell-history-index'. As a special case, if POS is nil | ||
| 384 | and `eshell--stored-incomplete-input' is a non-empty string, restore the | ||
| 385 | saved input." | ||
| 386 | (when (null eshell-history-index) | ||
| 387 | (setq eshell--stored-incomplete-input | ||
| 388 | (buffer-substring-no-properties eshell-last-output-end | ||
| 389 | (point-max)))) | ||
| 390 | (setq eshell-history-index pos) | ||
| 391 | ;; Can't use kill-region as it sets this-command | ||
| 392 | (delete-region eshell-last-output-end (point-max)) | ||
| 393 | (if (and pos (not (ring-empty-p eshell-history-ring))) | ||
| 394 | (insert-and-inherit (eshell-get-history pos)) | ||
| 395 | (when (> (length eshell--stored-incomplete-input) 0) | ||
| 396 | (insert-and-inherit eshell--stored-incomplete-input)))) | ||
| 397 | |||
| 387 | (defun eshell-add-input-to-history (input) | 398 | (defun eshell-add-input-to-history (input) |
| 388 | "Add the string INPUT to the history ring. | 399 | "Add the string INPUT to the history ring. |
| 389 | Input is entered into the input history ring, if the value of | 400 | Input is entered into the input history ring, if the value of |
| @@ -897,12 +908,12 @@ If N is negative, find the next or Nth next match." | |||
| 897 | ;; Has a match been found? | 908 | ;; Has a match been found? |
| 898 | (if (null pos) | 909 | (if (null pos) |
| 899 | (error "Not found") | 910 | (error "Not found") |
| 900 | (setq eshell-history-index pos) | 911 | (eshell-goto-history pos) |
| 901 | (unless (minibuffer-window-active-p (selected-window)) | 912 | (unless (or (minibuffer-window-active-p (selected-window)) |
| 902 | (message "History item: %d" (- (ring-length eshell-history-ring) pos))) | 913 | ;; No messages for Isearch because it will show the |
| 903 | ;; Can't use kill-region as it sets this-command | 914 | ;; same messages (and more). |
| 904 | (delete-region eshell-last-output-end (point)) | 915 | isearch-mode) |
| 905 | (insert-and-inherit (eshell-get-history pos))))) | 916 | (message "History item: %d" (- (ring-length eshell-history-ring) pos)))))) |
| 906 | 917 | ||
| 907 | (defun eshell-next-matching-input (regexp arg) | 918 | (defun eshell-next-matching-input (regexp arg) |
| 908 | "Search forwards through input history for match for REGEXP. | 919 | "Search forwards through input history for match for REGEXP. |
| @@ -937,114 +948,161 @@ If N is negative, search backwards for the -Nth previous match." | |||
| 937 | (interactive "p") | 948 | (interactive "p") |
| 938 | (eshell-previous-matching-input-from-input (- arg))) | 949 | (eshell-previous-matching-input-from-input (- arg))) |
| 939 | 950 | ||
| 940 | (defun eshell-test-imatch () | 951 | (defun eshell--isearch-setup () |
| 941 | "If isearch match good, put point at the beginning and return non-nil." | 952 | "Set up Isearch to search the input history. |
| 942 | (if (get-text-property (point) 'history) | 953 | Intended to be added to `isearch-mode-hook' in an Eshell buffer." |
| 943 | (progn (beginning-of-line) t) | 954 | (when (and |
| 944 | (let ((before (point))) | 955 | ;; Eshell is busy running a foreground process |
| 945 | (beginning-of-line) | 956 | (not eshell-foreground-command) |
| 946 | (if (and (not (bolp)) | 957 | (or eshell--force-history-isearch |
| 947 | (<= (point) before)) | 958 | (eq eshell-history-isearch t) |
| 948 | t | 959 | (and (eq eshell-history-isearch 'dwim) |
| 949 | (if isearch-forward | 960 | (>= (point) eshell-last-output-end)))) |
| 950 | (progn | 961 | (setq isearch-message-prefix-add "history ") |
| 951 | (end-of-line) | 962 | (setq-local isearch-lazy-count nil) |
| 952 | (forward-char)) | 963 | (setq-local isearch-search-fun-function #'eshell-history-isearch-search |
| 953 | (beginning-of-line) | 964 | isearch-message-function #'eshell-history-isearch-message |
| 954 | (backward-char)))))) | 965 | isearch-wrap-function #'eshell-history-isearch-wrap |
| 955 | 966 | isearch-push-state-function #'eshell-history-isearch-push-state) | |
| 956 | (defun eshell-return-to-prompt () | 967 | (add-hook 'isearch-mode-end-hook #'eshell-history-isearch-end nil t))) |
| 957 | "Once a search string matches, insert it at the end and go there." | 968 | |
| 958 | (setq isearch-other-end nil) | 969 | (defun eshell-history-isearch-end () |
| 959 | (let ((found (eshell-test-imatch)) before) | 970 | "Clean up after terminating history Isearch." |
| 960 | (while (and (not found) | 971 | (when (overlayp eshell--history-isearch-message-overlay) |
| 961 | (setq before | 972 | (delete-overlay eshell--history-isearch-message-overlay)) |
| 962 | (funcall (if isearch-forward | 973 | (setq isearch-message-prefix-add nil) |
| 963 | 're-search-forward | 974 | (kill-local-variable 'isearch-lazy-count) |
| 964 | 're-search-backward) | 975 | (setq-local isearch-search-fun-function #'isearch-search-fun-default |
| 965 | isearch-string nil t))) | 976 | isearch-message-function nil |
| 966 | (setq found (eshell-test-imatch))) | 977 | isearch-wrap-function nil |
| 967 | (if (not found) | 978 | isearch-push-state-function nil) |
| 968 | (progn | 979 | (remove-hook 'isearch-mode-end-hook #'eshell-history-isearch-end t) |
| 969 | (goto-char eshell-last-output-end) | 980 | (setq isearch-opoint (point)) |
| 970 | (delete-region (point) (point-max))) | 981 | (unless isearch-suspended |
| 971 | (setq before (point)) | 982 | (setq eshell--force-history-isearch nil))) |
| 972 | (let ((text (buffer-substring-no-properties | 983 | |
| 973 | (point) (line-end-position))) | 984 | (defun eshell-history-isearch-search () |
| 974 | (orig (marker-position eshell-last-output-end))) | 985 | "Return search function for Isearch in input history." |
| 975 | (goto-char eshell-last-output-end) | 986 | (lambda (string bound noerror) |
| 976 | (delete-region (point) (point-max)) | 987 | (let ((search-fun (isearch-search-fun-default)) |
| 977 | (when (and text (> (length text) 0)) | 988 | (found nil)) |
| 978 | (insert text) | 989 | ;; Avoid highlighting matches in and before the last prompt |
| 979 | (put-text-property (1- (point)) (point) | 990 | (when (and bound isearch-forward |
| 980 | 'last-search-pos before) | 991 | (< (point) eshell-last-output-end)) |
| 981 | (set-marker eshell-last-output-end orig) | 992 | (goto-char eshell-last-output-end)) |
| 982 | (goto-char eshell-last-output-end)))))) | 993 | (or |
| 983 | 994 | ;; First search in the initial input | |
| 984 | (defun eshell-prepare-for-search () | 995 | (funcall search-fun string |
| 985 | "Make sure the old history file is at the beginning of the buffer." | 996 | (if isearch-forward bound eshell-last-output-end) |
| 986 | (unless (get-text-property (point-min) 'history) | 997 | noerror) |
| 987 | (save-excursion | 998 | ;; Then search in the input history: put next/previous history |
| 988 | (goto-char (point-min)) | 999 | ;; element in the command line successively, then search the |
| 989 | (let ((end (copy-marker (point) t))) | 1000 | ;; string in the command line. Do this only when not |
| 990 | (insert-file-contents eshell-history-file-name) | 1001 | ;; lazy-highlighting (`bound' is nil). |
| 991 | (set-text-properties (point-min) end | 1002 | (unless bound |
| 992 | '(history t invisible t)))))) | 1003 | (condition-case nil |
| 1004 | (progn | ||
| 1005 | (while (not found) | ||
| 1006 | (cond (isearch-forward | ||
| 1007 | ;; Signal an error explicitly to break | ||
| 1008 | (when (or (null eshell-history-index) | ||
| 1009 | (eq eshell-history-index 0)) | ||
| 1010 | (error "End of history; no next item")) | ||
| 1011 | (eshell-next-input 1) | ||
| 1012 | (goto-char eshell-last-output-end)) | ||
| 1013 | (t | ||
| 1014 | ;; Signal an error explicitly to break | ||
| 1015 | (when (eq eshell-history-index | ||
| 1016 | (1- (ring-length eshell-history-ring))) | ||
| 1017 | (error "Beginning of history; no preceding item")) | ||
| 1018 | (eshell-previous-input 1) | ||
| 1019 | (goto-char (point-max)))) | ||
| 1020 | (setq isearch-barrier (point) | ||
| 1021 | isearch-opoint (point)) | ||
| 1022 | ;; After putting an history element in the command | ||
| 1023 | ;; line, search the string in them. | ||
| 1024 | (setq found (funcall search-fun string | ||
| 1025 | (unless isearch-forward | ||
| 1026 | eshell-last-output-end) | ||
| 1027 | noerror))) | ||
| 1028 | (point)) | ||
| 1029 | ;; Return when no next/preceding element error signaled | ||
| 1030 | (error nil))))))) | ||
| 1031 | |||
| 1032 | (defun eshell-history-isearch-message (&optional c-q-hack ellipsis) | ||
| 1033 | "Display the input history search prompt. | ||
| 1034 | If there are no search errors, this function displays an overlay with | ||
| 1035 | the Isearch prompt which replaces the original Eshell prompt. | ||
| 1036 | Otherwise, it displays the standard Isearch message returned from the | ||
| 1037 | function `isearch-message'." | ||
| 1038 | (if (not (and isearch-success (not isearch-error))) | ||
| 1039 | ;; Use standard message function (which displays a message in the | ||
| 1040 | ;; echo area) when not in command line, or search fails or has | ||
| 1041 | ;; errors (like incomplete regexp). | ||
| 1042 | (isearch-message c-q-hack ellipsis) | ||
| 1043 | ;; Otherwise, use an overlay over the Eshell prompt. | ||
| 1044 | (if (overlayp eshell--history-isearch-message-overlay) | ||
| 1045 | (move-overlay eshell--history-isearch-message-overlay | ||
| 1046 | (save-excursion | ||
| 1047 | (goto-char eshell-last-output-end) | ||
| 1048 | (forward-line 0) | ||
| 1049 | (point)) | ||
| 1050 | eshell-last-output-end) | ||
| 1051 | (setq eshell--history-isearch-message-overlay | ||
| 1052 | (make-overlay (save-excursion | ||
| 1053 | (goto-char eshell-last-output-end) | ||
| 1054 | (forward-line 0) | ||
| 1055 | (point)) | ||
| 1056 | eshell-last-output-end)) | ||
| 1057 | (overlay-put eshell--history-isearch-message-overlay 'evaporate t)) | ||
| 1058 | (overlay-put eshell--history-isearch-message-overlay | ||
| 1059 | 'display (isearch-message-prefix ellipsis | ||
| 1060 | isearch-nonincremental)) | ||
| 1061 | (if (and eshell-history-index (not ellipsis)) | ||
| 1062 | (message "History item: %d" (- (ring-length eshell-history-ring) | ||
| 1063 | eshell-history-index)) | ||
| 1064 | (message "")))) | ||
| 1065 | |||
| 1066 | (defun eshell-history-isearch-wrap () | ||
| 1067 | "Wrap the input history search." | ||
| 1068 | (if isearch-forward | ||
| 1069 | (eshell-goto-history (1- (ring-length eshell-history-ring))) | ||
| 1070 | (eshell-goto-history nil)) | ||
| 1071 | (goto-char (if isearch-forward eshell-last-output-end (point-max)))) | ||
| 1072 | |||
| 1073 | (defun eshell-history-isearch-push-state () | ||
| 1074 | "Save a function restoring the state of input history search. | ||
| 1075 | Save `eshell-history-index' to the additional state parameter in the | ||
| 1076 | search status stack." | ||
| 1077 | (let ((index eshell-history-index)) | ||
| 1078 | (lambda (_cmd) | ||
| 1079 | (eshell-goto-history index)))) | ||
| 993 | 1080 | ||
| 994 | (defun eshell-isearch-backward (&optional invert) | 1081 | (defun eshell-isearch-backward (&optional invert) |
| 995 | "Do incremental regexp search backward through past commands." | 1082 | "Do incremental search backward through past commands." |
| 996 | (interactive) | 1083 | (interactive nil eshell-mode) |
| 997 | (let ((inhibit-read-only t)) | 1084 | (setq eshell--force-history-isearch t) |
| 998 | (eshell-prepare-for-search) | 1085 | (if invert |
| 999 | (goto-char (point-max)) | 1086 | (isearch-forward nil t) |
| 1000 | (set-marker eshell-last-output-end (point)) | 1087 | (isearch-backward nil t))) |
| 1001 | (delete-region (point) (point-max))) | ||
| 1002 | (isearch-mode invert t 'eshell-return-to-prompt)) | ||
| 1003 | |||
| 1004 | (defun eshell-isearch-repeat-backward (&optional invert) | ||
| 1005 | "Do incremental regexp search backward through past commands." | ||
| 1006 | (interactive) | ||
| 1007 | (let ((old-pos (get-text-property (1- (point-max)) | ||
| 1008 | 'last-search-pos))) | ||
| 1009 | (when old-pos | ||
| 1010 | (goto-char old-pos) | ||
| 1011 | (if invert | ||
| 1012 | (end-of-line) | ||
| 1013 | (backward-char))) | ||
| 1014 | (setq isearch-forward invert) | ||
| 1015 | (isearch-search-and-update))) | ||
| 1016 | 1088 | ||
| 1017 | (defun eshell-isearch-forward () | 1089 | (defun eshell-isearch-forward () |
| 1018 | "Do incremental regexp search backward through past commands." | 1090 | "Do incremental search forward through past commands." |
| 1019 | (interactive) | 1091 | (interactive nil eshell-mode) |
| 1020 | (eshell-isearch-backward t)) | 1092 | (eshell-isearch-backward t)) |
| 1021 | 1093 | ||
| 1022 | (defun eshell-isearch-repeat-forward () | 1094 | (defun eshell-isearch-backward-regexp (&optional invert) |
| 1023 | "Do incremental regexp search backward through past commands." | 1095 | "Do incremental regexp search backward through past commands." |
| 1024 | (interactive) | 1096 | (interactive nil eshell-mode) |
| 1025 | (eshell-isearch-repeat-backward t)) | 1097 | (setq eshell--force-history-isearch t) |
| 1026 | 1098 | (if invert | |
| 1027 | (defun eshell-isearch-cancel () | 1099 | (isearch-forward-regexp nil t) |
| 1028 | (interactive) | 1100 | (isearch-backward-regexp nil t))) |
| 1029 | (goto-char eshell-last-output-end) | 1101 | |
| 1030 | (delete-region (point) (point-max)) | 1102 | (defun eshell-isearch-forward-regexp () |
| 1031 | (call-interactively 'isearch-cancel)) | 1103 | "Do incremental regexp search forward through past commands." |
| 1032 | 1104 | (interactive nil eshell-mode) | |
| 1033 | (defun eshell-isearch-abort () | 1105 | (eshell-isearch-backward-regexp t)) |
| 1034 | (interactive) | ||
| 1035 | (goto-char eshell-last-output-end) | ||
| 1036 | (delete-region (point) (point-max)) | ||
| 1037 | (call-interactively 'isearch-abort)) | ||
| 1038 | |||
| 1039 | (defun eshell-isearch-delete-char () | ||
| 1040 | (interactive) | ||
| 1041 | (save-excursion | ||
| 1042 | (isearch-delete-char))) | ||
| 1043 | |||
| 1044 | (defun eshell-isearch-return () | ||
| 1045 | (interactive) | ||
| 1046 | (isearch-done) | ||
| 1047 | (eshell-send-input)) | ||
| 1048 | 1106 | ||
| 1049 | (defun em-hist-unload-function () | 1107 | (defun em-hist-unload-function () |
| 1050 | (remove-hook 'kill-emacs-hook 'eshell-save-some-history)) | 1108 | (remove-hook 'kill-emacs-hook 'eshell-save-some-history)) |