Fix/improve 'apropos' output
authorPhilippe Waroquiers <philippe.waroquiers@skynet.be>
Sun, 10 May 2020 18:21:51 +0000 (20:21 +0200)
committerPhilippe Waroquiers <philippe.waroquiers@skynet.be>
Fri, 15 May 2020 20:17:45 +0000 (22:17 +0200)
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

2020-05-15  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

2020-05-15  Philippe Waroquiers  <philippe.waroquiers@skynet.be>

* gdb.base/help.exp: Test apropos and help for commands
having aliases.  Fixed comments not starting with an
upper-case letter or not finishing with a dot.

gdb/ChangeLog
gdb/cli/cli-decode.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.base/help.exp

index 2298843350b78b20467c5545b366c5dda070675e..f685addecd1c55e4073f25a2bac45f9f04f81894 100644 (file)
@@ -1,3 +1,10 @@
+2020-05-15  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.
+
 2020-05-15  Philippe Waroquiers  <philippe.waroquiers@skynet.be>
 
        * cli/cli-decode.h (help_cmd_list): Remove declaration.
index 093692e7ac0d27dd95c55053c8637575ad5dd246..2b24e57d4635206e182f9c706f4f16d2ccaf3475 100644 (file)
@@ -1078,9 +1078,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
@@ -1106,6 +1104,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)
        {
@@ -1115,6 +1121,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)
        {
@@ -1124,10 +1141,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.  */
@@ -1150,7 +1165,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)
     {
@@ -1164,11 +1179,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.
@@ -1181,6 +1199,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);
 
index 36afa3dbd3d928c397bb46bdc50a4dd286f45dc5..bf2b9384d26cc9f0a105df56c78d9904d4c46376 100644 (file)
@@ -1,3 +1,9 @@
+2020-05-15  Philippe Waroquiers  <philippe.waroquiers@skynet.be>
+
+       * gdb.base/help.exp: Test apropos and help for commands
+       having aliases.  Fixed comments not starting with an
+       upper-case letter or not finishing with a dot.
+
 2020-05-15  Philippe Waroquiers  <philippe.waroquiers@skynet.be>
 
        * gdb.base/alias.exp: Update help output check.
index 9316a705b1a5529f3001a39ce5266bad03183516..8ed0be45dbc3a62f3decf06a5c823bb000382b95 100644 (file)
@@ -21,7 +21,7 @@
 
 gdb_start
 
-# disable pagination
+# Disable pagination.
 gdb_test_no_output "set height 0" "disable pagination"
 
 # Test all the help classes.
@@ -61,30 +61,30 @@ with_read1_timeout_factor 10 {
 
     # Test help of an abbreviated command.  "break" is picked at random.
     set help_breakpoint_text "Set breakpoint at specified location\..*"
-    # test help breakpoint "b" abbreviation
+    # Test help breakpoint "b" abbreviation.
     gdb_test "help b" $help_breakpoint_text "help breakpoint \"b\" abbreviation"
-    # test help breakpoint "br" abbreviation
+    # Test help breakpoint "br" abbreviation.
     gdb_test "help br" $help_breakpoint_text "help breakpoint \"br\" abbreviation"
-    # test help breakpoint "bre" abbreviation
+    # Test help breakpoint "bre" abbreviation;
     gdb_test "help bre" $help_breakpoint_text "help breakpoint \"bre\" abbreviation"
-    # test help breakpoint "brea" abbreviation
+    # Test help breakpoint "brea" abbreviation.
 }
 gdb_test "help brea" $help_breakpoint_text "help breakpoint \"brea\" abbreviation"
-# test help breakpoint "break" abbreviation
+# Test help breakpoint "break" abbreviation.
 gdb_test "help break" $help_breakpoint_text "help breakpoint \"break\" abbreviation"
 
 # Test help of an aliased command.  "bt" is picked at random.
 set help_backtrace_text "Print backtrace of all stack frames, or innermost COUNT frames\..*"
-# test help backtrace "bt" abbreviation
+# Test help backtrace "bt" abbreviation.
 gdb_test "help bt" $help_backtrace_text "help backtrace \"bt\" abbreviation"
-# test help backtrace
+# Test help backtrace.
 gdb_test "help backtrace" $help_backtrace_text
 
-# test help commands
+# Test help commands.
 gdb_test "help commands" "Set commands to be executed when the given breakpoints are hit\.\[\r\n\]+Give a space-separated breakpoint list as argument after \"commands\"\.\[\r\n\]+A list element can be a breakpoint number \\(e.g. `5'\\) or a range of numbers\[\r\n\]+\\(e.g. `5-7'\\)\.\[\r\n\]+With no argument, the targeted breakpoint is the last one set\.\[\r\n\]+The commands themselves follow starting on the next line\.\[\r\n\]+Type a line containing \"end\" to indicate the end of them\.\[\r\n\]+Give \"silent\" as the first line to make the breakpoint silent;\[\r\n\]+then no output is printed when it is hit, except what the commands print\."
 
 # Test a prefix command.  "delete" is picked at random.
-# test help delete "d" abbreviation
+# Test help delete "d" abbreviation.
 set expected_help_delete {
     "Delete all or some breakpoints\.\[\r\n\]+"
     "Usage: delete \\\[BREAKPOINTNUM\\\]...\[\r\n\]+"
@@ -93,36 +93,43 @@ set expected_help_delete {
     "Also a prefix command for deletion of other GDB objects\.\[\r\n\]+"
 }
 test_prefix_command_help {"d" "delete"} $expected_help_delete "help delete \"d\" abbreviation"
-# test help delete
+# Test help delete.
 test_prefix_command_help "delete" $expected_help_delete
 
 # Make sure help for help itself is present.
-# test help help "h" abbreviation 
+# Test help help "h" abbreviation.
 gdb_test "help h" "Print list of commands\." "help help \"h\" abbreviation"
-# test help help
+# Test help help.
 gdb_test "help help" "Print list of commands\."
 
 # The startup banner refers to "show copying" and "show warranty",
 # might as well test for them.
-# test help info copying
+# Test help info copying.
 gdb_test "help show copying" "Conditions for redistributing copies of GDB\."
-# test help info warranty
+# Test help info warranty.
 gdb_test "help show warranty" "Various kinds of warranty you do not have\."
 
 # Test a few other random "help show" commands.
-# test help show commands
+# Test help show commands.
 gdb_test "help show commands" "Show the history of commands you typed\.\[\r\n\]+You can supply a command number to start with, or a `\[+\]' to start after\[\r\n\]+the previous command number shown\."
-# test help show confirm
+# Test help show confirm.
 gdb_test "help show confirm" "Show whether to confirm potentially dangerous operations\."
 
-# test help info bogus-gdb-command
+# Test help info bogus-gdb-command.
 gdb_test "help info bogus-gdb-command" "Undefined info command: \"bogus-gdb-command\"\.  Try \"help info\"\."
-# test help gotcha
+# Test help gotcha.
 gdb_test "help gotcha" "Undefined command: \"gotcha\"\.  Try \"help\"\."
 
-# test apropos regex
+# Test apropos regex.
 gdb_test "apropos \\\(print\[\^\[ bsiedf\\\".-\]\\\)" "handle -- Specify how to handle signals\."
-# test apropos >1 word string
+# Test apropos >1 word string.
 gdb_test "apropos handle signal" "handle -- Specify how to handle signals\."
-# test apropos apropos
+# 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\..*"