Add window-status-separator option, from Thomas Adam.
[tmux-openbsd.git] / cmd-find-window.c
blob3ac3c68b4b1c1c2252406313a60757191e0d0428
1 /* $OpenBSD$ */
3 /*
4 * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
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.
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.
19 #include <sys/types.h>
21 #include <fnmatch.h>
22 #include <string.h>
24 #include "tmux.h"
27 * Find window containing text.
30 int cmd_find_window_exec(struct cmd *, struct cmd_ctx *);
32 u_int cmd_find_window_match_flags(struct args *);
33 void cmd_find_window_callback(void *, int);
34 void cmd_find_window_free(void *);
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
41 #define CMD_FIND_WINDOW_ALL \
42 (CMD_FIND_WINDOW_BY_TITLE | \
43 CMD_FIND_WINDOW_BY_CONTENT | \
44 CMD_FIND_WINDOW_BY_NAME)
47 const struct cmd_entry cmd_find_window_entry = {
48 "find-window", "findw",
49 "CNt:T", 1, 4,
50 "[-CNT] " CMD_TARGET_WINDOW_USAGE " match-string",
52 NULL,
53 NULL,
54 cmd_find_window_exec
57 struct cmd_find_window_data {
58 struct session *session;
61 u_int
62 cmd_find_window_match_flags(struct args *args)
64 u_int match_flags = 0;
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;
74 /* If none of the flags were set, default to matching anything. */
75 if (match_flags == 0)
76 match_flags = CMD_FIND_WINDOW_ALL;
78 return (match_flags);
81 int
82 cmd_find_window_exec(struct cmd *self, struct cmd_ctx *ctx)
84 struct args *args = self->args;
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;
92 char *str, *sres, *sctx, *searchstr;
93 u_int i, line, match_flags;
95 if (ctx->curclient == NULL) {
96 ctx->error(ctx, "must be run interactively");
97 return (-1);
99 s = ctx->curclient->session;
101 if ((wl = cmd_find_window(ctx, args_get(args, 't'), NULL)) == NULL)
102 return (-1);
104 match_flags = cmd_find_window_match_flags(args);
105 str = args->argv[0];
107 ARRAY_INIT(&list_idx);
108 ARRAY_INIT(&list_ctx);
110 xasprintf(&searchstr, "*%s*", str);
111 RB_FOREACH(wm, winlinks, &s->windows) {
112 i = 0;
113 TAILQ_FOREACH(wp, &wm->window->panes, entry) {
114 i++;
116 if ((match_flags & CMD_FIND_WINDOW_BY_NAME) &&
117 fnmatch(searchstr, wm->window->name, 0) == 0)
118 sctx = xstrdup("");
119 else {
120 sres = NULL;
121 if (match_flags & CMD_FIND_WINDOW_BY_CONTENT) {
122 sres = window_pane_search(
123 wp, str, &line);
126 if (sres == NULL &&
127 (!(match_flags & CMD_FIND_WINDOW_BY_TITLE) ||
128 fnmatch(searchstr, wp->base.title, 0) != 0))
129 continue;
131 if (sres == NULL) {
132 xasprintf(&sctx,
133 "pane %u title: \"%s\"", i - 1,
134 wp->base.title);
135 } else {
136 xasprintf(&sctx,
137 "pane %u line %u: \"%s\"", i - 1,
138 line + 1, sres);
139 xfree(sres);
143 ARRAY_ADD(&list_idx, wm->idx);
144 ARRAY_ADD(&list_ctx, sctx);
145 break;
148 xfree(searchstr);
150 if (ARRAY_LENGTH(&list_idx) == 0) {
151 ctx->error(ctx, "no windows matching: %s", str);
152 ARRAY_FREE(&list_idx);
153 ARRAY_FREE(&list_ctx);
154 return (-1);
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;
164 if (window_pane_set_mode(wl->window->active, &window_choose_mode) != 0)
165 goto out;
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;
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);
179 cdata = xmalloc(sizeof *cdata);
180 cdata->session = s;
181 cdata->session->references++;
183 window_choose_ready(wl->window->active,
184 0, cmd_find_window_callback, cmd_find_window_free, cdata);
186 out:
187 ARRAY_FREE(&list_idx);
188 ARRAY_FREE(&list_ctx);
190 return (0);
193 void
194 cmd_find_window_callback(void *data, int idx)
196 struct cmd_find_window_data *cdata = data;
197 struct session *s = cdata->session;
199 if (idx == -1)
200 return;
201 if (!session_alive(s))
202 return;
204 if (session_select(s, idx) == 0) {
205 server_redraw_session(s);
206 recalculate_sizes();
210 void
211 cmd_find_window_free(void *data)
213 struct cmd_find_window_data *cdata = data;
215 cdata->session->references--;
216 xfree(cdata);