summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmd-list-panes.c4
-rw-r--r--cmd.c99
-rw-r--r--server.c1
-rw-r--r--tmux.111
-rw-r--r--tmux.h8
-rw-r--r--window.c31
6 files changed, 140 insertions, 14 deletions
diff --git a/cmd-list-panes.c b/cmd-list-panes.c
index 03fd7afd..e58fd671 100644
--- a/cmd-list-panes.c
+++ b/cmd-list-panes.c
@@ -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/cmd.c b/cmd.c
index 5333a023..11910aac 100644
--- a/cmd.c
+++ b/cmd.c
@@ -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/server.c b/server.c
index 72f3880d..a548a694 100644
--- a/server.c
+++ b/server.c
@@ -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/tmux.1 b/tmux.1
index 7d42984a..d69321dd 100644
--- a/tmux.1
+++ b/tmux.1
@@ -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/tmux.h b/tmux.h
index 2e53a24a..2d9e992a 100644
--- a/tmux.h
+++ b/tmux.h
@@ -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/window.c b/window.c
index 2d332c40..4270013f 100644
--- a/window.c
+++ b/window.c
@@ -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);