aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog9
-rw-r--r--gdb/NEWS4
-rw-r--r--gdb/doc/ChangeLog5
-rw-r--r--gdb/doc/gdb.texinfo15
-rw-r--r--gdb/testsuite/ChangeLog4
-rw-r--r--gdb/testsuite/gdb.base/history-duplicates.exp117
-rw-r--r--gdb/top.c66
7 files changed, 219 insertions, 1 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 696a593..8cd835d 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,14 @@
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.
(_initialize_tui_win): Set the completion function of the
"focus" command to focus_completer.
diff --git a/gdb/NEWS b/gdb/NEWS
index 3ec5851..6d29004 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -145,6 +145,10 @@ show max-completions
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.
diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog
index 6d86750..e0beb7f 100644
--- a/gdb/doc/ChangeLog
+++ b/gdb/doc/ChangeLog
@@ -1,3 +1,8 @@
+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
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index c9a532a..20a9563 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -22644,6 +22644,21 @@ to 256 if this variable is not set. Non-numeric values of @env{GDBHISTSIZE}
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{!}.
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index ce792be..af7f131 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,5 +1,9 @@
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"
command.
diff --git a/gdb/testsuite/gdb.base/history-duplicates.exp b/gdb/testsuite/gdb.base/history-duplicates.exp
new file mode 100644
index 0000000..11bb1ed
--- /dev/null
+++ b/gdb/testsuite/gdb.base/history-duplicates.exp
@@ -0,0 +1,117 @@
+# 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"
+}
diff --git a/gdb/top.c b/gdb/top.c
index 77fe096..01fddd2 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -698,6 +698,20 @@ show_history_size (struct ui_file *file, int from_tty,
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,
@@ -897,8 +911,43 @@ static int command_count = 0;
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
@@ -1880,6 +1929,21 @@ variable \"GDBHISTSIZE\", or to 256 if this variable is not set."),
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"), _("\