Try this. Use -t $TMUX_PANE.
Note that if tmux needs the session as well it'll follow the normal process to get it ("current" session if it contains the pane, otherwise best session from all of those with the pane). For example, paste-buffer takes a pane target but it needs the session to know where to paste from (probably -b should accept session:buffer but that's a separate issue). Index: cmd.c =================================================================== RCS file: /cvs/src/usr.bin/tmux/cmd.c,v retrieving revision 1.46 diff -u -p -r1.46 cmd.c --- cmd.c 29 Oct 2010 20:11:57 -0000 1.46 +++ cmd.c 13 Nov 2010 18:02:40 -0000 @@ -118,9 +118,12 @@ struct client *cmd_lookup_client(const c 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) @@ -629,21 +632,81 @@ cmd_lookup_index(struct session *s, cons 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 sessions ss; + struct winlink *wl; + u_int i; + + /* 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); + for (i = 0; i < ARRAY_LENGTH(&sessions); i++) { + if ((s = ARRAY_ITEM(&sessions, i)) == NULL) + continue; + if (winlink_find_by_window(&s->windows, wp->window) != NULL) + ARRAY_ADD(&ss, s); + } + s = cmd_choose_session(&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] == ':') @@ -672,11 +735,12 @@ cmd_find_session(struct cmd_ctx *ctx, co 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 @@ -694,6 +758,14 @@ cmd_find_window(struct cmd_ctx *ctx, con 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; @@ -986,6 +1058,12 @@ cmd_find_pane(struct cmd_ctx *ctx, if (arg == NULL) { *wpp = s->curw->window->active; return (s->curw); + } + + /* Lookup as pane id. */ + if ((*wpp = cmd_lookup_paneid(arg)) != NULL) { + *sp = cmd_pane_session(ctx, *wpp, &wl); + return (wl); } /* Look for a separating period. */ Index: server.c =================================================================== RCS file: /cvs/src/usr.bin/tmux/server.c,v retrieving revision 1.96 diff -u -p -r1.96 server.c --- server.c 18 Oct 2010 20:00:02 -0000 1.96 +++ server.c 13 Nov 2010 18:02:40 -0000 @@ -145,6 +145,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); ARRAY_INIT(&sessions); Index: tmux.h =================================================================== RCS file: /cvs/src/usr.bin/tmux/tmux.h,v retrieving revision 1.246 diff -u -p -r1.246 tmux.h --- tmux.h 11 Nov 2010 20:51:30 -0000 1.246 +++ tmux.h 13 Nov 2010 18:02:41 -0000 @@ -781,6 +781,8 @@ struct window_mode { /* Child window structure. */ struct window_pane { + u_int id; + struct window *window; struct layout_cell *layout_cell; @@ -823,8 +825,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 { @@ -1833,8 +1837,11 @@ int screen_check_selection(struct scree /* 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); @@ -1868,6 +1875,7 @@ struct window_pane *window_pane_previous 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 *, Index: window.c =================================================================== RCS file: /cvs/src/usr.bin/tmux/window.c,v retrieving revision 1.58 diff -u -p -r1.58 window.c --- window.c 23 Oct 2010 13:04:34 -0000 1.58 +++ window.c 13 Nov 2010 18:02:42 -0000 @@ -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 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) { @@ -461,6 +475,16 @@ window_destroy_panes(struct window *w) } } +/* 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) { @@ -469,6 +493,9 @@ window_pane_create(struct window *w, u_i 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; @@ -521,6 +548,8 @@ window_pane_destroy(struct window_pane * 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) @@ -536,7 +565,7 @@ window_pane_spawn(struct window_pane *wp { struct winsize ws; int mode; - char *argv0; + char *argv0, paneid[16]; const char *ptr; struct termios tio2; @@ -583,6 +612,8 @@ window_pane_spawn(struct window_pane *wp closefrom(STDERR_FILENO + 1); + xsnprintf(paneid, sizeof paneid, "%%%u", wp->id); + environ_set(env, "TMUX_PANE", paneid); environ_push(env); clear_signals(1); On Sat, Nov 13, 2010 at 04:53:56PM +0000, Nicholas Marriott wrote: > Other problem is this could be reused... maybe an ever-increasing pane > id is a better move. > > > On Sat, Nov 13, 2010 at 04:51:23PM +0000, Nicholas Marriott wrote: > > > > > > > > Also, since panes and such can move around, tracking a specific pane to > > > > interact with via scripts and such can be hard. Would it be possible to > > > > have tmux inject a TMUX_PANE_ID into a pane's environment that is static > > > > and unique for the life of the pane so that panes can always be reached? > > > > Maybe using '%' as an ID identifier in target commands would be > > > > possible. Commands to query for the current pane with focus and get back > > > > its address and ID would also make sense. > > > > > > This is a nice idea, I'll add it to the todo list. > > > > I was thinking about this and in fact every pane already has a unique > > identifier - the name of the slave side of the pty. So if we just made > > it so that you could pass that as a pane target and so the pty was in eg > > list-panes, it'd work. > > > > It isn't in the environment, but we could put it in as part of $TMUX or > > in $TMUX_TTY or something (probably the latter, I regret making TMUX > > compound rather than separate variables). > > > > Only problem is confusion with client identifiers which use their pty. > > > > > > > > > > > > > This problem arises in screen.vim[1] which cannot reliably track a tmux > > > > pane to interact with a specific one. > > > > > > > > --Ben > > > > > > > > [1]https://github.com/ervandew/screen > > > > > > > > > > > > > ------------------------------------------------------------------------------ > > > > Centralized Desktop Delivery: Dell and VMware Reference Architecture > > > > Simplifying enterprise desktop deployment and management using > > > > Dell EqualLogic storage and VMware View: A highly scalable, end-to-end > > > > client virtualization framework. Read more! > > > > http://p.sf.net/sfu/dell-eql-dev2dev > > > > > > > _______________________________________________ > > > > tmux-users mailing list > > > > tmux-users@lists.sourceforge.net > > > > https://lists.sourceforge.net/lists/listinfo/tmux-users > > > > > > > ------------------------------------------------------------------------------ > > Centralized Desktop Delivery: Dell and VMware Reference Architecture > > Simplifying enterprise desktop deployment and management using > > Dell EqualLogic storage and VMware View: A highly scalable, end-to-end > > client virtualization framework. Read more! > > http://p.sf.net/sfu/dell-eql-dev2dev > > _______________________________________________ > > tmux-users mailing list > > tmux-users@lists.sourceforge.net > > https://lists.sourceforge.net/lists/listinfo/tmux-users ------------------------------------------------------------------------------ Centralized Desktop Delivery: Dell and VMware Reference Architecture Simplifying enterprise desktop deployment and management using Dell EqualLogic storage and VMware View: A highly scalable, end-to-end client virtualization framework. Read more! http://p.sf.net/sfu/dell-eql-dev2dev _______________________________________________ tmux-users mailing list tmux-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/tmux-users