summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmd-break-pane.c25
-rw-r--r--cmd-clear-history.c23
-rw-r--r--cmd-generic.c90
-rw-r--r--cmd-kill-pane.c23
-rw-r--r--cmd-resize-pane.c25
-rw-r--r--cmd-select-pane.c25
-rw-r--r--cmd-swap-pane.c263
-rw-r--r--cmd.c85
-rw-r--r--tmux.169
-rw-r--r--tmux.h20
10 files changed, 235 insertions, 413 deletions
diff --git a/cmd-break-pane.c b/cmd-break-pane.c
index 6a237c6d..57622119 100644
--- a/cmd-break-pane.c
+++ b/cmd-break-pane.c
@@ -30,39 +30,30 @@ int cmd_break_pane_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_break_pane_entry = {
"break-pane", "breakp",
- CMD_PANE_WINDOW_USAGE " [-d]",
+ CMD_TARGET_PANE_USAGE " [-d]",
0, CMD_CHFLAG('d'),
- cmd_pane_init,
- cmd_pane_parse,
+ cmd_target_init,
+ cmd_target_parse,
cmd_break_pane_exec,
- cmd_pane_free,
- cmd_pane_print
+ cmd_target_free,
+ cmd_target_print
};
int
cmd_break_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{
- struct cmd_pane_data *data = self->data;
+ struct cmd_target_data *data = self->data;
struct winlink *wl;
struct session *s;
struct window_pane *wp;
struct window *w;
char *cause;
- if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL)
+ if ((wl = cmd_find_pane(ctx, data->target, &s, &wp)) == NULL)
return (-1);
- if (data->pane == -1)
- wp = wl->window->active;
- else {
- wp = window_pane_at_index(wl->window, data->pane);
- if (wp == NULL) {
- ctx->error(ctx, "no pane: %d", data->pane);
- return (-1);
- }
- }
if (window_count_panes(wl->window) == 1) {
- ctx->error(ctx, "can't break pane: %d", data->pane);
+ ctx->error(ctx, "can't break with only one pane");
return (-1);
}
diff --git a/cmd-clear-history.c b/cmd-clear-history.c
index 2e4c118d..0a87b9b0 100644
--- a/cmd-clear-history.c
+++ b/cmd-clear-history.c
@@ -28,34 +28,25 @@ int cmd_clear_history_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_clear_history_entry = {
"clear-history", "clearhist",
- CMD_PANE_WINDOW_USAGE,
+ CMD_TARGET_PANE_USAGE,
0, 0,
- cmd_pane_init,
- cmd_pane_parse,
+ cmd_target_init,
+ cmd_target_parse,
cmd_clear_history_exec,
- cmd_pane_free,
- cmd_pane_print
+ cmd_target_free,
+ cmd_target_print
};
int
cmd_clear_history_exec(struct cmd *self, struct cmd_ctx *ctx)
{
- struct cmd_pane_data *data = self->data;
+ struct cmd_target_data *data = self->data;
struct winlink *wl;
struct window_pane *wp;
struct grid *gd;
- if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
+ if ((wl = cmd_find_pane(ctx, data->target, NULL, &wp)) == NULL)
return (-1);
- if (data->pane == -1)
- wp = wl->window->active;
- else {
- wp = window_pane_at_index(wl->window, data->pane);
- if (wp == NULL) {
- ctx->error(ctx, "no pane: %d", data->pane);
- return (-1);
- }
- }
gd = wp->base.grid;
grid_move_lines(gd, 0, gd->hsize, gd->sy);
diff --git a/cmd-generic.c b/cmd-generic.c
index 39c18d51..92d9a9bd 100644
--- a/cmd-generic.c
+++ b/cmd-generic.c
@@ -467,93 +467,3 @@ cmd_option_print(struct cmd *self, char *buf, size_t len)
off += xsnprintf(buf + off, len - off, " %s", data->value);
return (off);
}
-
-void
-cmd_pane_init(struct cmd *self, unused int key)
-{
- struct cmd_pane_data *data;
-
- self->data = data = xmalloc(sizeof *data);
- data->chflags = 0;
- data->target = NULL;
- data->arg = NULL;
- data->pane = -1;
-}
-
-int
-cmd_pane_parse(struct cmd *self, int argc, char **argv, char **cause)
-{
- struct cmd_pane_data *data;
- const struct cmd_entry *entry = self->entry;
- int opt, n;
- const char *errstr;
-
- /* Don't use the entry version since it may be dependent on key. */
- cmd_pane_init(self, 0);
- data = self->data;
-
- while ((opt = cmd_getopt(argc, argv, "p:t:", entry->chflags)) != -1) {
- if (cmd_flags(opt, entry->chflags, &data->chflags) == 0)
- continue;
- switch (opt) {
- case 'p':
- if (data->pane == -1) {
- n = strtonum(optarg, 0, INT_MAX, &errstr);
- if (errstr != NULL) {
- xasprintf(cause, "pane %s", errstr);
- goto error;
- }
- data->pane = n;
- }
- break;
- case 't':
- if (data->target == NULL)
- data->target = xstrdup(optarg);
- break;
- default:
- goto usage;
- }
- }
- argc -= optind;
- argv += optind;
-
- if (cmd_fill_argument(self->entry->flags, &data->arg, argc, argv) != 0)
- goto usage;
- return (0);
-
-usage:
- xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
-
-error:
- self->entry->free(self);
- return (-1);
-}
-
-void
-cmd_pane_free(struct cmd *self)
-{
- struct cmd_pane_data *data = self->data;
-
- if (data->target != NULL)
- xfree(data->target);
- if (data->arg != NULL)
- xfree(data->arg);
- xfree(data);
-}
-
-size_t
-cmd_pane_print(struct cmd *self, char *buf, size_t len)
-{
- struct cmd_pane_data *data = self->data;
- size_t off = 0;
-
- off += xsnprintf(buf, len, "%s", self->entry->name);
- if (data == NULL)
- return (off);
- off += cmd_print_flags(buf, len, off, data->chflags);
- if (off < len && data->target != NULL)
- off += cmd_prarg(buf + off, len - off, " -t ", data->target);
- if (off < len && data->arg != NULL)
- off += cmd_prarg(buf + off, len - off, " ", data->arg);
- return (off);
-}
diff --git a/cmd-kill-pane.c b/cmd-kill-pane.c
index 14b07c82..1548a75e 100644
--- a/cmd-kill-pane.c
+++ b/cmd-kill-pane.c
@@ -30,33 +30,24 @@ int cmd_kill_pane_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_kill_pane_entry = {
"kill-pane", "killp",
- CMD_PANE_WINDOW_USAGE,
+ CMD_TARGET_PANE_USAGE,
0, 0,
- cmd_pane_init,
- cmd_pane_parse,
+ cmd_target_init,
+ cmd_target_parse,
cmd_kill_pane_exec,
- cmd_pane_free,
- cmd_pane_print
+ cmd_target_free,
+ cmd_target_print
};
int
cmd_kill_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{
- struct cmd_pane_data *data = self->data;
+ struct cmd_target_data *data = self->data;
struct winlink *wl;
struct window_pane *wp;
- if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
+ if ((wl = cmd_find_pane(ctx, data->target, NULL, &wp)) == NULL)
return (-1);
- if (data->pane == -1)
- wp = wl->window->active;
- else {
- wp = window_pane_at_index(wl->window, data->pane);
- if (wp == NULL) {
- ctx->error(ctx, "no pane: %d", data->pane);
- return (-1);
- }
- }
if (window_count_panes(wl->window) == 1) {
/* Only one pane, kill the window. */
diff --git a/cmd-resize-pane.c b/cmd-resize-pane.c
index f7928803..30fbc76a 100644
--- a/cmd-resize-pane.c
+++ b/cmd-resize-pane.c
@@ -31,22 +31,22 @@ int cmd_resize_pane_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_resize_pane_entry = {
"resize-pane", "resizep",
- CMD_PANE_WINDOW_USAGE "[-DU] [adjustment]",
+ "[-DU] " CMD_TARGET_PANE_USAGE " [adjustment]",
CMD_ARG01,
CMD_CHFLAG('D')|CMD_CHFLAG('L')|CMD_CHFLAG('R')|CMD_CHFLAG('U'),
cmd_resize_pane_init,
- cmd_pane_parse,
+ cmd_target_parse,
cmd_resize_pane_exec,
- cmd_pane_free,
- cmd_pane_print
+ cmd_target_free,
+ cmd_target_print
};
void
cmd_resize_pane_init(struct cmd *self, int key)
{
- struct cmd_pane_data *data;
+ struct cmd_target_data *data;
- cmd_pane_init(self, key);
+ cmd_target_init(self, key);
data = self->data;
if (key == (KEYC_UP | KEYC_CTRL))
@@ -79,23 +79,14 @@ cmd_resize_pane_init(struct cmd *self, int key)
int
cmd_resize_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{
- struct cmd_pane_data *data = self->data;
+ struct cmd_target_data *data = self->data;
struct winlink *wl;
const char *errstr;
struct window_pane *wp;
u_int adjust;
- if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
+ if ((wl = cmd_find_pane(ctx, data->target, NULL, &wp)) == NULL)
return (-1);
- if (data->pane == -1)
- wp = wl->window->active;
- else {
- wp = window_pane_at_index(wl->window, data->pane);
- if (wp == NULL) {
- ctx->error(ctx, "no pane: %d", data->pane);
- return (-1);
- }
- }
if (data->arg == NULL)
adjust = 1;
diff --git a/cmd-select-pane.c b/cmd-select-pane.c
index 055c2e3b..3923ea73 100644
--- a/cmd-select-pane.c
+++ b/cmd-select-pane.c
@@ -28,36 +28,27 @@ int cmd_select_pane_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_select_pane_entry = {
"select-pane", "selectp",
- CMD_PANE_WINDOW_USAGE,
+ CMD_TARGET_PANE_USAGE,
0, 0,
- cmd_pane_init,
- cmd_pane_parse,
+ cmd_target_init,
+ cmd_target_parse,
cmd_select_pane_exec,
- cmd_pane_free,
- cmd_pane_print
+ cmd_target_free,
+ cmd_target_print
};
int
cmd_select_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{
- struct cmd_pane_data *data = self->data;
+ struct cmd_target_data *data = self->data;
struct winlink *wl;
struct window_pane *wp;
- if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
+ if ((wl = cmd_find_pane(ctx, data->target, NULL, &wp)) == NULL)
return (-1);
- if (data->pane == -1)
- wp = wl->window->active;
- else {
- wp = window_pane_at_index(wl->window, data->pane);
- if (wp == NULL) {
- ctx->error(ctx, "no pane: %d", data->pane);
- return (-1);
- }
- }
if (!window_pane_visible(wp)) {
- ctx->error(ctx, "pane %d is not visible", data->pane);
+ ctx->error(ctx, "pane not visible: %s", data->target);
return (-1);
}
window_set_active_pane(wl->window, wp);
diff --git a/cmd-swap-pane.c b/cmd-swap-pane.c
index 7222e12c..4516d2ca 100644
--- a/cmd-swap-pane.c
+++ b/cmd-swap-pane.c
@@ -26,191 +26,93 @@
* Swap two panes.
*/
-int cmd_swap_pane_parse(struct cmd *, int, char **, char **);
-int cmd_swap_pane_exec(struct cmd *, struct cmd_ctx *);
-void cmd_swap_pane_free(struct cmd *);
void cmd_swap_pane_init(struct cmd *, int);
-size_t cmd_swap_pane_print(struct cmd *, char *, size_t);
-
-struct cmd_swap_pane_data {
- char *target;
- int src;
- int dst;
- int flag_detached;
- int flag_up;
- int flag_down;
-};
+int cmd_swap_pane_exec(struct cmd *, struct cmd_ctx *);
const struct cmd_entry cmd_swap_pane_entry = {
"swap-pane", "swapp",
- "[-dDU] [-t target-window] [-p src-index] [-q dst-index]",
- 0, 0,
+ "[-dDU] " CMD_SRCDST_PANE_USAGE,
+ 0, CMD_CHFLAG('d')|CMD_CHFLAG('D')|CMD_CHFLAG('U'),
cmd_swap_pane_init,
- cmd_swap_pane_parse,
+ cmd_srcdst_parse,
cmd_swap_pane_exec,
- cmd_swap_pane_free,
- cmd_swap_pane_print
+ cmd_srcdst_free,
+ cmd_srcdst_print
};
void
cmd_swap_pane_init(struct cmd *self, int key)
{
- struct cmd_swap_pane_data *data;
-
- self->data = data = xmalloc(sizeof *data);
- data->target = NULL;
- data->src = -1;
- data->dst = -1;
- data->flag_detached = 0;
- data->flag_up = 0;
- data->flag_down = 0;
-
- switch (key) {
- case '{':
- data->flag_up = 1;
- break;
- case '}':
- data->flag_down = 1;
- break;
- }
-}
-
-int
-cmd_swap_pane_parse(struct cmd *self, int argc, char **argv, char **cause)
-{
- struct cmd_swap_pane_data *data;
- int opt, n;
- const char *errstr;
+ struct cmd_target_data *data;
- self->entry->init(self, 0);
+ cmd_srcdst_init(self, key);
data = self->data;
- while ((opt = getopt(argc, argv, "dDt:p:q:U")) != -1) {
- switch (opt) {
- case 'd':
- data->flag_detached = 1;
- break;
- case 'D':
- data->flag_up = 0;
- data->flag_down = 1;
- data->dst = -1;
- break;
- case 't':
- if (data->target == NULL)
- data->target = xstrdup(optarg);
- break;
- case 'p':
- if (data->src == -1) {
- n = strtonum(optarg, 0, INT_MAX, &errstr);
- if (errstr != NULL) {
- xasprintf(cause, "src %s", errstr);
- goto error;
- }
- data->src = n;
- }
- break;
- case 'q':
- if (data->dst == -1) {
- n = strtonum(optarg, 0, INT_MAX, &errstr);
- if (errstr != NULL) {
- xasprintf(cause, "dst %s", errstr);
- goto error;
- }
- data->dst = n;
- }
- data->flag_up = 0;
- data->flag_down = 0;
- break;
- case 'U':
- data->flag_up = 1;
- data->flag_down = 0;
- data->dst = -1;
- break;
-
- default:
- goto usage;
- }
- }
- argc -= optind;
- argv += optind;
- if (argc != 0)
- goto usage;
-
- return (0);
-
-usage:
- xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
-
-error:
- self->entry->free(self);
- return (-1);
+ if (key == '{')
+ data->chflags |= CMD_CHFLAG('U');
+ else if (key == '}')
+ data->chflags |= CMD_CHFLAG('D');
}
int
cmd_swap_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
{
- struct cmd_swap_pane_data *data = self->data;
- struct winlink *wl;
- struct window *w;
- struct window_pane *tmp_wp, *src_wp, *dst_wp;
- struct layout_cell *lc;
- u_int sx, sy, xoff, yoff;
+ struct cmd_srcdst_data *data = self->data;
+ struct winlink *src_wl, *dst_wl;
+ struct window *src_w, *dst_w;
+ struct window_pane *tmp_wp, *src_wp, *dst_wp;
+ struct layout_cell *src_lc, *dst_lc;
+ u_int sx, sy, xoff, yoff;
if (data == NULL)
return (0);
- if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL)
+ if ((dst_wl = cmd_find_pane(ctx, data->dst, NULL, &dst_wp)) == NULL)
return (-1);
- w = wl->window;
-
- if (data->src == -1)
- src_wp = w->active;
- else {
- src_wp = window_pane_at_index(w, data->src);
- if (src_wp == NULL) {
- ctx->error(ctx, "no pane: %d", data->src);
- return (-1);
- }
- }
- if (data->dst == -1)
- dst_wp = w->active;
- else {
- dst_wp = window_pane_at_index(w, data->dst);
- if (dst_wp == NULL) {
- ctx->error(ctx, "no pane: %d", data->dst);
+ dst_w = dst_wl->window;
+
+ if (data->src == NULL) {
+ src_wl = dst_wl;
+ src_w = dst_w;
+ if (data->chflags & CMD_CHFLAG('D')) {
+ src_wp = TAILQ_NEXT(dst_wp, entry);
+ if (src_wp == NULL)
+ src_wp = TAILQ_FIRST(&dst_w->panes);
+ } else if (data->chflags & CMD_CHFLAG('U')) {
+ src_wp = TAILQ_PREV(dst_wp, window_panes, entry);
+ if (src_wp == NULL)
+ src_wp = TAILQ_LAST(&dst_w->panes, window_panes);
+ } else
+ return (0);
+ } else {
+ src_wl = cmd_find_pane(ctx, data->src, NULL, &src_wp);
+ if (src_wl == NULL)
return (-1);
- }
- }
-
- if (data->dst == -1 && data->flag_up) {
- if ((dst_wp = TAILQ_PREV(src_wp, window_panes, entry)) == NULL)
- dst_wp = TAILQ_LAST(&w->panes, window_panes);
- }
- if (data->dst == -1 && data->flag_down) {
- if ((dst_wp = TAILQ_NEXT(src_wp, entry)) == NULL)
- dst_wp = TAILQ_FIRST(&w->panes);
+ src_w = src_wl->window;
}
if (src_wp == dst_wp)
return (0);
tmp_wp = TAILQ_PREV(dst_wp, window_panes, entry);
- TAILQ_REMOVE(&w->panes, dst_wp, entry);
- TAILQ_REPLACE(&w->panes, src_wp, dst_wp, entry);
+ TAILQ_REMOVE(&dst_w->panes, dst_wp, entry);
+ TAILQ_REPLACE(&src_w->panes, src_wp, dst_wp, entry);
if (tmp_wp == src_wp)
tmp_wp = dst_wp;
if (tmp_wp == NULL)
- TAILQ_INSERT_HEAD(&w->panes, src_wp, entry);
+ TAILQ_INSERT_HEAD(&dst_w->panes, src_wp, entry);
else
- TAILQ_INSERT_AFTER(&w->panes, tmp_wp, src_wp, entry);
-
- lc = src_wp->layout_cell;
- src_wp->layout_cell = dst_wp->layout_cell;
- if (src_wp->layout_cell != NULL)
- src_wp->layout_cell->wp = src_wp;
- dst_wp->layout_cell = lc;
- if (dst_wp->layout_cell != NULL)
- dst_wp->layout_cell->wp = dst_wp;
+ TAILQ_INSERT_AFTER(&dst_w->panes, tmp_wp, src_wp, entry);
+
+ src_lc = src_wp->layout_cell;
+ dst_lc = dst_wp->layout_cell;
+ src_lc->wp = dst_wp;
+ dst_wp->layout_cell = src_lc;
+ dst_lc->wp = src_wp;
+ src_wp->layout_cell = dst_lc;
+
+ src_wp->window = dst_w;
+ dst_wp->window = src_w;
sx = src_wp->sx; sy = src_wp->sy;
xoff = src_wp->xoff; yoff = src_wp->yoff;
@@ -219,51 +121,24 @@ cmd_swap_pane_exec(struct cmd *self, struct cmd_ctx *ctx)
dst_wp->xoff = xoff; dst_wp->yoff = yoff;
window_pane_resize(dst_wp, sx, sy);
- if (!data->flag_detached) {
- tmp_wp = dst_wp;
- if (!window_pane_visible(tmp_wp))
- tmp_wp = src_wp;
- window_set_active_pane(w, tmp_wp);
+ if (!(data->chflags & CMD_CHFLAG('d'))) {
+ if (src_w != dst_w) {
+ window_set_active_pane(src_w, dst_wp);
+ window_set_active_pane(dst_w, src_wp);
+ } else {
+ tmp_wp = dst_wp;
+ if (!window_pane_visible(tmp_wp))
+ tmp_wp = src_wp;
+ window_set_active_pane(src_w, tmp_wp);
+ }
+ } else {
+ if (src_w->active == src_wp)
+ window_set_active_pane(src_w, dst_wp);
+ if (dst_w->active == dst_wp)
+ window_set_active_pane(dst_w, src_wp);
}
- server_redraw_window(w);
+ server_redraw_window(src_w);
+ server_redraw_window(dst_w);
return (0);
}
-
-void
-cmd_swap_pane_free(struct cmd *self)
-{
- struct cmd_swap_pane_data *data = self->data;
-
- if (data->target != NULL)
- xfree(data->target);
- xfree(data);
-}
-
-size_t
-cmd_swap_pane_print(struct cmd *self, char *buf, size_t len)
-{
- struct cmd_swap_pane_data *data = self->data;
- size_t off = 0;
-
- off += xsnprintf(buf, len, "%s", self->entry->name);
- if (data == NULL)
- return (off);
- if (off < len &&
- (data->flag_down || data->flag_up || data->flag_detached)) {
- off += xsnprintf(buf + off, len - off, " -");
- if (off < len && data->flag_detached)
- off += xsnprintf(buf + off, len - off, "d");
- if (off < len && data->flag_up)
- off += xsnprintf(buf + off, len - off, "D");
- if (off < len && data->flag_down)
- off += xsnprintf(buf + off, len - off, "U");
- }
- if (off < len && data->target != NULL)
- off += cmd_prarg(buf + off, len - off, " -t ", data->target);
- if (off < len && data->src != -1)
- off += xsnprintf(buf + off, len - off, " -p %d", data->src);
- if (off < len && data->dst != -1)
- off += xsnprintf(buf + off, len - off, " -q %d", data->dst);
- return (off);
-}
diff --git a/cmd.c b/cmd.c
index 820521d0..31b80b50 100644
--- a/cmd.c
+++ b/cmd.c
@@ -771,3 +771,88 @@ not_found:
xfree(sessptr);
return (-2);
}
+
+/*
+ * Find the target session, window and pane number or report an error and
+ * return NULL. The pane number is separated from the session:window by a .,
+ * such as mysession:mywindow.0.
+ */
+struct winlink *
+cmd_find_pane(struct cmd_ctx *ctx,
+ const char *arg, struct session **sp, struct window_pane **wpp)
+{
+ struct session *s;
+ struct winlink *wl;
+ const char *period;
+ char *winptr, *paneptr;
+ const char *errstr;
+ u_int idx;
+
+ /* Get the current session. */
+ if ((s = cmd_current_session(ctx)) == NULL) {
+ ctx->error(ctx, "can't establish current session");
+ return (NULL);
+ }
+ if (sp != NULL)
+ *sp = s;
+
+ /* A NULL argument means the current session, window and pane. */
+ if (arg == NULL) {
+ *wpp = s->curw->window->active;
+ return (s->curw);
+ }
+
+ /* Look for a separating period. */
+ if ((period = strrchr(arg, '.')) == NULL)
+ goto no_period;
+
+ /* Pull out the window part and parse it. */
+ winptr = xstrdup(arg);
+ winptr[period - arg] = '\0';
+ if (*winptr == '\0')
+ wl = s->curw;
+ else if ((wl = cmd_find_window(ctx, winptr, sp)) == NULL)
+ goto error;
+
+ /* Find the pane section and look it up. */
+ paneptr = winptr + (period - arg) + 1;
+ if (*paneptr == '\0')
+ *wpp = wl->window->active;
+ else {
+ idx = strtonum(paneptr, 0, INT_MAX, &errstr);
+ if (errstr != NULL) {
+ ctx->error(ctx, "pane %s: %s", errstr, paneptr);
+ goto error;
+ }
+ *wpp = window_pane_at_index(wl->window, idx);
+ if (*wpp == NULL) {
+ ctx->error(ctx, "no such pane: %u", idx);
+ goto error;
+ }
+ }
+
+ xfree(winptr);
+ return (wl);
+
+no_period:
+ /* Try as a pane number alone. */
+ idx = strtonum(arg, 0, INT_MAX, &errstr);
+ if (errstr != NULL)
+ goto lookup_window;
+
+ /* Try index in the current session and window. */
+ if ((*wpp = window_pane_at_index(s->curw->window, idx)) == NULL)
+ goto lookup_window;
+
+ return (s->curw);
+
+lookup_window:
+ /* Try as a window and use the active pane. */
+ if ((wl = cmd_find_window(ctx, arg, sp)) != NULL)
+ *wpp = wl->window->active;
+ return (wl);
+
+error:
+ xfree(winptr);
+ return (NULL);
+}
diff --git a/tmux.1 b/tmux.1
index e23ebaaa..7a2a3bf2 100644
--- a/tmux.1
+++ b/tmux.1
@@ -534,9 +534,10 @@ Most commands accept the optional
argument with one of
.Ar target-client ,
.Ar target-session
+.Ar target-window ,
or
-.Ar target-window .
-These specify the client, session or window which a command should affect.
+.Ar target-pane .
+These specify the client, session, window or pane which a command should affect.
.Ar target-client
is the name of the
.Xr pty 4
@@ -598,6 +599,19 @@ When the argument does not contain a colon,
first attempts to parse it as window; if that fails, an attempt is made to
match a session.
.Pp
+.Ar target-pane
+takes a similar form to
+.Ar target-window
+but with the optional addition of a period followed by a pane index, for
+example: mysession:mywindow.1.
+If the pane index is omitted, the currently active pane in the specified
+window is used.
+If neither a colon nor period appears,
+.Nm
+first attempts to use the argument as a pane index; if that fails, it is looked
+up as for
+.Ar target-window .
+.Pp
Multiple commands may be specified together as part of a
.Em command sequence .
Each command should be separated by spaces and a semicolon;
@@ -687,12 +701,12 @@ To view the default bindings and possible commands, see the
command.
.It Xo Ic break-pane
.Op Fl d
-.Op Fl p Ar pane-index
-.Op Fl t Ar target-window
+.Op Fl t Ar target-pane
.Xc
.D1 (alias: Ic breakp )
-Break the current pane off from its containing window to make it the only pane
-in a new window.
+Break
+.Ar target-pane
+off from its containing window to make it the only pane in a new window.
If
.Fl d
is given, the new window does not become the current window.
@@ -711,8 +725,7 @@ attached to the current client may be selected interactively from a list.
This command works only from inside
.Nm .
.It Xo Ic clear-history
-.Op Fl p Ar pane-index
-.Op Fl t Ar target-window
+.Op Fl t Ar target-pane
.Xc
.D1 (alias: Ic clearhist )
Remove and free the history for the specified pane.
@@ -782,8 +795,7 @@ Display a message (see the
option below)
in the status line.
.It Xo Ic down-pane
-.Op Fl p Ar pane-index
-.Op Fl t Ar target-window
+.Op Fl t Ar target-pane
.Xc
.D1 (alias: Ic downp )
Move down a pane.
@@ -818,8 +830,7 @@ if
.Ar shell-command
returns success.
.It Xo Ic kill-pane
-.Op Fl p Ar pane-index
-.Op Fl t Ar target-window
+.Op Fl t Ar target-pane
.Xc
.D1 (alias: Ic killp )
Destroy the given pane.
@@ -1058,8 +1069,7 @@ if specified, to
.Ar new-name .
.It Xo Ic resize-pane
.Op Fl DLRU
-.Op Fl p Ar pane-index
-.Op Fl t Ar target-window
+.Op Fl t Ar target-pane
.Op Ar adjustment
.Xc
.D1 (alias: Ic resizep )
@@ -1130,12 +1140,11 @@ If
.Ar layout-name
is not given, the last layout used (if any) is reapplied.
.It Xo Ic select-pane
-.Op Fl p Ar pane-index
-.Op Fl t Ar target-window
+.Op Fl t Ar target-pane
.Xc
.D1 (alias: Ic selectp )
Make pane
-.Ar pane-index
+.Ar target-pane
the active pane in window
.Ar target-window .
.It Xo Ic select-prompt
@@ -1297,11 +1306,9 @@ Whether a key repeats may be set when it is bound using the
.Fl r
flag to
.Ic bind-key .
-Repeat is enabled for the default keys of the
-.Ic resize-pane-up
-and
-.Ic resize-pane-down
-commands.
+Repeat is enabled for the default keys bound to the
+.Ic resize-pane
+command.
.It Xo Ic set-remain-on-exit
.Op Ic on | Ic off
.Xc
@@ -1659,19 +1666,18 @@ Suspend a client by sending
(tty stop).
.It Xo Ic swap-pane
.Op Fl dDU
-.Op Fl p Ar src-index
-.Op Fl t Ar target-window
-.Op Fl q Ar dst-index
+.Op Fl s Ar src-pane
+.Op Fl t Ar dst-pane
.Xc
.D1 (alias: Ic swapp )
-Swap two panes within a window.
+Swap two panes.
If
.Fl U
-is used, the pane is swapped with the pane above (before it numerically);
+is used and no source pane is specified with
+.Fl s ,
+.Ar dst-pane is swapped with the previous pane (before it numerically);
.Fl D
-swaps with the pane below (the next numerically); or
-.Ar dst-index
-may be give to swap with a specific pane.
+swaps with the next pane (after it numerically).
.It Xo Ic swap-window
.Op Fl d
.Op Fl s Ar src-window
@@ -1733,8 +1739,7 @@ if
is specified and the window is linked to only one session, it is unlinked and
destroyed.
.It Xo Ic up-pane
-.Op Fl p Ar pane-index
-.Op Fl t Ar target-window
+.Op Fl t Ar target-pane
.Xc
.D1 (alias: Ic upp )
Move up a pane.
diff --git a/tmux.h b/tmux.h
index f16652a7..900aa200 100644
--- a/tmux.h
+++ b/tmux.h
@@ -1023,13 +1023,6 @@ struct cmd_option_data {
char *value;
};
-struct cmd_pane_data {
- uint64_t chflags;
- char *target;
- char *arg;
- int pane;
-};
-
/* Key binding. */
struct key_binding {
int key;
@@ -1222,6 +1215,8 @@ struct winlink *cmd_find_window(
struct cmd_ctx *, const char *, struct session **);
int cmd_find_index(
struct cmd_ctx *, const char *, struct session **);
+struct winlink *cmd_find_pane(struct cmd_ctx *,
+ const char *, struct session **, struct window_pane **);
extern const struct cmd_entry *cmd_table[];
extern const struct cmd_entry cmd_attach_session_entry;
extern const struct cmd_entry cmd_bind_key_entry;
@@ -1307,6 +1302,7 @@ int cmd_string_parse(const char *, struct cmd_list **, char **);
/* cmd-generic.c */
size_t cmd_prarg(char *, size_t, const char *, char *);
+#define CMD_TARGET_PANE_USAGE "[-t target-pane]"
#define CMD_TARGET_WINDOW_USAGE "[-t target-window]"
#define CMD_TARGET_SESSION_USAGE "[-t target-session]"
#define CMD_TARGET_CLIENT_USAGE "[-t target-client]"
@@ -1314,6 +1310,7 @@ void cmd_target_init(struct cmd *, int);
int cmd_target_parse(struct cmd *, int, char **, char **);
void cmd_target_free(struct cmd *);
size_t cmd_target_print(struct cmd *, char *, size_t);
+#define CMD_SRCDST_PANE_USAGE "[-s src-pane] [-t dst-pane]"
#define CMD_SRCDST_WINDOW_USAGE "[-s src-window] [-t dst-window]"
#define CMD_SRCDST_SESSION_USAGE "[-s src-session] [-t dst-session]"
#define CMD_SRCDST_CLIENT_USAGE "[-s src-client] [-t dst-client]"
@@ -1321,6 +1318,7 @@ void cmd_srcdst_init(struct cmd *, int);
int cmd_srcdst_parse(struct cmd *, int, char **, char **);
void cmd_srcdst_free(struct cmd *);
size_t cmd_srcdst_print(struct cmd *, char *, size_t);
+#define CMD_BUFFER_PANE_USAGE "[-b buffer-index] [-t target-pane]"
#define CMD_BUFFER_WINDOW_USAGE "[-b buffer-index] [-t target-window]"
#define CMD_BUFFER_SESSION_USAGE "[-b buffer-index] [-t target-session]"
#define CMD_BUFFER_CLIENT_USAGE "[-b buffer-index] [-t target-client]"
@@ -1328,6 +1326,7 @@ void cmd_buffer_init(struct cmd *, int);
int cmd_buffer_parse(struct cmd *, int, char **, char **);
void cmd_buffer_free(struct cmd *);
size_t cmd_buffer_print(struct cmd *, char *, size_t);
+#define CMD_OPTION_PANE_USAGE "[-gu] [-t target-pane] option [value]"
#define CMD_OPTION_WINDOW_USAGE "[-gu] [-t target-window] option [value]"
#define CMD_OPTION_SESSION_USAGE "[-gu] [-t target-session] option [value]"
#define CMD_OPTION_CLIENT_USAGE "[-gu] [-t target-client] option [value]"
@@ -1335,13 +1334,6 @@ void cmd_option_init(struct cmd *, int);
int cmd_option_parse(struct cmd *, int, char **, char **);
void cmd_option_free(struct cmd *);
size_t cmd_option_print(struct cmd *, char *, size_t);
-#define CMD_PANE_WINDOW_USAGE "[-t target-window] [-p pane-index]"
-#define CMD_PANE_SESSION_USAGE "[-t target-session] [-p pane-index]"
-#define CMD_PANE_CLIENT_USAGE "[-t target-client] [-p pane-index]"
-void cmd_pane_init(struct cmd *, int);
-int cmd_pane_parse(struct cmd *, int, char **, char **);
-void cmd_pane_free(struct cmd *);
-size_t cmd_pane_print(struct cmd *, char *, size_t);
/* client.c */
int client_init(char *, struct client_ctx *, int, int);