Annotation of embedaddon/tmux/cmd-choose-tree.c, revision 1.1
1.1 ! misho 1: /* $OpenBSD$ */
! 2:
! 3: /*
! 4: * Copyright (c) 2012 Thomas Adam <thomas@xteddy.org>
! 5: *
! 6: * Permission to use, copy, modify, and distribute this software for any
! 7: * purpose with or without fee is hereby granted, provided that the above
! 8: * copyright notice and this permission notice appear in all copies.
! 9: *
! 10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
! 11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
! 12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
! 13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
! 14: * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
! 15: * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
! 16: * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
! 17: */
! 18:
! 19: #include <sys/types.h>
! 20:
! 21: #include <ctype.h>
! 22: #include <stdlib.h>
! 23:
! 24: #include <string.h>
! 25:
! 26: #include "tmux.h"
! 27:
! 28: #define CMD_CHOOSE_TREE_WINDOW_ACTION "select-window -t '%%'"
! 29: #define CMD_CHOOSE_TREE_SESSION_ACTION "switch-client -t '%%'"
! 30:
! 31: /*
! 32: * Enter choice mode to choose a session and/or window.
! 33: */
! 34:
! 35: #define CHOOSE_TREE_SESSION_TEMPLATE \
! 36: "#{session_name}: #{session_windows} windows" \
! 37: "#{?session_grouped, (group ,}" \
! 38: "#{session_group}#{?session_grouped,),}" \
! 39: "#{?session_attached, (attached),}"
! 40: #define CHOOSE_TREE_WINDOW_TEMPLATE \
! 41: "#{window_index}: #{window_name}#{window_flags} " \
! 42: "\"#{pane_title}\""
! 43:
! 44: static enum cmd_retval cmd_choose_tree_exec(struct cmd *, struct cmdq_item *);
! 45:
! 46: const struct cmd_entry cmd_choose_tree_entry = {
! 47: .name = "choose-tree",
! 48: .alias = NULL,
! 49:
! 50: .args = { "S:W:swub:c:t:", 0, 1 },
! 51: .usage = "[-suw] [-b session-template] [-c window template] "
! 52: "[-S format] [-W format] " CMD_TARGET_WINDOW_USAGE,
! 53:
! 54: .tflag = CMD_WINDOW,
! 55:
! 56: .flags = 0,
! 57: .exec = cmd_choose_tree_exec
! 58: };
! 59:
! 60: const struct cmd_entry cmd_choose_session_entry = {
! 61: .name = "choose-session",
! 62: .alias = NULL,
! 63:
! 64: .args = { "F:t:", 0, 1 },
! 65: .usage = CMD_TARGET_WINDOW_USAGE " [-F format] [template]",
! 66:
! 67: .tflag = CMD_WINDOW,
! 68:
! 69: .flags = 0,
! 70: .exec = cmd_choose_tree_exec
! 71: };
! 72:
! 73: const struct cmd_entry cmd_choose_window_entry = {
! 74: .name = "choose-window",
! 75: .alias = NULL,
! 76:
! 77: .args = { "F:t:", 0, 1 },
! 78: .usage = CMD_TARGET_WINDOW_USAGE "[-F format] [template]",
! 79:
! 80: .tflag = CMD_WINDOW,
! 81:
! 82: .flags = 0,
! 83: .exec = cmd_choose_tree_exec
! 84: };
! 85:
! 86: static enum cmd_retval
! 87: cmd_choose_tree_exec(struct cmd *self, struct cmdq_item *item)
! 88: {
! 89: struct args *args = self->args;
! 90: struct client *c = item->state.c;
! 91: struct winlink *wl = item->state.tflag.wl, *wm;
! 92: struct session *s = item->state.tflag.s, *s2;
! 93: struct window_choose_data *wcd = NULL;
! 94: const char *ses_template, *win_template;
! 95: char *final_win_action, *cur_win_template;
! 96: char *final_win_template_middle;
! 97: char *final_win_template_last;
! 98: const char *ses_action, *win_action;
! 99: u_int cur_win, idx_ses, win_ses, win_max;
! 100: u_int wflag, sflag;
! 101:
! 102: ses_template = win_template = NULL;
! 103: ses_action = win_action = NULL;
! 104:
! 105: if (c == NULL) {
! 106: cmdq_error(item, "no client available");
! 107: return (CMD_RETURN_ERROR);
! 108: }
! 109:
! 110: if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0)
! 111: return (CMD_RETURN_NORMAL);
! 112:
! 113: /* Sort out which command this is. */
! 114: wflag = sflag = 0;
! 115: if (self->entry == &cmd_choose_session_entry) {
! 116: sflag = 1;
! 117: if ((ses_template = args_get(args, 'F')) == NULL)
! 118: ses_template = CHOOSE_TREE_SESSION_TEMPLATE;
! 119:
! 120: if (args->argc != 0)
! 121: ses_action = args->argv[0];
! 122: else
! 123: ses_action = CMD_CHOOSE_TREE_SESSION_ACTION;
! 124: } else if (self->entry == &cmd_choose_window_entry) {
! 125: wflag = 1;
! 126: if ((win_template = args_get(args, 'F')) == NULL)
! 127: win_template = CHOOSE_TREE_WINDOW_TEMPLATE;
! 128:
! 129: if (args->argc != 0)
! 130: win_action = args->argv[0];
! 131: else
! 132: win_action = CMD_CHOOSE_TREE_WINDOW_ACTION;
! 133: } else {
! 134: wflag = args_has(args, 'w');
! 135: sflag = args_has(args, 's');
! 136:
! 137: if ((ses_action = args_get(args, 'b')) == NULL)
! 138: ses_action = CMD_CHOOSE_TREE_SESSION_ACTION;
! 139:
! 140: if ((win_action = args_get(args, 'c')) == NULL)
! 141: win_action = CMD_CHOOSE_TREE_WINDOW_ACTION;
! 142:
! 143: if ((ses_template = args_get(args, 'S')) == NULL)
! 144: ses_template = CHOOSE_TREE_SESSION_TEMPLATE;
! 145:
! 146: if ((win_template = args_get(args, 'W')) == NULL)
! 147: win_template = CHOOSE_TREE_WINDOW_TEMPLATE;
! 148: }
! 149:
! 150: /*
! 151: * If not asking for windows and sessions, assume no "-ws" given and
! 152: * hence display the entire tree outright.
! 153: */
! 154: if (!wflag && !sflag)
! 155: wflag = sflag = 1;
! 156:
! 157: /*
! 158: * If we're drawing in tree mode, including sessions, then pad the
! 159: * window template, otherwise just render the windows as a flat list
! 160: * without any padding.
! 161: */
! 162: if (wflag && sflag) {
! 163: xasprintf(&final_win_template_middle,
! 164: " \001tq\001> %s", win_template);
! 165: xasprintf(&final_win_template_last,
! 166: " \001mq\001> %s", win_template);
! 167: } else if (wflag) {
! 168: final_win_template_middle = xstrdup(win_template);
! 169: final_win_template_last = xstrdup(win_template);
! 170: } else
! 171: final_win_template_middle = final_win_template_last = NULL;
! 172:
! 173: idx_ses = cur_win = -1;
! 174: RB_FOREACH(s2, sessions, &sessions) {
! 175: idx_ses++;
! 176:
! 177: /*
! 178: * If we're just choosing windows, jump straight there. Note
! 179: * that this implies the current session, so only choose
! 180: * windows when the session matches this one.
! 181: */
! 182: if (wflag && !sflag) {
! 183: if (s != s2)
! 184: continue;
! 185: goto windows_only;
! 186: }
! 187:
! 188: wcd = window_choose_add_session(wl->window->active,
! 189: c, s2, ses_template, ses_action, idx_ses);
! 190:
! 191: /* If we're just choosing sessions, skip choosing windows. */
! 192: if (sflag && !wflag) {
! 193: if (s == s2)
! 194: cur_win = idx_ses;
! 195: continue;
! 196: }
! 197: windows_only:
! 198: win_ses = win_max = -1;
! 199: RB_FOREACH(wm, winlinks, &s2->windows)
! 200: win_max++;
! 201: RB_FOREACH(wm, winlinks, &s2->windows) {
! 202: win_ses++;
! 203: if (sflag && wflag)
! 204: idx_ses++;
! 205:
! 206: if (wm == s2->curw && s == s2) {
! 207: if (wflag && !sflag) {
! 208: /*
! 209: * Then we're only counting windows.
! 210: * So remember which is the current
! 211: * window in the list.
! 212: */
! 213: cur_win = win_ses;
! 214: } else
! 215: cur_win = idx_ses;
! 216: }
! 217:
! 218: xasprintf(&final_win_action, "%s %s %s",
! 219: wcd != NULL ? wcd->command : "",
! 220: wcd != NULL ? ";" : "", win_action);
! 221:
! 222: if (win_ses != win_max)
! 223: cur_win_template = final_win_template_middle;
! 224: else
! 225: cur_win_template = final_win_template_last;
! 226:
! 227: window_choose_add_window(wl->window->active,
! 228: c, s2, wm, cur_win_template,
! 229: final_win_action,
! 230: (wflag && !sflag) ? win_ses : idx_ses);
! 231:
! 232: free(final_win_action);
! 233: }
! 234:
! 235: /*
! 236: * If we're just drawing windows, don't consider moving on to
! 237: * other sessions as we only list windows in this session.
! 238: */
! 239: if (wflag && !sflag)
! 240: break;
! 241: }
! 242: free(final_win_template_middle);
! 243: free(final_win_template_last);
! 244:
! 245: window_choose_ready(wl->window->active, cur_win, NULL);
! 246:
! 247: if (args_has(args, 'u')) {
! 248: window_choose_expand_all(wl->window->active);
! 249: window_choose_set_current(wl->window->active, cur_win);
! 250: }
! 251:
! 252: return (CMD_RETURN_NORMAL);
! 253: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>