+2015-06-26 Patrick Palka <patrick@parcs.ath.cx>
+
+ * NEWS: Mention the new option "history remove-duplicates".
+ * top.c (history_remove_duplicates): New static variable.
+ (show_history_remove_duplicates): New static function.
+ (gdb_add_history): Conditionally remove duplicate history
+ entries.
+ (init_main): Add "history remove-duplicates" option.
+
2015-06-26 Patrick Palka <patrick@parcs.ath.cx>
* tui/tui-win.c (focus_completer): New static function.
to avoid generating large completion lists, the computation of
which can cause the debugger to become temporarily unresponsive.
+set history remove-duplicates
+show history remove-duplicates
+ Control the removal of duplicate history entries.
+
maint set symbol-cache-size
maint show symbol-cache-size
Control the size of the symbol cache.
+2015-06-26 Patrick Palka <patrick@parcs.ath.cx>
+
+ * gdb.texinfo (Command History): Document the new option
+ "history remove-duplicates".
+
2015-06-19 Doug Evans <dje@google.com>
* stabs.texinfo (ELF Linker Relocation): Mention Sun stabs is no
are ignored. If @var{size} is @code{unlimited} or if @env{GDBHISTSIZE} is
either a negative number or the empty string, then the number of commands
@value{GDBN} keeps in the history list is unlimited.
+
+@cindex remove duplicate history
+@kindex set history remove-duplicates
+@item set history remove-duplicates @var{count}
+@itemx set history remove-duplicates unlimited
+Control the removal of duplicate history entries in the command history list.
+If @var{count} is non-zero, @value{GDBN} will look back at the last @var{count}
+history entries and remove the first entry that is a duplicate of the current
+entry being added to the command history list. If @var{count} is
+@code{unlimited} then this lookbehind is unbounded. If @var{count} is 0, then
+removal of duplicate history entries is disabled.
+
+Only history entries added during the current session are considered for
+removal. This option is set to 0 by default.
+
@end table
History expansion assigns special meaning to the character @kbd{!}.
+2015-06-26 Patrick Palka <patrick@parcs.ath.cx>
+
+ * gdb.base/history-duplicates.exp: New test.
+
2015-06-26 Patrick Palka <patrick@parcs.ath.cx>
* gdb.base/completion.exp: Test the completion of the "focus"
--- /dev/null
+# Copyright 2015 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# This file is part of the gdb testsuite.
+
+# Test the operation of the "history remove-duplicates" option.
+
+
+# Check that the previous history entry is ENTRY.
+
+proc check_prev_history_entry { entry { test_suffix "" } } {
+ set test_name "history entry is $entry"
+ if { $test_suffix != "" } {
+ append test_name " $test_suffix"
+ }
+
+ # Send ^P followed by ^L.
+ send_gdb "\x10\x0c"
+
+ gdb_expect {
+ -re $entry {
+ pass $test_name
+ }
+ timeout {
+ fail $test_name
+ }
+ }
+}
+
+# Foreach element ELT in THINGS, run the command "print $ELT", making sure that
+# each invocation of "print" has a unique test name.
+
+proc run_print_on_each_thing { things } {
+ set index 0
+
+ foreach thing $things {
+ gdb_test "print $thing" "" "printing $thing (item #$index)"
+ incr index
+ }
+}
+
+# By default the option is set to 0.
+gdb_exit
+gdb_start
+gdb_test "show history remove-duplicates" "is 0\\."
+
+# Test the "unlimited" setting.
+with_test_prefix "remove-duplicates=unlimited" {
+ gdb_exit
+ gdb_start
+ gdb_test "set history remove-duplicates unlimited"
+
+ run_print_on_each_thing { 0 1 2 1 1 2 3 3 4 1 2 3 4 }
+
+ check_prev_history_entry "print 4"
+ check_prev_history_entry "print 3"
+ check_prev_history_entry "print 2"
+ check_prev_history_entry "print 1"
+ check_prev_history_entry "print 0"
+}
+
+
+# Test the "1" setting.
+with_test_prefix "remove-duplicates=1" {
+ gdb_exit
+ gdb_start
+ gdb_test "set history remove-duplicates 1"
+
+ run_print_on_each_thing { 0 1 0 2 2 1 }
+
+ check_prev_history_entry "print 1"
+ check_prev_history_entry "print 2"
+ check_prev_history_entry "print 0"
+ check_prev_history_entry "print 1" "(again)"
+ check_prev_history_entry "print 0" "(again)"
+}
+
+
+# Test the "0" setting.
+with_test_prefix "remove-duplicates=0" {
+ gdb_exit
+ gdb_start
+ gdb_test "set history remove-duplicates 0"
+
+ run_print_on_each_thing { 0 0 1 1 }
+
+ check_prev_history_entry "print 1"
+ check_prev_history_entry "print 1" "(again)"
+ check_prev_history_entry "print 0"
+ check_prev_history_entry "print 0" "(again)"
+}
+
+
+# Test the "2" setting.
+with_test_prefix "remove-duplicates=2" {
+ gdb_exit
+ gdb_start
+ gdb_test "set history remove-duplicates 2"
+
+ run_print_on_each_thing { 1 2 0 2 0 }
+
+ check_prev_history_entry "print 0"
+ check_prev_history_entry "print 2"
+ check_prev_history_entry "print 1"
+}
value);
}
+/* Variable associated with the "history remove-duplicates" option.
+ The value -1 means unlimited. */
+static int history_remove_duplicates = 0;
+
+static void
+show_history_remove_duplicates (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c, const char *value)
+{
+ fprintf_filtered (file,
+ _("The number of history entries to look back at for "
+ "duplicates is %s.\n"),
+ value);
+}
+
static char *history_filename;
static void
show_history_filename (struct ui_file *file, int from_tty,
void
gdb_add_history (const char *command)
{
- add_history (command);
command_count++;
+
+ if (history_remove_duplicates != 0)
+ {
+ int lookbehind;
+ int lookbehind_threshold;
+
+ /* The lookbehind threshold for finding a duplicate history entry is
+ bounded by command_count because we can't meaningfully delete
+ history entries that are already stored in the history file since
+ the history file is appended to. */
+ if (history_remove_duplicates == -1
+ || history_remove_duplicates > command_count)
+ lookbehind_threshold = command_count;
+ else
+ lookbehind_threshold = history_remove_duplicates;
+
+ using_history ();
+ for (lookbehind = 0; lookbehind < lookbehind_threshold; lookbehind++)
+ {
+ HIST_ENTRY *temp = previous_history ();
+
+ if (temp == NULL)
+ break;
+
+ if (strcmp (temp->line, command) == 0)
+ {
+ HIST_ENTRY *prev = remove_history (where_history ());
+ command_count--;
+ free_history_entry (prev);
+ break;
+ }
+ }
+ using_history ();
+ }
+
+ add_history (command);
}
/* Safely append new history entries to the history file in a corruption-free
show_history_size,
&sethistlist, &showhistlist);
+ add_setshow_zuinteger_unlimited_cmd ("remove-duplicates", no_class,
+ &history_remove_duplicates, _("\
+Set how far back in history to look for and remove duplicate entries."), _("\
+Show how far back in history to look for and remove duplicate entries."), _("\
+If set to a nonzero value N, GDB will look back at the last N history entries\n\
+and remove the first history entry that is a duplicate of the most recent\n\
+entry, each time a new history entry is added.\n\
+If set to \"unlimited\", this lookbehind is unbounded.\n\
+Only history entries added during this session are considered for removal.\n\
+If set to 0, removal of duplicate history entries is disabled.\n\
+By default this option is set to 0."),
+ NULL,
+ show_history_remove_duplicates,
+ &sethistlist, &showhistlist);
+
add_setshow_filename_cmd ("filename", no_class, &history_filename, _("\
Set the filename in which to record the command history"), _("\
Show the filename in which to record the command history"), _("\