Replace %% in command lists (by copying them) for template arguments ,
authornicm <nicm@openbsd.org>
Fri, 27 Aug 2021 17:25:55 +0000 (17:25 +0000)
committernicm <nicm@openbsd.org>
Fri, 27 Aug 2021 17:25:55 +0000 (17:25 +0000)
this means they can be used with {} as well. Also make argument
processing from an existing vector preserve commands. GitHub issue 2858.

16 files changed:
usr.bin/tmux/arguments.c
usr.bin/tmux/client.c
usr.bin/tmux/cmd-bind-key.c
usr.bin/tmux/cmd-choose-tree.c
usr.bin/tmux/cmd-command-prompt.c
usr.bin/tmux/cmd-display-menu.c
usr.bin/tmux/cmd-new-session.c
usr.bin/tmux/cmd-new-window.c
usr.bin/tmux/cmd-parse.y
usr.bin/tmux/cmd-respawn-pane.c
usr.bin/tmux/cmd-respawn-window.c
usr.bin/tmux/cmd-split-window.c
usr.bin/tmux/cmd.c
usr.bin/tmux/key-bindings.c
usr.bin/tmux/server-client.c
usr.bin/tmux/tmux.h

index 0702420..a8ed55b 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: arguments.c,v 1.47 2021/08/25 08:51:55 nicm Exp $ */
+/* $OpenBSD: arguments.c,v 1.48 2021/08/27 17:25:55 nicm Exp $ */
 
 /*
  * Copyright (c) 2010 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -166,7 +166,7 @@ args_parse(const struct args_parse *parse, struct args_value *values,
                        }
                        argument = *++found;
                        if (argument != ':') {
-                               log_debug("%s: add -%c", __func__, flag);
+                               log_debug("%s: -%c", __func__, flag);
                                args_set(args, flag, NULL);
                                continue;
                        }
@@ -192,7 +192,7 @@ args_parse(const struct args_parse *parse, struct args_value *values,
                                args_copy_value(new, &values[i++]);
                        }
                        s = args_value_as_string(new);
-                       log_debug("%s: add -%c = %s", __func__, flag, s);
+                       log_debug("%s: -%c = %s", __func__, flag, s);
                        args_set(args, flag, new);
                        break;
                }
@@ -203,7 +203,8 @@ args_parse(const struct args_parse *parse, struct args_value *values,
                        value = &values[i];
 
                        s = args_value_as_string(value);
-                       log_debug("%s: %u = %s", __func__, i, s);
+                       log_debug("%s: %u = %s (type %d)", __func__, i, s,
+                           value->type);
 
                        if (parse->cb != NULL) {
                                type = parse->cb(args, args->count, cause);
@@ -265,6 +266,63 @@ args_parse(const struct args_parse *parse, struct args_value *values,
        return (args);
 }
 
+/* Copy and expand a value. */
+static void
+args_copy_copy_value(struct args_value *to, struct args_value *from, int argc,
+    char **argv)
+{
+       char    *s, *expanded;
+       int      i;
+
+       to->type = from->type;
+       switch (from->type) {
+       case ARGS_NONE:
+               break;
+       case ARGS_STRING:
+               expanded = xstrdup(from->string);
+               for (i = 0; i < argc; i++) {
+                       s = cmd_template_replace(expanded, argv[i], i + 1);
+                       free(expanded);
+                       expanded = s;
+               }
+               to->string = expanded;
+               break;
+       case ARGS_COMMANDS:
+               to->cmdlist = cmd_list_copy(from->cmdlist, argc, argv);
+               break;
+       }
+}
+
+/* Copy an arguments set. */
+struct args *
+args_copy(struct args *args, int argc, char **argv)
+{
+       struct args             *new_args;
+       struct args_entry       *entry;
+       struct args_value       *value, *new_value;
+       u_int                    i;
+
+       new_args = args_create();
+       RB_FOREACH(entry, args_tree, &args->tree) {
+               if (entry->count == 1) {
+                       args_set(new_args, entry->flag, NULL);
+                       continue;
+               }
+               TAILQ_FOREACH(value, &entry->values, entry) {
+                       new_value = xcalloc(1, sizeof *new_value);
+                       args_copy_copy_value(new_value, value, argc, argv);
+                       args_set(new_args, entry->flag, new_value);
+               }
+       }
+       new_args->count = args->count;
+       new_args->values = xcalloc(args->count, sizeof *new_args->values);
+       for (i = 0; i < args->count; i++) {
+               new_value = &new_args->values[i];
+               args_copy_copy_value(new_value, &args->values[i], argc, argv);
+       }
+       return (new_args);
+}
+
 /* Free a value. */
 void
 args_free_value(struct args_value *value)
@@ -282,6 +340,16 @@ args_free_value(struct args_value *value)
        free(value->cached);
 }
 
+/* Free values. */
+void
+args_free_values(struct args_value *values, u_int count)
+{
+       u_int   i;
+
+       for (i = 0; i < count; i++)
+               args_free_value(&values[i]);
+}
+
 /* Free an arguments set. */
 void
 args_free(struct args *args)
@@ -290,10 +358,8 @@ args_free(struct args *args)
        struct args_entry       *entry1;
        struct args_value       *value;
        struct args_value       *value1;
-       u_int                    i;
 
-       for (i = 0; i < args->count; i++)
-               args_free_value(&args->values[i]);
+       args_free_values(args->values, args->count);
        free(args->values);
 
        RB_FOREACH_SAFE(entry, args_tree, &args->tree, entry1) {
@@ -311,7 +377,7 @@ args_free(struct args *args)
 
 /* Convert arguments to vector. */
 void
-args_vector(struct args *args, int *argc, char ***argv)
+args_to_vector(struct args *args, int *argc, char ***argv)
 {
        char    *s;
        u_int    i;
@@ -335,6 +401,21 @@ args_vector(struct args *args, int *argc, char ***argv)
        }
 }
 
+/* Convert arguments from vector. */
+struct args_value *
+args_from_vector(int argc, char **argv)
+{
+       struct args_value       *values;
+       int                      i;
+
+       values = xcalloc(argc, sizeof *values);
+       for (i = 0; i < argc; i++) {
+               values[i].type = ARGS_STRING;
+               values[i].string = xstrdup(argv[i]);
+       }
+       return (values);
+}
+
 /* Add to string. */
 static void printflike(3, 4)
 args_print_add(char **buf, size_t *len, const char *fmt, ...)
