From f20c6fe0099a15002c6c2a7693ca9061aa6367ba Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Sun, 8 Jul 2012 16:04:38 +0000 Subject: [PATCH] Add choose-tree command to show windows and sessions in the same list. Change choose-window and -session to use the same code. From Thomas Adam. --- Makefile | 3 +- cmd-choose-session.c | 114 -------------------- cmd-choose-tree.c | 251 +++++++++++++++++++++++++++++++++++++++++++ cmd-choose-window.c | 121 --------------------- cmd.c | 1 + key-bindings.c | 2 +- tmux.1 | 62 +++++++++++ tmux.h | 1 + 8 files changed, 317 insertions(+), 238 deletions(-) delete mode 100644 cmd-choose-session.c create mode 100644 cmd-choose-tree.c delete mode 100644 cmd-choose-window.c diff --git a/Makefile b/Makefile index 5e7b94c1..efad64a0 100644 --- a/Makefile +++ b/Makefile @@ -12,8 +12,7 @@ SRCS= arguments.c \ cmd-capture-pane.c \ cmd-choose-buffer.c \ cmd-choose-client.c \ - cmd-choose-session.c \ - cmd-choose-window.c \ + cmd-choose-tree.c \ cmd-clear-history.c \ cmd-clock-mode.c \ cmd-command-prompt.c \ diff --git a/cmd-choose-session.c b/cmd-choose-session.c deleted file mode 100644 index 2f30c309..00000000 --- a/cmd-choose-session.c +++ /dev/null @@ -1,114 +0,0 @@ -/* $OpenBSD$ */ - -/* - * Copyright (c) 2009 Nicholas Marriott - * - * 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 "tmux.h" - -/* - * Enter choice mode to choose a session. - */ - -int cmd_choose_session_exec(struct cmd *, struct cmd_ctx *); - -void cmd_choose_session_callback(struct window_choose_data *); -void cmd_choose_session_free(struct window_choose_data *); - -const struct cmd_entry cmd_choose_session_entry = { - "choose-session", NULL, - "F:t:", 0, 1, - CMD_TARGET_WINDOW_USAGE " [-F format] [template]", - 0, - NULL, - NULL, - cmd_choose_session_exec -}; - -int -cmd_choose_session_exec(struct cmd *self, struct cmd_ctx *ctx) -{ - struct args *args = self->args; - struct winlink *wl; - struct session *s; - char *action; - const char *template; - u_int idx, cur; - - if (ctx->curclient == NULL) { - ctx->error(ctx, "must be run interactively"); - return (-1); - } - - if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL) - return (-1); - - if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0) - return (0); - - 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++; - - 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); - - return (0); -} - -void -cmd_choose_session_callback(struct window_choose_data *cdata) -{ - if (cdata == NULL) - return; - if (cdata->client->flags & CLIENT_DEAD) - return; - - window_choose_ctx(cdata); -} - -void -cmd_choose_session_free(struct window_choose_data *cdata) -{ - if (cdata == NULL) - return; - - cdata->client->references--; - cdata->session->references--; - - xfree(cdata->command); - xfree(cdata->ft_template); - format_free(cdata->ft); - xfree(cdata); -} diff --git a/cmd-choose-tree.c b/cmd-choose-tree.c new file mode 100644 index 00000000..385621cf --- /dev/null +++ b/cmd-choose-tree.c @@ -0,0 +1,251 @@ +/* $OpenBSD$ */ + +/* + * 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 "tmux.h" + +#define CMD_CHOOSE_TREE_WINDOW_ACTION "select-window -t '%%'" +#define CMD_CHOOSE_TREE_SESSION_ACTION "switch-client -t '%%'" +#define CMD_CHOOSE_TREE_WINDOW_TEMPLATE \ + DEFAULT_WINDOW_TEMPLATE " \"#{pane_title}\"" + +/* + * Enter choice mode to choose a session and/or window. + */ + +int cmd_choose_tree_exec(struct cmd *, struct cmd_ctx *); + +void cmd_choose_tree_callback(struct window_choose_data *); +void cmd_choose_tree_free(struct window_choose_data *); + +const struct cmd_entry cmd_choose_tree_entry = { + "choose-tree", NULL, + "S:W:swb:c:t:", 0, 1, + "[-SW] [-s format] [-w format ] [-b session template] " \ + "[-c window template] " CMD_TARGET_WINDOW_USAGE, + 0, + NULL, + NULL, + cmd_choose_tree_exec +}; + +const struct cmd_entry cmd_choose_session_entry = { + "choose-session", NULL, + "F:t:", 0, 1, + CMD_TARGET_WINDOW_USAGE " [-F format] [template]", + 0, + NULL, + NULL, + cmd_choose_tree_exec +}; + +const struct cmd_entry cmd_choose_window_entry = { + "choose-window", NULL, + "F:t:", 0, 1, + CMD_TARGET_WINDOW_USAGE "[-F format] [template]", + 0, + NULL, + NULL, + cmd_choose_tree_exec +}; + +int +cmd_choose_tree_exec(struct cmd *self, struct cmd_ctx *ctx) +{ + struct args *args = self->args; + struct winlink *wl, *wm; + struct session *s, *s2; + struct tty *tty; + struct window_choose_data *wcd = NULL; + const char *ses_template, *win_template; + char *final_win_action, *final_win_template; + const char *ses_action, *win_action; + u_int cur_win, idx_ses, win_ses; + u_int wflag, sflag; + + ses_template = win_template = NULL; + ses_action = win_action = NULL; + + if (ctx->curclient == NULL) { + ctx->error(ctx, "must be run interactively"); + return (-1); + } + + s = ctx->curclient->session; + tty = &ctx->curclient->tty; + + if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL) + return (-1); + + if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0) + return (0); + + /* Sort out which command this is. */ + wflag = sflag = 0; + if (self->entry == &cmd_choose_session_entry) { + sflag = 1; + if ((ses_template = args_get(args, 'F')) == NULL) + ses_template = DEFAULT_SESSION_TEMPLATE; + + if (args->argc != 0) + ses_action = args->argv[0]; + else + ses_action = CMD_CHOOSE_TREE_SESSION_ACTION; + } else if (self->entry == &cmd_choose_window_entry) { + wflag = 1; + if ((win_template = args_get(args, 'F')) == NULL) + win_template = CMD_CHOOSE_TREE_WINDOW_TEMPLATE; + + if (args->argc != 0) + win_action = args->argv[0]; + else + win_action = CMD_CHOOSE_TREE_WINDOW_ACTION; + } else { + wflag = args_has(args, 'w'); + sflag = args_has(args, 's'); + + if ((ses_action = args_get(args, 'b')) == NULL) + ses_action = CMD_CHOOSE_TREE_SESSION_ACTION; + + if ((win_action = args_get(args, 'c')) == NULL) + win_action = CMD_CHOOSE_TREE_WINDOW_ACTION; + + if ((ses_template = args_get(args, 'S')) == NULL) + ses_template = DEFAULT_SESSION_TEMPLATE; + + if ((win_template = args_get(args, 'W')) == NULL) + win_template = CMD_CHOOSE_TREE_WINDOW_TEMPLATE; + } + + /* + * If not asking for windows and sessions, assume no "-ws" given and + * hence display the entire tree outright. + */ + if (!wflag && !sflag) + wflag = sflag = 1; + + /* + * If we're drawing in tree mode, including sessions, then pad the + * window template, otherwise just render the windows as a flat list + * without any padding. + */ + if (wflag && sflag) + xasprintf(&final_win_template, " --> %s", win_template); + else if (wflag) + final_win_template = xstrdup(win_template); + else + final_win_template = NULL; + + idx_ses = cur_win = -1; + RB_FOREACH(s2, sessions, &sessions) { + idx_ses++; + + /* + * If we're just choosing windows, jump straight there. Note + * that this implies the current session, so only choose + * windows when the session matches this one. + */ + if (wflag && !sflag) { + if (s != s2) + continue; + goto windows_only; + } + + wcd = window_choose_add_session(wl->window->active, + ctx, s2, ses_template, (char *)ses_action, idx_ses); + + /* If we're just choosing sessions, skip choosing windows. */ + if (sflag && !wflag) { + if (s == s2) + cur_win = idx_ses; + continue; + } +windows_only: + win_ses = -1; + RB_FOREACH(wm, winlinks, &s2->windows) { + win_ses++; + if (sflag && wflag) + idx_ses++; + + if (wm == s2->curw && s == s2) { + if (wflag && !sflag) { + /* + * Then we're only counting windows. + * So remember which is the current + * window in the list. + */ + cur_win = win_ses; + } else + cur_win = idx_ses; + } + + xasprintf(&final_win_action, "%s ; %s", win_action, + wcd ? wcd->command : ""); + + window_choose_add_window(wl->window->active, + ctx, s2, wm, final_win_template, + final_win_action, idx_ses); + + xfree(final_win_action); + } + /* + * If we're just drawing windows, don't consider moving on to + * other sessions as we only list windows in this session. + */ + if (wflag && !sflag) + break; + } + if (final_win_template != NULL) + xfree(final_win_template); + + window_choose_ready(wl->window->active, cur_win, + cmd_choose_tree_callback, cmd_choose_tree_free); + + return (0); +} + +void +cmd_choose_tree_callback(struct window_choose_data *cdata) +{ + if (cdata == NULL) + return; + + if (cdata->client->flags & CLIENT_DEAD) + return; + + window_choose_ctx(cdata); +} + +void +cmd_choose_tree_free(struct window_choose_data *cdata) +{ + cdata->session->references--; + cdata->client->references--; + + xfree(cdata->ft_template); + xfree(cdata->command); + format_free(cdata->ft); + xfree(cdata); + +} + diff --git a/cmd-choose-window.c b/cmd-choose-window.c deleted file mode 100644 index 3c8831eb..00000000 --- a/cmd-choose-window.c +++ /dev/null @@ -1,121 +0,0 @@ -/* $OpenBSD$ */ - -/* - * Copyright (c) 2009 Nicholas Marriott - * - * 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 "tmux.h" - -/* - * Enter choice mode to choose a window. - */ - -int cmd_choose_window_exec(struct cmd *, struct cmd_ctx *); - -void cmd_choose_window_callback(struct window_choose_data *); -void cmd_choose_window_free(struct window_choose_data *); - -const struct cmd_entry cmd_choose_window_entry = { - "choose-window", NULL, - "F:t:", 0, 1, - CMD_TARGET_WINDOW_USAGE " [-F format] [template]", - 0, - NULL, - NULL, - cmd_choose_window_exec -}; - -int -cmd_choose_window_exec(struct cmd *self, struct cmd_ctx *ctx) -{ - struct args *args = self->args; - struct session *s; - struct winlink *wl, *wm; - const char *template; - char *action; - u_int idx, cur; - - if (ctx->curclient == NULL) { - ctx->error(ctx, "must be run interactively"); - return (-1); - } - s = ctx->curclient->session; - - if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL) - return (-1); - - if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0) - return (0); - - 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++; - - 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); - - return (0); -} - -void -cmd_choose_window_callback(struct window_choose_data *cdata) -{ - struct session *s; - - if (cdata == NULL) - return; - if (cdata->client->flags & CLIENT_DEAD) - return; - - s = cdata->session; - if (!session_alive(s)) - return; - - window_choose_ctx(cdata); -} - -void -cmd_choose_window_free(struct window_choose_data *cdata) -{ - if (cdata == NULL) - return; - - cdata->session->references--; - cdata->client->references--; - - xfree(cdata->ft_template); - xfree(cdata->command); - format_free(cdata->ft); - xfree(cdata); -} diff --git a/cmd.c b/cmd.c index 16758589..5f97a854 100644 --- a/cmd.c +++ b/cmd.c @@ -36,6 +36,7 @@ const struct cmd_entry *cmd_table[] = { &cmd_choose_buffer_entry, &cmd_choose_client_entry, &cmd_choose_session_entry, + &cmd_choose_tree_entry, &cmd_choose_window_entry, &cmd_clear_history_entry, &cmd_clock_mode_entry, diff --git a/key-bindings.c b/key-bindings.c index f020c19d..8511ea7c 100644 --- a/key-bindings.c +++ b/key-bindings.c @@ -147,7 +147,7 @@ key_bindings_init(void) { 'p', 0, &cmd_previous_window_entry }, { 'q', 0, &cmd_display_panes_entry }, { 'r', 0, &cmd_refresh_client_entry }, - { 's', 0, &cmd_choose_session_entry }, + { 's', 0, &cmd_choose_tree_entry }, { 't', 0, &cmd_clock_mode_entry }, { 'u', 1, &cmd_select_layout_entry }, { 'w', 0, &cmd_choose_window_entry }, diff --git a/tmux.1 b/tmux.1 index e91046ed..96762511 100644 --- a/tmux.1 +++ b/tmux.1 @@ -1090,6 +1090,68 @@ section. This command works only from inside .Nm . .It Xo +.Ic choose-tree +.Op Fl s +.Op Fl w +.Op Fl b Ar session-template +.Op Fl c Ar window-template +.Op Fl S Ar format +.Op Fl W Ar format +.Op Fl t Ar target-window +.Xc +Put a window into tree choice mode, where either sessions or windows may be +selected interactively from a list. +By default, windows belonging to a session are indented to show their +relationship to a session. +.Pp +Note that the +.Ic choose-window +and +.Ic choose-session +commands are wrappers around +.Ic choose-tree . +. +.Pp +If +.Fl s +is given, will show sessions. +If +.Fl w +is given, will show windows. +If +.Fl b +is given, will override the default session command. +Note that +.Ql %% +can be used, and will be replaced with the session name. +The default option if not specified is "switch-client -t '%%'". +If +.Fl c +is given, will override the default window command. +Note that +.Ql %% +can be used, and will be replaced with the session name and window index. +This command will run +.Ar session-template +before it. +If +.Fl S +is given will display the specified format instead of the default session +format. +If +.Fl W +is given will display the specified format instead of the default window +format. +For the meaning of the +.Fl s +and +.Fl w +options, see the +.Sx FORMATS +section. +This command only works from inside +.Nm . +.It Xo .Ic choose-window .Op Fl F Ar format .Op Fl t Ar target-window diff --git a/tmux.h b/tmux.h index e04bd2f4..02237f8a 100644 --- a/tmux.h +++ b/tmux.h @@ -1664,6 +1664,7 @@ 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_session_entry; +extern const struct cmd_entry cmd_choose_tree_entry; extern const struct cmd_entry cmd_choose_window_entry; extern const struct cmd_entry cmd_clear_history_entry; extern const struct cmd_entry cmd_clock_mode_entry;