From patchwork Fri Jun 26 15:12:30 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Palka X-Patchwork-Id: 7391 Received: (qmail 50686 invoked by alias); 26 Jun 2015 15:12:40 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 50671 invoked by uid 89); 26 Jun 2015 15:12:40 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.0 required=5.0 tests=AWL, BAYES_05, KAM_LAZY_DOMAIN_SECURITY, RCVD_IN_DNSWL_LOW autolearn=no version=3.3.2 X-HELO: mail-qc0-f176.google.com Received: from mail-qc0-f176.google.com (HELO mail-qc0-f176.google.com) (209.85.216.176) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-GCM-SHA256 encrypted) ESMTPS; Fri, 26 Jun 2015 15:12:38 +0000 Received: by qcmc1 with SMTP id c1so30170258qcm.2 for ; Fri, 26 Jun 2015 08:12:36 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=DGDg/2RYVDSspoGvf3TNoEUEeP3aT+uZPlkcBQvo3Ng=; b=cQ6o6TqdHLpIOKdJ69bcxZC2LNcUQWpWrsyjhT63t/l2Ecy1mUzysHM1XLHZPMGwp0 dSO845RKcRovetQouIjz0rvkjhQKtpoZz/1Ubt+GZ6wvLdXl6EyaArNlUHOtzBCBGAkf mvdCNNc65CV5Et6tc+mNgFi1tFiU/sxTdsscFCk0k75XqCanz67pS+NXszw20Fp1nh9O 5xdFYMOM36tAkmVM6hSfsOzOadnda0LWExICUJYnFKsGoj3Cb5KVlXgKhAmvolPm47yE OgdQa+jWgtJgqfDQYwFdK73HJaMy8UbFo2opBxbbUOB448qHM+jAHDEmzXDzTIj7TEHB jo+g== X-Gm-Message-State: ALoCoQlVPLk+6sk7cQ7RK7mtt8pEZnZ/bKJVz4tLESbK9SxNXyPFNIWpbBv95vzgVDfmEgNf2z6/ X-Received: by 10.140.194.199 with SMTP id p190mr3079161qha.76.1435331556010; Fri, 26 Jun 2015 08:12:36 -0700 (PDT) Received: from localhost.localdomain (ool-4353acd8.dyn.optonline.net. [67.83.172.216]) by mx.google.com with ESMTPSA id g81sm6585385qhc.8.2015.06.26.08.12.35 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 26 Jun 2015 08:12:35 -0700 (PDT) From: Patrick Palka To: gdb-patches@sourceware.org Cc: Patrick Palka Subject: [PATCH] Add option to remove duplicate command history entries Date: Fri, 26 Jun 2015 11:12:30 -0400 Message-Id: <1435331550-6809-1-git-send-email-patrick@parcs.ath.cx> In-Reply-To: <1434756821-7423-1-git-send-email-patrick@parcs.ath.cx> References: <1434756821-7423-1-git-send-email-patrick@parcs.ath.cx> For posterity, this is what I committed. --- gdb/ChangeLog | 9 ++ gdb/NEWS | 4 + gdb/doc/ChangeLog | 5 ++ gdb/doc/gdb.texinfo | 15 ++++ gdb/testsuite/ChangeLog | 4 + gdb/testsuite/gdb.base/history-duplicates.exp | 117 ++++++++++++++++++++++++++ gdb/top.c | 66 ++++++++++++++- 7 files changed, 219 insertions(+), 1 deletion(-) create mode 100644 gdb/testsuite/gdb.base/history-duplicates.exp 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 + * 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 + * 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 + + * gdb.texinfo (Command History): Document the new option + "history remove-duplicates". + 2015-06-19 Doug Evans * 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 + * gdb.base/history-duplicates.exp: New test. + +2015-06-26 Patrick Palka + * 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 . + +# 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"), _("\