Annotation of src/usr.bin/tmux/cmd-find-window.c, Revision 1.13
1.13 ! nicm 1: /* $OpenBSD: cmd-find-window.c,v 1.12 2012/04/01 20:53:47 nicm Exp $ */
1.1 nicm 2:
3: /*
4: * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
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:
1.2 nicm 21: #include <fnmatch.h>
1.1 nicm 22: #include <string.h>
23:
24: #include "tmux.h"
25:
26: /*
27: * Find window containing text.
28: */
29:
30: int cmd_find_window_exec(struct cmd *, struct cmd_ctx *);
31:
1.9 nicm 32: u_int cmd_find_window_match_flags(struct args *);
1.1 nicm 33: void cmd_find_window_callback(void *, int);
1.7 nicm 34: void cmd_find_window_free(void *);
1.1 nicm 35:
1.9 nicm 36: /* Flags for determining matching behavior. */
37: #define CMD_FIND_WINDOW_BY_TITLE 0x1
38: #define CMD_FIND_WINDOW_BY_CONTENT 0x2
39: #define CMD_FIND_WINDOW_BY_NAME 0x4
40:
41: #define CMD_FIND_WINDOW_ALL \
42: (CMD_FIND_WINDOW_BY_TITLE | \
43: CMD_FIND_WINDOW_BY_CONTENT | \
44: CMD_FIND_WINDOW_BY_NAME)
45:
46:
1.1 nicm 47: const struct cmd_entry cmd_find_window_entry = {
48: "find-window", "findw",
1.13 ! nicm 49: "F:CNt:T", 1, 4,
! 50: "[-CNT] [-F format] " CMD_TARGET_WINDOW_USAGE " match-string",
1.8 nicm 51: 0,
52: NULL,
53: NULL,
54: cmd_find_window_exec
1.1 nicm 55: };
56:
57: struct cmd_find_window_data {
1.7 nicm 58: struct session *session;
1.1 nicm 59: };
60:
1.9 nicm 61: u_int
62: cmd_find_window_match_flags(struct args *args)
63: {
64: u_int match_flags = 0;
65:
66: /* Turn on flags based on the options. */
67: if (args_has(args, 'T'))
68: match_flags |= CMD_FIND_WINDOW_BY_TITLE;
69: if (args_has(args, 'C'))
70: match_flags |= CMD_FIND_WINDOW_BY_CONTENT;
71: if (args_has(args, 'N'))
72: match_flags |= CMD_FIND_WINDOW_BY_NAME;
73:
74: /* If none of the flags were set, default to matching anything. */
75: if (match_flags == 0)
76: match_flags = CMD_FIND_WINDOW_ALL;
77:
1.12 nicm 78: return (match_flags);
1.9 nicm 79: }
80:
1.1 nicm 81: int
82: cmd_find_window_exec(struct cmd *self, struct cmd_ctx *ctx)
83: {
1.8 nicm 84: struct args *args = self->args;
1.1 nicm 85: struct cmd_find_window_data *cdata;
86: struct session *s;
87: struct winlink *wl, *wm;
88: struct window_pane *wp;
1.13 ! nicm 89: struct format_tree *ft;
1.1 nicm 90: ARRAY_DECL(, u_int) list_idx;
91: ARRAY_DECL(, char *) list_ctx;
1.8 nicm 92: char *str, *sres, *sctx, *searchstr;
1.13 ! nicm 93: char *find_line;
! 94: const char *template;
1.9 nicm 95: u_int i, line, match_flags;
1.1 nicm 96:
97: if (ctx->curclient == NULL) {
98: ctx->error(ctx, "must be run interactively");
99: return (-1);
100: }
101: s = ctx->curclient->session;
102:
1.8 nicm 103: if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL)
1.1 nicm 104: return (-1);
105:
1.13 ! nicm 106: if ((template = args_get(args, 'F')) == NULL)
! 107: template = DEFAULT_FIND_WINDOW_TEMPLATE;
! 108:
1.9 nicm 109: match_flags = cmd_find_window_match_flags(args);
1.8 nicm 110: str = args->argv[0];
111:
1.1 nicm 112: ARRAY_INIT(&list_idx);
113: ARRAY_INIT(&list_ctx);
114:
1.8 nicm 115: xasprintf(&searchstr, "*%s*", str);
1.1 nicm 116: RB_FOREACH(wm, winlinks, &s->windows) {
117: i = 0;
118: TAILQ_FOREACH(wp, &wm->window->panes, entry) {
119: i++;
120:
1.9 nicm 121: if ((match_flags & CMD_FIND_WINDOW_BY_NAME) &&
122: fnmatch(searchstr, wm->window->name, 0) == 0)
1.1 nicm 123: sctx = xstrdup("");
124: else {
1.9 nicm 125: sres = NULL;
126: if (match_flags & CMD_FIND_WINDOW_BY_CONTENT) {
127: sres = window_pane_search(
128: wp, str, &line);
129: }
130:
1.1 nicm 131: if (sres == NULL &&
1.9 nicm 132: (!(match_flags & CMD_FIND_WINDOW_BY_TITLE) ||
133: fnmatch(searchstr, wp->base.title, 0) != 0))
1.1 nicm 134: continue;
135:
136: if (sres == NULL) {
137: xasprintf(&sctx,
138: "pane %u title: \"%s\"", i - 1,
139: wp->base.title);
140: } else {
1.2 nicm 141: xasprintf(&sctx,
142: "pane %u line %u: \"%s\"", i - 1,
143: line + 1, sres);
1.1 nicm 144: xfree(sres);
145: }
146: }
147:
148: ARRAY_ADD(&list_idx, wm->idx);
149: ARRAY_ADD(&list_ctx, sctx);
1.11 nicm 150: break;
1.1 nicm 151: }
152: }
1.2 nicm 153: xfree(searchstr);
1.1 nicm 154:
155: if (ARRAY_LENGTH(&list_idx) == 0) {
1.8 nicm 156: ctx->error(ctx, "no windows matching: %s", str);
1.1 nicm 157: ARRAY_FREE(&list_idx);
158: ARRAY_FREE(&list_ctx);
159: return (-1);
160: }
161:
162: if (ARRAY_LENGTH(&list_idx) == 1) {
163: if (session_select(s, ARRAY_FIRST(&list_idx)) == 0)
164: server_redraw_session(s);
165: recalculate_sizes();
166: goto out;
167: }
168:
169: if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0)
170: goto out;
171:
172: for (i = 0; i < ARRAY_LENGTH(&list_idx); i++) {
173: wm = winlink_find_by_index(
174: &s->windows, ARRAY_ITEM(&list_idx, i));
175:
1.13 ! nicm 176: ft = format_create();
! 177: format_add(ft, "line", "%u", i);
! 178: format_add(ft, "window_find_matches", "%s",
! 179: ARRAY_ITEM(&list_ctx, i));
! 180: format_session(ft, s);
! 181: format_winlink(ft, s, wm);
! 182:
! 183: find_line = format_expand(ft, template);
! 184:
! 185: window_choose_add(wl->window->active, wm->idx, "%s", find_line);
! 186:
! 187: xfree(find_line);
! 188: format_free(ft);
1.1 nicm 189: }
190:
191: cdata = xmalloc(sizeof *cdata);
1.7 nicm 192: cdata->session = s;
193: cdata->session->references++;
1.1 nicm 194:
1.7 nicm 195: window_choose_ready(wl->window->active,
196: 0, cmd_find_window_callback, cmd_find_window_free, cdata);
1.1 nicm 197:
198: out:
199: ARRAY_FREE(&list_idx);
200: ARRAY_FREE(&list_ctx);
201:
202: return (0);
203: }
204:
205: void
206: cmd_find_window_callback(void *data, int idx)
207: {
208: struct cmd_find_window_data *cdata = data;
1.7 nicm 209: struct session *s = cdata->session;
210:
211: if (idx == -1)
212: return;
213: if (!session_alive(s))
214: return;
1.1 nicm 215:
1.7 nicm 216: if (session_select(s, idx) == 0) {
217: server_redraw_session(s);
1.1 nicm 218: recalculate_sizes();
219: }
1.7 nicm 220: }
221:
222: void
223: cmd_find_window_free(void *data)
224: {
225: struct cmd_find_window_data *cdata = data;
226:
227: cdata->session->references--;
228: xfree(cdata);
1.1 nicm 229: }