From patchwork Thu Jun 4 16:21:58 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Palka X-Patchwork-Id: 7040 Received: (qmail 94370 invoked by alias); 4 Jun 2015 16:22:10 -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 94355 invoked by uid 89); 4 Jun 2015 16:22:09 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.1 required=5.0 tests=AWL, BAYES_05, KAM_LAZY_DOMAIN_SECURITY, RCVD_IN_DNSWL_LOW autolearn=no version=3.3.2 X-HELO: mail-qg0-f43.google.com Received: from mail-qg0-f43.google.com (HELO mail-qg0-f43.google.com) (209.85.192.43) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-GCM-SHA256 encrypted) ESMTPS; Thu, 04 Jun 2015 16:22:07 +0000 Received: by qgep100 with SMTP id p100so18841717qge.3 for ; Thu, 04 Jun 2015 09:22:05 -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; bh=Ab3RXf8nwg1QjnCq98QOZ1Y4IsdHot83rOHf8ygIJpw=; b=B962kTqDtakLrprwvkbXgvwJy0bSHkizw63uacNb6vz2RVU5xvqondlKaoEQlCfzDL 7Moq57TTEoKuc6poTrPjVTw8o9Nin04WFpqsjIkTRWrbOApMzUimKsMiWhUWNI35ftdk tVpn0AH/xARxdxUjKjjfbTDaf6P4HfkVi2KBmDQxL3RAyfYwoiVVjR453I1SF6a7ONu1 CR7j7k84UGiC9/aMixBkb9IBS1EIv/XyAHO+CmMaf5wBngrSSHbJdP16k5YtSAI0qFhk 4cCECP8xa3M9oFnOSM1vv01aXsw0gAF2i+l7D5yC+Peq9mfpgqPuOGG6qVE7MOVAh0zw ItdA== X-Gm-Message-State: ALoCoQm7KS3Z5Mht7cFbGMHibXkzCJr8kSds4DdSTV6841QBZcCb2erQTCB6L/O1OhGJ7dTi9Ozi X-Received: by 10.55.18.103 with SMTP id c100mr72647930qkh.2.1433434925274; Thu, 04 Jun 2015 09:22:05 -0700 (PDT) Received: from localhost.localdomain (ool-4353acd8.dyn.optonline.net. [67.83.172.216]) by mx.google.com with ESMTPSA id 143sm2590637qhw.21.2015.06.04.09.22.04 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 04 Jun 2015 09:22:04 -0700 (PDT) From: Patrick Palka To: gdb-patches@sourceware.org Cc: Patrick Palka Subject: [PATCH] Add option to remove duplicate command history entries Date: Thu, 4 Jun 2015 12:21:58 -0400 Message-Id: <1433434918-30948-1-git-send-email-patrick@parcs.ath.cx> This patch implements the new option "history remove-duplicates", which controls whether GDB should remove duplicate command-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. [ I decided to go with a basic boolean option instead of a numeric lookbehind_threshold option because it is simpler, and the maximum lookbehind is already restricted by the number of unique commands invoked during the session, a number which will rarely exceed 100. ] gdb/ChangeLog: * NEWS: Mention the new option "history remove-duplicates". * top.c (history_remove_duplicates_p): New static variable. (show_history_remove_duplicates_p): New static function. (gdb_add_history): Conditionally remove duplicate history entries. (init_main): Add "history remove-duplicates" option. gdb/doc/ChangeLog: * gdb.texinfo: Document the new option "history remove-duplicates". gdb/testsuite/ChangeLog: * gdb.base/history-duplicates.exp: New test. --- gdb/NEWS | 4 ++ gdb/doc/gdb.texinfo | 13 ++++++ gdb/testsuite/gdb.base/history-duplicates.exp | 57 +++++++++++++++++++++++++++ gdb/top.c | 51 ++++++++++++++++++++++++ 4 files changed, 125 insertions(+) create mode 100644 gdb/testsuite/gdb.base/history-duplicates.exp diff --git a/gdb/NEWS b/gdb/NEWS index bbfb55d..411be32 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -123,6 +123,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 9ea846a..722186c 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -22607,6 +22607,19 @@ This defaults to the value of the environment variable @code{HISTSIZE}, or to 256 if this variable is not set. If @var{size} is @code{unlimited}, 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 +@itemx set history remove-duplicates on +Remove duplicate history entries added during the current session. Before a +history entry is added while this option is on, @value{GDBN} scans the command +history list in reverse-chronological order and removes the first duplicate +entry it finds. This option is off by default. + +@item set history remove-duplicates off +Do not remove duplicate history entries. + @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..ef6f6a3 --- /dev/null +++ b/gdb/testsuite/gdb.base/history-duplicates.exp @@ -0,0 +1,57 @@ +# 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 } { + set test "history entry is $entry" + + # Send ^P followed by ^L. + send_gdb "\x10\x0c" + + gdb_expect { + -re $entry { + pass $test + } + timeout { + fail $test + } + } +} + +gdb_start + +gdb_test "set history remove-duplicates" "" + +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" "" + +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" diff --git a/gdb/top.c b/gdb/top.c index f8f926b..f5a0819 100644 --- a/gdb/top.c +++ b/gdb/top.c @@ -698,6 +698,18 @@ show_history_size (struct ui_file *file, int from_tty, value); } +/* Variable which controls whether duplicate history entries added during this + session are scanned for and removed. */ +static int history_remove_duplicates_p = 0; + +static void +show_history_remove_duplicates_p (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + fprintf_filtered (file, _("Removal of duplicate history entries is %s.\n"), + value); +} + static char *history_filename; static void show_history_filename (struct ui_file *file, int from_tty, @@ -897,6 +909,34 @@ static int command_count = 0; void gdb_add_history (const char *command) { + if (history_remove_duplicates_p) + { + int lookbehind; + + /* Check to see whether we have an existing command history entry for + this command -- and remove it if so -- but only among history entries + added during this session. Since we update the history file by + appending to it, history entries that are already stored in the + history file can't be meaningfully deleted. */ + using_history (); + for (lookbehind = 0; lookbehind < command_count; 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); command_count++; } @@ -1862,6 +1902,17 @@ variable \"HISTSIZE\", or to 256 if this variable is not set."), show_history_size, &sethistlist, &showhistlist); + add_setshow_boolean_cmd ("remove-duplicates", no_class, + &history_remove_duplicates_p, _("\ +Set removal of duplicate history entries added during this session."), _("\ +Show removal of duplicate history entries added during this session."), _("\ +Use \"on\" to enable removal of duplicate entries, and \"off\" to disable it.\n\ +Only history entries added during this session are considered for removal.\n\ +Without an argument, removal of duplicate entries is enabled."), + NULL, + show_history_remove_duplicates_p, + &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"), _("\