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>
28 * Find window containing text.
31 enum cmd_retval
cmd_find_window_exec(struct cmd
*, struct cmd_q
*);
33 void cmd_find_window_callback(struct window_choose_data
*);
35 /* Flags for determining matching behavior. */
36 #define CMD_FIND_WINDOW_BY_TITLE 0x1
37 #define CMD_FIND_WINDOW_BY_CONTENT 0x2
38 #define CMD_FIND_WINDOW_BY_NAME 0x4
40 #define CMD_FIND_WINDOW_ALL \
41 (CMD_FIND_WINDOW_BY_TITLE | \
42 CMD_FIND_WINDOW_BY_CONTENT | \
43 CMD_FIND_WINDOW_BY_NAME)
45 const struct cmd_entry cmd_find_window_entry
= {
46 "find-window", "findw",
48 "[-CNT] [-F format] " CMD_TARGET_WINDOW_USAGE
" match-string",
54 struct cmd_find_window_data
{
59 ARRAY_DECL(cmd_find_window_data_list
, struct cmd_find_window_data
);
61 u_int
cmd_find_window_match_flags(struct args
*);
62 void cmd_find_window_match(struct cmd_find_window_data_list
*, int,
63 struct winlink
*, const char *, const char *);
66 cmd_find_window_match_flags(struct args
*args
)
68 u_int match_flags
= 0;
70 /* Turn on flags based on the options. */
71 if (args_has(args
, 'T'))
72 match_flags
|= CMD_FIND_WINDOW_BY_TITLE
;
73 if (args_has(args
, 'C'))
74 match_flags
|= CMD_FIND_WINDOW_BY_CONTENT
;
75 if (args_has(args
, 'N'))
76 match_flags
|= CMD_FIND_WINDOW_BY_NAME
;
78 /* If none of the flags were set, default to matching anything. */
80 match_flags
= CMD_FIND_WINDOW_ALL
;
86 cmd_find_window_match(struct cmd_find_window_data_list
*find_list
,
87 int match_flags
, struct winlink
*wl
, const char *str
, const char *searchstr
)
89 struct cmd_find_window_data find_data
;
90 struct window_pane
*wp
;
94 memset(&find_data
, 0, sizeof find_data
);
97 TAILQ_FOREACH(wp
, &wl
->window
->panes
, entry
) {
100 if ((match_flags
& CMD_FIND_WINDOW_BY_NAME
) &&
101 fnmatch(searchstr
, wl
->window
->name
, 0) == 0) {
102 find_data
.list_ctx
= xstrdup("");
106 if ((match_flags
& CMD_FIND_WINDOW_BY_TITLE
) &&
107 fnmatch(searchstr
, wp
->base
.title
, 0) == 0) {
108 xasprintf(&find_data
.list_ctx
,
109 "pane %u title: \"%s\"", i
- 1, wp
->base
.title
);
113 if (match_flags
& CMD_FIND_WINDOW_BY_CONTENT
&&
114 (sres
= window_pane_search(wp
, str
, &line
)) != NULL
) {
115 xasprintf(&find_data
.list_ctx
,
116 "pane %u line %u: \"%s\"", i
- 1, line
+ 1, sres
);
121 if (find_data
.list_ctx
!= NULL
) {
123 find_data
.pane_id
= i
- 1;
124 ARRAY_ADD(find_list
, find_data
);
129 cmd_find_window_exec(struct cmd
*self
, struct cmd_q
*cmdq
)
131 struct args
*args
= self
->args
;
133 struct window_choose_data
*cdata
;
135 struct winlink
*wl
, *wm
;
136 struct cmd_find_window_data_list find_list
;
137 char *str
, *searchstr
;
138 const char *template;
139 u_int i
, match_flags
;
141 if ((c
= cmd_current_client(cmdq
)) == NULL
) {
142 cmdq_error(cmdq
, "no client available");
143 return (CMD_RETURN_ERROR
);
147 if ((wl
= cmd_find_window(cmdq
, args_get(args
, 't'), NULL
)) == NULL
)
148 return (CMD_RETURN_ERROR
);
150 if ((template = args_get(args
, 'F')) == NULL
)
151 template = FIND_WINDOW_TEMPLATE
;
153 match_flags
= cmd_find_window_match_flags(args
);
156 ARRAY_INIT(&find_list
);
158 xasprintf(&searchstr
, "*%s*", str
);
159 RB_FOREACH(wm
, winlinks
, &s
->windows
)
160 cmd_find_window_match (&find_list
, match_flags
, wm
, str
, searchstr
);
163 if (ARRAY_LENGTH(&find_list
) == 0) {
164 cmdq_error(cmdq
, "no windows matching: %s", str
);
165 ARRAY_FREE(&find_list
);
166 return (CMD_RETURN_ERROR
);
169 if (ARRAY_LENGTH(&find_list
) == 1) {
170 if (session_select(s
, ARRAY_FIRST(&find_list
).wl
->idx
) == 0)
171 server_redraw_session(s
);
176 if (window_pane_set_mode(wl
->window
->active
, &window_choose_mode
) != 0)
179 for (i
= 0; i
< ARRAY_LENGTH(&find_list
); i
++) {
180 wm
= ARRAY_ITEM(&find_list
, i
).wl
;
182 cdata
= window_choose_data_create(TREE_OTHER
, c
, c
->session
);
183 cdata
->idx
= wm
->idx
;
186 cdata
->ft_template
= xstrdup(template);
187 cdata
->pane_id
= ARRAY_ITEM(&find_list
, i
).pane_id
;
189 format_add(cdata
->ft
, "line", "%u", i
);
190 format_add(cdata
->ft
, "window_find_matches", "%s",
191 ARRAY_ITEM(&find_list
, i
).list_ctx
);
192 format_session(cdata
->ft
, s
);
193 format_winlink(cdata
->ft
, s
, wm
);
194 format_window_pane(cdata
->ft
, wm
->window
->active
);
196 window_choose_add(wl
->window
->active
, cdata
);
199 window_choose_ready(wl
->window
->active
, 0, cmd_find_window_callback
);
202 ARRAY_FREE(&find_list
);
203 return (CMD_RETURN_NORMAL
);
207 cmd_find_window_callback(struct window_choose_data
*cdata
)
210 struct window_pane
*wp
;
215 s
= cdata
->start_session
;
216 if (!session_alive(s
))
219 wp
= window_pane_at_index(cdata
->wl
->window
, cdata
->pane_id
);
220 if (wp
!= NULL
&& window_pane_visible(wp
))
221 window_set_active_pane(cdata
->wl
->window
, wp
);
223 if (session_select(s
, cdata
->idx
) == 0) {
224 server_redraw_session(s
);