From adb76fd1ce8753a958d4ffe14db724f9f4d674ea Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 13 Apr 2020 14:46:04 +0000 Subject: Move cmdq_state into cmd-queue.c. --- cmd-attach-session.c | 5 ++--- cmd-break-pane.c | 3 +-- cmd-copy-mode.c | 6 +++--- cmd-display-menu.c | 14 +++++++------- cmd-find.c | 6 +++--- cmd-if-shell.c | 14 +++++++------- cmd-join-pane.c | 3 +-- cmd-new-session.c | 5 ++--- cmd-new-window.c | 3 +-- cmd-queue.c | 48 +++++++++++++++++++++++++++++++++++++++--------- cmd-resize-pane.c | 6 +++--- cmd-rotate-window.c | 3 +-- cmd-select-pane.c | 3 +-- cmd-select-window.c | 3 +-- cmd-send-keys.c | 4 ++-- cmd-split-window.c | 3 +-- cmd-switch-client.c | 5 ++--- control.c | 4 ++-- format.c | 7 ++----- key-bindings.c | 8 ++++---- menu.c | 6 +++--- popup.c | 6 +++--- server-client.c | 2 +- tmux.h | 21 +++++++-------------- 24 files changed, 99 insertions(+), 89 deletions(-) diff --git a/cmd-attach-session.c b/cmd-attach-session.c index 00a852fc..8c30c767 100644 --- a/cmd-attach-session.c +++ b/cmd-attach-session.c @@ -50,8 +50,7 @@ enum cmd_retval cmd_attach_session(struct cmdq_item *item, const char *tflag, int dflag, int xflag, int rflag, const char *cflag, int Eflag) { - struct cmdq_state *state = cmdq_get_state(item); - struct cmd_find_state *current = &state->current; + struct cmd_find_state *current = cmdq_get_current(item); struct cmd_find_state target; enum cmd_find_type type; int flags; @@ -120,7 +119,7 @@ cmd_attach_session(struct cmdq_item *item, const char *tflag, int dflag, environ_update(s->options, c->environ, s->environ); c->session = s; - if (~state->flags & CMDQ_STATE_REPEAT) + if (~cmdq_get_flags(item) & CMDQ_STATE_REPEAT) server_client_set_key_table(c, NULL); tty_update_client_offset(c); status_timer_start(c); diff --git a/cmd-break-pane.c b/cmd-break-pane.c index 1d0ad2ce..e12b09b6 100644 --- a/cmd-break-pane.c +++ b/cmd-break-pane.c @@ -49,8 +49,7 @@ static enum cmd_retval cmd_break_pane_exec(struct cmd *self, struct cmdq_item *item) { struct args *args = cmd_get_args(self); - struct cmdq_state *state = cmdq_get_state(item); - struct cmd_find_state *current = &state->current; + struct cmd_find_state *current = cmdq_get_current(item); struct cmd_find_state *target = cmdq_get_target(item); struct cmd_find_state *source = cmdq_get_source(item); struct client *c = cmd_find_client(item, NULL, 1); diff --git a/cmd-copy-mode.c b/cmd-copy-mode.c index 01006e5b..d8b4fd3e 100644 --- a/cmd-copy-mode.c +++ b/cmd-copy-mode.c @@ -57,7 +57,7 @@ static enum cmd_retval cmd_copy_mode_exec(struct cmd *self, struct cmdq_item *item) { struct args *args = cmd_get_args(self); - struct cmdq_state *state = cmdq_get_state(item); + struct key_event *event = cmdq_get_event(item); struct cmd_find_state *source = cmdq_get_source(item); struct cmd_find_state *target = cmdq_get_target(item); struct client *c = cmdq_get_client(item); @@ -70,7 +70,7 @@ cmd_copy_mode_exec(struct cmd *self, struct cmdq_item *item) } if (args_has(args, 'M')) { - if ((wp = cmd_mouse_pane(&state->event.m, &s, NULL)) == NULL) + if ((wp = cmd_mouse_pane(&event->m, &s, NULL)) == NULL) return (CMD_RETURN_NORMAL); if (c == NULL || c->session != s) return (CMD_RETURN_NORMAL); @@ -87,7 +87,7 @@ cmd_copy_mode_exec(struct cmd *self, struct cmdq_item *item) swp = wp; if (!window_pane_set_mode(wp, swp, &window_copy_mode, NULL, args)) { if (args_has(args, 'M')) - window_copy_start_drag(c, &state->event.m); + window_copy_start_drag(c, &event->m); } if (args_has(args, 'u')) window_copy_pageup(wp, 0); diff --git a/cmd-display-menu.c b/cmd-display-menu.c index df8e0329..830491dc 100644 --- a/cmd-display-menu.c +++ b/cmd-display-menu.c @@ -65,8 +65,8 @@ static void cmd_display_menu_get_position(struct client *c, struct cmdq_item *item, struct args *args, u_int *px, u_int *py, u_int w, u_int h) { - struct cmdq_state *state = cmdq_get_state(item); struct cmd_find_state *target = cmdq_get_target(item); + struct key_event *event = cmdq_get_event(item); struct session *s = c->session; struct winlink *wl = target->wl; struct window_pane *wp = target->wp; @@ -100,8 +100,8 @@ cmd_display_menu_get_position(struct client *c, struct cmdq_item *item, else *px = 0; } else if (strcmp(xp, "M") == 0) { - if (state->event.m.valid && state->event.m.x > w / 2) - *px = state->event.m.x - w / 2; + if (event->m.valid && event->m.x > w / 2) + *px = event->m.x - w / 2; else *px = 0; } else if (strcmp(xp, "W") == 0) { @@ -134,8 +134,8 @@ cmd_display_menu_get_position(struct client *c, struct cmdq_item *item, else *py = 0; } else if (strcmp(yp, "M") == 0) { - if (state->event.m.valid) - *py = state->event.m.y + h; + if (event->m.valid) + *py = event->m.y + h; else *py = 0; } else if (strcmp(yp, "S") == 0) { @@ -176,8 +176,8 @@ static enum cmd_retval cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item) { struct args *args = cmd_get_args(self); - struct cmdq_state *state = cmdq_get_state(item); struct cmd_find_state *target = cmdq_get_target(item); + struct key_event *event = cmdq_get_event(item); struct client *c; struct menu *menu = NULL; struct menu_item menu_item; @@ -230,7 +230,7 @@ cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item) cmd_display_menu_get_position(c, item, args, &px, &py, menu->width + 4, menu->count + 2); - if (!state->event.m.valid) + if (!event->m.valid) flags |= MENU_NOMOUSE; if (menu_display(menu, flags, item, px, py, c, target, NULL, NULL) != 0) return (CMD_RETURN_NORMAL); diff --git a/cmd-find.c b/cmd-find.c index a063f115..9c8bcbc1 100644 --- a/cmd-find.c +++ b/cmd-find.c @@ -961,8 +961,8 @@ cmd_find_target(struct cmd_find_state *fs, struct cmdq_item *item, if (server_check_marked() && (flags & CMD_FIND_DEFAULT_MARKED)) { fs->current = &marked_pane; log_debug("%s: current is marked pane", __func__); - } else if (cmd_find_valid_state(&cmdq_get_state(item)->current)) { - fs->current = &cmdq_get_state(item)->current; + } else if (cmd_find_valid_state(cmdq_get_current(item))) { + fs->current = cmdq_get_current(item); log_debug("%s: current is from queue", __func__); } else if (cmd_find_from_client(¤t, cmdq_get_client(item), flags) == 0) { @@ -982,7 +982,7 @@ cmd_find_target(struct cmd_find_state *fs, struct cmdq_item *item, /* Mouse target is a plain = or {mouse}. */ if (strcmp(target, "=") == 0 || strcmp(target, "{mouse}") == 0) { - m = &cmdq_get_state(item)->event.m; + m = &cmdq_get_event(item)->m; switch (type) { case CMD_FIND_PANE: fs->wp = cmd_mouse_pane(m, &fs->s, &fs->wl); diff --git a/cmd-if-shell.c b/cmd-if-shell.c index 4210392e..3657c730 100644 --- a/cmd-if-shell.c +++ b/cmd-if-shell.c @@ -56,16 +56,15 @@ struct cmd_if_shell_data { struct client *client; struct cmdq_item *item; - struct mouse_event mouse; + struct key_event event; }; static enum cmd_retval cmd_if_shell_exec(struct cmd *self, struct cmdq_item *item) { struct args *args = cmd_get_args(self); - struct cmdq_state *state = cmdq_get_state(item); struct cmd_find_state *target = cmdq_get_target(item); - struct mouse_event *m = &state->event.m; + struct key_event *event = cmdq_get_event(item); struct cmd_if_shell_data *cdata; char *shellcmd, *cmd; const char *file; @@ -102,7 +101,8 @@ cmd_if_shell_exec(struct cmd *self, struct cmdq_item *item) free(pr->error); return (CMD_RETURN_ERROR); case CMD_PARSE_SUCCESS: - new_item = cmdq_get_command(pr->cmdlist, target, m, 0); + new_item = cmdq_get_command(pr->cmdlist, target, event, + 0); cmdq_insert_after(item, new_item); cmd_list_free(pr->cmdlist); break; @@ -117,7 +117,7 @@ cmd_if_shell_exec(struct cmd *self, struct cmdq_item *item) cdata->cmd_else = xstrdup(args->argv[2]); else cdata->cmd_else = NULL; - memcpy(&cdata->mouse, m, sizeof cdata->mouse); + memcpy(&cdata->event, event, sizeof cdata->event); if (!args_has(args, 'b')) cdata->client = cmdq_get_client(item); @@ -161,7 +161,7 @@ cmd_if_shell_callback(struct job *job) { struct cmd_if_shell_data *cdata = job_get_data(job); struct client *c = cdata->client; - struct mouse_event *m = &cdata->mouse; + struct key_event *event = &cdata->event; struct cmdq_item *new_item = NULL; char *cmd; int status; @@ -185,7 +185,7 @@ cmd_if_shell_callback(struct job *job) free(pr->error); break; case CMD_PARSE_SUCCESS: - new_item = cmdq_get_command(pr->cmdlist, NULL, m, 0); + new_item = cmdq_get_command(pr->cmdlist, NULL, event, 0); cmd_list_free(pr->cmdlist); break; } diff --git a/cmd-join-pane.c b/cmd-join-pane.c index 99d7f366..45a56fc4 100644 --- a/cmd-join-pane.c +++ b/cmd-join-pane.c @@ -64,8 +64,7 @@ static enum cmd_retval cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item) { struct args *args = cmd_get_args(self); - struct cmdq_state *state = cmdq_get_state(item); - struct cmd_find_state *current = &state->current; + struct cmd_find_state *current = cmdq_get_current(item); struct cmd_find_state *target = cmdq_get_target(item); struct cmd_find_state *source = cmdq_get_source(item); struct session *dst_s; diff --git a/cmd-new-session.c b/cmd-new-session.c index 551cd74c..5286d320 100644 --- a/cmd-new-session.c +++ b/cmd-new-session.c @@ -67,8 +67,7 @@ static enum cmd_retval cmd_new_session_exec(struct cmd *self, struct cmdq_item *item) { struct args *args = cmd_get_args(self); - struct cmdq_state *state = cmdq_get_state(item); - struct cmd_find_state *current = &state->current; + struct cmd_find_state *current = cmdq_get_current(item); struct cmd_find_state *target = cmdq_get_target(item); struct client *c = cmdq_get_client(item); struct session *s, *as, *groupwith; @@ -317,7 +316,7 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item) } else if (c->session != NULL) c->last_session = c->session; c->session = s; - if (~state->flags & CMDQ_STATE_REPEAT) + if (~cmdq_get_flags(item) & CMDQ_STATE_REPEAT) server_client_set_key_table(c, NULL); tty_update_client_offset(c); status_timer_start(c); diff --git a/cmd-new-window.c b/cmd-new-window.c index f2a7fbc2..87aae659 100644 --- a/cmd-new-window.c +++ b/cmd-new-window.c @@ -52,8 +52,7 @@ static enum cmd_retval cmd_new_window_exec(struct cmd *self, struct cmdq_item *item) { struct args *args = cmd_get_args(self); - struct cmdq_state *state = cmdq_get_state(item); - struct cmd_find_state *current = &state->current; + struct cmd_find_state *current = cmdq_get_current(item); struct cmd_find_state *target = cmdq_get_target(item); struct spawn_context sc; struct client *c = cmd_find_client(item, NULL, 1); diff --git a/cmd-queue.c b/cmd-queue.c index 12ad8c2d..40db3fef 100644 --- a/cmd-queue.c +++ b/cmd-queue.c @@ -65,6 +65,23 @@ struct cmdq_item { }; TAILQ_HEAD(cmdq_list, cmdq_item); +/* + * Command queue state. This is the context for commands on the command queue. + * It holds information about how the commands were fired (the key and flags), + * any additional formats for the commands, and the current default target. + * Multiple commands can share the same state and a command may update the + * default target. + */ +struct cmdq_state { + int references; + int flags; + + struct format_tree *formats; + + struct key_event event; + struct cmd_find_state current; +}; + /* Get command queue name. */ static const char * cmdq_name(struct client *c) @@ -142,11 +159,25 @@ cmdq_get_source(struct cmdq_item *item) return (&item->source); } -/* Get item state. */ -struct cmdq_state * -cmdq_get_state(struct cmdq_item *item) +/* Get state event. */ +struct key_event * +cmdq_get_event(struct cmdq_item *item) +{ + return (&item->state->event); +} + +/* Get state current target. */ +struct cmd_find_state * +cmdq_get_current(struct cmdq_item *item) +{ + return (&item->state->current); +} + +/* Get state flags. */ +int +cmdq_get_flags(struct cmdq_item *item) { - return (item->state); + return (item->state->flags); } /* Merge formats from item. */ @@ -317,7 +348,7 @@ cmdq_remove_group(struct cmdq_item *item) /* Get a command for the command queue. */ struct cmdq_item * cmdq_get_command(struct cmd_list *cmdlist, struct cmd_find_state *current, - struct mouse_event *m, int flags) + struct key_event *event, int flags) { struct cmdq_item *item, *first = NULL, *last = NULL; struct cmd *cmd; @@ -333,10 +364,9 @@ cmdq_get_command(struct cmd_list *cmdlist, struct cmd_find_state *current, cmd_find_copy_state(&state->current, current); else cmd_find_clear_state(&state->current, 0); - if (m != NULL) { - state->event.key = KEYC_NONE; - memcpy(&state->event.m, m, - sizeof state->event.m); + if (event != NULL) { + memcpy(&state->event, event, + sizeof state->event); } state->flags = flags; last_group = group; diff --git a/cmd-resize-pane.c b/cmd-resize-pane.c index e8c2a5bc..105f48e0 100644 --- a/cmd-resize-pane.c +++ b/cmd-resize-pane.c @@ -50,8 +50,8 @@ static enum cmd_retval cmd_resize_pane_exec(struct cmd *self, struct cmdq_item *item) { struct args *args = cmd_get_args(self); - struct cmdq_state *state = cmdq_get_state(item); struct cmd_find_state *target = cmdq_get_target(item); + struct key_event *event = cmdq_get_event(item); struct window_pane *wp = target->wp; struct winlink *wl = target->wl; struct window *w = wl->window; @@ -76,12 +76,12 @@ cmd_resize_pane_exec(struct cmd *self, struct cmdq_item *item) } if (args_has(args, 'M')) { - if (cmd_mouse_window(&state->event.m, &s) == NULL) + if (!event->m.valid || cmd_mouse_window(&event->m, &s) == NULL) return (CMD_RETURN_NORMAL); if (c == NULL || c->session != s) return (CMD_RETURN_NORMAL); c->tty.mouse_drag_update = cmd_resize_pane_mouse_update; - cmd_resize_pane_mouse_update(c, &state->event.m); + cmd_resize_pane_mouse_update(c, &event->m); return (CMD_RETURN_NORMAL); } diff --git a/cmd-rotate-window.c b/cmd-rotate-window.c index 6ba2056e..55c1dde2 100644 --- a/cmd-rotate-window.c +++ b/cmd-rotate-window.c @@ -44,8 +44,7 @@ static enum cmd_retval cmd_rotate_window_exec(struct cmd *self, struct cmdq_item *item) { struct args *args = cmd_get_args(self); - struct cmdq_state *state = cmdq_get_state(item); - struct cmd_find_state *current = &state->current; + struct cmd_find_state *current = cmdq_get_current(item); struct cmd_find_state *target = cmdq_get_target(item); struct winlink *wl = target->wl; struct window *w = wl->window; diff --git a/cmd-select-pane.c b/cmd-select-pane.c index e0907812..5f4a2e63 100644 --- a/cmd-select-pane.c +++ b/cmd-select-pane.c @@ -85,8 +85,7 @@ cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item) { struct args *args = cmd_get_args(self); const struct cmd_entry *entry = cmd_get_entry(self); - struct cmdq_state *state = cmdq_get_state(item); - struct cmd_find_state *current = &state->current; + struct cmd_find_state *current = cmdq_get_current(item); struct cmd_find_state *target = cmdq_get_target(item); struct client *c = cmd_find_client(item, NULL, 1); struct winlink *wl = target->wl; diff --git a/cmd-select-window.c b/cmd-select-window.c index 0a84bf0e..377e3633 100644 --- a/cmd-select-window.c +++ b/cmd-select-window.c @@ -85,8 +85,7 @@ static enum cmd_retval cmd_select_window_exec(struct cmd *self, struct cmdq_item *item) { struct args *args = cmd_get_args(self); - struct cmdq_state *state = cmdq_get_state(item); - struct cmd_find_state *current = &state->current; + struct cmd_find_state *current = cmdq_get_current(item); struct cmd_find_state *target = cmdq_get_target(item); struct winlink *wl = target->wl; struct session *s = target->s; diff --git a/cmd-send-keys.c b/cmd-send-keys.c index 1f70db16..de910904 100644 --- a/cmd-send-keys.c +++ b/cmd-send-keys.c @@ -134,13 +134,13 @@ static enum cmd_retval cmd_send_keys_exec(struct cmd *self, struct cmdq_item *item) { struct args *args = cmd_get_args(self); - struct cmdq_state *state = cmdq_get_state(item); struct cmd_find_state *target = cmdq_get_target(item); struct client *c = cmd_find_client(item, NULL, 1); struct window_pane *wp = target->wp; struct session *s = target->s; struct winlink *wl = target->wl; - struct mouse_event *m = &state->event.m; + struct key_event *event = cmdq_get_event(item); + struct mouse_event *m = &event->m; struct window_mode_entry *wme = TAILQ_FIRST(&wp->modes); int i; key_code key; diff --git a/cmd-split-window.c b/cmd-split-window.c index 01d7cbc8..84419a1e 100644 --- a/cmd-split-window.c +++ b/cmd-split-window.c @@ -54,8 +54,7 @@ static enum cmd_retval cmd_split_window_exec(struct cmd *self, struct cmdq_item *item) { struct args *args = cmd_get_args(self); - struct cmdq_state *state = cmdq_get_state(item); - struct cmd_find_state *current = &state->current; + struct cmd_find_state *current = cmdq_get_current(item); struct cmd_find_state *target = cmdq_get_target(item); struct spawn_context sc; struct client *c = cmd_find_client(item, NULL, 1); diff --git a/cmd-switch-client.c b/cmd-switch-client.c index de85122f..bc6a8174 100644 --- a/cmd-switch-client.c +++ b/cmd-switch-client.c @@ -48,8 +48,7 @@ static enum cmd_retval cmd_switch_client_exec(struct cmd *self, struct cmdq_item *item) { struct args *args = cmd_get_args(self); - struct cmdq_state *state = cmdq_get_state(item); - struct cmd_find_state *current = &state->current; + struct cmd_find_state *current = cmdq_get_current(item); struct cmd_find_state target; const char *tflag = args_get(args, 't'); enum cmd_find_type type; @@ -137,7 +136,7 @@ cmd_switch_client_exec(struct cmd *self, struct cmdq_item *item) if (c->session != NULL && c->session != s) c->last_session = c->session; c->session = s; - if (~state->flags & CMDQ_STATE_REPEAT) + if (~cmdq_get_flags(item) & CMDQ_STATE_REPEAT) server_client_set_key_table(c, NULL); tty_update_client_offset(c); status_timer_start(c); diff --git a/control.c b/control.c index 088371f5..d3515005 100644 --- a/control.c +++ b/control.c @@ -85,8 +85,8 @@ control_callback(__unused struct client *c, __unused const char *path, cmdq_append(c, item); break; case CMD_PARSE_SUCCESS: - item = cmdq_get_command(pr->cmdlist, NULL, NULL, 0); - cmdq_get_state(item)->flags |= CMDQ_STATE_CONTROL; + item = cmdq_get_command(pr->cmdlist, NULL, NULL, + CMDQ_STATE_CONTROL); cmdq_append(c, item); cmd_list_free(pr->cmdlist); break; diff --git a/format.c b/format.c index 9274e353..08fa38df 100644 --- a/format.c +++ b/format.c @@ -1124,16 +1124,13 @@ format_merge(struct format_tree *ft, struct format_tree *from) static void format_create_add_item(struct format_tree *ft, struct cmdq_item *item) { - struct cmdq_state *state = cmdq_get_state(item); - struct mouse_event *m; + struct key_event *event = cmdq_get_event(item); + struct mouse_event *m = &event->m; struct window_pane *wp; u_int x, y; cmdq_merge_formats(item, ft); - if (state == NULL) - return; - m = &state->event.m; if (m->valid && ((wp = cmd_mouse_pane(m, NULL, NULL)) != NULL)) { format_add(ft, "mouse_pane", "%%%u", wp->id); if (cmd_mouse_at(wp, m, &x, &y, 0) == 0) { diff --git a/key-bindings.c b/key-bindings.c index 04a5cef7..13caa889 100644 --- a/key-bindings.c +++ b/key-bindings.c @@ -535,10 +535,10 @@ key_bindings_read_only(struct cmdq_item *item, __unused void *data) struct cmdq_item * key_bindings_dispatch(struct key_binding *bd, struct cmdq_item *item, - struct client *c, struct mouse_event *m, struct cmd_find_state *fs) + struct client *c, struct key_event *event, struct cmd_find_state *fs) { struct cmdq_item *new_item; - int readonly; + int readonly, flags = 0; if (c == NULL || (~c->flags & CLIENT_READONLY)) readonly = 1; @@ -547,9 +547,9 @@ key_bindings_dispatch(struct key_binding *bd, struct cmdq_item *item, if (!readonly) new_item = cmdq_get_callback(key_bindings_read_only, NULL); else { - new_item = cmdq_get_command(bd->cmdlist, fs, m, 0); if (bd->flags & KEY_BINDING_REPEAT) - cmdq_get_state(new_item)->flags |= CMDQ_STATE_REPEAT; + flags |= CMDQ_STATE_REPEAT; + new_item = cmdq_get_command(bd->cmdlist, fs, event, flags); } if (item != NULL) new_item = cmdq_insert_after(item, new_item); diff --git a/menu.c b/menu.c index 6c571473..c72be5ce 100644 --- a/menu.c +++ b/menu.c @@ -282,10 +282,10 @@ chosen: break; case CMD_PARSE_SUCCESS: if (md->item != NULL) - m = &cmdq_get_state(md->item)->event.m; + event = cmdq_get_event(md->item); else - m = NULL; - new_item = cmdq_get_command(pr->cmdlist, &md->fs, m, 0); + event = NULL; + new_item = cmdq_get_command(pr->cmdlist, &md->fs, event, 0); cmd_list_free(pr->cmdlist); cmdq_append(c, new_item); break; diff --git a/popup.c b/popup.c index 8359397c..c1530347 100644 --- a/popup.c +++ b/popup.c @@ -305,10 +305,10 @@ popup_key_cb(struct client *c, struct key_event *event) break; case CMD_PARSE_SUCCESS: if (pd->item != NULL) - m = &cmdq_get_state(pd->item)->event.m; + event = cmdq_get_event(pd->item); else - m = NULL; - new_item = cmdq_get_command(pr->cmdlist, fs, m, 0); + event = NULL; + new_item = cmdq_get_command(pr->cmdlist, fs, event, 0); cmd_list_free(pr->cmdlist); cmdq_append(c, new_item); break; diff --git a/server-client.c b/server-client.c index 12a65af2..9575fd4d 100644 --- a/server-client.c +++ b/server-client.c @@ -1223,7 +1223,7 @@ try_again: server_status_client(c); /* Execute the key binding. */ - key_bindings_dispatch(bd, item, c, m, &fs); + key_bindings_dispatch(bd, item, c, event, &fs); key_bindings_unref_table(table); goto out; } diff --git a/tmux.h b/tmux.h index dbd046c4..e5ecab9b 100644 --- a/tmux.h +++ b/tmux.h @@ -43,6 +43,7 @@ struct cmd; struct cmd_find_state; struct cmdq_item; struct cmdq_list; +struct cmdq_state; struct cmds; struct environ; struct format_job_tree; @@ -1378,21 +1379,11 @@ struct cmd_parse_input { struct cmd_find_state fs; }; -/* Command queue item state. */ -struct cmdq_state { - int references; - - int flags; +/* Command queue flags. */ #define CMDQ_STATE_REPEAT 0x1 #define CMDQ_STATE_CONTROL 0x2 #define CMDQ_STATE_NOHOOKS 0x4 - struct format_tree *formats; - - struct key_event event; - struct cmd_find_state current; -}; - /* Command queue callback. */ typedef enum cmd_retval (*cmdq_cb) (struct cmdq_item *, void *); @@ -2108,10 +2099,12 @@ const char *cmdq_get_name(struct cmdq_item *); struct client *cmdq_get_client(struct cmdq_item *); struct cmd_find_state *cmdq_get_target(struct cmdq_item *); struct cmd_find_state *cmdq_get_source(struct cmdq_item *); -struct cmdq_state *cmdq_get_state(struct cmdq_item *); +struct key_event *cmdq_get_event(struct cmdq_item *); +struct cmd_find_state *cmdq_get_current(struct cmdq_item *); +int cmdq_get_flags(struct cmdq_item *); void cmdq_merge_formats(struct cmdq_item *, struct format_tree *); struct cmdq_item *cmdq_get_command(struct cmd_list *, struct cmd_find_state *, - struct mouse_event *, int); + struct key_event *, int); #define cmdq_get_callback(cb, data) cmdq_get_callback1(#cb, cb, data) struct cmdq_item *cmdq_get_callback1(const char *, cmdq_cb, void *); struct cmdq_item *cmdq_get_error(const char *); @@ -2147,7 +2140,7 @@ void key_bindings_remove(const char *, key_code); void key_bindings_remove_table(const char *); void key_bindings_init(void); struct cmdq_item *key_bindings_dispatch(struct key_binding *, - struct cmdq_item *, struct client *, struct mouse_event *, + struct cmdq_item *, struct client *, struct key_event *, struct cmd_find_state *); /* key-string.c */ -- cgit From 3f86d6d46014ca55e42cecd570d7f269b1d386b3 Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 13 Apr 2020 15:55:51 +0000 Subject: When adding a list of commands to the queue, instead of automatically creating a new state for each group of commands, require the caller to create one and use it for all the commands in the list. This means the current target works even with list with multiple groups (which can happen if they are defined with newlines). --- cfg.c | 4 +- cmd-command-prompt.c | 2 +- cmd-confirm-before.c | 2 +- cmd-display-panes.c | 2 +- cmd-if-shell.c | 17 +++--- cmd-new-session.c | 4 +- cmd-queue.c | 170 ++++++++++++++++++++++++++++++++------------------- cmd.c | 23 ++++--- control.c | 6 +- key-bindings.c | 7 ++- menu.c | 5 +- mode-tree.c | 5 +- notify.c | 34 +++++------ popup.c | 5 +- server-client.c | 2 +- tmux.h | 20 +++--- 16 files changed, 187 insertions(+), 121 deletions(-) diff --git a/cfg.c b/cfg.c index 6740bce4..f67a765c 100644 --- a/cfg.c +++ b/cfg.c @@ -183,7 +183,7 @@ load_cfg(const char *path, struct client *c, struct cmdq_item *item, int flags, return (0); } - new_item0 = cmdq_get_command(pr->cmdlist, NULL, NULL, 0); + new_item0 = cmdq_get_command(pr->cmdlist, NULL); if (item != NULL) new_item0 = cmdq_insert_after(item, new_item0); else @@ -229,7 +229,7 @@ load_cfg_from_buffer(const void *buf, size_t len, const char *path, return (0); } - new_item0 = cmdq_get_command(pr->cmdlist, NULL, NULL, 0); + new_item0 = cmdq_get_command(pr->cmdlist, NULL); if (item != NULL) new_item0 = cmdq_insert_after(item, new_item0); else diff --git a/cmd-command-prompt.c b/cmd-command-prompt.c index 31a1ae78..81f392f5 100644 --- a/cmd-command-prompt.c +++ b/cmd-command-prompt.c @@ -177,7 +177,7 @@ cmd_command_prompt_callback(struct client *c, void *data, const char *s, cmdq_append(c, new_item); break; case CMD_PARSE_SUCCESS: - new_item = cmdq_get_command(pr->cmdlist, NULL, NULL, 0); + new_item = cmdq_get_command(pr->cmdlist, NULL); cmd_list_free(pr->cmdlist); cmdq_append(c, new_item); break; diff --git a/cmd-confirm-before.c b/cmd-confirm-before.c index 419efda5..7850706e 100644 --- a/cmd-confirm-before.c +++ b/cmd-confirm-before.c @@ -109,7 +109,7 @@ cmd_confirm_before_callback(struct client *c, void *data, const char *s, cmdq_append(c, new_item); break; case CMD_PARSE_SUCCESS: - new_item = cmdq_get_command(pr->cmdlist, NULL, NULL, 0); + new_item = cmdq_get_command(pr->cmdlist, NULL); cmd_list_free(pr->cmdlist); cmdq_append(c, new_item); break; diff --git a/cmd-display-panes.c b/cmd-display-panes.c index 41fe50da..011e3d13 100644 --- a/cmd-display-panes.c +++ b/cmd-display-panes.c @@ -225,7 +225,7 @@ cmd_display_panes_key(struct client *c, struct key_event *event) cmdq_append(c, new_item); break; case CMD_PARSE_SUCCESS: - new_item = cmdq_get_command(pr->cmdlist, NULL, NULL, 0); + new_item = cmdq_get_command(pr->cmdlist, NULL); cmd_list_free(pr->cmdlist); cmdq_append(c, new_item); break; diff --git a/cmd-if-shell.c b/cmd-if-shell.c index 3657c730..ab1b588d 100644 --- a/cmd-if-shell.c +++ b/cmd-if-shell.c @@ -56,7 +56,6 @@ struct cmd_if_shell_data { struct client *client; struct cmdq_item *item; - struct key_event event; }; static enum cmd_retval @@ -64,7 +63,7 @@ cmd_if_shell_exec(struct cmd *self, struct cmdq_item *item) { struct args *args = cmd_get_args(self); struct cmd_find_state *target = cmdq_get_target(item); - struct key_event *event = cmdq_get_event(item); + struct cmdq_state *state = cmdq_get_state(item); struct cmd_if_shell_data *cdata; char *shellcmd, *cmd; const char *file; @@ -101,8 +100,7 @@ cmd_if_shell_exec(struct cmd *self, struct cmdq_item *item) free(pr->error); return (CMD_RETURN_ERROR); case CMD_PARSE_SUCCESS: - new_item = cmdq_get_command(pr->cmdlist, target, event, - 0); + new_item = cmdq_get_command(pr->cmdlist, state); cmdq_insert_after(item, new_item); cmd_list_free(pr->cmdlist); break; @@ -117,7 +115,6 @@ cmd_if_shell_exec(struct cmd *self, struct cmdq_item *item) cdata->cmd_else = xstrdup(args->argv[2]); else cdata->cmd_else = NULL; - memcpy(&cdata->event, event, sizeof cdata->event); if (!args_has(args, 'b')) cdata->client = cmdq_get_client(item); @@ -161,8 +158,8 @@ cmd_if_shell_callback(struct job *job) { struct cmd_if_shell_data *cdata = job_get_data(job); struct client *c = cdata->client; - struct key_event *event = &cdata->event; struct cmdq_item *new_item = NULL; + struct cmdq_state *new_state = NULL; char *cmd; int status; struct cmd_parse_result *pr; @@ -185,7 +182,13 @@ cmd_if_shell_callback(struct job *job) free(pr->error); break; case CMD_PARSE_SUCCESS: - new_item = cmdq_get_command(pr->cmdlist, NULL, event, 0); + if (cdata->item == NULL) + new_state = cmdq_new_state(NULL, NULL, 0); + else + new_state = cmdq_get_state(cdata->item); + new_item = cmdq_get_command(pr->cmdlist, new_state); + if (cdata->item == NULL) + cmdq_free_state(new_state); cmd_list_free(pr->cmdlist); break; } diff --git a/cmd-new-session.c b/cmd-new-session.c index 5286d320..574cd5cd 100644 --- a/cmd-new-session.c +++ b/cmd-new-session.c @@ -344,10 +344,10 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item) free(cp); } - if (!detached) { + if (!detached) c->flags |= CLIENT_ATTACHED; + if (!args_has(args, 'd')) cmd_find_from_session(current, s, 0); - } cmd_find_from_session(&fs, s, 0); cmdq_insert_hook(s, item, &fs, "after-new-session"); diff --git a/cmd-queue.c b/cmd-queue.c index 40db3fef..97d19f81 100644 --- a/cmd-queue.c +++ b/cmd-queue.c @@ -145,6 +145,13 @@ cmdq_get_client(struct cmdq_item *item) return (item->client); } +/* Get item state. */ +struct cmdq_state * +cmdq_get_state(struct cmdq_item *item) +{ + return (item->state); +} + /* Get item target. */ struct cmd_find_state * cmdq_get_target(struct cmdq_item *item) @@ -180,6 +187,70 @@ cmdq_get_flags(struct cmdq_item *item) return (item->state->flags); } +/* Create a new state. */ +struct cmdq_state * +cmdq_new_state(struct cmd_find_state *current, struct key_event *event, + int flags) +{ + struct cmdq_state *state; + + state = xcalloc(1, sizeof *state); + state->references = 1; + state->flags = flags; + + if (event != NULL) + memcpy(&state->event, event, sizeof state->event); + else + state->event.key = KEYC_NONE; + if (current != NULL && cmd_find_valid_state(current)) + cmd_find_copy_state(&state->current, current); + else + cmd_find_clear_state(&state->current, 0); + + return (state); +} + +/* Add a reference to a state. */ +struct cmdq_state * +cmdq_link_state(struct cmdq_state *state) +{ + state->references++; + return (state); +} + +/* Make a copy of a state. */ +struct cmdq_state * +cmdq_copy_state(struct cmdq_state *state) +{ + return (cmdq_new_state(&state->current, &state->event, state->flags)); +} + +/* Free a state. */ +void +cmdq_free_state(struct cmdq_state *state) +{ + if (--state->references == 0) + free(state); +} + +/* Add a format to command queue. */ +void +cmdq_add_format(struct cmdq_state *state, const char *key, const char *fmt, ...) +{ + va_list ap; + char *value; + + va_start(ap, fmt); + xvasprintf(&value, fmt, ap); + va_end(ap); + + if (state->formats == NULL) + state->formats = format_create(NULL, NULL, FORMAT_NONE, 0); + format_add(state->formats, key, "%s", value); + + free(value); +} + /* Merge formats from item. */ void cmdq_merge_formats(struct cmdq_item *item, struct format_tree *ft) @@ -249,12 +320,14 @@ cmdq_insert_after(struct cmdq_item *after, struct cmdq_item *item) /* Insert a hook. */ void cmdq_insert_hook(struct session *s, struct cmdq_item *item, - struct cmd_find_state *fs, const char *fmt, ...) + struct cmd_find_state *current, const char *fmt, ...) { + struct cmdq_state *state = item->state; struct options *oo; va_list ap; char *name; struct cmdq_item *new_item; + struct cmdq_state *new_state; struct options_entry *o; struct options_array_item *a; struct cmd_list *cmdlist; @@ -277,25 +350,27 @@ cmdq_insert_hook(struct session *s, struct cmdq_item *item, } log_debug("running hook %s (parent %p)", name, item); + /* + * The hooks get a new state because they should not update the current + * target or formats for any subsequent commands. + */ + new_state = cmdq_new_state(current, &state->event, CMDQ_STATE_NOHOOKS); + cmdq_add_format(new_state, "hook", "%s", name); + a = options_array_first(o); while (a != NULL) { cmdlist = options_array_item_value(a)->cmdlist; - if (cmdlist == NULL) { - a = options_array_next(a); - continue; + if (cmdlist != NULL) { + new_item = cmdq_get_command(cmdlist, new_state); + if (item != NULL) + item = cmdq_insert_after(item, new_item); + else + item = cmdq_append(NULL, new_item); } - - new_item = cmdq_get_command(cmdlist, fs, NULL, - CMDQ_STATE_NOHOOKS); - cmdq_format(new_item, "hook", "%s", name); - if (item != NULL) - item = cmdq_insert_after(item, new_item); - else - item = cmdq_append(NULL, new_item); - a = options_array_next(a); } + cmdq_free_state(new_state); free(name); } @@ -310,17 +385,11 @@ cmdq_continue(struct cmdq_item *item) static void cmdq_remove(struct cmdq_item *item) { - if (item->state != NULL && --item->state->references == 0) { - if (item->state->formats != NULL) - format_free(item->state->formats); - free(item->state); - } - if (item->client != NULL) server_client_unref(item->client); - if (item->cmdlist != NULL) cmd_list_free(item->cmdlist); + cmdq_free_state(item->state); TAILQ_REMOVE(item->queue, item, entry); @@ -347,45 +416,34 @@ cmdq_remove_group(struct cmdq_item *item) /* Get a command for the command queue. */ struct cmdq_item * -cmdq_get_command(struct cmd_list *cmdlist, struct cmd_find_state *current, - struct key_event *event, int flags) +cmdq_get_command(struct cmd_list *cmdlist, struct cmdq_state *state) { struct cmdq_item *item, *first = NULL, *last = NULL; struct cmd *cmd; const struct cmd_entry *entry; - struct cmdq_state *state = NULL; - u_int group, last_group = 0; + int created = 0; - cmd = cmd_list_first(cmdlist, &group); + if (state == NULL) { + state = cmdq_new_state(NULL, NULL, 0); + created = 1; + } + + cmd = cmd_list_first(cmdlist); while (cmd != NULL) { - if (group != last_group) { - state = xcalloc(1, sizeof *state); - if (current != NULL) - cmd_find_copy_state(&state->current, current); - else - cmd_find_clear_state(&state->current, 0); - if (event != NULL) { - memcpy(&state->event, event, - sizeof state->event); - } - state->flags = flags; - last_group = group; - } entry = cmd_get_entry(cmd); item = xcalloc(1, sizeof *item); xasprintf(&item->name, "[%s/%p]", entry->name, item); item->type = CMDQ_COMMAND; - item->group = group; - item->state = state; + item->group = cmd_get_group(cmd); + item->state = cmdq_link_state(state); + item->cmdlist = cmdlist; item->cmd = cmd; - log_debug("%s: %s group %u", __func__, item->name, item->group); - - state->references++; cmdlist->references++; + log_debug("%s: %s group %u", __func__, item->name, item->group); if (first == NULL) first = item; @@ -393,8 +451,11 @@ cmdq_get_command(struct cmd_list *cmdlist, struct cmd_find_state *current, last->next = item; last = item; - cmd = cmd_list_next(cmd, &group); + cmd = cmd_list_next(cmd); } + + if (created) + cmdq_free_state(state); return (first); } @@ -484,7 +545,9 @@ cmdq_get_callback1(const char *name, cmdq_cb cb, void *data) item = xcalloc(1, sizeof *item); xasprintf(&item->name, "[%s/%p]", name, item); item->type = CMDQ_CALLBACK; + item->group = 0; + item->state = cmdq_new_state(NULL, NULL, 0); item->cb = cb; item->data = data; @@ -518,25 +581,6 @@ cmdq_fire_callback(struct cmdq_item *item) return (item->cb(item, item->data)); } -/* Add a format to command queue. */ -void -cmdq_format(struct cmdq_item *item, const char *key, const char *fmt, ...) -{ - struct cmdq_state *state = item->state; - va_list ap; - char *value; - - va_start(ap, fmt); - xvasprintf(&value, fmt, ap); - va_end(ap); - - if (state->formats == NULL) - state->formats = format_create(NULL, NULL, FORMAT_NONE, 0); - format_add(state->formats, key, "%s", value); - - free(value); -} - /* Process next item on command queue. */ u_int cmdq_next(struct client *c) diff --git a/cmd.c b/cmd.c index d0a8c267..b7b144b4 100644 --- a/cmd.c +++ b/cmd.c @@ -392,6 +392,13 @@ cmd_get_args(struct cmd *cmd) return (cmd->args); } +/* Get group for command. */ +u_int +cmd_get_group(struct cmd *cmd) +{ + return (cmd->group); +} + /* Get file and line for command. */ void cmd_get_source(struct cmd *cmd, const char **file, u_int *line) @@ -646,24 +653,16 @@ cmd_list_print(struct cmd_list *cmdlist, int escaped) /* Get first command in list. */ struct cmd * -cmd_list_first(struct cmd_list *cmdlist, u_int *group) +cmd_list_first(struct cmd_list *cmdlist) { - struct cmd *cmd; - - cmd = TAILQ_FIRST(cmdlist->list); - if (cmd != NULL && group != NULL) - *group = cmd->group; - return (cmd); + return (TAILQ_FIRST(cmdlist->list)); } /* Get next command in list. */ struct cmd * -cmd_list_next(struct cmd *cmd, u_int *group) +cmd_list_next(struct cmd *cmd) { - cmd = TAILQ_NEXT(cmd, qentry); - if (cmd != NULL && group != NULL) - *group = cmd->group; - return (cmd); + return (TAILQ_NEXT(cmd, qentry)); } /* Do all of the commands in this command list have this flag? */ diff --git a/control.c b/control.c index d3515005..ddbbda8e 100644 --- a/control.c +++ b/control.c @@ -60,6 +60,7 @@ control_callback(__unused struct client *c, __unused const char *path, { char *line; struct cmdq_item *item; + struct cmdq_state *state; struct cmd_parse_result *pr; if (closed || error != 0) @@ -85,9 +86,10 @@ control_callback(__unused struct client *c, __unused const char *path, cmdq_append(c, item); break; case CMD_PARSE_SUCCESS: - item = cmdq_get_command(pr->cmdlist, NULL, NULL, - CMDQ_STATE_CONTROL); + state = cmdq_new_state(NULL, NULL, CMDQ_STATE_CONTROL); + item = cmdq_get_command(pr->cmdlist, state); cmdq_append(c, item); + cmdq_free_state(state); cmd_list_free(pr->cmdlist); break; } diff --git a/key-bindings.c b/key-bindings.c index 13caa889..09f0e0b1 100644 --- a/key-bindings.c +++ b/key-bindings.c @@ -521,7 +521,7 @@ key_bindings_init(void) pr = cmd_parse_from_string(defaults[i], NULL); if (pr->status != CMD_PARSE_SUCCESS) fatalx("bad default key: %s", defaults[i]); - cmdq_append(NULL, cmdq_get_command(pr->cmdlist, NULL, NULL, 0)); + cmdq_append(NULL, cmdq_get_command(pr->cmdlist, NULL)); cmd_list_free(pr->cmdlist); } } @@ -538,6 +538,7 @@ key_bindings_dispatch(struct key_binding *bd, struct cmdq_item *item, struct client *c, struct key_event *event, struct cmd_find_state *fs) { struct cmdq_item *new_item; + struct cmdq_state *new_state; int readonly, flags = 0; if (c == NULL || (~c->flags & CLIENT_READONLY)) @@ -549,7 +550,9 @@ key_bindings_dispatch(struct key_binding *bd, struct cmdq_item *item, else { if (bd->flags & KEY_BINDING_REPEAT) flags |= CMDQ_STATE_REPEAT; - new_item = cmdq_get_command(bd->cmdlist, fs, event, flags); + new_state = cmdq_new_state(fs, event, flags); + new_item = cmdq_get_command(bd->cmdlist, new_state); + cmdq_free_state(new_state); } if (item != NULL) new_item = cmdq_insert_after(item, new_item); diff --git a/menu.c b/menu.c index c72be5ce..b76869bc 100644 --- a/menu.c +++ b/menu.c @@ -185,6 +185,7 @@ menu_key_cb(struct client *c, struct key_event *event) int count = menu->count, old = md->choice; const struct menu_item *item; struct cmdq_item *new_item; + struct cmdq_state *new_state; struct cmd_parse_result *pr; const char *name; @@ -285,7 +286,9 @@ chosen: event = cmdq_get_event(md->item); else event = NULL; - new_item = cmdq_get_command(pr->cmdlist, &md->fs, event, 0); + new_state = cmdq_new_state(&md->fs, event, 0); + new_item = cmdq_get_command(pr->cmdlist, new_state); + cmdq_free_state(new_state); cmd_list_free(pr->cmdlist); cmdq_append(c, new_item); break; diff --git a/mode-tree.c b/mode-tree.c index 843a74bc..d9af2ee3 100644 --- a/mode-tree.c +++ b/mode-tree.c @@ -1064,6 +1064,7 @@ mode_tree_run_command(struct client *c, struct cmd_find_state *fs, const char *template, const char *name) { struct cmdq_item *new_item; + struct cmdq_state *new_state; char *command; struct cmd_parse_result *pr; @@ -1085,7 +1086,9 @@ mode_tree_run_command(struct client *c, struct cmd_find_state *fs, free(pr->error); break; case CMD_PARSE_SUCCESS: - new_item = cmdq_get_command(pr->cmdlist, fs, NULL, 0); + new_state = cmdq_new_state(fs, NULL, 0); + new_item = cmdq_get_command(pr->cmdlist, new_state); + cmdq_free_state(new_state); cmdq_append(c, new_item); cmd_list_free(pr->cmdlist); break; diff --git a/notify.c b/notify.c index 1f48fb6e..3147c4e0 100644 --- a/notify.c +++ b/notify.c @@ -36,19 +36,19 @@ struct notify_entry { }; static void -notify_hook_formats(struct cmdq_item *item, struct session *s, struct window *w, - int pane) +notify_hook_formats(struct cmdq_state *state, struct session *s, + struct window *w, int pane) { if (s != NULL) { - cmdq_format(item, "hook_session", "$%u", s->id); - cmdq_format(item, "hook_session_name", "%s", s->name); + cmdq_add_format(state, "hook_session", "$%u", s->id); + cmdq_add_format(state, "hook_session_name", "%s", s->name); } if (w != NULL) { - cmdq_format(item, "hook_window", "@%u", w->id); - cmdq_format(item, "hook_window_name", "%s", w->name); + cmdq_add_format(state, "hook_window", "@%u", w->id); + cmdq_add_format(state, "hook_window_name", "%s", w->name); } if (pane != -1) - cmdq_format(item, "hook_pane", "%%%d", pane); + cmdq_add_format(state, "hook_pane", "%%%d", pane); } static void @@ -57,6 +57,7 @@ notify_insert_hook(struct cmdq_item *item, struct notify_entry *ne) struct cmd_find_state fs; struct options *oo; struct cmdq_item *new_item; + struct cmdq_state *new_state; struct session *s = ne->session; struct window *w = ne->window; struct options_entry *o; @@ -87,22 +88,21 @@ notify_insert_hook(struct cmdq_item *item, struct notify_entry *ne) if (o == NULL) return; + new_state = cmdq_new_state(&fs, NULL, CMDQ_STATE_NOHOOKS); + cmdq_add_format(new_state, "hook", "%s", ne->name); + notify_hook_formats(new_state, s, w, ne->pane); + a = options_array_first(o); while (a != NULL) { cmdlist = options_array_item_value(a)->cmdlist; - if (cmdlist == NULL) { - a = options_array_next(a); - continue; + if (cmdlist != NULL) { + new_item = cmdq_get_command(cmdlist, new_state); + item = cmdq_insert_after(item, new_item); } - - new_item = cmdq_get_command(cmdlist, &fs, NULL, - CMDQ_STATE_NOHOOKS); - cmdq_format(new_item, "hook", "%s", ne->name); - notify_hook_formats(new_item, s, w, ne->pane); - item = cmdq_insert_after(item, new_item); - a = options_array_next(a); } + + cmdq_free_state(new_state); } static enum cmd_retval diff --git a/popup.c b/popup.c index c1530347..c2db145c 100644 --- a/popup.c +++ b/popup.c @@ -223,6 +223,7 @@ popup_key_cb(struct client *c, struct key_event *event) struct mouse_event *m = &event->m; struct cmd_find_state *fs = &pd->fs; struct cmdq_item *new_item; + struct cmdq_state *new_state; struct cmd_parse_result *pr; struct format_tree *ft; const char *cmd, *buf; @@ -308,7 +309,9 @@ popup_key_cb(struct client *c, struct key_event *event) event = cmdq_get_event(pd->item); else event = NULL; - new_item = cmdq_get_command(pr->cmdlist, fs, event, 0); + new_state = cmdq_new_state(&pd->fs, event, 0); + new_item = cmdq_get_command(pr->cmdlist, new_state); + cmdq_free_state(new_state); cmd_list_free(pr->cmdlist); cmdq_append(c, new_item); break; diff --git a/server-client.c b/server-client.c index 9575fd4d..8042da9a 100644 --- a/server-client.c +++ b/server-client.c @@ -1949,7 +1949,7 @@ server_client_dispatch_command(struct client *c, struct imsg *imsg) } cmd_free_argv(argc, argv); - cmdq_append(c, cmdq_get_command(pr->cmdlist, NULL, NULL, 0)); + cmdq_append(c, cmdq_get_command(pr->cmdlist, NULL)); cmdq_append(c, cmdq_get_callback(server_client_command_done, NULL)); cmd_list_free(pr->cmdlist); diff --git a/tmux.h b/tmux.h index e5ecab9b..74b16c89 100644 --- a/tmux.h +++ b/tmux.h @@ -2058,6 +2058,7 @@ char *cmd_stringify_argv(int, char **); char *cmd_get_alias(const char *); const struct cmd_entry *cmd_get_entry(struct cmd *); struct args *cmd_get_args(struct cmd *); +u_int cmd_get_group(struct cmd *); void cmd_get_source(struct cmd *, const char **, u_int *); struct cmd *cmd_parse(int, char **, const char *, u_int, char **); void cmd_free(struct cmd *); @@ -2067,8 +2068,8 @@ void cmd_list_append(struct cmd_list *, struct cmd *); void cmd_list_move(struct cmd_list *, struct cmd_list *); void cmd_list_free(struct cmd_list *); char *cmd_list_print(struct cmd_list *, int); -struct cmd *cmd_list_first(struct cmd_list *, u_int *); -struct cmd *cmd_list_next(struct cmd *, u_int *); +struct cmd *cmd_list_first(struct cmd_list *); +struct cmd *cmd_list_next(struct cmd *); int cmd_list_all_have(struct cmd_list *, int); int cmd_list_any_have(struct cmd_list *, int); int cmd_mouse_at(struct window_pane *, struct mouse_event *, @@ -2093,18 +2094,25 @@ struct cmd_parse_result *cmd_parse_from_arguments(int, char **, struct cmd_parse_input *); /* cmd-queue.c */ +struct cmdq_state *cmdq_new_state(struct cmd_find_state *, struct key_event *, + int); +struct cmdq_state *cmdq_link_state(struct cmdq_state *); +struct cmdq_state *cmdq_copy_state(struct cmdq_state *); +void cmdq_free_state(struct cmdq_state *); +void printflike(3, 4) cmdq_add_format(struct cmdq_state *, const char *, + const char *, ...); +void cmdq_merge_formats(struct cmdq_item *, struct format_tree *); struct cmdq_list *cmdq_new(void); void cmdq_free(struct cmdq_list *); const char *cmdq_get_name(struct cmdq_item *); struct client *cmdq_get_client(struct cmdq_item *); +struct cmdq_state *cmdq_get_state(struct cmdq_item *); struct cmd_find_state *cmdq_get_target(struct cmdq_item *); struct cmd_find_state *cmdq_get_source(struct cmdq_item *); struct key_event *cmdq_get_event(struct cmdq_item *); struct cmd_find_state *cmdq_get_current(struct cmdq_item *); int cmdq_get_flags(struct cmdq_item *); -void cmdq_merge_formats(struct cmdq_item *, struct format_tree *); -struct cmdq_item *cmdq_get_command(struct cmd_list *, struct cmd_find_state *, - struct key_event *, int); +struct cmdq_item *cmdq_get_command(struct cmd_list *, struct cmdq_state *); #define cmdq_get_callback(cb, data) cmdq_get_callback1(#cb, cb, data) struct cmdq_item *cmdq_get_callback1(const char *, cmdq_cb, void *); struct cmdq_item *cmdq_get_error(const char *); @@ -2113,8 +2121,6 @@ struct cmdq_item *cmdq_append(struct client *, struct cmdq_item *); void cmdq_insert_hook(struct session *, struct cmdq_item *, struct cmd_find_state *, const char *, ...); void cmdq_continue(struct cmdq_item *); -void printflike(3, 4) cmdq_format(struct cmdq_item *, const char *, - const char *, ...); u_int cmdq_next(struct client *); void cmdq_guard(struct cmdq_item *, const char *, int); void printflike(2, 3) cmdq_print(struct cmdq_item *, const char *, ...); -- cgit From 34804f2709a16dca45dc072fb53d03f79db61e51 Mon Sep 17 00:00:00 2001 From: nicm Date: Mon, 13 Apr 2020 16:19:37 +0000 Subject: When parsing strings, put all commands in one group even if there are newlines. This means that for example bind q { a \n b } and bind q "a ; b" are the same. Also log commands in different groups separated by ;; rather than ; (a command list like this should never be user visible). --- cmd-parse.y | 21 ++++++++++++++++++--- cmd.c | 23 ++++++++++++++++------- tmux.h | 1 + 3 files changed, 35 insertions(+), 10 deletions(-) diff --git a/cmd-parse.y b/cmd-parse.y index aabfe2d3..2ca0124a 100644 --- a/cmd-parse.y +++ b/cmd-parse.y @@ -700,15 +700,17 @@ cmd_parse_build_commands(struct cmd_parse_commands *cmds, /* * Parse each command into a command list. Create a new command list - * for each line so they get a new group (so the queue knows which ones - * to remove if a command fails when executed). + * for each line (unless the flag is set) so they get a new group (so + * the queue knows which ones to remove if a command fails when + * executed). */ result = cmd_list_new(); TAILQ_FOREACH(cmd, cmds, entry) { log_debug("%s: %u %s", __func__, cmd->line, cmd->name); cmd_log_argv(cmd->argc, cmd->argv, __func__); - if (cmdlist == NULL || cmd->line != line) { + if (cmdlist == NULL || + ((~pi->flags & CMD_PARSE_ONEGROUP) && cmd->line != line)) { if (cmdlist != NULL) { cmd_parse_print_commands(pi, line, cmdlist); cmd_list_move(result, cmdlist); @@ -775,6 +777,19 @@ cmd_parse_from_file(FILE *f, struct cmd_parse_input *pi) struct cmd_parse_result * cmd_parse_from_string(const char *s, struct cmd_parse_input *pi) { + struct cmd_parse_input input; + + if (pi == NULL) { + memset(&input, 0, sizeof input); + pi = &input; + } + + /* + * When parsing a string, put commands in one group even if there are + * multiple lines. This means { a \n b } is identical to "a ; b" when + * given as an argument to another command. + */ + pi->flags |= CMD_PARSE_ONEGROUP; return (cmd_parse_from_buffer(s, strlen(s), pi)); } diff --git a/cmd.c b/cmd.c index b7b144b4..bc807cbe 100644 --- a/cmd.c +++ b/cmd.c @@ -624,7 +624,7 @@ cmd_list_free(struct cmd_list *cmdlist) char * cmd_list_print(struct cmd_list *cmdlist, int escaped) { - struct cmd *cmd; + struct cmd *cmd, *next; char *buf, *this; size_t len; @@ -634,15 +634,24 @@ cmd_list_print(struct cmd_list *cmdlist, int escaped) TAILQ_FOREACH(cmd, cmdlist->list, qentry) { this = cmd_print(cmd); - len += strlen(this) + 4; + len += strlen(this) + 6; buf = xrealloc(buf, len); strlcat(buf, this, len); - if (TAILQ_NEXT(cmd, qentry) != NULL) { - if (escaped) - strlcat(buf, " \\; ", len); - else - strlcat(buf, " ; ", len); + + next = TAILQ_NEXT(cmd, qentry); + if (next != NULL) { + if (cmd->group != next->group) { + if (escaped) + strlcat(buf, " \\;\\; ", len); + else + strlcat(buf, " ;; ", len); + } else { + if (escaped) + strlcat(buf, " \\; ", len); + else + strlcat(buf, " ; ", len); + } } free(this); diff --git a/tmux.h b/tmux.h index 74b16c89..c1b91f93 100644 --- a/tmux.h +++ b/tmux.h @@ -1370,6 +1370,7 @@ struct cmd_parse_input { #define CMD_PARSE_PARSEONLY 0x2 #define CMD_PARSE_NOALIAS 0x4 #define CMD_PARSE_VERBOSE 0x8 +#define CMD_PARSE_ONEGROUP 0x10 const char *file; u_int line; -- cgit