aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBasil L. Contovounesios2018-04-29 15:37:45 +0100
committerNoam Postavsky2018-05-02 20:18:07 -0400
commitf2c74543edc7e8d07655b459ba8898eec9b6d4e8 (patch)
treeb6612a1370f9c20399e8fa32ff50be643a0ecabd /src
parent05e9477ab5d5dba1b960415d60b9957caa90da48 (diff)
downloademacs-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.
Diffstat (limited to 'src')
-rw-r--r--src/callint.c27
-rw-r--r--src/minibuf.c40
2 files changed, 7 insertions, 60 deletions
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.
262See `interactive'. 262See `interactive'.
263 263
264Optional second arg RECORD-FLAG non-nil 264Optional second arg RECORD-FLAG non-nil
265means unconditionally put this command in the command-history. 265means unconditionally put this command in the variable `command-history'.
266Otherwise, this is done only if an arg is read using the minibuffer. 266Otherwise, this is done only if an arg is read using the minibuffer.
267 267
268Optional third arg KEYS, if given, specifies the sequence of events to 268Optional 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)