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",
55 struct cmd_find_window_data
{
60 ARRAY_DECL(cmd_find_window_data_list
, struct cmd_find_window_data
);
62 u_int
cmd_find_window_match_flags(struct args
*);
63 void cmd_find_window_match(struct cmd_find_window_data_list
*, int,
64 struct winlink
*, const char *, const char *);
67 cmd_find_window_match_flags(struct args
*args
)
69 u_int match_flags
= 0;
71 /* Turn on flags based on the options. */
72 if (args_has(args
, 'T'))
73 match_flags
|= CMD_FIND_WINDOW_BY_TITLE
;
74 if (args_has(args
, 'C'))
75 match_flags
|= CMD_FIND_WINDOW_BY_CONTENT
;
76 if (args_has(args
, 'N'))
77 match_flags
|= CMD_FIND_WINDOW_BY_NAME
;
79 /* If none of the flags were set, default to matching anything. */
81 match_flags
= CMD_FIND_WINDOW_ALL
;
87 cmd_find_window_match(struct cmd_find_window_data_list
*find_list
,
88 int match_flags
, struct winlink
*wl
, const char *str
, const char *searchstr
)
90 struct cmd_find_window_data find_data
;
91 struct window_pane
*wp
;
95 memset(&find_data
, 0, sizeof find_data
);
98 TAILQ_FOREACH(wp
, &wl
->window
->panes
, entry
) {
101 if ((match_flags
& CMD_FIND_WINDOW_BY_NAME
) &&
102 fnmatch(searchstr
, wl
->window
->name
, 0) == 0) {
103 find_data
.list_ctx
= xstrdup("");
107 if ((match_flags
& CMD_FIND_WINDOW_BY_TITLE
) &&
108 fnmatch(searchstr
, wp
->base
.title
, 0) == 0) {
109 xasprintf(&find_data
.list_ctx
,
110 "pane %u title: \"%s\"", i
- 1, wp
->base
.title
);
114 if (match_flags
& CMD_FIND_WINDOW_BY_CONTENT
&&
115 (sres
= window_pane_search(wp
, str
, &line
)) != NULL
) {
116 xasprintf(&find_data
.list_ctx
,
117 "pane %u line %u: \"%s\"", i
- 1, line
+ 1, sres
);
122 if (find_data
.list_ctx
!= NULL
) {
124 find_data
.pane_id
= i
- 1;
125 ARRAY_ADD(find_list
, find_data
);
130 cmd_find_window_exec(struct cmd
*self
, struct cmd_q
*cmdq
)
132 struct args
*args
= self
->args
;
134 struct window_choose_data
*cdata
;
136 struct winlink
*wl
, *wm
;
137 struct cmd_find_window_data_list find_list
;
138 char *str
, *searchstr
;
139 const char *template;
140 u_int i
, match_flags
;
142 if ((c
= cmd_current_client(cmdq
)) == NULL
) {
143 cmdq_error(cmdq
, "no client available");
144 return (CMD_RETURN_ERROR
);
148 if ((wl
= cmd_find_window(cmdq
, args_get(args
, 't'), NULL
)) == NULL
)
149 return (CMD_RETURN_ERROR
);
151 if ((template = args_get(args
, 'F')) == NULL
)
152 template = FIND_WINDOW_TEMPLATE
;
154 match_flags
= cmd_find_window_match_flags(args
);
157 ARRAY_INIT(&find_list
);
159 xasprintf(&searchstr
, "*%s*", str
);
160 RB_FOREACH(wm
, winlinks
, &s
->windows
)
161 cmd_find_window_match (&find_list
, match_flags
, wm
, str
, searchstr
);
164 if (ARRAY_LENGTH(&find_list
) == 0) {
165 cmdq_error(cmdq
, "no windows matching: %s", str
);
166 ARRAY_FREE(&find_list
);
167 return (CMD_RETURN_ERROR
);
170 if (ARRAY_LENGTH(&find_list
) == 1) {
171 if (session_select(s
, ARRAY_FIRST(&find_list
).wl
->idx
) == 0)
172 server_redraw_session(s
);
177 if (window_pane_set_mode(wl
->window
->active
, &window_choose_mode
) != 0)
180 for (i
= 0; i
< ARRAY_LENGTH(&find_list
); i
++) {
181 wm
= ARRAY_ITEM(&find_list
, i
).wl
;
183 cdata
= window_choose_data_create(TREE_OTHER
, c
, c
->session
);
184 cdata
->idx
= wm
->idx
;
187 cdata
->ft_template
= xstrdup(template);
188 cdata
->pane_id
= ARRAY_ITEM(&find_list
, i
).pane_id
;
190 format_add(cdata
->ft
, "line", "%u", i
);
191 format_add(cdata
->ft
, "window_find_matches", "%s",
192 ARRAY_ITEM(&find_list
, i
).list_ctx
);
193 format_session(cdata
->ft
, s
);
194 format_winlink(cdata
->ft
, s
, wm
);
195 format_window_pane(cdata
->ft
, wm
->window
->active
);
197 window_choose_add(wl
->window
->active
, cdata
);
200 window_choose_ready(wl
->window
->active
, 0, cmd_find_window_callback
);
203 ARRAY_FREE(&find_list
);
204 return (CMD_RETURN_NORMAL
);
208 cmd_find_window_callback(struct window_choose_data
*cdata
)
211 struct window_pane
*wp
;
216 s
= cdata
->start_session
;
217 if (!session_alive(s
))
220 wp
= window_pane_at_index(cdata
->wl
->window
, cdata
->pane_id
);
221 if (wp
!= NULL
&& window_pane_visible(wp
))
222 window_set_active_pane(cdata
->wl
->window
, wp
);
224 if (session_select(s
, cdata
->idx
) == 0) {
225 server_redraw_session(s
);