This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] Add option to remove duplicate command history entries


On Fri, Jun 19, 2015 at 7:33 PM, Patrick Palka <patrick@parcs.ath.cx> wrote:
> This patch implements the new option "history remove-duplicates", which
> controls the removal of duplicate history entries ("off" by default).
>
> The motivation for this option is to be able to reduce the prevalence of
> basic commands such as "up" and "down" in the history file.  These
> common commands crowd out more unique commands in the history file (when
> the history file has a fixed size), and they make navigation of the
> history file via ^P, ^N and ^R more inconvenient.
>
> The option takes an integer denoting the number of history entries to
> look back at for a history entry that is a duplicate of the latest one.
> "history remove-duplicates 1" is equivalent to bash's ignoredups option,
> and "history remove-duplicates unlimited" is equivalent to bash's
> erasedups option.
>
> [ I decided to go with this integer approach instead of a tri-state enum
>   because it's slightly more flexible and seemingly more intuitive than
>   leave/erase/ignore.  ]
>
> gdb/ChangeLog:
>
>         * 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.
>
> gdb/doc/ChangeLog:
>
>         * gdb.texinfo (Command History): Document the new option
>         "history remove-duplicates".
>
> gdb/testsuite/ChangeLog:
>
>         * gdb.base/history-duplicates.exp: New test.
> ---
>  gdb/NEWS                                      |   4 +
>  gdb/doc/gdb.texinfo                           |  15 +++
>  gdb/testsuite/gdb.base/history-duplicates.exp | 129 ++++++++++++++++++++++++++
>  gdb/top.c                                     |  66 ++++++++++++-
>  4 files changed, 213 insertions(+), 1 deletion(-)
>  create mode 100644 gdb/testsuite/gdb.base/history-duplicates.exp
>
> 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/gdb.texinfo b/gdb/doc/gdb.texinfo
> index c9a532a..c5885eb 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{size}
> +@itemx set history remove-duplicates unlimited
> +Control the removal of duplicate history entries in the command history list.
> +If @var{size} is non-zero, @value{GDBN} will look back at the last @var{size}
> +history entries and remove the first entry that is a duplicate of the current
> +entry being added to the command history list.  If @var{size} is
> +@code{unlimited} then this lookbehind is unbounded.  If @var{size} 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/gdb.base/history-duplicates.exp b/gdb/testsuite/gdb.base/history-duplicates.exp
> new file mode 100644
> index 0000000..f88607f
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/history-duplicates.exp
> @@ -0,0 +1,129 @@
> +# 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 "history entry is $entry"
> +    if { $test_suffix != "" } {
> +        append test " $test_suffix"
> +    }
> +
> +    # Send ^P followed by ^L.
> +    send_gdb "\x10\x0c"
> +
> +    gdb_expect {
> +       -re $entry {
> +           pass $test
> +       }
> +       timeout {
> +           fail $test
> +       }
> +    }
> +}
> +
> +# 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"
> +
> +    gdb_test "print 0"
> +    gdb_test "print 1"
> +    gdb_test "print 2"
> +    gdb_test "print 1"
> +    gdb_test "print 1"
> +    gdb_test "print 2"
> +    gdb_test "print 3"
> +    gdb_test "print 3"
> +    gdb_test "print 4"
> +    gdb_test "print 1"
> +    gdb_test "print 2"
> +    gdb_test "print 3"
> +    gdb_test "print 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"
> +
> +    gdb_test "print 0"
> +    gdb_test "print 1"
> +    gdb_test "print 0"
> +    gdb_test "print 2"
> +    gdb_test "print 2"
> +    gdb_test "print 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"
> +
> +    gdb_test "print 0"
> +    gdb_test "print 0"
> +    gdb_test "print 1"
> +    gdb_test "print 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"
> +
> +    gdb_test "print 1"
> +    gdb_test "print 2"
> +    gdb_test "print 0"
> +    gdb_test "print 2"
> +    gdb_test "print 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 6ae84ab..5114c2e 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
> @@ -1872,6 +1921,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 non-zero 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"), _("\
> --
> 2.4.4.410.g43ed522.dirty
>

Ping.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]