[RFA,08/10] Fix/improve 'apropos' output

Message ID 20200510205530.21923-9-philippe.waroquiers@skynet.be
State New
Headers show
Series
  • fix/improve cmd structure, class_alias, help, apropos
Related show

Commit Message

H.J. Lu via Gdb-patches May 10, 2020, 8:55 p.m.
Similarly to 'help CLASS', apropos possibly shows several
times the same help (for the command and for each of its aliases).

This patch changes 'apropos' so that the help for a command and
all its aliases is shown once.

So, apropos_cmd now skips all aliases/abbreviations, as these are printed
as part of the help of the aliased command.

When 'apropos' prints the help of a command, function 'help_cmd' now
unconditionally print the command name and its possible aliases (as we must
indicate to the user the command/aliases for which the help is printed).

When 'help somecommand' prints the help of a command, if the command is not
aliased, the command name is not printed (to avoid a useless first line), but if
it has aliases, then the command name and all its aliases are now printed.
In addition to provide to the user the choice of the best way to
type a command, it also avoids the strange behaviour that the output
of 'help somealias' does not mention somealias.

gdb/ChangeLog

YYYY-MM-DD  Philippe Waroquiers  <philippe.waroquiers@skynet.be>

	* cli/cli-decode.c (apropos_cmd): Produce output for aliases
	when their aliased command is traversed.
	(help_cmd): Add fput_command_names_styled call to
	output command name and aliases when command has an alias.

gdb/testsuite/ChangeLog

YYYY-MM-DD  Philippe Waroquiers  <philippe.waroquiers@skynet.be>

	* gdb.base/help.exp: Test apropos and help for commands
	having aliases.
---
 gdb/cli/cli-decode.c            | 37 ++++++++++++++++++++++++++-------
 gdb/testsuite/gdb.base/help.exp |  7 +++++++
 2 files changed, 36 insertions(+), 8 deletions(-)

-- 
2.20.1

Comments

Tom Tromey May 14, 2020, 4:30 p.m. | #1
>>>>> "Philippe" == Philippe Waroquiers via Gdb-patches <gdb-patches@sourceware.org> writes:


Philippe> YYYY-MM-DD  Philippe Waroquiers  <philippe.waroquiers@skynet.be>

Philippe> 	* cli/cli-decode.c (apropos_cmd): Produce output for aliases
Philippe> 	when their aliased command is traversed.
Philippe> 	(help_cmd): Add fput_command_names_styled call to
Philippe> 	output command name and aliases when command has an alias.

Philippe> gdb/testsuite/ChangeLog

Philippe> YYYY-MM-DD  Philippe Waroquiers  <philippe.waroquiers@skynet.be>

Philippe> 	* gdb.base/help.exp: Test apropos and help for commands
Philippe> 	having aliases.

Thanks.

Philippe> +	  /*  Command aliases/abbreviations are skipped to ensure we print the
Philippe> +	      doc of a command only once, when encountering the aliased
Philippe> +	      command.  */

The leading indent in the comment looks weird.

Philippe> +# test apropos for commands having aliases.
Philippe> +gdb_test "apropos Print backtrace of all stack frames, or innermost COUNT frames\." \
Philippe> +    "backtrace, where, bt -- Print backtrace of all stack frames, or innermost COUNT frames\."
Philippe> +
Philippe> +# test help for commands having aliases.
Philippe> +gdb_test "help bt" "backtrace, where, bt\[\r\n\]+Print backtrace of all stack frames, or innermost COUNT frames\..*"

The new comments here should start with an upper-case letter.

Ok with those nits fixed.

Tom

Patch

