aboutsummaryrefslogtreecommitdiff
path: root/gdb/cli
diff options
context:
space:
mode:
authorPedro Alves <palves@redhat.com>2019-07-03 16:57:51 +0100
committerPedro Alves <palves@redhat.com>2019-07-03 17:18:54 +0100
commit5f4ba3e701d74f280d4bd8820d9c39a854e0d2cf (patch)
treee3b67db8010eb2372226f3fbd5a33c2e5edbb8b3 /gdb/cli
parenta994424fa1e80d982644038f1ce6538e247aeed1 (diff)
downloadgdb-5f4ba3e701d74f280d4bd8820d9c39a854e0d2cf.zip
gdb-5f4ba3e701d74f280d4bd8820d9c39a854e0d2cf.tar.gz
gdb-5f4ba3e701d74f280d4bd8820d9c39a854e0d2cf.tar.bz2
pipe command completer
This commit adds a completer for the "pipe" command. It can complete "pipe"'s options, and the specified GDB command. To make the completer aware of the "-d" option, this converts the option processing to use gdb::option. Tests included. gdb/ChangeLog: 2019-07-03 Pedro Alves <palves@redhat.com> PR cli/24732 * cli/cli-cmds.c (struct pipe_cmd_opts): New. (pipe_cmd_option_defs): New. (make_pipe_cmd_options_def_group): New. (pipe_command): Use gdb::option::process_options. (pipe_command_completer): New function. (_initialize_cli_cmds): Install completer for "pipe" command. gdb/testsuite/ChangeLog: 2019-07-03 Pedro Alves <palves@redhat.com> PR cli/24732 * gdb.base/shell.exp: Load completion-support.exp. Adjust expected error output. Add completion tests.
Diffstat (limited to 'gdb/cli')
-rw-r--r--gdb/cli/cli-cmds.c92
1 files changed, 83 insertions, 9 deletions
diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
index d1ecd62..368ddf5 100644
--- a/gdb/cli/cli-cmds.c
+++ b/gdb/cli/cli-cmds.c
@@ -960,32 +960,68 @@ edit_command (const char *arg, int from_tty)
xfree (p);
}
+/* The options for the "pipe" command. */
+
+struct pipe_cmd_opts
+{
+ /* For "-d". */
+ char *delimiter = nullptr;
+
+ ~pipe_cmd_opts ()
+ {
+ xfree (delimiter);
+ }
+};
+
+static const gdb::option::option_def pipe_cmd_option_defs[] = {
+
+ gdb::option::string_option_def<pipe_cmd_opts> {
+ "d",
+ [] (pipe_cmd_opts *opts) { return &opts->delimiter; },
+ nullptr,
+ N_("Indicates to use the specified delimiter string to separate\n\
+COMMAND from SHELL_COMMAND, in alternative to |. This is useful in\n\
+case COMMAND contains a | character."),
+ },
+
+};
+
+/* Create an option_def_group for the "pipe" command's options, with
+ OPTS as context. */
+
+static inline gdb::option::option_def_group
+make_pipe_cmd_options_def_group (pipe_cmd_opts *opts)
+{
+ return {{pipe_cmd_option_defs}, opts};
+}
+
/* Implementation of the "pipe" command. */
static void
pipe_command (const char *arg, int from_tty)
{
- std::string delim ("|");
+ pipe_cmd_opts opts;
- if (arg != nullptr && check_for_argument (&arg, "-d", 2))
- {
- delim = extract_arg (&arg);
- if (delim.empty ())
- error (_("Missing delimiter DELIM after -d"));
- }
+ auto grp = make_pipe_cmd_options_def_group (&opts);
+ gdb::option::process_options
+ (&arg, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, grp);
+
+ const char *delim = "|";
+ if (opts.delimiter != nullptr)
+ delim = opts.delimiter;
const char *command = arg;
if (command == nullptr)
error (_("Missing COMMAND"));
- arg = strstr (arg, delim.c_str ());
+ arg = strstr (arg, delim);
if (arg == nullptr)
error (_("Missing delimiter before SHELL_COMMAND"));
std::string gdb_cmd (command, arg - command);
- arg += delim.length (); /* Skip the delimiter. */
+ arg += strlen (delim); /* Skip the delimiter. */
if (gdb_cmd.empty ())
gdb_cmd = repeat_previous ();
@@ -1019,6 +1055,43 @@ pipe_command (const char *arg, int from_tty)
exit_status_set_internal_vars (exit_status);
}
+/* Completer for the pipe command. */
+
+static void
+pipe_command_completer (struct cmd_list_element *ignore,
+ completion_tracker &tracker,
+ const char *text, const char *word_ignored)
+{
+ pipe_cmd_opts opts;
+
+ const char *org_text = text;
+ auto grp = make_pipe_cmd_options_def_group (&opts);
+ if (gdb::option::complete_options
+ (tracker, &text, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, grp))
+ return;
+
+ const char *delimiter = "|";
+ if (opts.delimiter != nullptr)
+ delimiter = opts.delimiter;
+
+ /* Check if we're past option values already. */
+ if (text > org_text && !isspace (text[-1]))
+ return;
+
+ const char *delim = strstr (text, delimiter);
+
+ /* If we're still not past the delimiter, complete the gdb
+ command. */
+ if (delim == nullptr || delim == text)
+ {
+ complete_nested_command_line (tracker, text);
+ return;
+ }
+
+ /* We're past the delimiter. What follows is a shell command, which
+ we don't know how to complete. */
+}
+
static void
list_command (const char *arg, int from_tty)
{
@@ -2045,6 +2118,7 @@ case COMMAND contains a | character.\n\
\n\
With no COMMAND, repeat the last executed command\n\
and send its output to SHELL_COMMAND."));
+ set_cmd_completer_handle_brkchars (c, pipe_command_completer);
add_com_alias ("|", "pipe", class_support, 0);
add_com ("list", class_files, list_command, _("\