Fix/improve 'apropos' output

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.
This commit is contained in:
Philippe Waroquiers 2020-05-10 20:21:51 +02:00
parent 3b3aaacba1
commit 7c05caf72d
4 changed files with 71 additions and 30 deletions

View 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.

View 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);

View 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.

View 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\..*"