4 * Copyright (c) 2012 George Nachman <tmux@georgester.com>
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 struct cmd_find_state fs
;
29 struct format_tree
*formats
;
31 struct client
*client
;
32 struct session
*session
;
33 struct window
*window
;
37 static struct cmdq_item
*
38 notify_insert_one_hook(struct cmdq_item
*item
, struct notify_entry
*ne
,
39 struct cmd_list
*cmdlist
, struct cmdq_state
*state
)
41 struct cmdq_item
*new_item
;
46 if (log_get_level() != 0) {
47 s
= cmd_list_print(cmdlist
, 0);
48 log_debug("%s: hook %s is: %s", __func__
, ne
->name
, s
);
51 new_item
= cmdq_get_command(cmdlist
, state
);
52 return (cmdq_insert_after(item
, new_item
));
56 notify_insert_hook(struct cmdq_item
*item
, struct notify_entry
*ne
)
58 struct cmd_find_state fs
;
60 struct cmdq_state
*state
;
61 struct options_entry
*o
;
62 struct options_array_item
*a
;
63 struct cmd_list
*cmdlist
;
65 struct cmd_parse_result
*pr
;
67 log_debug("%s: inserting hook %s", __func__
, ne
->name
);
69 cmd_find_clear_state(&fs
, 0);
70 if (cmd_find_empty_state(&ne
->fs
) || !cmd_find_valid_state(&ne
->fs
))
71 cmd_find_from_nothing(&fs
, 0);
73 cmd_find_copy_state(&fs
, &ne
->fs
);
76 oo
= global_s_options
;
79 o
= options_get(oo
, ne
->name
);
80 if (o
== NULL
&& fs
.wp
!= NULL
) {
82 o
= options_get(oo
, ne
->name
);
84 if (o
== NULL
&& fs
.wl
!= NULL
) {
85 oo
= fs
.wl
->window
->options
;
86 o
= options_get(oo
, ne
->name
);
89 log_debug("%s: hook %s not found", __func__
, ne
->name
);
93 state
= cmdq_new_state(&fs
, NULL
, CMDQ_STATE_NOHOOKS
);
94 cmdq_add_formats(state
, ne
->formats
);
96 if (*ne
->name
== '@') {
97 value
= options_get_string(oo
, ne
->name
);
98 pr
= cmd_parse_from_string(value
, NULL
);
100 case CMD_PARSE_ERROR
:
101 log_debug("%s: can't parse hook %s: %s", __func__
,
102 ne
->name
, pr
->error
);
105 case CMD_PARSE_SUCCESS
:
106 notify_insert_one_hook(item
, ne
, pr
->cmdlist
, state
);
110 a
= options_array_first(o
);
112 cmdlist
= options_array_item_value(a
)->cmdlist
;
113 item
= notify_insert_one_hook(item
, ne
, cmdlist
, state
);
114 a
= options_array_next(a
);
118 cmdq_free_state(state
);
121 static enum cmd_retval
122 notify_callback(struct cmdq_item
*item
, void *data
)
124 struct notify_entry
*ne
= data
;
126 log_debug("%s: %s", __func__
, ne
->name
);
128 if (strcmp(ne
->name
, "pane-mode-changed") == 0)
129 control_notify_pane_mode_changed(ne
->pane
);
130 if (strcmp(ne
->name
, "window-layout-changed") == 0)
131 control_notify_window_layout_changed(ne
->window
);
132 if (strcmp(ne
->name
, "window-pane-changed") == 0)
133 control_notify_window_pane_changed(ne
->window
);
134 if (strcmp(ne
->name
, "window-unlinked") == 0)
135 control_notify_window_unlinked(ne
->session
, ne
->window
);
136 if (strcmp(ne
->name
, "window-linked") == 0)
137 control_notify_window_linked(ne
->session
, ne
->window
);
138 if (strcmp(ne
->name
, "window-renamed") == 0)
139 control_notify_window_renamed(ne
->window
);
140 if (strcmp(ne
->name
, "client-session-changed") == 0)
141 control_notify_client_session_changed(ne
->client
);
142 if (strcmp(ne
->name
, "client-detached") == 0)
143 control_notify_client_detached(ne
->client
);
144 if (strcmp(ne
->name
, "session-renamed") == 0)
145 control_notify_session_renamed(ne
->session
);
146 if (strcmp(ne
->name
, "session-created") == 0)
147 control_notify_session_created(ne
->session
);
148 if (strcmp(ne
->name
, "session-closed") == 0)
149 control_notify_session_closed(ne
->session
);
150 if (strcmp(ne
->name
, "session-window-changed") == 0)
151 control_notify_session_window_changed(ne
->session
);
153 notify_insert_hook(item
, ne
);
155 if (ne
->client
!= NULL
)
156 server_client_unref(ne
->client
);
157 if (ne
->session
!= NULL
)
158 session_remove_ref(ne
->session
, __func__
);
159 if (ne
->window
!= NULL
)
160 window_remove_ref(ne
->window
, __func__
);
162 if (ne
->fs
.s
!= NULL
)
163 session_remove_ref(ne
->fs
.s
, __func__
);
165 format_free(ne
->formats
);
166 free((void *)ne
->name
);
169 return (CMD_RETURN_NORMAL
);
173 notify_add(const char *name
, struct cmd_find_state
*fs
, struct client
*c
,
174 struct session
*s
, struct window
*w
, struct window_pane
*wp
)
176 struct notify_entry
*ne
;
177 struct cmdq_item
*item
;
179 item
= cmdq_running(NULL
);
180 if (item
!= NULL
&& (cmdq_get_flags(item
) & CMDQ_STATE_NOHOOKS
))
183 ne
= xcalloc(1, sizeof *ne
);
184 ne
->name
= xstrdup(name
);
189 ne
->pane
= (wp
!= NULL
? wp
->id
: -1);
191 ne
->formats
= format_create(NULL
, NULL
, 0, FORMAT_NOJOBS
);
192 format_add(ne
->formats
, "hook", "%s", name
);
194 format_add(ne
->formats
, "hook_client", "%s", c
->name
);
196 format_add(ne
->formats
, "hook_session", "$%u", s
->id
);
197 format_add(ne
->formats
, "hook_session_name", "%s", s
->name
);
200 format_add(ne
->formats
, "hook_window", "@%u", w
->id
);
201 format_add(ne
->formats
, "hook_window_name", "%s", w
->name
);
204 format_add(ne
->formats
, "hook_pane", "%%%d", wp
->id
);
205 format_log_debug(ne
->formats
, __func__
);
210 session_add_ref(s
, __func__
);
212 window_add_ref(w
, __func__
);
214 cmd_find_copy_state(&ne
->fs
, fs
);
215 if (ne
->fs
.s
!= NULL
) /* cmd_find_valid_state needs session */
216 session_add_ref(ne
->fs
.s
, __func__
);
218 cmdq_append(NULL
, cmdq_get_callback(notify_callback
, ne
));
222 notify_hook(struct cmdq_item
*item
, const char *name
)
224 struct cmd_find_state
*target
= cmdq_get_target(item
);
225 struct notify_entry ne
;
227 memset(&ne
, 0, sizeof ne
);
230 cmd_find_copy_state(&ne
.fs
, target
);
232 ne
.client
= cmdq_get_client(item
);
233 ne
.session
= target
->s
;
234 ne
.window
= target
->w
;
235 ne
.pane
= (target
->wp
!= NULL
? target
->wp
->id
: -1);
237 ne
.formats
= format_create(NULL
, NULL
, 0, FORMAT_NOJOBS
);
238 format_add(ne
.formats
, "hook", "%s", name
);
239 format_log_debug(ne
.formats
, __func__
);
241 notify_insert_hook(item
, &ne
);
242 format_free(ne
.formats
);
246 notify_client(const char *name
, struct client
*c
)
248 struct cmd_find_state fs
;
250 cmd_find_from_client(&fs
, c
, 0);
251 notify_add(name
, &fs
, c
, NULL
, NULL
, NULL
);
255 notify_session(const char *name
, struct session
*s
)
257 struct cmd_find_state fs
;
259 if (session_alive(s
))
260 cmd_find_from_session(&fs
, s
, 0);
262 cmd_find_from_nothing(&fs
, 0);
263 notify_add(name
, &fs
, NULL
, s
, NULL
, NULL
);
267 notify_winlink(const char *name
, struct winlink
*wl
)
269 struct cmd_find_state fs
;
271 cmd_find_from_winlink(&fs
, wl
, 0);
272 notify_add(name
, &fs
, NULL
, wl
->session
, wl
->window
, NULL
);
276 notify_session_window(const char *name
, struct session
*s
, struct window
*w
)
278 struct cmd_find_state fs
;
280 cmd_find_from_session_window(&fs
, s
, w
, 0);
281 notify_add(name
, &fs
, NULL
, s
, w
, NULL
);
285 notify_window(const char *name
, struct window
*w
)
287 struct cmd_find_state fs
;
289 cmd_find_from_window(&fs
, w
, 0);
290 notify_add(name
, &fs
, NULL
, NULL
, w
, NULL
);
294 notify_pane(const char *name
, struct window_pane
*wp
)
296 struct cmd_find_state fs
;
298 cmd_find_from_pane(&fs
, wp
, 0);
299 notify_add(name
, &fs
, NULL
, NULL
, NULL
, wp
);