summaryrefslogtreecommitdiffstats
path: root/cmd-choose-tree.c
diff options
context:
space:
mode:
authornicm <nicm>2017-05-30 21:44:59 +0000
committernicm <nicm>2017-05-30 21:44:59 +0000
commitaad4e4ddb194cba9c01b0ddd696fb7b214e1a7eb (patch)
tree8a8a273bb54a7b4010b48b64a59aa5d3c3c96b55 /cmd-choose-tree.c
parentbd39fcbeea1930a2b36e98a622d864e2e27e5d14 (diff)
Rewrite of choose mode, both to simplify and tidy the code and to add
some modern features. Now the common code is in mode-tree.c, which provides an API used by the three modes now separated into window-{buffer,client,tree}.c. Buffer mode shows buffers, client mode clients and tree mode a tree of sessions, windows and panes. Each mode has a common set of key bindings plus a few that are specific to the mode. Other changes are: - each mode has a preview pane: for buffers this is the buffer content (very useful), for others it is a preview of the pane; - items may be sorted in different ways ('O' key); - multiple items may be tagged and an operation applied to all of them (for example, to delete multiple buffers at once); - in tree mode a command may be run on the selected item (session, window, pane) or on tagged items (key ':'); - displayed items may be filtered in tree mode by using a format (this is used to implement find-window) (key 'f'); - the custom format (-F) for the display is no longer available; - shortcut keys change from 0-9, a-z, A-Z which was always a bit weird with keys used for other uses to 0-9, M-a to M-z. Now that the code is simpler, other improvements will come later. Primary key bindings for each mode are documented under the commands in the man page (choose-buffer, choose-client, choose-tree). Parts written by Thomas Adam.
Diffstat (limited to 'cmd-choose-tree.c')
-rw-r--r--cmd-choose-tree.c219
1 files changed, 27 insertions, 192 deletions
diff --git a/cmd-choose-tree.c b/cmd-choose-tree.c
index 28b5013a..f8f24f12 100644
--- a/cmd-choose-tree.c
+++ b/cmd-choose-tree.c
@@ -18,66 +18,48 @@
#include <sys/types.h>
-#include <ctype.h>
-#include <stdlib.h>
-
-#include <string.h>
-
#include "tmux.h"
-#define CMD_CHOOSE_TREE_WINDOW_ACTION "select-window -t '%%'"
-#define CMD_CHOOSE_TREE_SESSION_ACTION "switch-client -t '%%'"
-
/*
- * Enter choice mode to choose a session and/or window.
+ * Enter a mode.
*/
-#define CHOOSE_TREE_SESSION_TEMPLATE \
- "#{session_name}: #{session_windows} windows" \
- "#{?session_grouped, (group ,}" \
- "#{session_group}#{?session_grouped,),}" \
- "#{?session_attached, (attached),}"
-#define CHOOSE_TREE_WINDOW_TEMPLATE \
- "#{window_index}: #{window_name}#{window_flags} " \
- "\"#{pane_title}\""
-
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 = { "S:W:swub:c:t:", 0, 1 },
- .usage = "[-suw] [-b session-template] [-c window template] "
- "[-S format] [-W format] " CMD_TARGET_WINDOW_USAGE,
+ .args = { "st:w", 0, 1 },
+ .usage = "[-sw] " CMD_TARGET_PANE_USAGE,
- .target = { 't', CMD_FIND_WINDOW, 0 },
+ .target = { 't', CMD_FIND_PANE, 0 },
.flags = 0,
.exec = cmd_choose_tree_exec
};
-const struct cmd_entry cmd_choose_session_entry = {
- .name = "choose-session",
+const struct cmd_entry cmd_choose_client_entry = {
+ .name = "choose-client",
.alias = NULL,
- .args = { "F:t:", 0, 1 },
- .usage = CMD_TARGET_WINDOW_USAGE " [-F format] [template]",
+ .args = { "t:", 0, 1 },
+ .usage = CMD_TARGET_PANE_USAGE,
- .target = { 't', CMD_FIND_WINDOW, 0 },
+ .target = { 't', CMD_FIND_PANE, 0 },
.flags = 0,
.exec = cmd_choose_tree_exec
};
-const struct cmd_entry cmd_choose_window_entry = {
- .name = "choose-window",
+const struct cmd_entry cmd_choose_buffer_entry = {
+ .name = "choose-buffer",
.alias = NULL,
- .args = { "F:t:", 0, 1 },
- .usage = CMD_TARGET_WINDOW_USAGE "[-F format] [template]",
+ .args = { "t:", 0, 1 },
+ .usage = CMD_TARGET_PANE_USAGE,
- .target = { 't', CMD_FIND_WINDOW, 0 },
+ .target = { 't', CMD_FIND_PANE, 0 },
.flags = 0,
.exec = cmd_choose_tree_exec
@@ -87,167 +69,20 @@ static enum cmd_retval
cmd_choose_tree_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
- struct client *c = cmd_find_client(item, NULL, 1);
- struct winlink *wl = item->target.wl, *wm;
- struct session *s = item->target.s, *s2;
- struct window_choose_data *wcd = NULL;
- const char *ses_template, *win_template;
- char *final_win_action, *cur_win_template;
- char *final_win_template_middle;
- char *final_win_template_last;
- const char *ses_action, *win_action;
- u_int cur_win, idx_ses, win_ses, win_max;
- u_int wflag, sflag;
-
- ses_template = win_template = NULL;
- ses_action = win_action = NULL;
-
- if (c == NULL) {
- cmdq_error(item, "no client available");
- return (CMD_RETURN_ERROR);
- }
-
- if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0)
- return (CMD_RETURN_NORMAL);
-
- /* 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 = CHOOSE_TREE_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 = 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 = CHOOSE_TREE_SESSION_TEMPLATE;
-
- if ((win_template = args_get(args, 'W')) == NULL)
- win_template = 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_middle,
- " \001tq\001> %s", win_template);
- xasprintf(&final_win_template_last,
- " \001mq\001> %s", win_template);
- } else if (wflag) {
- final_win_template_middle = xstrdup(win_template);
- final_win_template_last = xstrdup(win_template);
+ struct window_pane *wp = item->target.wp;
+ const struct window_mode *mode;
+
+ if (self->entry == &cmd_choose_buffer_entry) {
+ if (paste_get_top(NULL) == NULL)
+ return (CMD_RETURN_NORMAL);
+ mode = &window_buffer_mode;
+ } else if (self->entry == &cmd_choose_client_entry) {
+ if (server_client_how_many() == 0)
+ return (CMD_RETURN_NORMAL);
+ mode = &window_client_mode;
} else
- final_win_template_middle = final_win_template_last = 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,
- c, s2, ses_template, 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 = win_max = -1;
- RB_FOREACH(wm, winlinks, &s2->windows)
- win_max++;
- 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 %s",
- wcd != NULL ? wcd->command : "",
- wcd != NULL ? ";" : "", win_action);
-
- if (win_ses != win_max)
- cur_win_template = final_win_template_middle;
- else
- cur_win_template = final_win_template_last;
-
- window_choose_add_window(wl->window->active,
- c, s2, wm, cur_win_template,
- final_win_action,
- (wflag && !sflag) ? win_ses : idx_ses);
-
- free(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;
- }
- free(final_win_template_middle);
- free(final_win_template_last);
-
- window_choose_ready(wl->window->active, cur_win, NULL);
-
- if (args_has(args, 'u')) {
- window_choose_expand_all(wl->window->active);
- window_choose_set_current(wl->window->active, cur_win);
- }
+ mode = &window_tree_mode;
+ window_pane_set_mode(wp, mode, &item->target, args);
return (CMD_RETURN_NORMAL);
}