@@ -424,7 +505,7 @@ args_print(struct args *args)
 char *
 args_escape(const char *s)
 {
-       static const char        dquoted[] = " #';${}";
+       static const char        dquoted[] = " #';${}%";
        static const char        squoted[] = " \"";
        char                    *escaped, *result;
        int                      flags, quotes = 0;
@@ -538,6 +619,13 @@ args_count(struct args *args)
        return (args->count);
 }
 
+/* Get argument values. */
+struct args_value *
+args_values(struct args *args)
+{
+       return (args->values);
+}
+
 /* Get argument value. */
 struct args_value *
 args_value(struct args *args, u_int idx)
@@ -570,8 +658,8 @@ args_make_commands_now(struct cmd *self, struct cmdq_item *item, u_int idx)
                cmdq_error(item, "%s", error);
                free(error);
        }
-       else
-              cmdlist->references++;
+       else
+               cmdlist->references++;
        args_make_commands_free(state);
        return (cmdlist);
 }
@@ -631,8 +719,11 @@ args_make_commands(struct args_command_state *state, int argc, char **argv,
        char                    *cmd, *new_cmd;
        int                      i;
 
-       if (state->cmdlist != NULL)
-               return (state->cmdlist);
+       if (state->cmdlist != NULL) {
+               if (argc == 0)
+                       return (state->cmdlist);
+               return (cmd_list_copy(state->cmdlist, argc, argv));
+       }
 
        cmd = xstrdup(state->cmd);
        for (i = 0; i < argc; i++) {
index a1db86c..fb95629 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: client.c,v 1.155 2021/02/17 07:18:36 nicm Exp $ */
+/* $OpenBSD: client.c,v 1.156 2021/08/27 17:25:55 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -244,6 +244,7 @@ client_main(struct event_base *base, int argc, char **argv, uint64_t flags,
        ssize_t                  linelen;
        char                    *line = NULL, **caps = NULL, *cause;
        u_int                    ncaps = 0;
+       struct args_value       *values;
 
        /* Ignore SIGCHLD now or daemon() in the server will leave a zombie. */
        signal(SIGCHLD, SIG_IGN);
@@ -259,17 +260,20 @@ client_main(struct event_base *base, int argc, char **argv, uint64_t flags,
                msg = MSG_COMMAND;
 
                /*
-                * It sucks parsing the command string twice (in client and
-                * later in server) but it is necessary to get the start server
-                * flag.
+                * It's annoying parsing the command string twice (in client
+                * and later in server) but it is necessary to get the start
+                * server flag.
                 */
-               pr = cmd_parse_from_arguments(argc, argv, NULL);
+               values = args_from_vector(argc, argv);
+               pr = cmd_parse_from_arguments(values, argc, NULL);
                if (pr->status == CMD_PARSE_SUCCESS) {
                        if (cmd_list_any_have(pr->cmdlist, CMD_STARTSERVER))
                                flags |= CLIENT_STARTSERVER;
                        cmd_list_free(pr->cmdlist);
                } else
                        free(pr->error);
+               args_free_values(values, argc);
+               free(values);
        }
 
        /* Create client process structure (starts logging). */
index 418e0ad..062ac95 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-bind-key.c,v 1.45 2021/08/25 09:18:08 nicm Exp $ */
+/* $OpenBSD: cmd-bind-key.c,v 1.46 2021/08/27 17:25:55 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -58,8 +58,7 @@ cmd_bind_key_exec(struct cmd *self, struct cmdq_item *item)
        key_code                  key;
        const char               *tablename, *note = args_get(args, 'N');
        struct cmd_parse_result  *pr;
-       char                    **argv;
-       int                       argc, repeat;
+       int                       repeat;
        struct args_value        *value;
        u_int                     count = args_count(args);
 
@@ -92,9 +91,8 @@ cmd_bind_key_exec(struct cmd *self, struct cmdq_item *item)
        if (count == 2)
                pr = cmd_parse_from_string(args_string(args, 1), NULL);
        else {
-               args_vector(args, &argc, &argv);
-               pr = cmd_parse_from_arguments(argc - 1, argv + 1, NULL);
-               cmd_free_argv(argc, argv);
+               pr = cmd_parse_from_arguments(args_values(args) + 1, count - 1,
+                   NULL);
        }
        switch (pr->status) {
        case CMD_PARSE_ERROR:
index 5658001..e84c87e 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-choose-tree.c,v 1.49 2021/08/21 10:22:38 nicm Exp $ */
+/* $OpenBSD: cmd-choose-tree.c,v 1.50 2021/08/27 17:25:55 nicm Exp $ */
 
 /*
  * Copyright (c) 2012 Thomas Adam <thomas@xteddy.org>
  * Enter a mode.
  */
 
-static enum cmd_retval cmd_choose_tree_exec(struct cmd *, struct cmdq_item *);
+static enum args_parse_type    cmd_choose_tree_args_parse(struct args *args,
+                                   u_int idx, char **cause);
+static enum cmd_retval         cmd_choose_tree_exec(struct cmd *,
+                                   struct cmdq_item *);
 
 const struct cmd_entry cmd_choose_tree_entry = {
        .name = "choose-tree",
        .alias = NULL,
 
-       .args = { "F:f:GK:NO:rst:wZ", 0, 1, NULL },
+       .args = { "F:f:GK:NO:rst:wZ", 0, 1, cmd_choose_tree_args_parse },
        .usage = "[-GNrswZ] [-F format] [-f filter] [-K key-format] "
                 "[-O sort-order] " CMD_TARGET_PANE_USAGE " [template]",
 
@@ -44,7 +47,7 @@ const struct cmd_entry cmd_choose_client_entry = {
        .name = "choose-client",
        .alias = NULL,
 
-       .args = { "F:f:K:NO:rt:Z", 0, 1, NULL },
+       .args = { "F:f:K:NO:rt:Z", 0, 1, cmd_choose_tree_args_parse },
        .usage = "[-NrZ] [-F format] [-f filter] [-K key-format] "
                 "[-O sort-order] " CMD_TARGET_PANE_USAGE " [template]",
 
@@ -58,7 +61,7 @@ const struct cmd_entry cmd_choose_buffer_entry = {
        .name = "choose-buffer",
        .alias = NULL,
 
-       .args = { "F:f:K:NO:rt:Z", 0, 1, NULL },
+       .args = { "F:f:K:NO:rt:Z", 0, 1, cmd_choose_tree_args_parse },
        .usage = "[-NrZ] [-F format] [-f filter] [-K key-format] "
                 "[-O sort-order] " CMD_TARGET_PANE_USAGE " [template]",
 
@@ -81,6 +84,13 @@ const struct cmd_entry cmd_customize_mode_entry = {
        .exec = cmd_choose_tree_exec
 };
 
+static enum args_parse_type
+cmd_choose_tree_args_parse(__unused struct args *args, __unused u_int idx,
+    __unused char **cause)
+{
+       return (ARGS_PARSE_COMMANDS_OR_STRING);
+}
+
 static enum cmd_retval
 cmd_choose_tree_exec(struct cmd *self, struct cmdq_item *item)
 {
index 1f9097b..ae66d20 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-command-prompt.c,v 1.62 2021/08/25 08:51:55 nicm Exp $ */
+/* $OpenBSD: cmd-command-prompt.c,v 1.63 2021/08/27 17:25:55 nicm Exp $ */
 
 /*
  * Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -169,11 +169,13 @@ static int
 cmd_command_prompt_callback(struct client *c, void *data, const char *s,
     int done)
 {
-       struct cmd_command_prompt_cdata         *cdata = data;
-       char                                    *error;
-       struct cmdq_item                        *item = cdata->item, *new_item;
-       struct cmd_list                         *cmdlist;
-       struct cmd_command_prompt_prompt        *prompt;
+       struct cmd_command_prompt_cdata          *cdata = data;
+       char                                     *error;
+       struct cmdq_item                         *item = cdata->item, *new_item;
+       struct cmd_list                          *cmdlist;
+       struct cmd_command_prompt_prompt         *prompt;
+       int                                       argc = 0;
+       char                                    **argv = NULL;
 
        if (s == NULL)
                goto out;
@@ -181,7 +183,6 @@ cmd_command_prompt_callback(struct client *c, void *data, const char *s,
                if (cdata->flags & PROMPT_INCREMENTAL)
                        goto out;
 
-               cmd_append_argv(&cdata->argc, &cdata->argv, s);
                if (++cdata->current != cdata->count) {
                        prompt = &cdata->prompts[cdata->current];
                        status_prompt_update(c, prompt->prompt, prompt->input);
@@ -189,8 +190,15 @@ cmd_command_prompt_callback(struct client *c, void *data, const char *s,
                }
        }
 
-       cmdlist = args_make_commands(cdata->state, cdata->argc, cdata->argv,
-           &error);
+       argc = cdata->argc;
+       argv = cmd_copy_argv(cdata->argc, cdata->argv);
+       cmd_append_argv(&argc, &argv, s);
+       if (done) {
+               cdata->argc = argc;
+               cdata->argv = cmd_copy_argv(argc, argv);
+       }
+
+       cmdlist = args_make_commands(cdata->state, argc, argv, &error);
        if (cmdlist == NULL) {
                cmdq_append(c, cmdq_get_error(error));
                free(error);
@@ -201,6 +209,7 @@ cmd_command_prompt_callback(struct client *c, void *data, const char *s,
                new_item = cmdq_get_command(cmdlist, cmdq_get_state(item));
                cmdq_insert_after(item, new_item);
        }
+       cmd_free_argv(argc, argv);
 
        if (c->prompt_inputcb != cmd_command_prompt_callback)
                return (1);
index ada9889..80b2806 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-display-menu.c,v 1.32 2021/08/25 08:51:55 nicm Exp $ */
+/* $OpenBSD: cmd-display-menu.c,v 1.33 2021/08/27 17:25:55 nicm Exp $ */
 
 /*
  * Copyright (c) 2019 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -408,7 +408,7 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item)
                        shell = _PATH_BSHELL;
                cmd_append_argv(&argc, &argv, shell);
        } else
-               args_vector(args, &argc, &argv);
+               args_to_vector(args, &argc, &argv);
 
        if (args_has(args, 'E') > 1)
                flags |= POPUP_CLOSEEXITZERO;
index 5a3eba8..eb71df9 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-new-session.c,v 1.143 2021/08/21 10:28:05 nicm Exp $ */
+/* $OpenBSD: cmd-new-session.c,v 1.144 2021/08/27 17:25:55 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -42,7 +42,8 @@ const struct cmd_entry cmd_new_session_entry = {
        .args = { "Ac:dDe:EF:f:n:Ps:t:x:Xy:", 0, -1, NULL },
        .usage = "[-AdDEPX] [-c start-directory] [-e environment] [-F format] "
                 "[-f flags] [-n window-name] [-s session-name] "
-                CMD_TARGET_SESSION_USAGE " [-x width] [-y height] [command]",
+                CMD_TARGET_SESSION_USAGE " [-x width] [-y height] "
+                "[shell-command]",
 
        .target = { 't', CMD_FIND_SESSION, CMD_FIND_CANFAIL },
 
@@ -283,7 +284,7 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
                sc.tc = c;
 
        sc.name = args_get(args, 'n');
-       args_vector(args, &sc.argc, &sc.argv);
+       args_to_vector(args, &sc.argc, &sc.argv);
 
        sc.idx = -1;
        sc.cwd = args_get(args, 'c');
index aab1938..599ebd2 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-new-window.c,v 1.95 2021/08/21 10:28:05 nicm Exp $ */
+/* $OpenBSD: cmd-new-window.c,v 1.96 2021/08/27 17:25:55 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -40,7 +40,7 @@ const struct cmd_entry cmd_new_window_entry = {
 
        .args = { "abc:de:F:kn:PSt:", 0, -1, NULL },
        .usage = "[-abdkPS] [-c start-directory] [-e environment] [-F format] "
-                "[-n window-name] " CMD_TARGET_WINDOW_USAGE " [command]",
+                "[-n window-name] " CMD_TARGET_WINDOW_USAGE " [shell-command]",
 
        .target = { 't', CMD_FIND_WINDOW, CMD_FIND_WINDOW_INDEX },
 
@@ -105,7 +105,7 @@ cmd_new_window_exec(struct cmd *self, struct cmdq_item *item)
        sc.tc = tc;
 
        sc.name = args_get(args, 'n');
-       args_vector(args, &sc.argc, &sc.argv);
+       args_to_vector(args, &sc.argc, &sc.argv);
        sc.environ = environ_create();
 
        av = args_first_value(args, 'e');
index 6d7c773..8f4cbc1 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-parse.y,v 1.45 2021/08/23 11:48:21 nicm Exp $ */
+/* $OpenBSD: cmd-parse.y,v 1.46 2021/08/27 17:25:55 nicm Exp $ */
 
 /*
  * Copyright (c) 2019 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -44,13 +44,15 @@ struct cmd_parse_scope {
 
 enum cmd_parse_argument_type {
        CMD_PARSE_STRING,
-       CMD_PARSE_COMMANDS
+       CMD_PARSE_COMMANDS,
+       CMD_PARSE_PARSED_COMMANDS
 };
 
 struct cmd_parse_argument {
        enum cmd_parse_argument_type     type;
        char                            *string;
        struct cmd_parse_commands       *commands;
+       struct cmd_list                 *cmdlist;
 
        TAILQ_ENTRY(cmd_parse_argument)  entry;
 };
@@ -608,6 +610,9 @@ cmd_parse_free_argument(struct cmd_parse_argument *arg)
        case CMD_PARSE_COMMANDS:
                cmd_parse_free_commands(arg->commands);
                break;
+       case CMD_PARSE_PARSED_COMMANDS:
+               cmd_list_free(arg->cmdlist);
+               break;
        }
        free(arg);
 }
@@ -723,6 +728,11 @@ cmd_parse_log_commands(struct cmd_parse_commands *cmds, const char *prefix)
                                cmd_parse_log_commands(arg->commands, s);
                                free(s);
                                break;
+                       case CMD_PARSE_PARSED_COMMANDS:
+                               s = cmd_list_print(arg->cmdlist, 0);
+                               log_debug("%s %u:%u: %s", prefix, i, j, s);
+                               free(s);
+                               break;
                        }
                        j++;
                }
@@ -818,6 +828,11 @@ cmd_parse_build_command(struct cmd_parse_command *cmd,
                        values[count].type = ARGS_COMMANDS;
                        values[count].cmdlist = pr->cmdlist;
                        break;
+               case CMD_PARSE_PARSED_COMMANDS:
+                       values[count].type = ARGS_COMMANDS;
+                       values[count].cmdlist = arg->cmdlist;
+                       values[count].cmdlist->references++;
+                       break;
                }
                count++;
        }
@@ -1023,39 +1038,19 @@ cmd_parse_from_buffer(const void *buf, size_t len, struct cmd_parse_input *pi)
        return (&pr);
 }
 
-static void
-cmd_parse_add_command(struct cmd_parse_commands *cmds,
-    struct cmd_parse_input *pi, int argc, char **argv)
+struct cmd_parse_result *
+cmd_parse_from_arguments(struct args_value *values, u_int count,
+    struct cmd_parse_input *pi)
 {
+       static struct cmd_parse_result   pr;
+       struct cmd_parse_input           input;
+       struct cmd_parse_commands       *cmds;
        struct cmd_parse_command        *cmd;
        struct cmd_parse_argument       *arg;
-       int                              i;
-
-       cmd_log_argv(argc, argv, "%s", __func__);
-
-       cmd = xcalloc(1, sizeof *cmd);
-       cmd->line = pi->line;
-
-       TAILQ_INIT(&cmd->arguments);
-       for (i = 0; i < argc; i++) {
-               arg = xcalloc(1, sizeof *arg);
-               arg->type = CMD_PARSE_STRING;
-               arg->string = xstrdup(argv[i]);
-               TAILQ_INSERT_TAIL(&cmd->arguments, arg, entry);
-       }
-
-       TAILQ_INSERT_TAIL(cmds, cmd, entry);
-}
-
-struct cmd_parse_result *
-cmd_parse_from_arguments(int argc, char **argv, struct cmd_parse_input *pi)
-{
-       static struct cmd_parse_result    pr;
-       struct cmd_parse_input            input;
-       struct cmd_parse_commands        *cmds;
-       char                            **copy, **new_argv;
-       size_t                            size;
-       int                               i, last, new_argc;
+       u_int                            i;
+       char                            *copy;
+       size_t                           size;
+       int                              end;
 
        /*
         * The commands are already split up into arguments, so just separate
@@ -1066,40 +1061,51 @@ cmd_parse_from_arguments(int argc, char **argv, struct cmd_parse_input *pi)
                memset(&input, 0, sizeof input);
                pi = &input;
        }
-       cmd_log_argv(argc, argv, "%s", __func__);
 
        cmds = cmd_parse_new_commands();
-       copy = cmd_copy_argv(argc, argv);
-
-       last = 0;
-       for (i = 0; i < argc; i++) {
-               size = strlen(copy[i]);
-               if (size == 0 || copy[i][size - 1] != ';')
-                       continue;
-               copy[i][--size] = '\0';
-               if (size > 0 && copy[i][size - 1] == '\\') {
-                       copy[i][size - 1] = ';';
-                       continue;
-               }
-
-               new_argc = i - last;
-               new_argv = copy + last;
-               if (size != 0)
-                       new_argc++;
 
-               if (new_argc != 0)
-                       cmd_parse_add_command(cmds, pi, new_argc, new_argv);
-               last = i + 1;
-       }
-       if (last != argc) {
-               new_argv = copy + last;
-               new_argc = argc - last;
+       cmd = xcalloc(1, sizeof *cmd);
+       cmd->line = pi->line;
+       TAILQ_INIT(&cmd->arguments);
 
-               if (new_argc != 0)
-                       cmd_parse_add_command(cmds, pi, new_argc, new_argv);
+       for (i = 0; i < count; i++) {
+               end = 0;
+               if (values[i].type == ARGS_STRING) {
+                       copy = xstrdup(values[i].string);
+                       size = strlen(copy);
+                       if (size != 0 && copy[size - 1] == ';') {
+                               copy[--size] = '\0';
+                               if (size > 0 && copy[size - 1] == '\\')
+                                       copy[size - 1] = ';';
+                               else
+                                       end = 1;
+                       }
+                       if (!end || size != 0) {
+                               arg = xcalloc(1, sizeof *arg);
+                               arg->type = CMD_PARSE_STRING;
+                               arg->string = copy;
+                               TAILQ_INSERT_TAIL(&cmd->arguments, arg, entry);
+                       }
+               } else if (values[i].type == ARGS_COMMANDS) {
+                       arg = xcalloc(1, sizeof *arg);
+                       arg->type = CMD_PARSE_PARSED_COMMANDS;
+                       arg->cmdlist = values[i].cmdlist;
+                       arg->cmdlist->references++;
+                       TAILQ_INSERT_TAIL(&cmd->arguments, arg, entry);
+               } else
+                       fatalx("unknown argument type");
+               if (end) {
+                       TAILQ_INSERT_TAIL(cmds, cmd, entry);
+                       cmd = xcalloc(1, sizeof *cmd);
+                       cmd->line = pi->line;
+                       TAILQ_INIT(&cmd->arguments);
+               }
        }
+       if (!TAILQ_EMPTY(&cmd->arguments))
+               TAILQ_INSERT_TAIL(cmds, cmd, entry);
+       else
+               free(cmd);
 
-       cmd_free_argv(argc, copy);
        cmd_parse_build_commands(cmds, pi, &pr);
        cmd_parse_free_commands(cmds);
        return (&pr);
index 93e8d65..520317d 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-respawn-pane.c,v 1.37 2021/08/21 10:28:05 nicm Exp $ */
+/* $OpenBSD: cmd-respawn-pane.c,v 1.38 2021/08/27 17:25:55 nicm Exp $ */
 
 /*
  * Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -36,7 +36,7 @@ const struct cmd_entry cmd_respawn_pane_entry = {
 
        .args = { "c:e:kt:", 0, -1, NULL },
        .usage = "[-k] [-c start-directory] [-e environment] "
-                CMD_TARGET_PANE_USAGE " [command]",
+                CMD_TARGET_PANE_USAGE " [shell-command]",
 
        .target = { 't', CMD_FIND_PANE, 0 },
 
@@ -61,10 +61,8 @@ cmd_respawn_pane_exec(struct cmd *self, struct cmdq_item *item)
        sc.wl = wl;
 
        sc.wp0 = wp;
-       sc.lc = NULL;
 
-       sc.name = NULL;
-       args_vector(args, &sc.argc, &sc.argv);
+       args_to_vector(args, &sc.argc, &sc.argv);
        sc.environ = environ_create();
 
        av = args_first_value(args, 'e');
index 31b4359..de43b63 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-respawn-window.c,v 1.48 2021/08/21 10:28:05 nicm Exp $ */
+/* $OpenBSD: cmd-respawn-window.c,v 1.49 2021/08/27 17:25:55 nicm Exp $ */
 
 /*
  * Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -36,7 +36,7 @@ const struct cmd_entry cmd_respawn_window_entry = {
 
        .args = { "c:e:kt:", 0, -1, NULL },
        .usage = "[-k] [-c start-directory] [-e environment] "
-                CMD_TARGET_WINDOW_USAGE " [command]",
+                CMD_TARGET_WINDOW_USAGE " [shell-command]",
 
        .target = { 't', CMD_FIND_WINDOW, 0 },
 
@@ -61,8 +61,7 @@ cmd_respawn_window_exec(struct cmd *self, struct cmdq_item *item)
        sc.wl = wl;
        sc.tc = tc;
 
-       sc.name = NULL;
-       args_vector(args, &sc.argc, &sc.argv);
+       args_to_vector(args, &sc.argc, &sc.argv);
        sc.environ = environ_create();
 
        av = args_first_value(args, 'e');
index 909c6bb..4c71c47 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-split-window.c,v 1.109 2021/08/21 10:28:05 nicm Exp $ */
+/* $OpenBSD: cmd-split-window.c,v 1.110 2021/08/27 17:25:55 nicm Exp $ */
 
 /*
  * Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -42,7 +42,8 @@ const struct cmd_entry cmd_split_window_entry = {
 
        .args = { "bc:de:fF:hIl:p:Pt:vZ", 0, -1, NULL },
        .usage = "[-bdefhIPvZ] [-c start-directory] [-e environment] "
-                "[-F format] [-l size] " CMD_TARGET_PANE_USAGE " [command]",
+                "[-F format] [-l size] " CMD_TARGET_PANE_USAGE
+                "[shell-command]",
 
        .target = { 't', CMD_FIND_PANE, 0 },
 
@@ -136,8 +137,7 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
        sc.wp0 = wp;
        sc.lc = lc;
 
-       sc.name = NULL;
-       args_vector(args, &sc.argc, &sc.argv);
+       args_to_vector(args, &sc.argc, &sc.argv);
        sc.environ = environ_create();
 
        av = args_first_value(args, 'e');
index fe18169..719dbdf 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd.c,v 1.171 2021/08/25 08:51:55 nicm Exp $ */
+/* $OpenBSD: cmd.c,v 1.172 2021/08/27 17:25:55 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -544,6 +544,23 @@ cmd_free(struct cmd *cmd)
        free(cmd);
 }
 
+/* Copy a command. */
+struct cmd *
+cmd_copy(struct cmd *cmd, int argc, char **argv)
+{
+       struct cmd      *new_cmd;
+
+       new_cmd = xcalloc(1, sizeof *new_cmd);
+       new_cmd->entry = cmd->entry;
+       new_cmd->args = args_copy(cmd->args, argc, argv);
+
+       if (cmd->file != NULL)
+               new_cmd->file = xstrdup(cmd->file);
+       new_cmd->line = cmd->line;
+
+       return (new_cmd);
+}
+
 /* Get a command as a string. */
 char *
 cmd_print(struct cmd *cmd)
@@ -618,6 +635,37 @@ cmd_list_free(struct cmd_list *cmdlist)
        free(cmdlist);
 }
 
+/* Copy a command list, expanding %s in arguments. */
+struct cmd_list *
+cmd_list_copy(struct cmd_list *cmdlist, int argc, char **argv)
+{
+       struct cmd      *cmd;
+       struct cmd_list *new_cmdlist;
+       struct cmd      *new_cmd;
+       u_int            group = cmdlist->group;
+       char            *s;
+
+       s = cmd_list_print(cmdlist, 0);
+       log_debug("%s: %s", __func__, s);
+       free(s);
+
+       new_cmdlist = cmd_list_new();
+       TAILQ_FOREACH(cmd, cmdlist->list, qentry) {
+               if (cmd->group != group) {
+                       new_cmdlist->group = cmd_list_next_group++;
+                       group = cmd->group;
+               }
+               new_cmd = cmd_copy(cmd, argc, argv);
+               cmd_list_append(new_cmdlist, new_cmd);
+       }
+
+       s = cmd_list_print(new_cmdlist, 0);
+       log_debug("%s: %s", __func__, s);
+       free(s);
+
+       return (new_cmdlist);
+}
+
 /* Get a command list as a string. */
 char *
 cmd_list_print(struct cmd_list *cmdlist, int escaped)
index e3e6825..e0fb4d4 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: key-bindings.c,v 1.140 2021/08/25 08:51:55 nicm Exp $ */
+/* $OpenBSD: key-bindings.c,v 1.141 2021/08/27 17:25:55 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -29,7 +29,7 @@
        " 'Previous' 'p' {switch-client -p}" \
        " ''" \
        " 'Renumber' 'N' {move-window -r}" \
-       " 'Rename' 'n' {command-prompt -I \"#S\" \"rename-session -- '%%'\"}" \
+       " 'Rename' 'n' {command-prompt -I \"#S\" {rename-session -- '%%'}}" \
        " ''" \
        " 'New Session' 's' {new-session}" \
        " 'New Window' 'w' {new-window}"
@@ -41,7 +41,7 @@
        " 'Kill' 'X' {kill-window}" \
        " 'Respawn' 'R' {respawn-window -k}" \
        " '#{?pane_marked,Unmark,Mark}' 'm' {select-pane -m}" \
-       " 'Rename' 'n' {command-prompt -FI \"#W\" \"rename-window -t#{window_id} -- '%%'\"}" \
+       " 'Rename' 'n' {command-prompt -FI \"#W\" {rename-window -t '#{window_id}' -- '%%'}}" \
        " ''" \
        " 'New After' 'w' {new-window -a}" \
        " 'New At End' 'W' {new-window}"
@@ -350,16 +350,16 @@ key_bindings_init(void)
                "bind -N 'Break pane to a new window' ! { break-pane }",
                "bind -N 'Split window vertically' '\"' { split-window }",
                "bind -N 'List all paste buffers' '#' { list-buffers }",
-               "bind -N 'Rename current session' '$' { command-prompt -I'#S' \"rename-session -- '%%'\" }",
+               "bind -N 'Rename current session' '$' { command-prompt -I'#S' { rename-session -- '%%' } }",
                "bind -N 'Split window horizontally' % { split-window -h }",
                "bind -N 'Kill current window' & { confirm-before -p\"kill-window #W? (y/n)\" kill-window }",
-               "bind -N 'Prompt for window index to select' \"'\" { command-prompt -T window-target -pindex \"select-window -t ':%%'\" }",
+               "bind -N 'Prompt for window index to select' \"'\" { command-prompt -T window-target -pindex { select-window -t ':%%' } }",
                "bind -N 'Switch to previous client' ( { switch-client -p }",
                "bind -N 'Switch to next client' ) { switch-client -n }",
-               "bind -N 'Rename current window' , { command-prompt -I'#W' \"rename-window -- '%%'\" }",
+               "bind -N 'Rename current window' , { command-prompt -I'#W' { rename-window -- '%%' } }",
                "bind -N 'Delete the most recent paste buffer' - { delete-buffer }",
-               "bind -N 'Move the current window' . { command-prompt -T target \"move-window -t '%%'\" }",
-               "bind -N 'Describe key binding' '/' { command-prompt -kpkey 'list-keys -1N \"%%%\"' }",
+               "bind -N 'Move the current window' . { command-prompt -T target { move-window -t '%%' } }",
+               "bind -N 'Describe key binding' '/' { command-prompt -kpkey  { list-keys -1N '%%' } }",
                "bind -N 'Select window 0' 0 { select-window -t:=0 }",
                "bind -N 'Select window 1' 1 { select-window -t:=1 }",
                "bind -N 'Select window 2' 2 { select-window -t:=2 }",
@@ -382,7 +382,7 @@ key_bindings_init(void)
                "bind -N 'Paste the most recent paste buffer' ] { paste-buffer -p }",
                "bind -N 'Create a new window' c { new-window }",
                "bind -N 'Detach the current client' d { detach-client }",
-               "bind -N 'Search for a pane' f { command-prompt \"find-window -Z -- '%%'\" }",
+               "bind -N 'Search for a pane' f { command-prompt { find-window -Z -- '%%' } }",
                "bind -N 'Display window information' i { display-message }",
                "bind -N 'Select the previously current window' l { last-window }",
                "bind -N 'Toggle the marked pane' m { select-pane -m }",
@@ -482,25 +482,25 @@ key_bindings_init(void)
                "bind -Tcopy-mode C-k { send -X copy-pipe-end-of-line-and-cancel }",
                "bind -Tcopy-mode C-n { send -X cursor-down }",
                "bind -Tcopy-mode C-p { send -X cursor-up }",
-               "bind -Tcopy-mode C-r { command-prompt -T search -ip'(search up)' -I'#{pane_search_string}' 'send -X search-backward-incremental \"%%%\"' }",
-               "bind -Tcopy-mode C-s { command-prompt -T search -ip'(search down)' -I'#{pane_search_string}' 'send -X search-forward-incremental \"%%%\"' }",
+               "bind -Tcopy-mode C-r { command-prompt -T search -ip'(search up)' -I'#{pane_search_string}' { send -X search-backward-incremental '%%' } }",
+               "bind -Tcopy-mode C-s { command-prompt -T search -ip'(search down)' -I'#{pane_search_string}' { send -X search-forward-incremental '%%' } }",
                "bind -Tcopy-mode C-v { send -X page-down }",
                "bind -Tcopy-mode C-w { send -X copy-pipe-and-cancel }",
                "bind -Tcopy-mode Escape { send -X cancel }",
                "bind -Tcopy-mode Space { send -X page-down }",
                "bind -Tcopy-mode , { send -X jump-reverse }",
                "bind -Tcopy-mode \\; { send -X jump-again }",
-               "bind -Tcopy-mode F { command-prompt -1p'(jump backward)' 'send -X jump-backward \"%%%\"' }",
+               "bind -Tcopy-mode F { command-prompt -1p'(jump backward)' { send -X jump-backward '%%' } }",
                "bind -Tcopy-mode N { send -X search-reverse }",
                "bind -Tcopy-mode R { send -X rectangle-toggle }",
-               "bind -Tcopy-mode T { command-prompt -1p'(jump to backward)' 'send -X jump-to-backward \"%%%\"' }",
+               "bind -Tcopy-mode T { command-prompt -1p'(jump to backward)' { send -X jump-to-backward '%%' } }",
                "bind -Tcopy-mode X { send -X set-mark }",
-               "bind -Tcopy-mode f { command-prompt -1p'(jump forward)' 'send -X jump-forward \"%%%\"' }",
-               "bind -Tcopy-mode g { command-prompt -p'(goto line)' 'send -X goto-line \"%%%\"' }",
+               "bind -Tcopy-mode f { command-prompt -1p'(jump forward)' { send -X jump-forward '%%' } }",
+               "bind -Tcopy-mode g { command-prompt -p'(goto line)' { send -X goto-line '%%' } }",
                "bind -Tcopy-mode n { send -X search-again }",
                "bind -Tcopy-mode q { send -X cancel }",
                "bind -Tcopy-mode r { send -X refresh-from-pane }",
-               "bind -Tcopy-mode t { command-prompt -1p'(jump to forward)' 'send -X jump-to-forward \"%%%\"' }",
+               "bind -Tcopy-mode t { command-prompt -1p'(jump to forward)' { send -X jump-to-forward '%%' } }",
                "bind -Tcopy-mode Home { send -X start-of-line }",
                "bind -Tcopy-mode End { send -X end-of-line }",
                "bind -Tcopy-mode MouseDown1Pane select-pane",
@@ -516,15 +516,15 @@ key_bindings_init(void)
                "bind -Tcopy-mode Down { send -X cursor-down }",
                "bind -Tcopy-mode Left { send -X cursor-left }",
                "bind -Tcopy-mode Right { send -X cursor-right }",
-               "bind -Tcopy-mode M-1 { command-prompt -Np'(repeat)' -I1 'send -N \"%%%\"' }",
-               "bind -Tcopy-mode M-2 { command-prompt -Np'(repeat)' -I2 'send -N \"%%%\"' }",
-               "bind -Tcopy-mode M-3 { command-prompt -Np'(repeat)' -I3 'send -N \"%%%\"' }",
-               "bind -Tcopy-mode M-4 { command-prompt -Np'(repeat)' -I4 'send -N \"%%%\"' }",
-               "bind -Tcopy-mode M-5 { command-prompt -Np'(repeat)' -I5 'send -N \"%%%\"' }",
-               "bind -Tcopy-mode M-6 { command-prompt -Np'(repeat)' -I6 'send -N \"%%%\"' }",
-               "bind -Tcopy-mode M-7 { command-prompt -Np'(repeat)' -I7 'send -N \"%%%\"' }",
-               "bind -Tcopy-mode M-8 { command-prompt -Np'(repeat)' -I8 'send -N \"%%%\"' }",
-               "bind -Tcopy-mode M-9 { command-prompt -Np'(repeat)' -I9 'send -N \"%%%\"' }",
+               "bind -Tcopy-mode M-1 { command-prompt -Np'(repeat)' -I1 { send -N '%%' } }",
+               "bind -Tcopy-mode M-2 { command-prompt -Np'(repeat)' -I2 { send -N '%%' } }",
+               "bind -Tcopy-mode M-3 { command-prompt -Np'(repeat)' -I3 { send -N '%%' } }",
+               "bind -Tcopy-mode M-4 { command-prompt -Np'(repeat)' -I4 { send -N '%%' } }",
+               "bind -Tcopy-mode M-5 { command-prompt -Np'(repeat)' -I5 { send -N '%%' } }",
+               "bind -Tcopy-mode M-6 { command-prompt -Np'(repeat)' -I6 { send -N '%%' } }",
+               "bind -Tcopy-mode M-7 { command-prompt -Np'(repeat)' -I7 { send -N '%%' } }",
+               "bind -Tcopy-mode M-8 { command-prompt -Np'(repeat)' -I8 { send -N '%%' } }",
+               "bind -Tcopy-mode M-9 { command-prompt -Np'(repeat)' -I9 { send -N '%%' } }",
                "bind -Tcopy-mode M-< { send -X history-top }",
                "bind -Tcopy-mode M-> { send -X history-bottom }",
                "bind -Tcopy-mode M-R { send -X top-line }",
@@ -562,25 +562,25 @@ key_bindings_init(void)
                "bind -Tcopy-mode-vi Space { send -X begin-selection }",
                "bind -Tcopy-mode-vi '$' { send -X end-of-line }",
                "bind -Tcopy-mode-vi , { send -X jump-reverse }",
-               "bind -Tcopy-mode-vi / { command-prompt -T search -p'(search down)' 'send -X search-forward \"%%%\"' }",
+               "bind -Tcopy-mode-vi / { command-prompt -T search -p'(search down)' { send -X search-forward '%%' } }",
                "bind -Tcopy-mode-vi 0 { send -X start-of-line }",
-               "bind -Tcopy-mode-vi 1 { command-prompt -Np'(repeat)' -I1 'send -N \"%%%\"' }",
-               "bind -Tcopy-mode-vi 2 { command-prompt -Np'(repeat)' -I2 'send -N \"%%%\"' }",
-               "bind -Tcopy-mode-vi 3 { command-prompt -Np'(repeat)' -I3 'send -N \"%%%\"' }",
-               "bind -Tcopy-mode-vi 4 { command-prompt -Np'(repeat)' -I4 'send -N \"%%%\"' }",
-               "bind -Tcopy-mode-vi 5 { command-prompt -Np'(repeat)' -I5 'send -N \"%%%\"' }",
-               "bind -Tcopy-mode-vi 6 { command-prompt -Np'(repeat)' -I6 'send -N \"%%%\"' }",
-               "bind -Tcopy-mode-vi 7 { command-prompt -Np'(repeat)' -I7 'send -N \"%%%\"' }",
-               "bind -Tcopy-mode-vi 8 { command-prompt -Np'(repeat)' -I8 'send -N \"%%%\"' }",
-               "bind -Tcopy-mode-vi 9 { command-prompt -Np'(repeat)' -I9 'send -N \"%%%\"' }",
-               "bind -Tcopy-mode-vi : { command-prompt -p'(goto line)' 'send -X goto-line \"%%%\"' }",
+               "bind -Tcopy-mode-vi 1 { command-prompt -Np'(repeat)' -I1 { send -N '%%' } }",
+               "bind -Tcopy-mode-vi 2 { command-prompt -Np'(repeat)' -I2 { send -N '%%' } }",
+               "bind -Tcopy-mode-vi 3 { command-prompt -Np'(repeat)' -I3 { send -N '%%' } }",
+               "bind -Tcopy-mode-vi 4 { command-prompt -Np'(repeat)' -I4 { send -N '%%' } }",
+               "bind -Tcopy-mode-vi 5 { command-prompt -Np'(repeat)' -I5 { send -N '%%' } }",
+               "bind -Tcopy-mode-vi 6 { command-prompt -Np'(repeat)' -I6 { send -N '%%' } }",
+               "bind -Tcopy-mode-vi 7 { command-prompt -Np'(repeat)' -I7 { send -N '%%' } }",
+               "bind -Tcopy-mode-vi 8 { command-prompt -Np'(repeat)' -I8 { send -N '%%' } }",
+               "bind -Tcopy-mode-vi 9 { command-prompt -Np'(repeat)' -I9 { send -N '%%' } }",
+               "bind -Tcopy-mode-vi : { command-prompt -p'(goto line)' { send -X goto-line '%%' } }",
                "bind -Tcopy-mode-vi \\; { send -X jump-again }",
-               "bind -Tcopy-mode-vi ? { command-prompt -T search -p'(search up)' 'send -X search-backward \"%%%\"' }",
+               "bind -Tcopy-mode-vi ? { command-prompt -T search -p'(search up)' { send -X search-backward '%%' } }",
                "bind -Tcopy-mode-vi A { send -X append-selection-and-cancel }",
                "bind -Tcopy-mode-vi B { send -X previous-space }",
                "bind -Tcopy-mode-vi D { send -X copy-pipe-end-of-line-and-cancel }",
                "bind -Tcopy-mode-vi E { send -X next-space-end }",
-               "bind -Tcopy-mode-vi F { command-prompt -1p'(jump backward)' 'send -X jump-backward \"%%%\"' }",
+               "bind -Tcopy-mode-vi F { command-prompt -1p'(jump backward)' { send -X jump-backward '%%' } }",
                "bind -Tcopy-mode-vi G { send -X history-bottom }",
                "bind -Tcopy-mode-vi H { send -X top-line }",
                "bind -Tcopy-mode-vi J { send -X scroll-down }",
@@ -588,14 +588,14 @@ key_bindings_init(void)
                "bind -Tcopy-mode-vi L { send -X bottom-line }",
                "bind -Tcopy-mode-vi M { send -X middle-line }",
                "bind -Tcopy-mode-vi N { send -X search-reverse }",
-               "bind -Tcopy-mode-vi T { command-prompt -1p'(jump to backward)' 'send -X jump-to-backward \"%%%\"' }",
+               "bind -Tcopy-mode-vi T { command-prompt -1p'(jump to backward)' { send -X jump-to-backward '%%' } }",
                "bind -Tcopy-mode-vi V { send -X select-line }",
                "bind -Tcopy-mode-vi W { send -X next-space }",
                "bind -Tcopy-mode-vi X { send -X set-mark }",
                "bind -Tcopy-mode-vi ^ { send -X back-to-indentation }",
                "bind -Tcopy-mode-vi b { send -X previous-word }",
                "bind -Tcopy-mode-vi e { send -X next-word-end }",
-               "bind -Tcopy-mode-vi f { command-prompt -1p'(jump forward)' 'send -X jump-forward \"%%%\"' }",
+               "bind -Tcopy-mode-vi f { command-prompt -1p'(jump forward)' { send -X jump-forward '%%' } }",
                "bind -Tcopy-mode-vi g { send -X history-top }",
                "bind -Tcopy-mode-vi h { send -X cursor-left }",
                "bind -Tcopy-mode-vi j { send -X cursor-down }",
@@ -605,7 +605,7 @@ key_bindings_init(void)
                "bind -Tcopy-mode-vi o { send -X other-end }",
                "bind -Tcopy-mode-vi q { send -X cancel }",
                "bind -Tcopy-mode-vi r { send -X refresh-from-pane }",
-               "bind -Tcopy-mode-vi t { command-prompt -1p'(jump to forward)' 'send -X jump-to-forward \"%%%\"' }",
+               "bind -Tcopy-mode-vi t { command-prompt -1p'(jump to forward)' { send -X jump-to-forward '%%' } }",
                "bind -Tcopy-mode-vi v { send -X rectangle-toggle }",
                "bind -Tcopy-mode-vi w { send -X next-word }",
                "bind -Tcopy-mode-vi '{' { send -X previous-paragraph }",
index b65c355..57972f4 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: server-client.c,v 1.385 2021/08/27 17:15:57 nicm Exp $ */
+/* $OpenBSD: server-client.c,v 1.386 2021/08/27 17:25:55 nicm Exp $ */
 
 /*
  * Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -2124,6 +2124,7 @@ server_client_dispatch_command(struct client *c, struct imsg *imsg)
        int                       argc;
        char                    **argv, *cause;
        struct cmd_parse_result  *pr;
+       struct args_value        *values;
 
        if (c->flags & CLIENT_EXIT)
                return;
@@ -2149,7 +2150,8 @@ server_client_dispatch_command(struct client *c, struct imsg *imsg)
                *argv = xstrdup("new-session");
        }
 
-       pr = cmd_parse_from_arguments(argc, argv, NULL);
+       values = args_from_vector(argc, argv);
+       pr = cmd_parse_from_arguments(values, argc, NULL);
        switch (pr->status) {
        case CMD_PARSE_ERROR:
                cause = pr->error;
@@ -2157,6 +2159,8 @@ server_client_dispatch_command(struct client *c, struct imsg *imsg)
        case CMD_PARSE_SUCCESS:
                break;
        }
+       args_free_values(values, argc);
+       free(values);
        cmd_free_argv(argc, argv);
 
        cmdq_append(c, cmdq_get_command(pr->cmdlist, NULL));
index e402d14..abe1c23 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: tmux.h,v 1.1138 2021/08/27 17:15:57 nicm Exp $ */
+/* $OpenBSD: tmux.h,v 1.1139 2021/08/27 17:25:55 nicm Exp $ */
 
 /*
  * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -2217,8 +2217,11 @@ void              args_set(struct args *, u_char, struct args_value *);
 struct args    *args_create(void);
 struct args    *args_parse(const struct args_parse *, struct args_value *,
                     u_int, char **);
-void            args_vector(struct args *, int *, char ***);
+struct args    *args_copy(struct args *, int, char **);
+void            args_to_vector(struct args *, int *, char ***);
+struct args_value *args_from_vector(int, char **);
 void            args_free_value(struct args_value *);
+void            args_free_values(struct args_value *, u_int);
 void            args_free(struct args *);
 char           *args_print(struct args *);
 char           *args_escape(const char *);
@@ -2227,6 +2230,7 @@ const char        *args_get(struct args *, u_char);
 u_char          args_first(struct args *, struct args_entry **);
 u_char          args_next(struct args_entry **);
 u_int           args_count(struct args *);
+struct args_value *args_values(struct args *);
 struct args_value *args_value(struct args *, u_int);
 const char     *args_string(struct args *, u_int);
 struct cmd_list        *args_make_commands_now(struct cmd *, struct cmdq_item *,
@@ -2291,9 +2295,11 @@ u_int             cmd_get_group(struct cmd *);
 void            cmd_get_source(struct cmd *, const char **, u_int *);
 struct cmd     *cmd_parse(struct args_value *, u_int, const char *, u_int,
                     char **);
+struct cmd     *cmd_copy(struct cmd *, int, char **);
 void            cmd_free(struct cmd *);
 char           *cmd_print(struct cmd *);
 struct cmd_list        *cmd_list_new(void);
+struct cmd_list        *cmd_list_copy(struct cmd_list *, int, char **);
 void            cmd_list_append(struct cmd_list *, struct cmd *);
 void            cmd_list_append_all(struct cmd_list *, struct cmd_list *);
 void            cmd_list_move(struct cmd_list *, struct cmd_list *);
@@ -2327,7 +2333,7 @@ enum cmd_parse_status cmd_parse_and_append(const char *,
                     struct cmdq_state *, char **);
 struct cmd_parse_result *cmd_parse_from_buffer(const void *, size_t,
                     struct cmd_parse_input *);
-struct cmd_parse_result *cmd_parse_from_arguments(int, char **,
+struct cmd_parse_result *cmd_parse_from_arguments(struct args_value *, u_int,
                     struct cmd_parse_input *);
 
 /* cmd-queue.c */