From 7e02d2f459531107770e925bebf1fbc548719de0 Mon Sep 17 00:00:00 2001 From: Tiago Cunha Date: Wed, 4 Jul 2012 11:03:20 +0000 Subject: [PATCH] Sync OpenBSD patchset 1143: Provide common helper function for adding windows and sessions to choose lists and expand %% in command before using it rather than at callback time. From Thomas Adam. --- cmd-choose-buffer.c | 22 +++++++++------ cmd-choose-client.c | 17 +++++++----- cmd-choose-session.c | 34 +++++++---------------- cmd-choose-window.c | 31 ++++++++------------- tmux.h | 14 ++++++---- window-choose.c | 66 ++++++++++++++++++++++++++++++++++++++------ 6 files changed, 110 insertions(+), 74 deletions(-) diff --git a/cmd-choose-buffer.c b/cmd-choose-buffer.c index ec024e74..66b9223c 100644 --- a/cmd-choose-buffer.c +++ b/cmd-choose-buffer.c @@ -48,8 +48,9 @@ cmd_choose_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) struct window_choose_data *cdata; struct winlink *wl; struct paste_buffer *pb; - u_int idx; + char *action, *action_data; const char *template; + u_int idx; if (ctx->curclient == NULL) { ctx->error(ctx, "must be run interactively"); @@ -68,14 +69,14 @@ cmd_choose_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0) return (0); + if (args->argc != 0) + action = xstrdup(args->argv[0]); + else + action = xstrdup("paste-buffer -b '%%'"); + idx = 0; while ((pb = paste_walk_stack(&global_buffers, &idx)) != NULL) { cdata = window_choose_data_create(ctx); - if (args->argc != 0) - cdata->action = xstrdup(args->argv[0]); - else - cdata->action = xstrdup("paste-buffer -b '%%'"); - cdata->idx = idx - 1; cdata->client->references++; @@ -83,8 +84,13 @@ cmd_choose_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) format_add(cdata->ft, "line", "%u", idx - 1); format_paste_buffer(cdata->ft, pb); + xasprintf(&action_data, "%u", idx - 1); + cdata->command = cmd_template_replace(action, action_data, 1); + xfree(action_data); + window_choose_add(wl->window->active, cdata); } + xfree(action); window_choose_ready(wl->window->active, 0, cmd_choose_buffer_callback, cmd_choose_buffer_free); @@ -100,7 +106,6 @@ cmd_choose_buffer_callback(struct window_choose_data *cdata) if (cdata->client->flags & CLIENT_DEAD) return; - xasprintf(&cdata->raw_format, "%u", cdata->idx); window_choose_ctx(cdata); } @@ -114,8 +119,7 @@ cmd_choose_buffer_free(struct window_choose_data *data) cdata->client->references--; + xfree(cdata->command); xfree(cdata->ft_template); - xfree(cdata->action); - xfree(cdata->raw_format); xfree(cdata); } diff --git a/cmd-choose-client.c b/cmd-choose-client.c index 230ff4a8..5b3e6bf4 100644 --- a/cmd-choose-client.c +++ b/cmd-choose-client.c @@ -54,6 +54,7 @@ cmd_choose_client_exec(struct cmd *self, struct cmd_ctx *ctx) struct winlink *wl; struct client *c; const char *template; + char *action; u_int i, idx, cur; if (ctx->curclient == NULL) { @@ -70,6 +71,11 @@ cmd_choose_client_exec(struct cmd *self, struct cmd_ctx *ctx) if ((template = args_get(args, 'F')) == NULL) template = DEFAULT_CLIENT_TEMPLATE; + if (args->argc != 0) + action = xstrdup(args->argv[0]); + else + action = xstrdup("detach-client -t '%%'"); + cur = idx = 0; for (i = 0; i < ARRAY_LENGTH(&clients); i++) { c = ARRAY_ITEM(&clients, i); @@ -80,11 +86,6 @@ cmd_choose_client_exec(struct cmd *self, struct cmd_ctx *ctx) idx++; cdata = window_choose_data_create(ctx); - if (args->argc != 0) - cdata->action = xstrdup(args->argv[0]); - else - cdata->action = xstrdup("detach-client -t '%%'"); - cdata->idx = i; cdata->client->references++; @@ -93,8 +94,11 @@ cmd_choose_client_exec(struct cmd *self, struct cmd_ctx *ctx) format_session(cdata->ft, c->session); format_client(cdata->ft, c); + cdata->command = cmd_template_replace(action, c->tty.path, 1); + window_choose_add(wl->window->active, cdata); } + xfree(action); window_choose_ready(wl->window->active, cur, cmd_choose_client_callback, cmd_choose_client_free); @@ -118,7 +122,6 @@ cmd_choose_client_callback(struct window_choose_data *cdata) if (c == NULL || c->session == NULL) return; - xasprintf(&cdata->raw_format, "%s", c->tty.path); window_choose_ctx(cdata); } @@ -131,7 +134,7 @@ cmd_choose_client_free(struct window_choose_data *cdata) cdata->client->references--; xfree(cdata->ft_template); - xfree(cdata->action); + xfree(cdata->command); format_free(cdata->ft); xfree(cdata); } diff --git a/cmd-choose-session.c b/cmd-choose-session.c index 2c859d9e..18d4fbfd 100644 --- a/cmd-choose-session.c +++ b/cmd-choose-session.c @@ -45,9 +45,9 @@ int cmd_choose_session_exec(struct cmd *self, struct cmd_ctx *ctx) { struct args *args = self->args; - struct window_choose_data *cdata; struct winlink *wl; struct session *s; + char *action; const char *template; u_int idx, cur; @@ -65,28 +65,21 @@ cmd_choose_session_exec(struct cmd *self, struct cmd_ctx *ctx) if ((template = args_get(args, 'F')) == NULL) template = DEFAULT_SESSION_TEMPLATE; + if (args->argc != 0) + action = xstrdup(args->argv[0]); + else + action = xstrdup("switch-client -t '%%'"); + cur = idx = 0; RB_FOREACH(s, sessions, &sessions) { if (s == ctx->curclient->session) cur = idx; idx++; - cdata = window_choose_data_create(ctx); - if (args->argc != 0) - cdata->action = xstrdup(args->argv[0]); - else - cdata->action = xstrdup("switch-client -t '%%'"); - cdata->idx = s->idx; - - cdata->client->references++; - cdata->session->references++; - - cdata->ft_template = xstrdup(template); - format_add(cdata->ft, "line", "%u", idx); - format_session(cdata->ft, s); - - window_choose_add(wl->window->active, cdata); + window_choose_add_session(wl->window->active, + ctx, s, template, action, idx); } + xfree(action); window_choose_ready(wl->window->active, cur, cmd_choose_session_callback, cmd_choose_session_free); @@ -97,18 +90,11 @@ cmd_choose_session_exec(struct cmd *self, struct cmd_ctx *ctx) void cmd_choose_session_callback(struct window_choose_data *cdata) { - struct session *s; - if (cdata == NULL) return; if (cdata->client->flags & CLIENT_DEAD) return; - s = session_find_by_index(cdata->idx); - if (s == NULL) - return; - - cdata->raw_format = xstrdup(s->name); window_choose_ctx(cdata); } @@ -121,8 +107,8 @@ cmd_choose_session_free(struct window_choose_data *cdata) cdata->client->references--; cdata->session->references--; + xfree(cdata->command); xfree(cdata->ft_template); - xfree(cdata->action); format_free(cdata->ft); xfree(cdata); } diff --git a/cmd-choose-window.c b/cmd-choose-window.c index 2955e609..07b8705b 100644 --- a/cmd-choose-window.c +++ b/cmd-choose-window.c @@ -45,10 +45,10 @@ int cmd_choose_window_exec(struct cmd *self, struct cmd_ctx *ctx) { struct args *args = self->args; - struct window_choose_data *cdata; struct session *s; struct winlink *wl, *wm; const char *template; + char *action; u_int idx, cur; if (ctx->curclient == NULL) { @@ -66,30 +66,22 @@ cmd_choose_window_exec(struct cmd *self, struct cmd_ctx *ctx) if ((template = args_get(args, 'F')) == NULL) template = DEFAULT_WINDOW_TEMPLATE " \"#{pane_title}\""; + if (args->argc != 0) + action = xstrdup(args->argv[0]); + else + action = xstrdup("select-window -t '%%'"); + cur = idx = 0; RB_FOREACH(wm, winlinks, &s->windows) { if (wm == s->curw) cur = idx; idx++; - cdata = window_choose_data_create(ctx); - if (args->argc != 0) - cdata->action = xstrdup(args->argv[0]); - else - cdata->action = xstrdup("select-window -t '%%'"); - - cdata->idx = wm->idx; - cdata->client->references++; - cdata->session->references++; - - cdata->ft_template = xstrdup(template); - format_add(cdata->ft, "line", "%u", idx); - format_session(cdata->ft, s); - format_winlink(cdata->ft, s, wm); - format_window_pane(cdata->ft, wm->window->active); - - window_choose_add(wl->window->active, cdata); + window_choose_add_window(wl->window->active, ctx, s, wm, + template, action, idx); } + xfree(action); + window_choose_ready(wl->window->active, cur, cmd_choose_window_callback, cmd_choose_window_free); @@ -110,7 +102,6 @@ cmd_choose_window_callback(struct window_choose_data *cdata) if (!session_alive(s)) return; - xasprintf(&cdata->raw_format, "%s:%u", s->name, cdata->idx); window_choose_ctx(cdata); } @@ -124,7 +115,7 @@ cmd_choose_window_free(struct window_choose_data *cdata) cdata->client->references--; xfree(cdata->ft_template); - xfree(cdata->action); + xfree(cdata->command); format_free(cdata->ft); xfree(cdata); } diff --git a/tmux.h b/tmux.h index 2c902c77..df05dd33 100644 --- a/tmux.h +++ b/tmux.h @@ -848,8 +848,7 @@ struct window_choose_data { struct session *session; struct format_tree *ft; char *ft_template; - char *raw_format; - char *action; + char *command; u_int idx; }; @@ -2131,16 +2130,19 @@ void window_copy_pageup(struct window_pane *); /* window-choose.c */ extern const struct window_mode window_choose_mode; -void window_choose_vadd( - struct window_pane *, int, const char *, va_list); void window_choose_add(struct window_pane *, struct window_choose_data *); void window_choose_ready(struct window_pane *, u_int, void (*)(struct window_choose_data *), void (*)(struct window_choose_data *)); -struct window_choose_data *window_choose_data_create( - struct cmd_ctx *); +struct window_choose_data *window_choose_data_create(struct cmd_ctx *); void window_choose_ctx(struct window_choose_data *); +struct window_choose_data *window_choose_add_window(struct window_pane *, + struct cmd_ctx *, struct session *, struct winlink *, + const char *, char *, u_int); +struct window_choose_data *window_choose_add_session(struct window_pane *, + struct cmd_ctx *, struct session *, const char *, + char *, u_int); /* names.c */ void queue_window_name(struct window *); diff --git a/window-choose.c b/window-choose.c index 90a43f93..62c38b1c 100644 --- a/window-choose.c +++ b/window-choose.c @@ -133,8 +133,7 @@ window_choose_data_create(struct cmd_ctx *ctx) wcd = xmalloc(sizeof *wcd); wcd->ft = format_create(); wcd->ft_template = NULL; - wcd->action = NULL; - wcd->raw_format = NULL; + wcd->command = NULL; wcd->client = ctx->curclient; wcd->session = ctx->curclient->session; wcd->idx = -1; @@ -482,21 +481,22 @@ window_choose_ctx(struct window_choose_data *cdata) { struct cmd_ctx ctx; struct cmd_list *cmdlist; - char *template, *cause; + char *cause; - template = cmd_template_replace(cdata->action, - cdata->raw_format, 1); + /* The command template will have already been replaced. But if it's + * NULL, bail here. + */ + if (cdata->command == NULL) + return; - if (cmd_string_parse(template, &cmdlist, &cause) != 0) { + if (cmd_string_parse(cdata->command, &cmdlist, &cause) != 0) { if (cause != NULL) { *cause = toupper((u_char) *cause); status_message_set(cdata->client, "%s", cause); xfree(cause); } - xfree(template); return; } - xfree(template); ctx.msgdata = NULL; ctx.curclient = cdata->client; @@ -510,3 +510,53 @@ window_choose_ctx(struct window_choose_data *cdata) cmd_list_exec(cmdlist, &ctx); cmd_list_free(cmdlist); } + +struct window_choose_data * +window_choose_add_session(struct window_pane *wp, struct cmd_ctx *ctx, + struct session *s, const char *template, char *action, u_int idx) +{ + struct window_choose_data *wcd; + + wcd = window_choose_data_create(ctx); + wcd->idx = s->idx; + wcd->command = cmd_template_replace(action, s->name, 1); + wcd->ft_template = xstrdup(template); + format_add(wcd->ft, "line", "%u", idx); + format_session(wcd->ft, s); + + wcd->client->references++; + wcd->session->references++; + + window_choose_add(wp, wcd); + + return (wcd); +} + +struct window_choose_data * +window_choose_add_window(struct window_pane *wp, struct cmd_ctx *ctx, + struct session *s, struct winlink *wl, const char *template, + char *action, u_int idx) +{ + struct window_choose_data *wcd; + char *action_data; + + wcd = window_choose_data_create(ctx); + + xasprintf(&action_data, "%s:%d", s->name, wl->idx); + wcd->command = cmd_template_replace(action, action_data, 1); + xfree(action_data); + + wcd->idx = wl->idx; + wcd->ft_template = xstrdup(template); + format_add(wcd->ft, "line", "%u", idx); + format_session(wcd->ft, s); + format_winlink(wcd->ft, s, wl); + format_window_pane(wcd->ft, wl->window->active); + + wcd->client->references++; + wcd->session->references++; + + window_choose_add(wp, wcd); + + return (wcd); +}