diff options
author | Nicholas Marriott <nicm@cvs.openbsd.org> | 2011-03-27 20:27:28 +0000 |
---|---|---|
committer | Nicholas Marriott <nicm@cvs.openbsd.org> | 2011-03-27 20:27:28 +0000 |
commit | 2f0df4178cff2f6e1e1df0bb6742264a66259fc8 (patch) | |
tree | 2684699df3c62ac19d2176119865ba3ecf98bfa3 /usr.bin/tmux | |
parent | 270ad45d7f0f1e62bf9c4e27e635a8f1f6e8ecd0 (diff) |
Give each pane created in a tmux server a unique id (starting from 0),
put it in the TMUX_PANE environment variable and accept it as a
target. Suggested by and with testing and tweaks from Ben Boeckel.
Diffstat (limited to 'usr.bin/tmux')
-rw-r--r-- | usr.bin/tmux/cmd-list-panes.c | 6 | ||||
-rw-r--r-- | usr.bin/tmux/cmd.c | 101 | ||||
-rw-r--r-- | usr.bin/tmux/server.c | 3 | ||||
-rw-r--r-- | usr.bin/tmux/tmux.1 | 15 | ||||
-rw-r--r-- | usr.bin/tmux/tmux.h | 10 | ||||
-rw-r--r-- | usr.bin/tmux/window.c | 33 |
6 files changed, 147 insertions, 21 deletions
diff --git a/usr.bin/tmux/cmd-list-panes.c b/usr.bin/tmux/cmd-list-panes.c index 2e9a40fb891..664382bf167 100644 --- a/usr.bin/tmux/cmd-list-panes.c +++ b/usr.bin/tmux/cmd-list-panes.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd-list-panes.c,v 1.7 2011/01/04 00:42:46 nicm Exp $ */ +/* $OpenBSD: cmd-list-panes.c,v 1.8 2011/03/27 20:27:26 nicm Exp $ */ /* * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> @@ -64,8 +64,8 @@ cmd_list_panes_exec(struct cmd *self, struct cmd_ctx *ctx) } size += gd->hsize * sizeof *gd->linedata; - ctx->print(ctx, "%u: [%ux%u] [history %u/%u, %llu bytes]%s%s", - n, wp->sx, wp->sy, gd->hsize, gd->hlimit, size, + ctx->print(ctx, "%u: [%ux%u] [history %u/%u, %llu bytes] %%%u%s%s", + n, wp->sx, wp->sy, gd->hsize, gd->hlimit, size, wp->id, wp == wp->window->active ? " (active)" : "", wp->fd == -1 ? " (dead)" : ""); n++; diff --git a/usr.bin/tmux/cmd.c b/usr.bin/tmux/cmd.c index f56358ab34d..45c7d43d354 100644 --- a/usr.bin/tmux/cmd.c +++ b/usr.bin/tmux/cmd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cmd.c,v 1.50 2011/01/23 11:03:43 nicm Exp $ */ +/* $OpenBSD: cmd.c,v 1.51 2011/03/27 20:27:26 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -118,9 +118,12 @@ struct client *cmd_lookup_client(const char *); struct session *cmd_lookup_session(const char *, int *); struct winlink *cmd_lookup_window(struct session *, const char *, int *); int cmd_lookup_index(struct session *, const char *, int *); +struct window_pane *cmd_lookup_paneid(const char *); +struct session *cmd_pane_session(struct cmd_ctx *, + struct window_pane *, struct winlink **); struct winlink *cmd_find_window_offset(const char *, struct session *, int *); int cmd_find_index_offset(const char *, struct session *, int *); -struct window_pane *cmd_find_pane_offset(const char *, struct winlink *); +struct window_pane *cmd_find_pane_offset(const char *, struct winlink *); int cmd_pack_argv(int argc, char **argv, char *buf, size_t len) @@ -639,21 +642,78 @@ cmd_lookup_index(struct session *s, const char *name, int *ambiguous) return (-1); } +/* + * Lookup pane id. An initial % means a pane id. sp must already point to the + * current session. + */ +struct window_pane * +cmd_lookup_paneid(const char *arg) +{ + const char *errstr; + u_int paneid; + + if (*arg != '%') + return (NULL); + + paneid = strtonum(arg + 1, 0, UINT_MAX, &errstr); + if (errstr != NULL) + return (NULL); + return (window_pane_find_by_id(paneid)); +} + +/* Find session and winlink for pane. */ +struct session * +cmd_pane_session(struct cmd_ctx *ctx, struct window_pane *wp, + struct winlink **wlp) +{ + struct session *s; + struct sessionslist ss; + struct winlink *wl; + + /* If this pane is in the current session, return that winlink. */ + s = cmd_current_session(ctx); + if (s != NULL) { + wl = winlink_find_by_window(&s->windows, wp->window); + if (wl != NULL) { + if (wlp != NULL) + *wlp = wl; + return (s); + } + } + + /* Otherwise choose from all sessions with this pane. */ + ARRAY_INIT(&ss); + RB_FOREACH(s, sessions, &sessions) { + if (winlink_find_by_window(&s->windows, wp->window) != NULL) + ARRAY_ADD(&ss, s); + } + s = cmd_choose_session_list(&ss); + ARRAY_FREE(&ss); + if (wlp != NULL) + *wlp = winlink_find_by_window(&s->windows, wp->window); + return (s); +} + /* Find the target session or report an error and return NULL. */ struct session * cmd_find_session(struct cmd_ctx *ctx, const char *arg) { - struct session *s; - struct client *c; - char *tmparg; - size_t arglen; - int ambiguous; + struct session *s; + struct window_pane *wp; + struct client *c; + char *tmparg; + size_t arglen; + int ambiguous; /* A NULL argument means the current session. */ if (arg == NULL) return (cmd_current_session(ctx)); tmparg = xstrdup(arg); + /* Lookup as pane id. */ + if ((wp = cmd_lookup_paneid(arg)) != NULL) + return (cmd_pane_session(ctx, wp, NULL)); + /* Trim a single trailing colon if any. */ arglen = strlen(tmparg); if (arglen != 0 && tmparg[arglen - 1] == ':') @@ -682,11 +742,12 @@ cmd_find_session(struct cmd_ctx *ctx, const char *arg) struct winlink * cmd_find_window(struct cmd_ctx *ctx, const char *arg, struct session **sp) { - struct session *s; - struct winlink *wl; - const char *winptr; - char *sessptr = NULL; - int ambiguous = 0; + struct session *s; + struct winlink *wl; + struct window_pane *wp; + const char *winptr; + char *sessptr = NULL; + int ambiguous = 0; /* * Find the current session. There must always be a current session, if @@ -704,6 +765,14 @@ cmd_find_window(struct cmd_ctx *ctx, const char *arg, struct session **sp) return (s->curw); } + /* Lookup as pane id. */ + if ((wp = cmd_lookup_paneid(arg)) != NULL) { + s = cmd_pane_session(ctx, wp, &wl); + if (sp != NULL) + *sp = s; + return (wl); + } + /* Time to look at the argument. If it is empty, that is an error. */ if (*arg == '\0') goto not_found; @@ -998,6 +1067,14 @@ cmd_find_pane(struct cmd_ctx *ctx, return (s->curw); } + /* Lookup as pane id. */ + if ((*wpp = cmd_lookup_paneid(arg)) != NULL) { + s = cmd_pane_session(ctx, *wpp, &wl); + if (sp != NULL) + *sp = s; + return (wl); + } + /* Look for a separating period. */ if ((period = strrchr(arg, '.')) == NULL) goto no_period; diff --git a/usr.bin/tmux/server.c b/usr.bin/tmux/server.c index 9588bbb6105..876fe320f15 100644 --- a/usr.bin/tmux/server.c +++ b/usr.bin/tmux/server.c @@ -1,4 +1,4 @@ -/* $OpenBSD: server.c,v 1.101 2011/01/26 00:11:47 nicm Exp $ */ +/* $OpenBSD: server.c,v 1.102 2011/03/27 20:27:26 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -143,6 +143,7 @@ server_start(void) log_debug("server started, pid %ld", (long) getpid()); ARRAY_INIT(&windows); + RB_INIT(&all_window_panes); ARRAY_INIT(&clients); ARRAY_INIT(&dead_clients); RB_INIT(&sessions); diff --git a/usr.bin/tmux/tmux.1 b/usr.bin/tmux/tmux.1 index 7252027d677..c37b5a1402c 100644 --- a/usr.bin/tmux/tmux.1 +++ b/usr.bin/tmux/tmux.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: tmux.1,v 1.211 2011/03/03 08:51:47 nicm Exp $ +.\" $OpenBSD: tmux.1,v 1.212 2011/03/27 20:27:26 nicm Exp $ .\" .\" Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> .\" @@ -14,7 +14,7 @@ .\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING .\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: March 3 2011 $ +.Dd $Mdocdate: March 27 2011 $ .Dt TMUX 1 .Os .Sh NAME @@ -449,6 +449,17 @@ select-window -t:+2 When dealing with a session that doesn't contain sequential window indexes, they will be correctly skipped. .Pp +.Nm +also gives each pane created in a server an identifier consisting of a +.Ql % +and a number, starting from zero. +A pane's identifier is unique for the life of the +.Nm +server and is passed to the child process of the pane in the +.Ev TMUX_PANE +environment variable. +It may be used alone to target a pane or the window containing it. +.Pp .Ar shell-command arguments are .Xr sh 1 diff --git a/usr.bin/tmux/tmux.h b/usr.bin/tmux/tmux.h index 9f3204a2990..c20d76b278c 100644 --- a/usr.bin/tmux/tmux.h +++ b/usr.bin/tmux/tmux.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tmux.h,v 1.273 2011/03/07 23:46:27 nicm Exp $ */ +/* $OpenBSD: tmux.h,v 1.274 2011/03/27 20:27:27 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -779,6 +779,8 @@ struct window_mode { /* Child window structure. */ struct window_pane { + u_int id; + struct window *window; struct layout_cell *layout_cell; @@ -821,8 +823,10 @@ struct window_pane { void *modedata; TAILQ_ENTRY(window_pane) entry; + RB_ENTRY(window_pane) tree_entry; }; TAILQ_HEAD(window_panes, window_pane); +RB_HEAD(window_pane_tree, window_pane); /* Window structure. */ struct window { @@ -1825,8 +1829,11 @@ int screen_check_selection(struct screen *, u_int, u_int); /* window.c */ extern struct windows windows; +extern struct window_pane_tree all_window_panes; int winlink_cmp(struct winlink *, struct winlink *); RB_PROTOTYPE(winlinks, winlink, entry, winlink_cmp); +int window_pane_cmp(struct window_pane *, struct window_pane *); +RB_PROTOTYPE(window_pane_tree, window_pane, tree_entry, window_pane_cmp); struct winlink *winlink_find_by_index(struct winlinks *, int); struct winlink *winlink_find_by_window(struct winlinks *, struct window *); int winlink_next_index(struct winlinks *, int); @@ -1861,6 +1868,7 @@ struct window_pane *window_pane_previous_by_number(struct window *, u_int window_pane_index(struct window *, struct window_pane *); u_int window_count_panes(struct window *); void window_destroy_panes(struct window *); +struct window_pane *window_pane_find_by_id(u_int); struct window_pane *window_pane_create(struct window *, u_int, u_int, u_int); void window_pane_destroy(struct window_pane *); int window_pane_spawn(struct window_pane *, const char *, diff --git a/usr.bin/tmux/window.c b/usr.bin/tmux/window.c index d330d9df431..4bc7b9db100 100644 --- a/usr.bin/tmux/window.c +++ b/usr.bin/tmux/window.c @@ -1,4 +1,4 @@ -/* $OpenBSD: window.c,v 1.63 2011/01/25 22:31:50 nicm Exp $ */ +/* $OpenBSD: window.c,v 1.64 2011/03/27 20:27:27 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> @@ -56,6 +56,10 @@ /* Global window list. */ struct windows windows; +/* Global panes tree. */ +struct window_pane_tree all_window_panes; +u_int next_window_pane; + void window_pane_read_callback(struct bufferevent *, void *); void window_pane_error_callback(struct bufferevent *, short, void *); @@ -67,6 +71,14 @@ winlink_cmp(struct winlink *wl1, struct winlink *wl2) return (wl1->idx - wl2->idx); } +RB_GENERATE(window_pane_tree, window_pane, tree_entry, window_pane_cmp); + +int +window_pane_cmp(struct window_pane *wp1, struct window_pane *wp2) +{ + return (wp1->id - wp2->id); +} + struct winlink * winlink_find_by_window(struct winlinks *wwl, struct window *w) { @@ -495,6 +507,16 @@ window_printable_flags(struct session *s, struct winlink *wl) return (xstrdup(flags)); } +/* Find pane in global tree by id. */ +struct window_pane * +window_pane_find_by_id(u_int id) +{ + struct window_pane wp; + + wp.id = id; + return (RB_FIND(window_pane_tree, &all_window_panes, &wp)); +} + struct window_pane * window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit) { @@ -503,6 +525,9 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit) wp = xcalloc(1, sizeof *wp); wp->window = w; + wp->id = next_window_pane++; + RB_INSERT(window_pane_tree, &all_window_panes, wp); + wp->cmd = NULL; wp->shell = NULL; wp->cwd = NULL; @@ -555,6 +580,8 @@ window_pane_destroy(struct window_pane *wp) bufferevent_free(wp->pipe_event); } + RB_REMOVE(window_pane_tree, &all_window_panes, wp); + if (wp->cwd != NULL) xfree(wp->cwd); if (wp->shell != NULL) @@ -569,7 +596,7 @@ window_pane_spawn(struct window_pane *wp, const char *cmd, const char *shell, const char *cwd, struct environ *env, struct termios *tio, char **cause) { struct winsize ws; - char *argv0; + char *argv0, paneid[16]; const char *ptr; struct termios tio2; @@ -616,6 +643,8 @@ window_pane_spawn(struct window_pane *wp, const char *cmd, const char *shell, closefrom(STDERR_FILENO + 1); + xsnprintf(paneid, sizeof paneid, "%%%u", wp->id); + environ_set(env, "TMUX_PANE", paneid); environ_push(env); clear_signals(1); |