aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Adam <thomas@xteddy.org>2015-12-17 00:01:08 +0000
committerThomas Adam <thomas@xteddy.org>2015-12-17 00:01:08 +0000
commite0cae08c04a1adca313ec94b7557496142cc2173 (patch)
treeb46acbb209ba4514de75ce8aafe2163f1f97048b
parent7c94dae702798db66424897159a44832f5dbc392 (diff)
parent99e9a4c7864c188857fe57b411312ee669f16b54 (diff)
downloadrtmux-e0cae08c04a1adca313ec94b7557496142cc2173.tar.gz
rtmux-e0cae08c04a1adca313ec94b7557496142cc2173.tar.bz2
rtmux-e0cae08c04a1adca313ec94b7557496142cc2173.zip
Merge branch 'obsd-master'
-rw-r--r--cmd-attach-session.c2
-rw-r--r--cmd-find.c53
-rw-r--r--cmd-queue.c4
-rw-r--r--cmd-respawn-window.c2
-rw-r--r--cmd-send-keys.c2
-rw-r--r--hooks.c20
-rw-r--r--input.c44
-rw-r--r--server-client.c4
-rw-r--r--server-fn.c9
-rw-r--r--server.c2
-rw-r--r--tmux.16
-rw-r--r--tmux.h19
-rw-r--r--window.c2
13 files changed, 128 insertions, 41 deletions
diff --git a/cmd-attach-session.c b/cmd-attach-session.c
index 586863aa..4d8a75f8 100644
--- a/cmd-attach-session.c
+++ b/cmd-attach-session.c
@@ -144,7 +144,7 @@ cmd_attach_session(struct cmd_q *cmdq, int dflag, int rflag, const char *cflag,
if (~c->flags & CLIENT_CONTROL)
proc_send(c->peer, MSG_READY, -1, NULL, 0);
- hooks_run(c->session->hooks, c, "client-attached");
+ hooks_run(c->session->hooks, c, NULL, "client-attached");
cmdq->client_exit = 0;
}
recalculate_sizes();
diff --git a/cmd-find.c b/cmd-find.c
index b2192bbe..2d8f8178 100644
--- a/cmd-find.c
+++ b/cmd-find.c
@@ -189,7 +189,7 @@ cmd_find_best_session_with_window(struct cmd_find_state *fs)
u_int ssize;
struct session *s;
- if (fs->cmdq->client != NULL) {
+ if (fs->cmdq != NULL && fs->cmdq->client != NULL) {
fs->s = cmd_find_try_TMUX(fs->cmdq->client, fs->w);
if (fs->s != NULL)
return (cmd_find_best_winlink_with_window(fs));
@@ -253,7 +253,7 @@ cmd_find_current_session_with_client(struct cmd_find_state *fs)
* sessions to those containing that pane (we still use the current
* window in the best session).
*/
- if (fs->cmdq->client->tty.path != NULL) {
+ if (fs->cmdq != NULL && fs->cmdq->client->tty.path != NULL) {
RB_FOREACH(wp, window_pane_tree, &all_window_panes) {
if (strcmp(wp->tty, fs->cmdq->client->tty.path) == 0)
break;
@@ -288,7 +288,9 @@ cmd_find_current_session_with_client(struct cmd_find_state *fs)
return (0);
unknown_pane:
- fs->s = cmd_find_try_TMUX(fs->cmdq->client, NULL);
+ fs->s = NULL;
+ if (fs->cmdq != NULL)
+ fs->s = cmd_find_try_TMUX(fs->cmdq->client, NULL);
if (fs->s == NULL)
fs->s = cmd_find_best_session(NULL, 0, fs->flags);
if (fs->s == NULL)
@@ -309,7 +311,7 @@ int
cmd_find_current_session(struct cmd_find_state *fs)
{
/* If we know the current client, use it. */
- if (fs->cmdq->client != NULL) {
+ if (fs->cmdq != NULL && fs->cmdq->client != NULL) {
log_debug("%s: have client %p%s", __func__, fs->cmdq->client,
fs->cmdq->client->session == NULL ? "" : " (with session)");
if (fs->cmdq->client->session == NULL)
@@ -861,6 +863,49 @@ cmd_find_log_state(const char *prefix, struct cmd_find_state *fs)
log_debug("%s: idx=none", prefix);
}
+/* Find state from a session. */
+int
+cmd_find_from_session(struct cmd_find_state *fs, struct session *s)
+{
+ cmd_find_clear_state(fs, NULL, 0);
+
+ fs->s = s;
+ fs->wl = fs->s->curw;
+ fs->w = fs->wl->window;
+ fs->wp = fs->w->active;
+
+ cmd_find_log_state(__func__, fs);
+ return (0);
+}
+
+/* Find state from a window. */
+int
+cmd_find_from_window(struct cmd_find_state *fs, struct window *w)
+{
+ cmd_find_clear_state(fs, NULL, 0);
+
+ fs->w = w;
+ if (cmd_find_best_session_with_window(fs) != 0)
+ return (-1);
+ if (cmd_find_best_winlink_with_window(fs) != 0)
+ return (-1);
+
+ cmd_find_log_state(__func__, fs);
+ return (0);
+}
+
+/* Find state from a pane. */
+int
+cmd_find_from_pane(struct cmd_find_state *fs, struct window_pane *wp)
+{
+ if (cmd_find_from_window(fs, wp->window) != 0)
+ return (-1);
+ fs->wp = wp;
+
+ cmd_find_log_state(__func__, fs);
+ return (0);
+}
+
/*
* Split target into pieces and resolve for the given type. Fills in the given
* state. Returns 0 on success or -1 on error.
diff --git a/cmd-queue.c b/cmd-queue.c
index c0fc26c6..5bc3226a 100644
--- a/cmd-queue.c
+++ b/cmd-queue.c
@@ -44,6 +44,9 @@ cmdq_new(struct client *c)
cmdq->item = NULL;
cmdq->cmd = NULL;
+ cmd_find_clear_state(&cmdq->current, NULL, 0);
+ cmdq->parent = NULL;
+
return (cmdq);
}
@@ -286,3 +289,4 @@ cmdq_flush(struct cmd_q *cmdq)
}
cmdq->item = NULL;
}
+
diff --git a/cmd-respawn-window.c b/cmd-respawn-window.c
index aa4e169b..da9a365a 100644
--- a/cmd-respawn-window.c
+++ b/cmd-respawn-window.c
@@ -90,7 +90,7 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_q *cmdq)
cmdq_error(cmdq, "respawn window failed: %s", cause);
free(cause);
environ_free(env);
- server_destroy_pane(wp);
+ server_destroy_pane(wp, 0);
return (CMD_RETURN_ERROR);
}
layout_init(w, wp);
diff --git a/cmd-send-keys.c b/cmd-send-keys.c
index 377453b0..7b0b952c 100644
--- a/cmd-send-keys.c
+++ b/cmd-send-keys.c
@@ -86,7 +86,7 @@ cmd_send_keys_exec(struct cmd *self, struct cmd_q *cmdq)
}
if (args_has(args, 'R'))
- input_reset(wp);
+ input_reset(wp, 1);
for (i = 0; i < args->argc; i++) {
literal = args_has(args, 'l');
diff --git a/hooks.c b/hooks.c
index 424faf0c..c1a016ae 100644
--- a/hooks.c
+++ b/hooks.c
@@ -43,6 +43,14 @@ hooks_cmp(struct hook *hook1, struct hook *hook2)
}
struct hooks *
+hooks_get(struct session *s)
+{
+ if (s != NULL)
+ return (s->hooks);
+ return (global_hooks);
+}
+
+struct hooks *
hooks_create(struct hooks *parent)
{
struct hooks *hooks;
@@ -148,7 +156,8 @@ hooks_emptyfn(struct cmd_q *hooks_cmdq)
}
int
-hooks_run(struct hooks *hooks, struct client *c, const char *fmt, ...)
+hooks_run(struct hooks *hooks, struct client *c, struct cmd_find_state *fs,
+ const char *fmt, ...)
{
struct hook *hook;
struct cmd_q *hooks_cmdq;
@@ -169,6 +178,9 @@ hooks_run(struct hooks *hooks, struct client *c, const char *fmt, ...)
hooks_cmdq = cmdq_new(c);
hooks_cmdq->flags |= CMD_Q_NOHOOKS;
+
+ if (fs != NULL)
+ cmd_find_copy_state(&hooks_cmdq->current, fs);
hooks_cmdq->parent = NULL;
cmdq_run(hooks_cmdq, hook->cmdlist, NULL);
@@ -177,7 +189,8 @@ hooks_run(struct hooks *hooks, struct client *c, const char *fmt, ...)
}
int
-hooks_wait(struct hooks *hooks, struct cmd_q *cmdq, const char *fmt, ...)
+hooks_wait(struct hooks *hooks, struct cmd_q *cmdq, struct cmd_find_state *fs,
+ const char *fmt, ...)
{
struct hook *hook;
struct cmd_q *hooks_cmdq;
@@ -198,6 +211,9 @@ hooks_wait(struct hooks *hooks, struct cmd_q *cmdq, const char *fmt, ...)
hooks_cmdq = cmdq_new(cmdq->client);
hooks_cmdq->flags |= CMD_Q_NOHOOKS;
+
+ if (fs != NULL)
+ cmd_find_copy_state(&hooks_cmdq->current, fs);
hooks_cmdq->parent = cmdq;
hooks_cmdq->emptyfn = hooks_emptyfn;
diff --git a/input.c b/input.c
index d8e80afb..ed1ebffc 100644
--- a/input.c
+++ b/input.c
@@ -762,24 +762,12 @@ input_init(struct window_pane *wp)
ictx = wp->ictx = xcalloc(1, sizeof *ictx);
- input_reset_cell(ictx);
-
- *ictx->interm_buf = '\0';
- ictx->interm_len = 0;
-
- *ictx->param_buf = '\0';
- ictx->param_len = 0;
-
ictx->input_space = INPUT_BUF_START;
ictx->input_buf = xmalloc(INPUT_BUF_START);
- *ictx->input_buf = '\0';
- ictx->input_len = 0;
-
- ictx->state = &input_state_ground;
- ictx->flags = 0;
-
ictx->since_ground = evbuffer_new();
+
+ input_reset(wp, 0);
}
/* Destroy input parser. */
@@ -797,18 +785,32 @@ input_free(struct window_pane *wp)
/* Reset input state and clear screen. */
void
-input_reset(struct window_pane *wp)
+input_reset(struct window_pane *wp, int clear)
{
struct input_ctx *ictx = wp->ictx;
input_reset_cell(ictx);
- if (wp->mode == NULL)
- screen_write_start(&ictx->ctx, wp, &wp->base);
- else
- screen_write_start(&ictx->ctx, NULL, &wp->base);
- screen_write_reset(&ictx->ctx);
- screen_write_stop(&ictx->ctx);
+ if (clear) {
+ if (wp->mode == NULL)
+ screen_write_start(&ictx->ctx, wp, &wp->base);
+ else
+ screen_write_start(&ictx->ctx, NULL, &wp->base);
+ screen_write_reset(&ictx->ctx);
+ screen_write_stop(&ictx->ctx);
+ }
+
+ *ictx->interm_buf = '\0';
+ ictx->interm_len = 0;
+
+ *ictx->param_buf = '\0';
+ ictx->param_len = 0;
+
+ *ictx->input_buf = '\0';
+ ictx->input_len = 0;
+
+ ictx->state = &input_state_ground;
+ ictx->flags = 0;
}
/* Return pending data. */
diff --git a/server-client.c b/server-client.c
index c124afb0..611b2212 100644
--- a/server-client.c
+++ b/server-client.c
@@ -281,7 +281,7 @@ server_client_detach(struct client *c, enum msgtype msgtype)
if (s == NULL)
return;
- hooks_run(c->session->hooks, c, "client-detached");
+ hooks_run(c->session->hooks, c, NULL, "client-detached");
proc_send_s(c->peer, msgtype, s->name);
}
@@ -1035,7 +1035,7 @@ server_client_dispatch(struct imsg *imsg, void *arg)
server_redraw_client(c);
}
if (c->session != NULL)
- hooks_run(c->session->hooks, c, "client-resized");
+ hooks_run(c->session->hooks, c, NULL, "client-resized");
break;
case MSG_EXITING:
if (datalen != 0)
diff --git a/server-fn.c b/server-fn.c
index 3afeb090..5c005c6f 100644
--- a/server-fn.c
+++ b/server-fn.c
@@ -291,12 +291,13 @@ server_unlink_window(struct session *s, struct winlink *wl)
}
void
-server_destroy_pane(struct window_pane *wp)
+server_destroy_pane(struct window_pane *wp, int hooks)
{
struct window *w = wp->window;
int old_fd;
struct screen_write_ctx ctx;
struct grid_cell gc;
+ struct cmd_find_state fs;
old_fd = wp->fd;
if (wp->fd != -1) {
@@ -320,6 +321,9 @@ server_destroy_pane(struct window_pane *wp)
screen_write_puts(&ctx, &gc, "Pane is dead");
screen_write_stop(&ctx);
wp->flags |= PANE_REDRAW;
+
+ if (hooks && cmd_find_from_pane(&fs, wp) == 0)
+ hooks_run(hooks_get(fs.s), NULL, &fs, "pane-died");
return;
}
@@ -327,6 +331,9 @@ server_destroy_pane(struct window_pane *wp)
layout_close_pane(wp);
window_remove_pane(w, wp);
+ if (hooks && cmd_find_from_window(&fs, w) == 0)
+ hooks_run(hooks_get(fs.s), NULL, &fs, "pane-exited");
+
if (TAILQ_EMPTY(&w->panes))
server_kill_window(w);
else
diff --git a/server.c b/server.c
index cc0fe889..bbf278f6 100644
--- a/server.c
+++ b/server.c
@@ -389,7 +389,7 @@ server_child_exited(pid_t pid, int status)
TAILQ_FOREACH(wp, &w->panes, entry) {
if (wp->pid == pid) {
wp->status = status;
- server_destroy_pane(wp);
+ server_destroy_pane(wp, 1);
break;
}
}
diff --git a/tmux.1 b/tmux.1
index ac8a7394..f3c8066d 100644
--- a/tmux.1
+++ b/tmux.1
@@ -3234,6 +3234,12 @@ Run when a client is attached.
Run when a client is detached
.It client-resized
Run when a client is resized.
+.It pane-died
+Run when the program running in a pane exits, but
+.Ic remain-on-exit
+is on so the pane has not closed.
+.It pane-exited
+Run when the program running in a pane exits.
.El
.Pp
Hooks are managed with these commands:
diff --git a/tmux.h b/tmux.h
index 105dd144..0bb6b742 100644
--- a/tmux.h
+++ b/tmux.h
@@ -1381,6 +1381,7 @@ struct cmd_q {
struct cmd *cmd;
struct cmd_q *parent;
+ struct cmd_find_state current;
struct cmd_state state;
time_t time;
@@ -1578,6 +1579,7 @@ void format_defaults_paste_buffer(struct format_tree *,
/* hooks.c */
struct hook;
+struct hooks *hooks_get(struct session *);
struct hooks *hooks_create(struct hooks *);
void hooks_free(struct hooks *);
struct hook *hooks_first(struct hooks *);
@@ -1586,10 +1588,10 @@ void hooks_add(struct hooks *, const char *, struct cmd_list *);
void hooks_copy(struct hooks *, struct hooks *);
void hooks_remove(struct hooks *, const char *);
struct hook *hooks_find(struct hooks *, const char *);
-int printflike(3, 4) hooks_run(struct hooks *, struct client *, const char *,
- ...);
-int printflike(3, 4) hooks_wait(struct hooks *, struct cmd_q *, const char *,
- ...);
+int printflike(4, 5) hooks_run(struct hooks *, struct client *,
+ struct cmd_find_state *, const char *, ...);
+int printflike(4, 5) hooks_wait(struct hooks *, struct cmd_q *,
+ struct cmd_find_state *, const char *, ...);
/* mode-key.c */
extern const struct mode_key_table mode_key_tables[];
@@ -1778,6 +1780,11 @@ int cmd_find_valid_state(struct cmd_find_state *);
void cmd_find_copy_state(struct cmd_find_state *,
struct cmd_find_state *);
void cmd_find_log_state(const char *, struct cmd_find_state *);
+int cmd_find_from_session(struct cmd_find_state *,
+ struct session *);
+int cmd_find_from_window(struct cmd_find_state *, struct window *);
+int cmd_find_from_pane(struct cmd_find_state *,
+ struct window_pane *);
/* cmd.c */
int cmd_pack_argv(int, char **, char *, size_t);
@@ -1898,7 +1905,7 @@ void server_kill_window(struct window *);
int server_link_window(struct session *,
struct winlink *, struct session *, int, int, int, char **);
void server_unlink_window(struct session *, struct winlink *);
-void server_destroy_pane(struct window_pane *);
+void server_destroy_pane(struct window_pane *, int);
void server_destroy_session_group(struct session *);
void server_destroy_session(struct session *);
void server_check_unattached(void);
@@ -1932,7 +1939,7 @@ void recalculate_sizes(void);
/* input.c */
void input_init(struct window_pane *);
void input_free(struct window_pane *);
-void input_reset(struct window_pane *);
+void input_reset(struct window_pane *, int);
struct evbuffer *input_pending(struct window_pane *);
void input_parse(struct window_pane *);
diff --git a/window.c b/window.c
index f412da64..8a9152fb 100644
--- a/window.c
+++ b/window.c
@@ -987,7 +987,7 @@ window_pane_error_callback(__unused struct bufferevent *bufev,
{
struct window_pane *wp = data;
- server_destroy_pane(wp);
+ server_destroy_pane(wp, 1);
}
void