diff --git a/cmd-choose-list.c b/cmd-choose-list.c new file mode 100644 index 00000000..8b605d08 --- /dev/null +++ b/cmd-choose-list.c @@ -0,0 +1,117 @@ +/* $Id$ */ + +/* + * Copyright (c) 2012 Thomas Adam + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include + +#include + +#include "tmux.h" + +#define CMD_CHOOSE_LIST_DEFAULT_TEMPLATE "run-shell '%%'" + +/* + * Enter choose mode to choose a custom list. + */ + +enum cmd_retval cmd_choose_list_exec(struct cmd *, struct cmd_ctx *); + +void cmd_choose_list_callback(struct window_choose_data *); +void cmd_choose_list_free(struct window_choose_data *); + +const struct cmd_entry cmd_choose_list_entry = { + "choose-list", NULL, + "l:t:", 0, 1, + "[-l items] " CMD_TARGET_WINDOW_USAGE "[template]", + 0, + NULL, + NULL, + cmd_choose_list_exec +}; + +enum cmd_retval +cmd_choose_list_exec(struct cmd *self, struct cmd_ctx *ctx) +{ + struct args *args = self->args; + struct winlink *wl; + const char *lists; + char *template, *list, *copy, *lists1; + u_int idx; + + if (ctx->curclient == NULL) { + ctx->error(ctx, "must be run interactively"); + return (CMD_RETURN_ERROR); + } + + if ((lists = args_get(args, 'l')) == NULL) + return (CMD_RETURN_ERROR); + + if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL) + return (CMD_RETURN_ERROR); + + if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0) + return (CMD_RETURN_NORMAL); + + if (args->argc != 0) + template = xstrdup(args->argv[0]); + else + template = xstrdup(CMD_CHOOSE_LIST_DEFAULT_TEMPLATE); + + copy = lists1 = xstrdup(lists); + idx = 0; + while ((list = strsep(&lists1, ",")) != NULL) + { + if (*list == '\0') /* no empty entries */ + continue; + window_choose_add_item(wl->window->active, ctx, wl, list, + template, idx); + idx++; + } + free(copy); + + window_choose_ready(wl->window->active, 0, cmd_choose_list_callback, + cmd_choose_list_free); + + free(template); + + return (CMD_RETURN_NORMAL); +} + +void +cmd_choose_list_callback(struct window_choose_data *cdata) +{ + if (cdata == NULL || (cdata->client->flags & CLIENT_DEAD)) + return; + + window_choose_ctx(cdata); +} + +void +cmd_choose_list_free(struct window_choose_data *cdata) +{ + cdata->session->references--; + cdata->client->references--; + + free(cdata->ft_template); + free(cdata->command); + format_free(cdata->ft); + free(cdata); + +} diff --git a/cmd.c b/cmd.c index 24136429..d4b7e979 100644 --- a/cmd.c +++ b/cmd.c @@ -34,6 +34,7 @@ const struct cmd_entry *cmd_table[] = { &cmd_capture_pane_entry, &cmd_choose_buffer_entry, &cmd_choose_client_entry, + &cmd_choose_list_entry, &cmd_choose_session_entry, &cmd_choose_tree_entry, &cmd_choose_window_entry, diff --git a/tmux.1 b/tmux.1 index 1a683b52..7d32dbeb 100644 --- a/tmux.1 +++ b/tmux.1 @@ -1071,6 +1071,33 @@ section. This command works only from inside .Nm . .It Xo +.Ic choose-list +.Op Fl l Ar items +.Op Fl t Ar target-window +.Op Ar template +.Xc +Put a window into list choice mode, allowing +.Ar items +to be selected. +.Ar items +can be a comma-separated list to display more than one item. +If an item has spaces, that entry must be quoted. +After an item is chosen, +.Ql %% +is replaced by the chosen item in the +.Ar template +and the result is executed as a command. +If +.Ar template +is not given, "run-shell '%%'" is used. +.Ar items +also accepts format specifiers. +For the meaning of this see the +.Sx FORMATS +section. +This command works only from inside +.Nm . +.It Xo .Ic choose-session .Op Fl F Ar format .Op Fl t Ar target-window diff --git a/tmux.h b/tmux.h index c593b71f..442874b4 100644 --- a/tmux.h +++ b/tmux.h @@ -1712,6 +1712,7 @@ extern const struct cmd_entry cmd_break_pane_entry; extern const struct cmd_entry cmd_capture_pane_entry; extern const struct cmd_entry cmd_choose_buffer_entry; extern const struct cmd_entry cmd_choose_client_entry; +extern const struct cmd_entry cmd_choose_list_entry; extern const struct cmd_entry cmd_choose_session_entry; extern const struct cmd_entry cmd_choose_tree_entry; extern const struct cmd_entry cmd_choose_window_entry; @@ -2200,6 +2201,9 @@ struct window_choose_data *window_choose_add_window(struct window_pane *, struct window_choose_data *window_choose_add_session(struct window_pane *, struct cmd_ctx *, struct session *, const char *, char *, u_int); +struct window_choose_data *window_choose_add_item(struct window_pane *, + struct cmd_ctx *, struct winlink *, const char *, + char *, u_int); /* names.c */ void queue_window_name(struct window *); diff --git a/window-choose.c b/window-choose.c index 9ab277d6..c77a1d39 100644 --- a/window-choose.c +++ b/window-choose.c @@ -636,6 +636,38 @@ window_choose_add_session(struct window_pane *wp, struct cmd_ctx *ctx, return (wcd); } +struct window_choose_data * +window_choose_add_item(struct window_pane *wp, struct cmd_ctx *ctx, + 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); + wcd->idx = wl->idx; + wcd->ft_template = xstrdup(template); + format_add(wcd->ft, "line", "%u", idx); + format_session(wcd->ft, wcd->session); + format_winlink(wcd->ft, wcd->session, wl); + format_window_pane(wcd->ft, wl->window->active); + + wcd->client->references++; + wcd->session->references++; + + window_choose_add(wp, wcd); + + /* + * Interpolate action_data here, since the data we pass back is the + * expanded template itself. + */ + xasprintf(&action_data, "%s", format_expand(wcd->ft, wcd->ft_template)); + wcd->command = cmd_template_replace(action, action_data, 1); + free(action_data); + + 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,