diff --git a/gdb/cli/cli-decode.c b/gdb/cli/cli-decode.c
index aeaee3db30..48187e8583 100644
--- a/gdb/cli/cli-decode.c
+++ b/gdb/cli/cli-decode.c
@@ -1076,9 +1076,7 @@  print_doc_of_command (struct cmd_list_element *c, const char *prefix,
   if (verbose)
     fputs_filtered ("\n", stream);
 
-  fprintf_styled (stream, title_style.style (),
-		  "%s%s", prefix, c->name);
-  fputs_filtered (" -- ", stream);
+  fput_command_names_styled (c, true, " -- ", stream);
   if (verbose)
     fputs_highlighted (c->doc, highlight, stream);
   else
@@ -1104,6 +1102,14 @@  apropos_cmd (struct ui_file *stream,
   /* Walk through the commands.  */
   for (c=commandlist;c;c=c->next)
     {
+      if (c->cmd_pointer != nullptr)
+	{
+	  /*  Command aliases/abbreviations are skipped to ensure we print the
+	      doc of a command only once, when encountering the aliased
+	      command.  */
+	  continue;
+	}
+
       returnvalue = -1; /* Needed to avoid double printing.  */
       if (c->name != NULL)
 	{
@@ -1113,6 +1119,17 @@  apropos_cmd (struct ui_file *stream,
 	  returnvalue = regex.search (c->name, name_len, 0, name_len, NULL);
 	  if (returnvalue >= 0)
 	    print_doc_of_command (c, prefix, verbose, regex, stream);
+
+	  /* Try to match against the name of the aliases.  */
+	  for (cmd_list_element *iter = c->aliases;
+	       returnvalue < 0 && iter;
+	       iter = iter->alias_chain)
+	    {
+	      name_len = strlen (iter->name);
+	      returnvalue = regex.search (iter->name, name_len, 0, name_len, NULL);
+	      if (returnvalue >= 0)
+		print_doc_of_command (c, prefix, verbose, regex, stream);
+	    }
 	}
       if (c->doc != NULL && returnvalue < 0)
 	{
@@ -1122,10 +1139,8 @@  apropos_cmd (struct ui_file *stream,
 	  if (regex.search (c->doc, doc_len, 0, doc_len, NULL) >= 0)
 	    print_doc_of_command (c, prefix, verbose, regex, stream);
 	}
-      /* Check if this command has subcommands and is not an
-	 abbreviation.  We skip listing subcommands of abbreviations
-	 in order to avoid duplicates in the output.  */
-      if (c->prefixlist != NULL && !c->abbrev_flag)
+      /* Check if this command has subcommands.  */
+      if (c->prefixlist != NULL)
 	{
 	  /* Recursively call ourselves on the subcommand list,
 	     passing the right prefix in.  */
@@ -1148,7 +1163,7 @@  apropos_cmd (struct ui_file *stream,
 void
 help_cmd (const char *command, struct ui_file *stream)
 {
-  struct cmd_list_element *c;
+  struct cmd_list_element *c, *alias, *prefix_cmd, *c_cmd;
 
   if (!command)
     {
@@ -1162,11 +1177,14 @@  help_cmd (const char *command, struct ui_file *stream)
       return;
     }
 
+  const char *orig_command = command;
   c = lookup_cmd (&command, cmdlist, "", 0, 0);
 
   if (c == 0)
     return;
 
+  lookup_cmd_composition (orig_command, &alias, &prefix_cmd, &c_cmd);
+
   /* There are three cases here.
      If c->prefixlist is nonzero, we have a prefix command.
      Print its documentation, then list its subcommands.
@@ -1179,6 +1197,9 @@  help_cmd (const char *command, struct ui_file *stream)
      number of this class so that the commands in the class will be
      listed.  */
 
+  /* If the user asked 'help somecommand' and there is no alias,
+     the false indicates to not output the (single) command name.  */
+  fput_command_names_styled (c, false, "\n", stream);
   fputs_filtered (c->doc, stream);
   fputs_filtered ("\n", stream);
 
diff --git a/gdb/testsuite/gdb.base/help.exp b/gdb/testsuite/gdb.base/help.exp
index 9316a705b1..a2d33ba95c 100644
--- a/gdb/testsuite/gdb.base/help.exp
+++ b/gdb/testsuite/gdb.base/help.exp
@@ -126,3 +126,10 @@  gdb_test "apropos \\\(print\[\^\[ bsiedf\\\".-\]\\\)" "handle -- Specify how to
 gdb_test "apropos handle signal" "handle -- Specify how to handle signals\."
 # test apropos apropos
 gdb_test "apropos apropos" "apropos -- Search for commands matching a REGEXP.*"
+
+# test apropos for commands having aliases.
+gdb_test "apropos Print backtrace of all stack frames, or innermost COUNT frames\." \
+    "backtrace, where, bt -- Print backtrace of all stack frames, or innermost COUNT frames\."
+
+# test help for commands having aliases.
+gdb_test "help bt" "backtrace, where, bt\[\r\n\]+Print backtrace of all stack frames, or innermost COUNT frames\..*"