Annotation of src/usr.bin/tmux/cmd-find-window.c, Revision 1.11
1.11 ! nicm 1: /* $OpenBSD: cmd-find-window.c,v 1.10 2012/03/20 23:20:08 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.9 nicm 49: "CNt:T", 1, 4,
50: "[-CNT] " 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:
78: return match_flags;
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 *w;
89: struct window_pane *wp;
90: ARRAY_DECL(, u_int) list_idx;
91: ARRAY_DECL(, char *) list_ctx;
1.8 nicm 92: char *str, *sres, *sctx, *searchstr;
1.9 nicm 93: u_int i, line, match_flags;
1.1 nicm 94:
95: if (ctx->curclient == NULL) {
96: ctx->error(ctx, "must be run interactively");
97: return (-1);
98: }
99: s = ctx->curclient->session;
100:
1.8 nicm 101: if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL)
1.1 nicm 102: return (-1);
103:
1.9 nicm 104: match_flags = cmd_find_window_match_flags(args);
1.8 nicm 105: str = args->argv[0];
106:
1.1 nicm 107: ARRAY_INIT(&list_idx);
108: ARRAY_INIT(&list_ctx);
109:
1.8 nicm 110: xasprintf(&searchstr, "*%s*", str);
1.1 nicm 111: RB_FOREACH(wm, winlinks, &s->windows) {
112: i = 0;
113: TAILQ_FOREACH(wp, &wm->window->panes, entry) {
114: i++;
115:
1.9 nicm 116: if ((match_flags & CMD_FIND_WINDOW_BY_NAME) &&
117: fnmatch(searchstr, wm->window->name, 0) == 0)
1.1 nicm 118: sctx = xstrdup("");
119: else {
1.9 nicm 120: sres = NULL;
121: if (match_flags & CMD_FIND_WINDOW_BY_CONTENT) {
122: sres = window_pane_search(
123: wp, str, &line);
124: }
125:
1.1 nicm 126: if (sres == NULL &&
1.9 nicm 127: (!(match_flags & CMD_FIND_WINDOW_BY_TITLE) ||
128: fnmatch(searchstr, wp->base.title, 0) != 0))
1.1 nicm 129: continue;
130:
131: if (sres == NULL) {
132: xasprintf(&sctx,
133: "pane %u title: \"%s\"", i - 1,
134: wp->base.title);
135: } else {
1.2 nicm 136: xasprintf(&sctx,
137: "pane %u line %u: \"%s\"", i - 1,
138: line + 1, sres);
1.1 nicm 139: xfree(sres);
140: }
141: }
142:
143: ARRAY_ADD(&list_idx, wm->idx);
144: ARRAY_ADD(&list_ctx, sctx);
1.11 ! nicm 145: break;
1.1 nicm 146: }
147: }
1.2 nicm 148: xfree(searchstr);
1.1 nicm 149:
150: if (ARRAY_LENGTH(&list_idx) == 0) {
1.8 nicm 151: ctx->error(ctx, "no windows matching: %s", str);
1.1 nicm 152: ARRAY_FREE(&list_idx);
153: ARRAY_FREE(&list_ctx);
154: return (-1);
155: }
156:
157: if (ARRAY_LENGTH(&list_idx) == 1) {
158: if (session_select(s, ARRAY_FIRST(&list_idx)) == 0)
159: server_redraw_session(s);
160: recalculate_sizes();
161: goto out;
162: }
163:
164: if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0)
165: goto out;
166:
167: for (i = 0; i < ARRAY_LENGTH(&list_idx); i++) {
168: wm = winlink_find_by_index(
169: &s->windows, ARRAY_ITEM(&list_idx, i));
170: w = wm->window;
171:
172: sctx = ARRAY_ITEM(&list_ctx, i);
173: window_choose_add(wl->window->active,
174: wm->idx, "%3d: %s [%ux%u] (%u panes) %s", wm->idx, w->name,
175: w->sx, w->sy, window_count_panes(w), sctx);
176: xfree(sctx);
177: }
178:
179: cdata = xmalloc(sizeof *cdata);
1.7 nicm 180: cdata->session = s;
181: cdata->session->references++;
1.1 nicm 182:
1.7 nicm 183: window_choose_ready(wl->window->active,
184: 0, cmd_find_window_callback, cmd_find_window_free, cdata);
1.1 nicm 185:
186: out:
187: ARRAY_FREE(&list_idx);
188: ARRAY_FREE(&list_ctx);
189:
190: return (0);
191: }
192:
193: void
194: cmd_find_window_callback(void *data, int idx)
195: {
196: struct cmd_find_window_data *cdata = data;
1.7 nicm 197: struct session *s = cdata->session;
198:
199: if (idx == -1)
200: return;
201: if (!session_alive(s))
202: return;
1.1 nicm 203:
1.7 nicm 204: if (session_select(s, idx) == 0) {
205: server_redraw_session(s);
1.1 nicm 206: recalculate_sizes();
207: }
1.7 nicm 208: }
209:
210: void
211: cmd_find_window_free(void *data)
212: {
213: struct cmd_find_window_data *cdata = data;
214:
215: cdata->session->references--;
216: xfree(cdata);
1.1 nicm 217: }