From: Philippe Waroquiers via Gdb-patches <gdb-patches@sourceware.org>
To: gdb-patches@sourceware.org
Subject: Re: [RFAv2] Allow to document user-defined aliases.
Date: Sun, 21 Aug 2022 14:06:50 +0200 [thread overview]
Message-ID: <f6d77b5c81af1eabc7d76142120591f88b98eb41.camel@skynet.be> (raw)
In-Reply-To: <20220808194018.3781686-1-philippe.waroquiers@skynet.be>
Ping^2 ?
Note that the doc was reviewed by Eli (ok with a few nits to fix)
and a first code review was done by Tom (I handled the minor comments given
+ ensured that the alias definition is shown in the help of a user-documented alias).
Thanks
Philippe
On Mon, 2022-08-08 at 21:40 +0200, Philippe Waroquiers wrote:
> Compared to the previous version, this version fixes the comments reported by
> Tom Tromey and ensures that the 'help some-user-documented-alias'
> shows the alias definition to ensure the user understands this is an
> alias even if specifically documented.
>
> When using 'help ALIASNAME', GDB shows the help of the aliased command.
> This is a good default behaviour.
>
> However, GDB alias command allows to define aliases with arguments
> possibly changing or tuning significantly the behaviour of
> the aliased command. In such a case, showing the help of the aliased
> command might not be ideal.
>
> This is particularly true when defining an alias as a set of
> nested 'with' followed by a last command to launch, such as:
> (gdb) alias pp10 = with print pretty -- with print elements 10 -- print
> Asking 'help pp10' shows the help of the 'with' command, which is
> not particularly useful:
> (gdb) help pp10
> with, pp10, w
> alias pp10 = with print pretty -- with print elements 10 -- print
> Temporarily set SETTING to VALUE, run COMMAND, and restore SETTING.
> Usage: with SETTING [VALUE] [-- COMMAND]
> ....
>
> Such an alias can now be documented by the user:
> (gdb) document pp10
> >Pretty printing an expressiong, printing 10 elements.
> >Usage: pp10 [PRINT-COMMAND-OPTIONS] EXP
> >See 'help print' for more information.
> >end
> (gdb) help pp10
> alias pp10 = with print pretty -- with print elements 10 -- print
> Pretty printing an expressiong, printing 10 elements.
> Usage: pp10 [PRINT-COMMAND-OPTIONS] EXP
> See 'help print' for more information.
> (gdb)
>
> When a user-defined alias is documented specifically, help and apropos
> use the provided alias documentation instead of the documentation of
> the aliased command.
>
> Such a documented alias is also not shown anymore in the help of the
> aliased command, and the alias is not listed anymore in the help
> of the aliased command. In particular for cases such as pp10 example above,
> indicating that pp10 is an alias of the 'with' command is confusing.
> ---
> gdb/NEWS | 10 ++++++
> gdb/cli/cli-decode.c | 59 ++++++++++++++++++++++++---------
> gdb/cli/cli-script.c | 41 ++++++++++++++---------
> gdb/doc/gdb.texinfo | 26 ++++++++++++++-
> gdb/testsuite/gdb.base/help.exp | 44 ++++++++++++++++++++++--
> 5 files changed, 146 insertions(+), 34 deletions(-)
>
> diff --git a/gdb/NEWS b/gdb/NEWS
> index 8c837df76e5..1b74e0fc1bd 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -93,6 +93,16 @@ show style disassembler symbol
>
>
> * Changed commands
>
>
> +document user-defined
> + It is now possible to document user-defined aliases.
> + When a user-defined alias is documented, the help and apropos commands
> + use the provided documentation instead of the documentation of the
> + aliased command.
> + Documenting a user-defined alias is particularly useful when the alias
> + is a set of nested 'with' commands to avoid showing the help of
> + the with command for an alias that will in fact launch the
> + last command given in the nested commands.
> +
> maintenance info line-table
> Add a PROLOGUE-END column to the output which indicates that an
> entry corresponds to an address where a breakpoint should be placed
> diff --git a/gdb/cli/cli-decode.c b/gdb/cli/cli-decode.c
> index fde554c7e6c..7c98029f9f4 100644
> --- a/gdb/cli/cli-decode.c
> +++ b/gdb/cli/cli-decode.c
> @@ -1349,6 +1349,18 @@ fput_command_name_styled (const cmd_list_element &c, struct ui_file *stream)
> prefixname.c_str (), c.name);
> }
>
>
> +/* True if ALIAS has a user-defined documentation. */
> +
> +static bool
> +user_documented_alias (const cmd_list_element &alias)
> +{
> + gdb_assert (alias.is_alias ());
> + /* Alias is user documented if it has an allocated documentation
> + that differs from the aliased command. */
> + return (alias.doc_allocated
> + && strcmp (alias.doc, alias.alias_target->doc) != 0);
> +}
> +
> /* Print the definition of alias C using title style for alias
> and aliased command. */
>
>
> @@ -1364,20 +1376,22 @@ fput_alias_definition_styled (const cmd_list_element &c,
> gdb_printf (stream, " %s\n", c.default_args.c_str ());
> }
>
>
> -/* Print the definition of the aliases of CMD that have default args. */
> +/* Print the definition of CMD aliases not deprecated and having default args
> + and not specifically documented by the user. */
>
>
> static void
> fput_aliases_definition_styled (const cmd_list_element &cmd,
> struct ui_file *stream)
> {
> for (const cmd_list_element &alias : cmd.aliases)
> - if (!alias.cmd_deprecated && !alias.default_args.empty ())
> + if (!alias.cmd_deprecated
> + && !user_documented_alias (alias)
> + && !alias.default_args.empty ())
> fput_alias_definition_styled (alias, stream);
> }
>
>
> -
> -/* If C has one or more aliases, style print the name of C and
> - the name of its aliases, separated by commas.
> +/* If C has one or more aliases, style print the name of C and the name of its
> + aliases not documented specifically by the user, separated by commas.
> If ALWAYS_FPUT_C_NAME, print the name of C even if it has no aliases.
> If one or more names are printed, POSTFIX is printed after the last name.
> */
> @@ -1389,11 +1403,11 @@ fput_command_names_styled (const cmd_list_element &c,
> {
> /* First, check if we are going to print something. That is, either if
> ALWAYS_FPUT_C_NAME is true or if there exists at least one non-deprecated
> - alias. */
> + alias not documented specifically by the user. */
>
>
> auto print_alias = [] (const cmd_list_element &alias)
> {
> - return !alias.cmd_deprecated;
> + return !alias.cmd_deprecated && !user_documented_alias (alias);
> };
>
>
> bool print_something = always_fput_c_name;
> @@ -1474,11 +1488,11 @@ apropos_cmd (struct ui_file *stream,
> /* Walk through the commands. */
> for (c=commandlist;c;c=c->next)
> {
> - if (c->is_alias ())
> + if (c->is_alias () && !user_documented_alias (*c))
> {
> - /* Command aliases/abbreviations are skipped to ensure we print the
> - doc of a command only once, when encountering the aliased
> - command. */
> + /* Command aliases/abbreviations not specifically documented by the
> + user are skipped to ensure we print the doc of a command only once,
> + when encountering the aliased command. */
> continue;
> }
>
>
> @@ -1571,11 +1585,24 @@ 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);
> - fput_aliases_definition_styled (*c, stream);
> - gdb_puts (c->doc, stream);
> + if (alias == nullptr || !user_documented_alias (*alias))
> + {
> + /* Case of a normal command, or an alias not explictly
> + documented by the user. */
> + /* 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);
> + fput_aliases_definition_styled (*c, stream);
> + gdb_puts (c->doc, stream);
> + }
> + else
> + {
> + /* Case of an alias explictly documented by the user.
> + Only output the alias definition and its explicit documentation. */
> + fput_alias_definition_styled (*alias, stream);
> + fput_command_names_styled (*alias, false, "\n", stream);
> + gdb_puts (alias->doc, stream);
> + }
> gdb_puts ("\n", stream);
>
>
> if (!c->is_prefix () && !c->is_command_class_help ())
> diff --git a/gdb/cli/cli-script.c b/gdb/cli/cli-script.c
> index 5f81db418bc..6c67b60e721 100644
> --- a/gdb/cli/cli-script.c
> +++ b/gdb/cli/cli-script.c
> @@ -1500,39 +1500,49 @@ define_command (const char *comname, int from_tty)
> do_define_command (comname, from_tty, nullptr);
> }
>
>
> -/* Document a user-defined command. If COMMANDS is NULL, then this is a
> - top-level call and the document will be read using read_command_lines.
> - Otherwise, it is a "document" command in an existing command and the
> - commands are provided. */
> +/* Document a user-defined command or user defined alias. If COMMANDS is NULL,
> + then this is a top-level call and the document will be read using
> + read_command_lines. Otherwise, it is a "document" command in an existing
> + command and the commands are provided. */
> static void
> do_document_command (const char *comname, int from_tty,
> const counted_command_line *commands)
> {
> - struct cmd_list_element *c, **list;
> - const char *tem;
> + struct cmd_list_element *alias, *prefix_cmd, *c;
> const char *comfull;
>
>
> comfull = comname;
> - list = validate_comname (&comname);
> + validate_comname (&comname);
>
>
> - tem = comname;
> - c = lookup_cmd (&tem, *list, "", NULL, 0, 1);
> + lookup_cmd_composition (comfull, &alias, &prefix_cmd, &c);
>
>
> - if (c->theclass != class_user)
> - error (_("Command \"%s\" is built-in."), comfull);
> + if (c->theclass != class_user
> + && (alias == nullptr || alias->theclass != class_alias))
> + {
> + if (alias == nullptr)
> + error (_("Command \"%s\" is built-in."), comfull);
> + else
> + error (_("Alias \"%s\" is built-in."), comfull);
> + }
> +
> + /* If we found an alias of class_alias, the user is documenting this
> + user-defined alias. */
> + if (alias != nullptr)
> + c = alias;
>
>
> counted_command_line doclines;
>
>
> if (commands == nullptr)
> {
> - std::string prompt
> + std::string prompt
> = string_printf ("Type documentation for \"%s\".", comfull);
> doclines = read_command_lines (prompt.c_str (), from_tty, 0, 0);
> }
> else
> doclines = *commands;
>
>
> - xfree ((char *) c->doc);
> + if (c->doc_allocated)
> + xfree ((char *) c->doc);
>
>
> {
> struct command_line *cl1;
> @@ -1553,6 +1563,7 @@ do_document_command (const char *comname, int from_tty,
> }
>
>
> c->doc = doc;
> + c->doc_allocated = 1;
> }
> }
>
>
> @@ -1681,8 +1692,8 @@ _initialize_cli_script ()
> its prefixes. */
> document_cmd_element = add_com ("document", class_support, document_command,
> _("\
> -Document a user-defined command.\n\
> -Give command name as argument. Give documentation on following lines.\n\
> +Document a user-defined command or user-defined alias.\n\
> +Give command or alias name as argument. Give documentation on following lines.\n\
> End with a line of just \"end\"."));
> set_cmd_completer (document_cmd_element, command_completer);
> define_cmd_element = add_com ("define", class_support, define_command, _("\
> diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
> index 382df00ee7d..efa5d48a707 100644
> --- a/gdb/doc/gdb.texinfo
> +++ b/gdb/doc/gdb.texinfo
> @@ -2265,11 +2265,20 @@ one or more aliases, @value{GDBN} will display a first line with
> the command name and all its aliases separated by commas.
> This first line will be followed by the full definition of all aliases
> having default arguments.
> +When asking the help for an alias, the documentation for the aliased
> +command is shown.
> +
> +A user-defined alias can optionally be documented using the @code{document} command
> +(@pxref{Define, document}).
> +@value{GDBN} then considers this alias as different of the aliased
> +command: this alias is not listed in the aliased command help output and asking
> +help for this alias will show the user provided alias documentation
> +instead of the documentation of the aliased command.
>
>
> @kindex apropos
> @item apropos [-v] @var{regexp}
> The @code{apropos} command searches through all of the @value{GDBN}
> -commands, and their documentation, for the regular expression specified in
> +commands and aliases, and their documentation, for the regular expression specified in
> @var{args}. It prints out all matches found. The optional flag @samp{-v},
> which stands for @samp{verbose}, indicates to output the full documentation
> of the matching commands and highlight the parts of the documentation
> @@ -27967,6 +27976,13 @@ You may use the @code{document} command again to change the
> documentation of a command. Redefining the command with @code{define}
> does not change the documentation.
>
>
> +It is also possible to document user-defined aliases. The alias documentation
> +will then be used by the @code{help} and @code{apropos} commands
> +instead of the documentation of the aliased command.
> +Documenting a user-defined alias is particularly useful when defining
> +an alias as a set of nested @code{with} commands
> +(@pxref{Command aliases default args}).
> +
> @kindex define-prefix
> @item define-prefix @var{commandname}
> Define or mark the command @var{commandname} as a user-defined prefix
> @@ -28641,6 +28657,14 @@ by the user.
> For more information about the @code{with} command usage,
> see @ref{Command Settings}.
>
>
> +By default, asking the help for an alias shows the documentation of
> +the aliased command. When the alias is a set of nested commands, @code{help}
> +of an alias shows the documentation of the first command. This help
> +is not particularly useful for an alias such as @code{pp10}.
> +For such an alias, it is useful to give a specific documentation
> +using the @code{document} command (@pxref{Define, document}).
> +
> +
> @c Python docs live in a separate file.
> @include python.texi
>
>
> diff --git a/gdb/testsuite/gdb.base/help.exp b/gdb/testsuite/gdb.base/help.exp
> index 74da29e3d36..5ee8ce0726d 100644
> --- a/gdb/testsuite/gdb.base/help.exp
> +++ b/gdb/testsuite/gdb.base/help.exp
> @@ -128,8 +128,48 @@ gdb_test "apropos handle signal" "handle -- Specify how to handle signals\."
> gdb_test "apropos apropos" "apropos -- Search for commands matching a REGEXP.*"
>
>
> # Test apropos for commands having aliases.
> +gdb_test_no_output "alias mybt = backtrace" "define mybt alias"
> +gdb_test_no_output "alias mybt10 = backtrace 10" "define mybt10 alias"
> +
> 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\."
> + "backtrace, mybt10, mybt, where, bt -- Print backtrace of all stack frames, or innermost COUNT frames\.\[\r\n\]+ alias mybt10 = backtrace 10"
>
>
> # 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\..*"
> +gdb_test "help bt" "backtrace, mybt10, mybt, where, bt\[\r\n\]+ alias mybt10 = backtrace 10\[\r\n\]+Print backtrace of all stack frames, or innermost COUNT frames\..*"
> +
> +# Document the aliases. The apropos and help commands should then consider them
> +# as "standalone" commands.
> +gdb_test_multiple "document mybt" "document alias: mybt" {
> + -re "Type documentation for \"mybt\".\r\nEnd with a line saying just \"end\".\r\n>$" {
> + gdb_test "An alias of command backtrace without any args.\nend" \
> + "" \
> + "document alias: mybt"
> + }
> +}
> +gdb_test_multiple "document mybt10" "document alias: mybt10" {
> + -re "Type documentation for \"mybt10\".\r\nEnd with a line saying just \"end\".\r\n>$" {
> + gdb_test "An alias of command backtrace with arg 10.\nend" \
> + "" \
> + "document alias: mybt10"
> + }
> +}
> +
> +# As the aliases are now documented, they do not appear in apropos/help backtrace output anymore.
> +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\." \
> + "apropos after documenting aliases"
> +
> +gdb_test "help bt" "backtrace, where, bt\[\r\n\]+Print backtrace of all stack frames, or innermost COUNT frames\..*" \
> + "help after documenting aliases"
> +
> +# Check apropos and help use the alias documentation.
> +gdb_test "apropos An alias of command backtrace with arg 10" \
> + "mybt10 -- An alias of command backtrace with arg 10\." \
> + "apropos after documenting aliases showing mybt10 doc"
> +
> +gdb_test "help mybt" " alias mybt = backtrace \[\r\n\]+An alias of command backtrace without any args\." \
> + "help mybt after documenting aliases showing mybt doc"
> +
> +# Check pre-defined aliases cannot be documented.
> +gdb_test "document where" "Alias \"where\" is built-in.*" \
> + "documenting builtin where alias disallowed"
next prev parent reply other threads:[~2022-08-21 12:07 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-08-08 19:40 Philippe Waroquiers via Gdb-patches
2022-08-09 11:50 ` Eli Zaretskii via Gdb-patches
2022-08-14 14:07 ` Philippe Waroquiers via Gdb-patches
2022-08-21 12:06 ` Philippe Waroquiers via Gdb-patches [this message]
2022-08-23 19:33 ` Tom Tromey
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=f6d77b5c81af1eabc7d76142120591f88b98eb41.camel@skynet.be \
--to=gdb-patches@sourceware.org \
--cc=philippe.waroquiers@skynet.be \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox