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