[5/5] Add "save history" command

Message ID 20230129162105.526266-6-tom@tromey.com
State New
Headers
Series Additions to "save" command |

Commit Message

Tom Tromey Jan. 29, 2023, 4:21 p.m. UTC
  PR cli/23664 points out that it would sometimes be convenient to
immediately save the current history to a file.  This patch implements
this feature.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=23664
---
 gdb/NEWS                                |  3 +++
 gdb/doc/gdb.texinfo                     |  8 ++++++
 gdb/testsuite/gdb.base/save-history.exp | 36 +++++++++++++++++++++++++
 gdb/top.c                               | 18 +++++++++++++
 4 files changed, 65 insertions(+)
 create mode 100644 gdb/testsuite/gdb.base/save-history.exp
  

Comments

Eli Zaretskii Jan. 29, 2023, 4:56 p.m. UTC | #1
> From: Tom Tromey <tom@tromey.com>
> Cc: Tom Tromey <tom@tromey.com>
> Date: Sun, 29 Jan 2023 09:21:05 -0700
> 
> PR cli/23664 points out that it would sometimes be convenient to
> immediately save the current history to a file.  This patch implements
> this feature.
> 
> Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=23664
> ---
>  gdb/NEWS                                |  3 +++
>  gdb/doc/gdb.texinfo                     |  8 ++++++
>  gdb/testsuite/gdb.base/save-history.exp | 36 +++++++++++++++++++++++++
>  gdb/top.c                               | 18 +++++++++++++
>  4 files changed, 65 insertions(+)
>  create mode 100644 gdb/testsuite/gdb.base/save-history.exp

The documentation parts are okay, thanks.

> +Occasionally you may want to save your history to a file.  This
> +command will do just that, saving the commands in your current session
> +to the named file.  Note that you should normally edit the saved
> +history before using @code{source} to reload it, as the @code{save
> +history} command itself will be at the end of the file.

What is the rationale for saving the "save history" command as well?
Are there any circumstances when the user might want that?
  
Pedro Alves Jan. 30, 2023, 2:50 p.m. UTC | #2
On 2023-01-29 4:21 p.m., Tom Tromey wrote:
>  
> +@kindex save history
> +@item save history @var{filename}
> +Occasionally you may want to save your history to a file.  This
> +command will do just that, saving the commands in your current session
> +to the named file.  Note that you should normally edit the saved
> +history before using @code{source} to reload it, as the @code{save
> +history} command itself will be at the end of the file.

We could also suggest using "server save history" here.  Something like,
"Alternatively, you can use the server prefix to blah, blah.  @xref."

Prefixing a comment with "server" makes it so that it won't be added to
the history:

  https://sourceware.org/gdb/current/onlinedocs/gdb.html/Server-Prefix.html
  
Pedro Alves Jan. 30, 2023, 3:12 p.m. UTC | #3
On 2023-01-30 2:50 p.m., Pedro Alves wrote:
> On 2023-01-29 4:21 p.m., Tom Tromey wrote:
>>  
>> +@kindex save history
>> +@item save history @var{filename}
>> +Occasionally you may want to save your history to a file.  This
>> +command will do just that, saving the commands in your current session
>> +to the named file.  Note that you should normally edit the saved
>> +history before using @code{source} to reload it, as the @code{save
>> +history} command itself will be at the end of the file.
> 
> We could also suggest using "server save history" here.  Something like,
> "Alternatively, you can use the server prefix to blah, blah.  @xref."
> 
> Prefixing a comment with "server" makes it so that it won't be added to
> the history:
> 
>   https://sourceware.org/gdb/current/onlinedocs/gdb.html/Server-Prefix.html
> 

An alternative idea would be to make use of the fact that history entries are
already numbered, and to let the user say which history entry range to save.

E.g., we have:

 (gdb) help show commands 
 Show the history of commands you typed.
 You can supply a command number to start with, or a `+' to start after
 the previous command number shown.

and, e.g., I see currently:

 (gdb) show commands 
  1016  q
  1017  q
  1018  p 1
  1019  p 2
  1020  p 3
  1021  show commands
  1022  p 4
  1023  p 5
  1024  apropos history
  1025  show commands 

so we could support something like:

 (gdb) save history $filename 1020 1025  # save from 1020 to 1025

 (gdb) save history $filename 1020       # save from 1020 to $end

 (gdb) save history $filename -5         # save from 1020 ($last - 5) to end

 (gdb) save history $filename -5 -1      # save from 1020 ($last - 5) to 1024 ($last - 1)

or whatever other syntax makes sense and achieves a similar effect.

Being able to save just the last N entries seems like a useful feature.
  

Patch

diff --git a/gdb/NEWS b/gdb/NEWS
index a5b6f8df2ff..0003dfc9bcb 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -17,6 +17,9 @@  maintenance print record-instruction [ N ]
   prints how GDB would undo the N-th previous instruction, and if N is
   positive, it prints how GDB will redo the N-th following instruction.
 
+save history FILENAME
+  Save the command history to the given file.
+
 save skip FILENAME
   Save all current "skip"s to the given file.
 
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 31f73c33894..5ba8fbc5d16 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -26588,6 +26588,14 @@  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.
 
+@kindex save history
+@item save history @var{filename}
+Occasionally you may want to save your history to a file.  This
+command will do just that, saving the commands in your current session
+to the named file.  Note that you should normally edit the saved
+history before using @code{source} to reload it, as the @code{save
+history} command itself will be at the end of the file.
+
 @end table
 
 History expansion assigns special meaning to the character @kbd{!}.
diff --git a/gdb/testsuite/gdb.base/save-history.exp b/gdb/testsuite/gdb.base/save-history.exp
new file mode 100644
index 00000000000..bb7a56b2a72
--- /dev/null
+++ b/gdb/testsuite/gdb.base/save-history.exp
@@ -0,0 +1,36 @@ 
+# Copyright 2023 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 "save history" command.
+
+require {!is_remote host}
+
+gdb_start
+
+# Get something in history.
+gdb_test "print 23" " = 23"
+
+set filename [standard_output_file histfile]
+gdb_test_no_output "save history $filename" \
+    "save history"
+
+set expected "set height 0\n"
+append expected "set width 0\n"
+append expected "print 23\n"
+append expected "save history $filename\n"
+
+cmp_file_string $filename $expected "check history contents"
diff --git a/gdb/top.c b/gdb/top.c
index 205eb360ba3..f0c285e5989 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -1325,6 +1325,18 @@  gdb_safe_append_history (void)
     }
 }
 
+/* Implementation of 'save history' command.  */
+
+static void
+save_history_command (const char *filename, int from_tty)
+{
+  if (filename == nullptr || *filename == '\0')
+    error (_("Argument required (file name in which to save)"));
+
+  gdb::unique_xmalloc_ptr<char> expanded_filename (tilde_expand (filename));
+  write_history (expanded_filename.get ());
+}
+
 /* Read one line from the command input stream `instream'.
 
    CMD_LINE_BUFFER is a buffer that the function may use to store the result, if
@@ -2277,6 +2289,12 @@  Without an argument, saving is enabled."),
 			   show_write_history_p,
 			   &sethistlist, &showhistlist);
 
+  c = add_cmd ("history", no_class, save_history_command, _("\
+Save current history as a script.\n\
+Usage: save history FILE"),
+	       &save_cmdlist);
+  set_cmd_completer (c, filename_completer);
+
   add_setshow_zuinteger_unlimited_cmd ("size", no_class,
 				       &history_size_setshow_var, _("\
 Set the size of the command history."), _("\