Annotation of src/usr.bin/tmux/cmd-choose-tree.c, Revision 1.1
1.1 ! nicm 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:
! 23: #include <string.h>
! 24:
! 25: #include "tmux.h"
! 26:
! 27: #define CMD_CHOOSE_TREE_WINDOW_ACTION "select-window -t '%%'"
! 28: #define CMD_CHOOSE_TREE_SESSION_ACTION "switch-client -t '%%'"
! 29: #define CMD_CHOOSE_TREE_WINDOW_TEMPLATE \
! 30: DEFAULT_WINDOW_TEMPLATE " \"#{pane_title}\""
! 31:
! 32: /*
! 33: * Enter choice mode to choose a session and/or window.
! 34: */
! 35:
! 36: int cmd_choose_tree_exec(struct cmd *, struct cmd_ctx *);
! 37:
! 38: void cmd_choose_tree_callback(struct window_choose_data *);
! 39: void cmd_choose_tree_free(struct window_choose_data *);
! 40:
! 41: const struct cmd_entry cmd_choose_tree_entry = {
! 42: "choose-tree", NULL,
! 43: "S:W:swb:c:t:", 0, 1,
! 44: "[-SW] [-s format] [-w format ] [-b session template] " \
! 45: "[-c window template] " CMD_TARGET_WINDOW_USAGE,
! 46: 0,
! 47: NULL,
! 48: NULL,
! 49: cmd_choose_tree_exec
! 50: };
! 51:
! 52: const struct cmd_entry cmd_choose_session_entry = {
! 53: "choose-session", NULL,
! 54: "F:t:", 0, 1,
! 55: CMD_TARGET_WINDOW_USAGE " [-F format] [template]",
! 56: 0,
! 57: NULL,
! 58: NULL,
! 59: cmd_choose_tree_exec
! 60: };
! 61:
! 62: const struct cmd_entry cmd_choose_window_entry = {
! 63: "choose-window", NULL,
! 64: "F:t:", 0, 1,
! 65: CMD_TARGET_WINDOW_USAGE "[-F format] [template]",
! 66: 0,
! 67: NULL,
! 68: NULL,
! 69: cmd_choose_tree_exec
! 70: };
! 71:
! 72: int
! 73: cmd_choose_tree_exec(struct cmd *self, struct cmd_ctx *ctx)
! 74: {
! 75: struct args *args = self->args;
! 76: struct winlink *wl, *wm;
! 77: struct session *s, *s2;
! 78: struct tty *tty;
! 79: struct window_choose_data *wcd = NULL;
! 80: const char *ses_template, *win_template;
! 81: char *final_win_action, *final_win_template;
! 82: const char *ses_action, *win_action;
! 83: u_int cur_win, idx_ses, win_ses;
! 84: u_int wflag, sflag;
! 85:
! 86: ses_template = win_template = NULL;
! 87: ses_action = win_action = NULL;
! 88:
! 89: if (ctx->curclient == NULL) {
! 90: ctx->error(ctx, "must be run interactively");
! 91: return (-1);
! 92: }
! 93:
! 94: s = ctx->curclient->session;
! 95: tty = &ctx->curclient->tty;
! 96:
! 97: if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL)
! 98: return (-1);
! 99:
! 100: if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0)
! 101: return (0);
! 102:
! 103: /* Sort out which command this is. */
! 104: wflag = sflag = 0;
! 105: if (self->entry == &cmd_choose_session_entry) {
! 106: sflag = 1;
! 107: if ((ses_template = args_get(args, 'F')) == NULL)
! 108: ses_template = DEFAULT_SESSION_TEMPLATE;
! 109:
! 110: if (args->argc != 0)
! 111: ses_action = args->argv[0];
! 112: else
! 113: ses_action = CMD_CHOOSE_TREE_SESSION_ACTION;
! 114: } else if (self->entry == &cmd_choose_window_entry) {
! 115: wflag = 1;
! 116: if ((win_template = args_get(args, 'F')) == NULL)
! 117: win_template = CMD_CHOOSE_TREE_WINDOW_TEMPLATE;
! 118:
! 119: if (args->argc != 0)
! 120: win_action = args->argv[0];
! 121: else
! 122: win_action = CMD_CHOOSE_TREE_WINDOW_ACTION;
! 123: } else {
! 124: wflag = args_has(args, 'w');
! 125: sflag = args_has(args, 's');
! 126:
! 127: if ((ses_action = args_get(args, 'b')) == NULL)
! 128: ses_action = CMD_CHOOSE_TREE_SESSION_ACTION;
! 129:
! 130: if ((win_action = args_get(args, 'c')) == NULL)
! 131: win_action = CMD_CHOOSE_TREE_WINDOW_ACTION;
! 132:
! 133: if ((ses_template = args_get(args, 'S')) == NULL)
! 134: ses_template = DEFAULT_SESSION_TEMPLATE;
! 135:
! 136: if ((win_template = args_get(args, 'W')) == NULL)
! 137: win_template = CMD_CHOOSE_TREE_WINDOW_TEMPLATE;
! 138: }
! 139:
! 140: /*
! 141: * If not asking for windows and sessions, assume no "-ws" given and
! 142: * hence display the entire tree outright.
! 143: */
! 144: if (!wflag && !sflag)
! 145: wflag = sflag = 1;
! 146:
! 147: /*
! 148: * If we're drawing in tree mode, including sessions, then pad the
! 149: * window template, otherwise just render the windows as a flat list
! 150: * without any padding.
! 151: */
! 152: if (wflag && sflag)
! 153: xasprintf(&final_win_template, " --> %s", win_template);
! 154: else if (wflag)
! 155: final_win_template = xstrdup(win_template);
! 156: else
! 157: final_win_template = NULL;
! 158:
! 159: idx_ses = cur_win = -1;
! 160: RB_FOREACH(s2, sessions, &sessions) {
! 161: idx_ses++;
! 162:
! 163: /*
! 164: * If we're just choosing windows, jump straight there. Note
! 165: * that this implies the current session, so only choose
! 166: * windows when the session matches this one.
! 167: */
! 168: if (wflag && !sflag) {
! 169: if (s != s2)
! 170: continue;
! 171: goto windows_only;
! 172: }
! 173:
! 174: wcd = window_choose_add_session(wl->window->active,
! 175: ctx, s2, ses_template, (char *)ses_action, idx_ses);
! 176:
! 177: /* If we're just choosing sessions, skip choosing windows. */
! 178: if (sflag && !wflag) {
! 179: if (s == s2)
! 180: cur_win = idx_ses;
! 181: continue;
! 182: }
! 183: windows_only:
! 184: win_ses = -1;
! 185: RB_FOREACH(wm, winlinks, &s2->windows) {
! 186: win_ses++;
! 187: if (sflag && wflag)
! 188: idx_ses++;
! 189:
! 190: if (wm == s2->curw && s == s2) {
! 191: if (wflag && !sflag) {
! 192: /*
! 193: * Then we're only counting windows.
! 194: * So remember which is the current
! 195: * window in the list.
! 196: */
! 197: cur_win = win_ses;
! 198: } else
! 199: cur_win = idx_ses;
! 200: }
! 201:
! 202: xasprintf(&final_win_action, "%s ; %s", win_action,
! 203: wcd ? wcd->command : "");
! 204:
! 205: window_choose_add_window(wl->window->active,
! 206: ctx, s2, wm, final_win_template,
! 207: final_win_action, idx_ses);
! 208:
! 209: xfree(final_win_action);
! 210: }
! 211: /*
! 212: * If we're just drawing windows, don't consider moving on to
! 213: * other sessions as we only list windows in this session.
! 214: */
! 215: if (wflag && !sflag)
! 216: break;
! 217: }
! 218: if (final_win_template != NULL)
! 219: xfree(final_win_template);
! 220:
! 221: window_choose_ready(wl->window->active, cur_win,
! 222: cmd_choose_tree_callback, cmd_choose_tree_free);
! 223:
! 224: return (0);
! 225: }
! 226:
! 227: void
! 228: cmd_choose_tree_callback(struct window_choose_data *cdata)
! 229: {
! 230: if (cdata == NULL)
! 231: return;
! 232:
! 233: if (cdata->client->flags & CLIENT_DEAD)
! 234: return;
! 235:
! 236: window_choose_ctx(cdata);
! 237: }
! 238:
! 239: void
! 240: cmd_choose_tree_free(struct window_choose_data *cdata)
! 241: {
! 242: cdata->session->references--;
! 243: cdata->client->references--;
! 244:
! 245: xfree(cdata->ft_template);
! 246: xfree(cdata->command);
! 247: format_free(cdata->ft);
! 248: xfree(cdata);
! 249:
! 250: }
! 251: