diff options
| author | Basil L. Contovounesios | 2018-04-29 15:37:45 +0100 |
|---|---|---|
| committer | Noam Postavsky | 2018-05-02 20:18:07 -0400 |
| commit | f2c74543edc7e8d07655b459ba8898eec9b6d4e8 (patch) | |
| tree | b6612a1370f9c20399e8fa32ff50be643a0ecabd | |
| parent | 05e9477ab5d5dba1b960415d60b9957caa90da48 (diff) | |
| download | emacs-f2c74543edc7e8d07655b459ba8898eec9b6d4e8.tar.gz emacs-f2c74543edc7e8d07655b459ba8898eec9b6d4e8.zip | |
Fix off-by-one history pruning (bug#31211)
* lisp/subr.el (add-to-history): Clarify docstring.
Protect against negative history-length and unnecessary variable
modification, as per read_minibuf.
* lisp/ido.el (ido-record-command):
* lisp/international/mule-cmds.el (deactivate-input-method):
(set-language-environment-input-method):
* lisp/isearch.el (isearch-done):
* lisp/minibuffer.el (read-file-name-default):
* lisp/net/eww.el (eww-save-history):
* lisp/simple.el (edit-and-eval-command, repeat-complex-command):
(command-execute, kill-new, push-mark):
* src/callint.c (Fcall_interactively):
* src/minibuf.c (read_minibuf): Delegate to add-to-history.
* test/lisp/simple-tests.el (command-execute-prune-command-history):
* test/src/callint-tests.el
(call-interactively-prune-command-history): New tests.
| -rw-r--r-- | lisp/ido.el | 7 | ||||
| -rw-r--r-- | lisp/international/mule-cmds.el | 13 | ||||
| -rw-r--r-- | lisp/isearch.el | 13 | ||||
| -rw-r--r-- | lisp/minibuffer.el | 14 | ||||
| -rw-r--r-- | lisp/net/eww.el | 10 | ||||
| -rw-r--r-- | lisp/simple.el | 49 | ||||
| -rw-r--r-- | lisp/subr.el | 8 | ||||
| -rw-r--r-- | src/callint.c | 27 | ||||
| -rw-r--r-- | src/minibuf.c | 40 | ||||
| -rw-r--r-- | test/lisp/simple-tests.el | 11 | ||||
| -rw-r--r-- | test/src/callint-tests.el | 8 |
11 files changed, 68 insertions, 132 deletions
diff --git a/lisp/ido.el b/lisp/ido.el index 7ff3d6820b4..705e7dd6301 100644 --- a/lisp/ido.el +++ b/lisp/ido.el | |||
| @@ -1793,11 +1793,8 @@ is enabled then some keybindings are changed in the keymap." | |||
| 1793 | 1793 | ||
| 1794 | (defun ido-record-command (command arg) | 1794 | (defun ido-record-command (command arg) |
| 1795 | "Add (COMMAND ARG) to `command-history' if `ido-record-commands' is non-nil." | 1795 | "Add (COMMAND ARG) to `command-history' if `ido-record-commands' is non-nil." |
| 1796 | (if ido-record-commands ; FIXME: use `when' instead of `if'? | 1796 | (when ido-record-commands |
| 1797 | (let ((cmd (list command arg))) | 1797 | (add-to-history 'command-history (list command arg)))) |
| 1798 | (if (or (not command-history) ; FIXME: ditto | ||
| 1799 | (not (equal cmd (car command-history)))) | ||
| 1800 | (setq command-history (cons cmd command-history)))))) | ||
| 1801 | 1798 | ||
| 1802 | (defun ido-make-prompt (item prompt) | 1799 | (defun ido-make-prompt (item prompt) |
| 1803 | ;; Make the prompt for ido-read-internal | 1800 | ;; Make the prompt for ido-read-internal |
diff --git a/lisp/international/mule-cmds.el b/lisp/international/mule-cmds.el index 6c49b8fa6a0..c0b329bbaea 100644 --- a/lisp/international/mule-cmds.el +++ b/lisp/international/mule-cmds.el | |||
| @@ -1464,12 +1464,7 @@ If INPUT-METHOD is nil, deactivate any current input method." | |||
| 1464 | (defun deactivate-input-method () | 1464 | (defun deactivate-input-method () |
| 1465 | "Turn off the current input method." | 1465 | "Turn off the current input method." |
| 1466 | (when current-input-method | 1466 | (when current-input-method |
| 1467 | (if input-method-history | 1467 | (add-to-history 'input-method-history current-input-method) |
| 1468 | (unless (string= current-input-method (car input-method-history)) | ||
| 1469 | (setq input-method-history | ||
| 1470 | (cons current-input-method | ||
| 1471 | (delete current-input-method input-method-history)))) | ||
| 1472 | (setq input-method-history (list current-input-method))) | ||
| 1473 | (unwind-protect | 1468 | (unwind-protect |
| 1474 | (progn | 1469 | (progn |
| 1475 | (setq input-method-function nil | 1470 | (setq input-method-function nil |
| @@ -2022,10 +2017,8 @@ See `set-language-info-alist' for use in programs." | |||
| 2022 | (let ((input-method (get-language-info language-name 'input-method))) | 2017 | (let ((input-method (get-language-info language-name 'input-method))) |
| 2023 | (when input-method | 2018 | (when input-method |
| 2024 | (setq default-input-method input-method) | 2019 | (setq default-input-method input-method) |
| 2025 | (if input-method-history | 2020 | (when input-method-history |
| 2026 | (setq input-method-history | 2021 | (add-to-history 'input-method-history input-method))))) |
| 2027 | (cons input-method | ||
| 2028 | (delete input-method input-method-history))))))) | ||
| 2029 | 2022 | ||
| 2030 | (defun set-language-environment-nonascii-translation (language-name) | 2023 | (defun set-language-environment-nonascii-translation (language-name) |
| 2031 | "Do unibyte/multibyte translation setup for language environment LANGUAGE-NAME." | 2024 | "Do unibyte/multibyte translation setup for language environment LANGUAGE-NAME." |
diff --git a/lisp/isearch.el b/lisp/isearch.el index 5cbb4c941a5..feadf10e8b7 100644 --- a/lisp/isearch.el +++ b/lisp/isearch.el | |||
| @@ -1049,13 +1049,12 @@ For a failing search, NOPUSH is t. | |||
| 1049 | For going to the minibuffer to edit the search string, | 1049 | For going to the minibuffer to edit the search string, |
| 1050 | NOPUSH is t and EDIT is t." | 1050 | NOPUSH is t and EDIT is t." |
| 1051 | 1051 | ||
| 1052 | (if isearch-resume-in-command-history | 1052 | (when isearch-resume-in-command-history |
| 1053 | (let ((command `(isearch-resume ,isearch-string ,isearch-regexp | 1053 | (add-to-history 'command-history |
| 1054 | ,isearch-regexp-function ,isearch-forward | 1054 | `(isearch-resume ,isearch-string ,isearch-regexp |
| 1055 | ,isearch-message | 1055 | ,isearch-regexp-function ,isearch-forward |
| 1056 | ',isearch-case-fold-search))) | 1056 | ,isearch-message |
| 1057 | (unless (equal (car command-history) command) | 1057 | ',isearch-case-fold-search))) |
| 1058 | (setq command-history (cons command command-history))))) | ||
| 1059 | 1058 | ||
| 1060 | (remove-hook 'pre-command-hook 'isearch-pre-command-hook) | 1059 | (remove-hook 'pre-command-hook 'isearch-pre-command-hook) |
| 1061 | (remove-hook 'post-command-hook 'isearch-post-command-hook) | 1060 | (remove-hook 'post-command-hook 'isearch-post-command-hook) |
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el index f1cbdc0cc36..a7e6a8761ff 100644 --- a/lisp/minibuffer.el +++ b/lisp/minibuffer.el | |||
| @@ -2722,17 +2722,9 @@ See `read-file-name' for the meaning of the arguments." | |||
| 2722 | (if (string= val1 (cadr file-name-history)) | 2722 | (if (string= val1 (cadr file-name-history)) |
| 2723 | (pop file-name-history) | 2723 | (pop file-name-history) |
| 2724 | (setcar file-name-history val1))) | 2724 | (setcar file-name-history val1))) |
| 2725 | (if add-to-history | 2725 | (when add-to-history |
| 2726 | ;; Add the value to the history--but not if it matches | 2726 | (add-to-history 'file-name-history |
| 2727 | ;; the last value already there. | 2727 | (minibuffer-maybe-quote-filename val)))) |
| 2728 | (let ((val1 (minibuffer-maybe-quote-filename val))) | ||
| 2729 | (unless (and (consp file-name-history) | ||
| 2730 | (equal (car file-name-history) val1)) | ||
| 2731 | (setq file-name-history | ||
| 2732 | (cons val1 | ||
| 2733 | (if history-delete-duplicates | ||
| 2734 | (delete val1 file-name-history) | ||
| 2735 | file-name-history))))))) | ||
| 2736 | val)))) | 2728 | val)))) |
| 2737 | 2729 | ||
| 2738 | (defun internal-complete-buffer-except (&optional buffer) | 2730 | (defun internal-complete-buffer-except (&optional buffer) |
diff --git a/lisp/net/eww.el b/lisp/net/eww.el index e74f661ac75..97fdabd72bd 100644 --- a/lisp/net/eww.el +++ b/lisp/net/eww.el | |||
| @@ -1813,13 +1813,9 @@ If CHARSET is nil then use UTF-8." | |||
| 1813 | (defun eww-save-history () | 1813 | (defun eww-save-history () |
| 1814 | (plist-put eww-data :point (point)) | 1814 | (plist-put eww-data :point (point)) |
| 1815 | (plist-put eww-data :text (buffer-string)) | 1815 | (plist-put eww-data :text (buffer-string)) |
| 1816 | (push eww-data eww-history) | 1816 | (let ((history-delete-duplicates nil)) |
| 1817 | (setq eww-data (list :title "")) | 1817 | (add-to-history 'eww-history eww-data eww-history-limit t)) |
| 1818 | ;; Don't let the history grow infinitely. We store quite a lot of | 1818 | (setq eww-data (list :title ""))) |
| 1819 | ;; data per page. | ||
| 1820 | (when-let* ((tail (and eww-history-limit | ||
| 1821 | (nthcdr eww-history-limit eww-history)))) | ||
| 1822 | (setcdr tail nil))) | ||
| 1823 | 1819 | ||
| 1824 | (defvar eww-current-buffer) | 1820 | (defvar eww-current-buffer) |
| 1825 | 1821 | ||
diff --git a/lisp/simple.el b/lisp/simple.el index 5446159d319..9fde9a5c90a 100644 --- a/lisp/simple.el +++ b/lisp/simple.el | |||
| @@ -1646,13 +1646,10 @@ the minibuffer, then read and evaluate the result." | |||
| 1646 | 'command-history) | 1646 | 'command-history) |
| 1647 | ;; If command was added to command-history as a string, | 1647 | ;; If command was added to command-history as a string, |
| 1648 | ;; get rid of that. We want only evaluable expressions there. | 1648 | ;; get rid of that. We want only evaluable expressions there. |
| 1649 | (if (stringp (car command-history)) | 1649 | (when (stringp (car command-history)) |
| 1650 | (setq command-history (cdr command-history))))))) | 1650 | (pop command-history)))))) |
| 1651 | 1651 | ||
| 1652 | ;; If command to be redone does not match front of history, | 1652 | (add-to-history 'command-history command) |
| 1653 | ;; add it to the history. | ||
| 1654 | (or (equal command (car command-history)) | ||
| 1655 | (setq command-history (cons command command-history))) | ||
| 1656 | (eval command))) | 1653 | (eval command))) |
| 1657 | 1654 | ||
| 1658 | (defun repeat-complex-command (arg) | 1655 | (defun repeat-complex-command (arg) |
| @@ -1682,13 +1679,10 @@ to get different commands to edit and resubmit." | |||
| 1682 | ;; If command was added to command-history as a | 1679 | ;; If command was added to command-history as a |
| 1683 | ;; string, get rid of that. We want only | 1680 | ;; string, get rid of that. We want only |
| 1684 | ;; evaluable expressions there. | 1681 | ;; evaluable expressions there. |
| 1685 | (if (stringp (car command-history)) | 1682 | (when (stringp (car command-history)) |
| 1686 | (setq command-history (cdr command-history)))))) | 1683 | (pop command-history))))) |
| 1687 | 1684 | ||
| 1688 | ;; If command to be redone does not match front of history, | 1685 | (add-to-history 'command-history newcmd) |
| 1689 | ;; add it to the history. | ||
| 1690 | (or (equal newcmd (car command-history)) | ||
| 1691 | (setq command-history (cons newcmd command-history))) | ||
| 1692 | (apply #'funcall-interactively | 1686 | (apply #'funcall-interactively |
| 1693 | (car newcmd) | 1687 | (car newcmd) |
| 1694 | (mapcar (lambda (e) (eval e t)) (cdr newcmd)))) | 1688 | (mapcar (lambda (e) (eval e t)) (cdr newcmd)))) |
| @@ -1905,11 +1899,8 @@ a special event, so ignore the prefix argument and don't clear it." | |||
| 1905 | ;; If requested, place the macro in the command history. For | 1899 | ;; If requested, place the macro in the command history. For |
| 1906 | ;; other sorts of commands, call-interactively takes care of this. | 1900 | ;; other sorts of commands, call-interactively takes care of this. |
| 1907 | (when record-flag | 1901 | (when record-flag |
| 1908 | (push `(execute-kbd-macro ,final ,prefixarg) command-history) | 1902 | (add-to-history |
| 1909 | ;; Don't keep command history around forever. | 1903 | 'command-history `(execute-kbd-macro ,final ,prefixarg) nil t)) |
| 1910 | (when (and (numberp history-length) (> history-length 0)) | ||
| 1911 | (let ((cell (nthcdr history-length command-history))) | ||
| 1912 | (if (consp cell) (setcdr cell nil))))) | ||
| 1913 | (execute-kbd-macro final prefixarg)) | 1904 | (execute-kbd-macro final prefixarg)) |
| 1914 | (t | 1905 | (t |
| 1915 | ;; Pass `cmd' rather than `final', for the backtrace's sake. | 1906 | ;; Pass `cmd' rather than `final', for the backtrace's sake. |
| @@ -4408,9 +4399,8 @@ argument should still be a \"useful\" string for such uses." | |||
| 4408 | (equal-including-properties string (car kill-ring))) | 4399 | (equal-including-properties string (car kill-ring))) |
| 4409 | (if (and replace kill-ring) | 4400 | (if (and replace kill-ring) |
| 4410 | (setcar kill-ring string) | 4401 | (setcar kill-ring string) |
| 4411 | (push string kill-ring) | 4402 | (let ((history-delete-duplicates nil)) |
| 4412 | (if (> (length kill-ring) kill-ring-max) | 4403 | (add-to-history 'kill-ring string kill-ring-max t)))) |
| 4413 | (setcdr (nthcdr (1- kill-ring-max) kill-ring) nil)))) | ||
| 4414 | (setq kill-ring-yank-pointer kill-ring) | 4404 | (setq kill-ring-yank-pointer kill-ring) |
| 4415 | (if interprogram-cut-function | 4405 | (if interprogram-cut-function |
| 4416 | (funcall interprogram-cut-function string))) | 4406 | (funcall interprogram-cut-function string))) |
| @@ -5724,10 +5714,11 @@ purposes. See the documentation of `set-mark' for more information. | |||
| 5724 | 5714 | ||
| 5725 | In Transient Mark mode, activate mark if optional third arg ACTIVATE non-nil." | 5715 | In Transient Mark mode, activate mark if optional third arg ACTIVATE non-nil." |
| 5726 | (unless (null (mark t)) | 5716 | (unless (null (mark t)) |
| 5727 | (setq mark-ring (cons (copy-marker (mark-marker)) mark-ring)) | 5717 | (let ((old (nth mark-ring-max mark-ring)) |
| 5728 | (when (> (length mark-ring) mark-ring-max) | 5718 | (history-delete-duplicates nil)) |
| 5729 | (move-marker (car (nthcdr mark-ring-max mark-ring)) nil) | 5719 | (add-to-history 'mark-ring (copy-marker (mark-marker)) mark-ring-max t) |
| 5730 | (setcdr (nthcdr (1- mark-ring-max) mark-ring) nil))) | 5720 | (when old |
| 5721 | (set-marker old nil)))) | ||
| 5731 | (set-marker (mark-marker) (or location (point)) (current-buffer)) | 5722 | (set-marker (mark-marker) (or location (point)) (current-buffer)) |
| 5732 | ;; Now push the mark on the global mark ring. | 5723 | ;; Now push the mark on the global mark ring. |
| 5733 | (if (and global-mark-ring | 5724 | (if (and global-mark-ring |
| @@ -5735,10 +5726,12 @@ In Transient Mark mode, activate mark if optional third arg ACTIVATE non-nil." | |||
| 5735 | ;; The last global mark pushed was in this same buffer. | 5726 | ;; The last global mark pushed was in this same buffer. |
| 5736 | ;; Don't push another one. | 5727 | ;; Don't push another one. |
| 5737 | nil | 5728 | nil |
| 5738 | (setq global-mark-ring (cons (copy-marker (mark-marker)) global-mark-ring)) | 5729 | (let ((old (nth global-mark-ring-max global-mark-ring)) |
| 5739 | (when (> (length global-mark-ring) global-mark-ring-max) | 5730 | (history-delete-duplicates nil)) |
| 5740 | (move-marker (car (nthcdr global-mark-ring-max global-mark-ring)) nil) | 5731 | (add-to-history |
| 5741 | (setcdr (nthcdr (1- global-mark-ring-max) global-mark-ring) nil))) | 5732 | 'global-mark-ring (copy-marker (mark-marker)) global-mark-ring-max t) |
| 5733 | (when old | ||
| 5734 | (set-marker old nil)))) | ||
| 5742 | (or nomsg executing-kbd-macro (> (minibuffer-depth) 0) | 5735 | (or nomsg executing-kbd-macro (> (minibuffer-depth) 0) |
| 5743 | (message "Mark set")) | 5736 | (message "Mark set")) |
| 5744 | (if (or activate (not transient-mark-mode)) | 5737 | (if (or activate (not transient-mark-mode)) |
diff --git a/lisp/subr.el b/lisp/subr.el index 9f6cade0f71..35e220a10ee 100644 --- a/lisp/subr.el +++ b/lisp/subr.el | |||
| @@ -1798,7 +1798,7 @@ variable. The possible values of maximum length have the same meaning as | |||
| 1798 | the values of `history-length'. | 1798 | the values of `history-length'. |
| 1799 | Remove duplicates of NEWELT if `history-delete-duplicates' is non-nil. | 1799 | Remove duplicates of NEWELT if `history-delete-duplicates' is non-nil. |
| 1800 | If optional fourth arg KEEP-ALL is non-nil, add NEWELT to history even | 1800 | If optional fourth arg KEEP-ALL is non-nil, add NEWELT to history even |
| 1801 | if it is empty or a duplicate." | 1801 | if it is empty or duplicates the most recent entry in the history." |
| 1802 | (unless maxelt | 1802 | (unless maxelt |
| 1803 | (setq maxelt (or (get history-var 'history-length) | 1803 | (setq maxelt (or (get history-var 'history-length) |
| 1804 | history-length))) | 1804 | history-length))) |
| @@ -1814,12 +1814,12 @@ if it is empty or a duplicate." | |||
| 1814 | (setq history (delete newelt history))) | 1814 | (setq history (delete newelt history))) |
| 1815 | (setq history (cons newelt history)) | 1815 | (setq history (cons newelt history)) |
| 1816 | (when (integerp maxelt) | 1816 | (when (integerp maxelt) |
| 1817 | (if (= 0 maxelt) | 1817 | (if (>= 0 maxelt) |
| 1818 | (setq history nil) | 1818 | (setq history nil) |
| 1819 | (setq tail (nthcdr (1- maxelt) history)) | 1819 | (setq tail (nthcdr (1- maxelt) history)) |
| 1820 | (when (consp tail) | 1820 | (when (consp tail) |
| 1821 | (setcdr tail nil))))) | 1821 | (setcdr tail nil)))) |
| 1822 | (set history-var history))) | 1822 | (set history-var history)))) |
| 1823 | 1823 | ||
| 1824 | 1824 | ||
| 1825 | ;;;; Mode hooks. | 1825 | ;;;; Mode hooks. |
diff --git a/src/callint.c b/src/callint.c index 08a8bba4646..fd44494cfee 100644 --- a/src/callint.c +++ b/src/callint.c | |||
| @@ -262,7 +262,7 @@ to the function `interactive' at the top level of the function body. | |||
| 262 | See `interactive'. | 262 | See `interactive'. |
| 263 | 263 | ||
| 264 | Optional second arg RECORD-FLAG non-nil | 264 | Optional second arg RECORD-FLAG non-nil |
| 265 | means unconditionally put this command in the command-history. | 265 | means unconditionally put this command in the variable `command-history'. |
| 266 | Otherwise, this is done only if an arg is read using the minibuffer. | 266 | Otherwise, this is done only if an arg is read using the minibuffer. |
| 267 | 267 | ||
| 268 | Optional third arg KEYS, if given, specifies the sequence of events to | 268 | Optional third arg KEYS, if given, specifies the sequence of events to |
| @@ -328,18 +328,8 @@ invoke it. If KEYS is omitted or nil, the return value of | |||
| 328 | and turn them into things we can eval. */ | 328 | and turn them into things we can eval. */ |
| 329 | Lisp_Object values = quotify_args (Fcopy_sequence (specs)); | 329 | Lisp_Object values = quotify_args (Fcopy_sequence (specs)); |
| 330 | fix_command (input, values); | 330 | fix_command (input, values); |
| 331 | Lisp_Object this_cmd = Fcons (function, values); | 331 | call4 (intern ("add-to-history"), intern ("command-history"), |
| 332 | if (history_delete_duplicates) | 332 | Fcons (function, values), Qnil, Qt); |
| 333 | Vcommand_history = Fdelete (this_cmd, Vcommand_history); | ||
| 334 | Vcommand_history = Fcons (this_cmd, Vcommand_history); | ||
| 335 | |||
| 336 | /* Don't keep command history around forever. */ | ||
| 337 | if (INTEGERP (Vhistory_length) && XINT (Vhistory_length) > 0) | ||
| 338 | { | ||
| 339 | Lisp_Object teml = Fnthcdr (Vhistory_length, Vcommand_history); | ||
| 340 | if (CONSP (teml)) | ||
| 341 | XSETCDR (teml, Qnil); | ||
| 342 | } | ||
| 343 | } | 333 | } |
| 344 | 334 | ||
| 345 | Vthis_command = save_this_command; | 335 | Vthis_command = save_this_command; |
| @@ -768,15 +758,8 @@ invoke it. If KEYS is omitted or nil, the return value of | |||
| 768 | visargs[i] = (varies[i] > 0 | 758 | visargs[i] = (varies[i] > 0 |
| 769 | ? list1 (intern (callint_argfuns[varies[i]])) | 759 | ? list1 (intern (callint_argfuns[varies[i]])) |
| 770 | : quotify_arg (args[i])); | 760 | : quotify_arg (args[i])); |
| 771 | Vcommand_history = Fcons (Flist (nargs - 1, visargs + 1), | 761 | call4 (intern ("add-to-history"), intern ("command-history"), |
| 772 | Vcommand_history); | 762 | Flist (nargs - 1, visargs + 1), Qnil, Qt); |
| 773 | /* Don't keep command history around forever. */ | ||
| 774 | if (INTEGERP (Vhistory_length) && XINT (Vhistory_length) > 0) | ||
| 775 | { | ||
| 776 | Lisp_Object teml = Fnthcdr (Vhistory_length, Vcommand_history); | ||
| 777 | if (CONSP (teml)) | ||
| 778 | XSETCDR (teml, Qnil); | ||
| 779 | } | ||
| 780 | } | 763 | } |
| 781 | 764 | ||
| 782 | /* If we used a marker to hold point, mark, or an end of the region, | 765 | /* If we used a marker to hold point, mark, or an end of the region, |
diff --git a/src/minibuf.c b/src/minibuf.c index c41958d85f9..e18c99bef28 100644 --- a/src/minibuf.c +++ b/src/minibuf.c | |||
| @@ -702,44 +702,8 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt, | |||
| 702 | histstring = Qnil; | 702 | histstring = Qnil; |
| 703 | 703 | ||
| 704 | /* Add the value to the appropriate history list, if any. */ | 704 | /* Add the value to the appropriate history list, if any. */ |
| 705 | if (!NILP (Vhistory_add_new_input) | 705 | if (! (NILP (Vhistory_add_new_input) || NILP (histstring))) |
| 706 | && SYMBOLP (Vminibuffer_history_variable) | 706 | call2 (intern ("add-to-history"), Vminibuffer_history_variable, histstring); |
| 707 | && !NILP (histstring)) | ||
| 708 | { | ||
| 709 | /* If the caller wanted to save the value read on a history list, | ||
| 710 | then do so if the value is not already the front of the list. */ | ||
| 711 | |||
| 712 | /* The value of the history variable must be a cons or nil. Other | ||
| 713 | values are unacceptable. We silently ignore these values. */ | ||
| 714 | |||
| 715 | if (NILP (histval) | ||
| 716 | || (CONSP (histval) | ||
| 717 | /* Don't duplicate the most recent entry in the history. */ | ||
| 718 | && (NILP (Fequal (histstring, Fcar (histval)))))) | ||
| 719 | { | ||
| 720 | Lisp_Object length; | ||
| 721 | |||
| 722 | if (history_delete_duplicates) Fdelete (histstring, histval); | ||
| 723 | histval = Fcons (histstring, histval); | ||
| 724 | Fset (Vminibuffer_history_variable, histval); | ||
| 725 | |||
| 726 | /* Truncate if requested. */ | ||
| 727 | length = Fget (Vminibuffer_history_variable, Qhistory_length); | ||
| 728 | if (NILP (length)) length = Vhistory_length; | ||
| 729 | if (INTEGERP (length)) | ||
| 730 | { | ||
| 731 | if (XINT (length) <= 0) | ||
| 732 | Fset (Vminibuffer_history_variable, Qnil); | ||
| 733 | else | ||
| 734 | { | ||
| 735 | Lisp_Object temp; | ||
| 736 | |||
| 737 | temp = Fnthcdr (Fsub1 (length), histval); | ||
| 738 | if (CONSP (temp)) Fsetcdr (temp, Qnil); | ||
| 739 | } | ||
| 740 | } | ||
| 741 | } | ||
| 742 | } | ||
| 743 | 707 | ||
| 744 | /* If Lisp form desired instead of string, parse it. */ | 708 | /* If Lisp form desired instead of string, parse it. */ |
| 745 | if (expflag) | 709 | if (expflag) |
diff --git a/test/lisp/simple-tests.el b/test/lisp/simple-tests.el index 64b341bd469..7a10df20587 100644 --- a/test/lisp/simple-tests.el +++ b/test/lisp/simple-tests.el | |||
| @@ -448,6 +448,17 @@ See Bug#21722." | |||
| 448 | (call-interactively #'eval-expression) | 448 | (call-interactively #'eval-expression) |
| 449 | (should (equal (current-message) "66 (#o102, #x42, ?B)")))))) | 449 | (should (equal (current-message) "66 (#o102, #x42, ?B)")))))) |
| 450 | 450 | ||
| 451 | (ert-deftest command-execute-prune-command-history () | ||
| 452 | "Check that Bug#31211 is fixed." | ||
| 453 | (let ((history-length 1) | ||
| 454 | (command-history ())) | ||
| 455 | (dotimes (_ (1+ history-length)) | ||
| 456 | (command-execute "" t)) | ||
| 457 | (should (= (length command-history) history-length)))) | ||
| 458 | |||
| 459 | |||
| 460 | ;;; `line-number-at-pos' | ||
| 461 | |||
| 451 | (ert-deftest line-number-at-pos-in-widen-buffer () | 462 | (ert-deftest line-number-at-pos-in-widen-buffer () |
| 452 | (let ((target-line 3)) | 463 | (let ((target-line 3)) |
| 453 | (with-temp-buffer | 464 | (with-temp-buffer |
diff --git a/test/src/callint-tests.el b/test/src/callint-tests.el index 9a812223ad0..feee9b692b7 100644 --- a/test/src/callint-tests.el +++ b/test/src/callint-tests.el | |||
| @@ -43,4 +43,12 @@ | |||
| 43 | (list a b)))) | 43 | (list a b)))) |
| 44 | '("a" "b")))) | 44 | '("a" "b")))) |
| 45 | 45 | ||
| 46 | (ert-deftest call-interactively-prune-command-history () | ||
| 47 | "Check that Bug#31211 is fixed." | ||
| 48 | (let ((history-length 1) | ||
| 49 | (command-history ())) | ||
| 50 | (dotimes (_ (1+ history-length)) | ||
| 51 | (call-interactively #'ignore t)) | ||
| 52 | (should (= (length command-history) history-length)))) | ||
| 53 | |||
| 46 | ;;; callint-tests.el ends here | 54 | ;;; callint-tests.el ends here |