Improve read/append behavior of eshell history command
* lisp/eshell/em-hist.el (eshell-hist--new-items): New variable. (eshell-hist-initialize): Initialize 'eshell-hist--new-items' to 0. (eshell/history): Change the behavior of 'history -a' to "append new history in current buffer to history file". Clarify the help text of 'history -r'. (eshell-add-input-to-history): Increase counter of new history items. (eshell-read-history): Respect 'eshell-hist-ignoredups' option. (eshell-write-history): If the optional argument APPEND is non-nil, appending new history items rather than the whole history. * test/lisp/eshell/em-hist-tests.el (em-hist-test/history-append) (em-hist-test/history-read): New tests (bug#66768).
This commit is contained in:
parent
400a71b8f2
commit
8b3969006f
2 changed files with 67 additions and 16 deletions
|
@ -195,6 +195,9 @@ element, regardless of any text on the command line. In that case,
|
|||
(defvar eshell-history-index nil)
|
||||
(defvar eshell-matching-input-from-input-string "")
|
||||
(defvar eshell-save-history-index nil)
|
||||
(defvar eshell-hist--new-items nil
|
||||
"The number of new history items that have not been written to
|
||||
file. This variable is local in each eshell buffer.")
|
||||
|
||||
(defvar-keymap eshell-isearch-map
|
||||
:doc "Keymap used in isearch in Eshell."
|
||||
|
@ -283,6 +286,7 @@ Returns nil if INPUT is prepended by blank space, otherwise non-nil."
|
|||
|
||||
(make-local-variable 'eshell-history-index)
|
||||
(make-local-variable 'eshell-save-history-index)
|
||||
(setq-local eshell-hist--new-items 0)
|
||||
|
||||
(if (minibuffer-window-active-p (selected-window))
|
||||
(setq-local eshell-save-history-on-exit nil)
|
||||
|
@ -323,11 +327,11 @@ Returns nil if INPUT is prepended by blank space, otherwise non-nil."
|
|||
(eshell-eval-using-options
|
||||
"history" args
|
||||
'((?r "read" nil read-history
|
||||
"read from history file to current history list")
|
||||
"clear current history list and read from history file to it")
|
||||
(?w "write" nil write-history
|
||||
"write current history list to history file")
|
||||
(?a "append" nil append-history
|
||||
"append current history list to history file")
|
||||
"append new history in current buffer to history file")
|
||||
(?h "help" nil nil "display this usage message")
|
||||
:usage "[n] [-rwa [filename]]"
|
||||
:post-usage
|
||||
|
@ -394,6 +398,8 @@ input."
|
|||
(_ ; Add if not already the latest entry
|
||||
(or (ring-empty-p eshell-history-ring)
|
||||
(not (string-equal (eshell-get-history 0) input))))))
|
||||
(setq eshell-hist--new-items
|
||||
(min eshell-history-size (1+ eshell-hist--new-items)))
|
||||
(eshell-put-history input))
|
||||
(setq eshell-save-history-index eshell-history-index)
|
||||
(setq eshell-history-index nil))
|
||||
|
@ -455,21 +461,30 @@ line, with the most recent command last. See also
|
|||
(re-search-backward "^[ \t]*\\([^#\n].*\\)[ \t]*$"
|
||||
nil t))
|
||||
(let ((history (match-string 1)))
|
||||
(if (or (null ignore-dups)
|
||||
(ring-empty-p ring)
|
||||
(not (string-equal (ring-ref ring 0) history)))
|
||||
(ring-insert-at-beginning
|
||||
ring (subst-char-in-string ?\177 ?\n history))))
|
||||
(setq count (1+ count))))
|
||||
(when (or (ring-empty-p ring)
|
||||
(null ignore-dups)
|
||||
(and (not (string-equal
|
||||
(ring-ref ring (1- (ring-length ring)))
|
||||
history))
|
||||
(not (and (eq ignore-dups 'erase)
|
||||
(ring-member ring history)))))
|
||||
(ring-insert-at-beginning
|
||||
ring (subst-char-in-string ?\177 ?\n history))
|
||||
(setq count (1+ count))))))
|
||||
(setq eshell-history-ring ring
|
||||
eshell-history-index nil))))))
|
||||
eshell-history-index nil
|
||||
eshell-hist--new-items 0))))))
|
||||
|
||||
(defun eshell-write-history (&optional filename append)
|
||||
"Writes the buffer's `eshell-history-ring' to a history file.
|
||||
The name of the file is given by the variable
|
||||
`eshell-history-file-name'. The original contents of the file are
|
||||
lost if `eshell-history-ring' is not empty. If
|
||||
`eshell-history-file-name' is nil this function does nothing.
|
||||
If the optional argument FILENAME is nil, the value of
|
||||
`eshell-history-file-name' is used. This function does nothing
|
||||
if the value resolves to nil.
|
||||
|
||||
If the optional argument APPEND is non-nil, then append new
|
||||
history items to the history file. Otherwise, overwrite the
|
||||
contents of the file with `eshell-history-ring' (so long as it is
|
||||
not empty).
|
||||
|
||||
Useful within process sentinels.
|
||||
|
||||
|
@ -480,13 +495,14 @@ See also `eshell-read-history'."
|
|||
((or (null file)
|
||||
(equal file "")
|
||||
(null eshell-history-ring)
|
||||
(ring-empty-p eshell-history-ring))
|
||||
(ring-empty-p eshell-history-ring)
|
||||
(and append (= eshell-hist--new-items 0)))
|
||||
nil)
|
||||
((not (file-writable-p resolved-file))
|
||||
(message "Cannot write history file %s" resolved-file))
|
||||
(t
|
||||
(let* ((ring eshell-history-ring)
|
||||
(index (ring-length ring)))
|
||||
(index (if append eshell-hist--new-items (ring-length ring))))
|
||||
;; Write it all out into a buffer first. Much faster, but
|
||||
;; messier, than writing it one line at a time.
|
||||
(with-temp-buffer
|
||||
|
@ -499,7 +515,8 @@ See also `eshell-read-history'."
|
|||
(subst-char-in-region start (1- (point)) ?\n ?\177)))
|
||||
(eshell-with-private-file-modes
|
||||
(write-region (point-min) (point-max) resolved-file append
|
||||
'no-message))))))))
|
||||
'no-message)))
|
||||
(setq eshell-hist--new-items 0))))))
|
||||
|
||||
(defun eshell-list-history ()
|
||||
"List in help buffer the buffer's input history."
|
||||
|
|
|
@ -41,6 +41,40 @@
|
|||
(propertize "echo bar" 'read-only t))
|
||||
(eshell-write-history histfile))))
|
||||
|
||||
(ert-deftest em-hist-test/history-append ()
|
||||
"Test 'history -a'."
|
||||
(ert-with-temp-file histfile
|
||||
(with-temp-eshell
|
||||
(let ((eshell-history-file-name histfile))
|
||||
(eshell-insert-command "echo hi")
|
||||
(eshell-insert-command "history -w")
|
||||
(eshell-insert-command "history -a")
|
||||
(eshell-insert-command "echo bye")
|
||||
(eshell-insert-command "history -a")
|
||||
(eshell-insert-command "history -r")
|
||||
(should (equal (ring-elements eshell-history-ring)
|
||||
'("history -a" "echo bye"
|
||||
"history -a" "history -w" "echo hi")))))))
|
||||
|
||||
(ert-deftest em-hist-test/history-read ()
|
||||
"Test 'history -r'."
|
||||
(ert-with-temp-file histfile
|
||||
(with-temp-eshell
|
||||
(let ((eshell-history-file-name histfile))
|
||||
(eshell-insert-command "echo hi")
|
||||
(eshell-insert-command "echo bye")
|
||||
(eshell-insert-command "echo bye")
|
||||
(eshell-insert-command "echo hi")
|
||||
(eshell-insert-command "history -w")
|
||||
(let ((eshell-hist-ignoredups t))
|
||||
(eshell-insert-command "history -r")
|
||||
(should (equal (ring-elements eshell-history-ring)
|
||||
'("history -w" "echo hi" "echo bye" "echo hi"))))
|
||||
(let ((eshell-hist-ignoredups 'erase))
|
||||
(eshell-insert-command "history -r")
|
||||
(should (equal (ring-elements eshell-history-ring)
|
||||
'("history -w" "echo hi" "echo bye"))))))))
|
||||
|
||||
(ert-deftest em-hist-test/add-to-history/allow-dups ()
|
||||
"Test adding to history, allowing dups."
|
||||
(let ((eshell-hist-ignoredups nil))
|
||||
|
|
Loading…
Add table
Reference in a new issue