Skip to content

Commit

Permalink
Add infrastructure to work out the best target given a pane or window
Browse files Browse the repository at this point in the history
alone and use it to add pane_died and pane_exited hooks.
  • Loading branch information
nicm committed Dec 16, 2015
1 parent 8eb1a7d commit 021c643
Show file tree
Hide file tree
Showing 10 changed files with 91 additions and 13 deletions.
2 changes: 1 addition & 1 deletion cmd-attach-session.c
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
53 changes: 49 additions & 4 deletions cmd-find.c
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,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));
Expand Down Expand Up @@ -254,7 +254,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;
Expand Down Expand Up @@ -289,7 +289,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)
Expand All @@ -310,7 +312,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)
Expand Down Expand Up @@ -862,6 +864,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.
Expand Down
4 changes: 4 additions & 0 deletions cmd-queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down Expand Up @@ -286,3 +289,4 @@ cmdq_flush(struct cmd_q *cmdq)
}
cmdq->item = NULL;
}

2 changes: 1 addition & 1 deletion cmd-respawn-window.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
20 changes: 18 additions & 2 deletions hooks.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@ hooks_cmp(struct hook *hook1, struct hook *hook2)
return (strcmp(hook1->name, hook2->name));
}

struct hooks *
hooks_get(struct session *s)
{
if (s != NULL)
return (s->hooks);
return (global_hooks);
}

struct hooks *
hooks_create(struct hooks *parent)
{
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand All @@ -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;
Expand All @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions server-client.c
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,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);
}

Expand Down Expand Up @@ -1027,7 +1027,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)
Expand Down
9 changes: 8 additions & 1 deletion server-fn.c
Original file line number Diff line number Diff line change
Expand Up @@ -293,12 +293,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) {
Expand All @@ -319,13 +320,19 @@ 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;
}

server_unzoom_window(w);
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
Expand Down
2 changes: 1 addition & 1 deletion server.c
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,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;
}
}
Expand Down
6 changes: 6 additions & 0 deletions tmux.1
Original file line number Diff line number Diff line change
Expand Up @@ -3230,6 +3230,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:
Expand Down
2 changes: 1 addition & 1 deletion window.c
Original file line number Diff line number Diff line change
Expand Up @@ -974,7 +974,7 @@ window_pane_error_callback(__unused struct bufferevent *bufev,
{
struct window_pane *wp = data;

server_destroy_pane(wp);
server_destroy_pane(wp, 1);
}

void
Expand Down

0 comments on commit 021c643

Please sign in to comment.