diff --git a/Makefile b/Makefile index e5a84a9d..a1dda3d2 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ SRCS= attributes.c cfg.c client.c clock.c \ cmd-pipe-pane.c cmd-capture-pane.c cmd.c \ colour.c environ.c grid-view.c grid-utf8.c grid.c input-keys.c \ imsg.c imsg-buffer.c input.c key-bindings.c key-string.c \ - layout-set.c layout.c log.c job.c \ + layout-set.c layout-string.c layout.c log.c job.c \ mode-key.c names.c options.c paste.c procname.c \ resize.c screen-redraw.c screen-write.c screen.c session.c status.c \ server-fn.c server.c server-client.c server-window.c \ diff --git a/cmd.c b/cmd.c index d094427b..5ad87c23 100644 --- a/cmd.c +++ b/cmd.c @@ -856,12 +856,12 @@ 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; + struct session *s; + struct winlink *wl; + struct layout_cell *lc; + const char *period, *errstr; + char *winptr, *paneptr; + u_int idx; /* Get the current session. */ if ((s = cmd_current_session(ctx)) == NULL) { @@ -895,20 +895,27 @@ cmd_find_pane(struct cmd_ctx *ctx, *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; - } + if (errstr != NULL) + goto lookup_string; *wpp = window_pane_at_index(wl->window, idx); - if (*wpp == NULL) { - ctx->error(ctx, "no such pane: %u", idx); - goto error; - } + if (*wpp == NULL) + goto lookup_string; } xfree(winptr); return (wl); +lookup_string: + /* Try pane string description. */ + if ((lc = layout_find_string(s->curw->window, paneptr)) == NULL) { + ctx->error(ctx, "can't find pane: %s", paneptr); + goto error; + } + *wpp = lc->wp; + + xfree(winptr); + return (s->curw); + no_period: /* Try as a pane number alone. */ idx = strtonum(arg, 0, INT_MAX, &errstr); @@ -922,6 +929,12 @@ no_period: return (s->curw); lookup_window: + /* Try pane string description. */ + if ((lc = layout_find_string(s->curw->window, arg)) != NULL) { + *wpp = lc->wp; + return (s->curw); + } + /* Try as a window and use the active pane. */ if ((wl = cmd_find_window(ctx, arg, sp)) != NULL) *wpp = wl->window->active; diff --git a/layout-string.c b/layout-string.c new file mode 100644 index 00000000..acaf09e4 --- /dev/null +++ b/layout-string.c @@ -0,0 +1,167 @@ +/* $Id$ */ + +/* + * Copyright (c) 2009 Nicholas Marriott + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include + +#include "tmux.h" + +/* + * Figure out the pane position based on a description. Fairly simple right + * now, just understands a set of strings: left, right, top, bottom, top-left + * top-right, bottom-left, bottom-right. + */ + +struct layout_cell *layout_find_top(struct layout_cell *); +struct layout_cell *layout_find_bottom(struct layout_cell *); +struct layout_cell *layout_find_left(struct layout_cell *); +struct layout_cell *layout_find_right(struct layout_cell *); +struct layout_cell *layout_find_topleft(struct layout_cell *); +struct layout_cell *layout_find_topright(struct layout_cell *); +struct layout_cell *layout_find_bottomleft(struct layout_cell *); +struct layout_cell *layout_find_bottomright(struct layout_cell *); + +/* Find the cell; returns NULL if string not understood. */ +struct layout_cell * +layout_find_string(struct window *w, const char *s) +{ + struct layout_cell *lc = w->layout_root; + + if (strcasecmp(s, "top") == 0) + lc = layout_find_top(lc); + else if (strcasecmp(s, "bottom") == 0) + lc = layout_find_bottom(lc); + else if (strcasecmp(s, "left") == 0) + lc = layout_find_left(lc); + else if (strcasecmp(s, "right") == 0) + lc = layout_find_right(lc); + else if (strcasecmp(s, "top-left") == 0) + lc = layout_find_topleft(lc); + else if (strcasecmp(s, "top-right") == 0) + lc = layout_find_topright(lc); + else if (strcasecmp(s, "bottom-left") == 0) + lc = layout_find_bottomleft(lc); + else if (strcasecmp(s, "bottom-right") == 0) + lc = layout_find_bottomright(lc); + + if (lc == NULL || lc->type != LAYOUT_WINDOWPANE) + return (NULL); + return (lc); +} + +/* + * Find the top cell. Because splits in the same direction are stored as a + * list, this is just the first in the list. Return NULL if no topmost cell. + * For an unnested cell (not split), the top cell is always itself. + */ +struct layout_cell * +layout_find_top(struct layout_cell *lc) +{ + if (lc->type == LAYOUT_WINDOWPANE) + return (lc); + else if (lc->type == LAYOUT_TOPBOTTOM) + return (TAILQ_FIRST(&lc->cells)); + return (NULL); +} + +/* + * Find the bottom cell. Similarly to the top cell, this is just the last in + * the list. + */ +struct layout_cell * +layout_find_bottom(struct layout_cell *lc) +{ + if (lc->type == LAYOUT_WINDOWPANE) + return (lc); + else if (lc->type == LAYOUT_TOPBOTTOM) + return (TAILQ_LAST(&lc->cells, layout_cells)); + return (NULL); +} + +/* Find the left cell. */ +struct layout_cell * +layout_find_left(struct layout_cell *lc) +{ + if (lc->type == LAYOUT_WINDOWPANE) + return (lc); + else if (lc->type == LAYOUT_LEFTRIGHT) + return (TAILQ_FIRST(&lc->cells)); + return (NULL); +} + +/* Find the right cell. */ +struct layout_cell * +layout_find_right(struct layout_cell *lc) +{ + if (lc->type == LAYOUT_WINDOWPANE) + return (lc); + else if (lc->type == LAYOUT_LEFTRIGHT) + return (TAILQ_LAST(&lc->cells, layout_cells)); + return (NULL); +} + +/* + * Find the top-left cell. This means recursing until there are no more moves + * to be made. + */ +struct layout_cell * +layout_find_topleft(struct layout_cell *lc) +{ + if (lc->type == LAYOUT_WINDOWPANE) + return (lc); + lc = TAILQ_FIRST(&lc->cells); + return (layout_find_topleft(lc)); +} + +/* Find the top-right cell. */ +struct layout_cell * +layout_find_topright(struct layout_cell *lc) +{ + if (lc->type == LAYOUT_WINDOWPANE) + return (lc); + if (lc->type == LAYOUT_LEFTRIGHT) + lc = TAILQ_LAST(&lc->cells, layout_cells); + else + lc = TAILQ_FIRST(&lc->cells); + return (layout_find_topright(lc)); +} + +/* Find the bottom-left cell. */ +struct layout_cell * +layout_find_bottomleft(struct layout_cell *lc) +{ + if (lc->type == LAYOUT_WINDOWPANE) + return (lc); + if (lc->type == LAYOUT_LEFTRIGHT) + lc = TAILQ_FIRST(&lc->cells); + else + lc = TAILQ_LAST(&lc->cells, layout_cells); + return (layout_find_bottomleft(lc)); +} + +/* Find the bottom-right cell. */ +struct layout_cell * +layout_find_bottomright(struct layout_cell *lc) +{ + if (lc->type == LAYOUT_WINDOWPANE) + return (lc); + lc = TAILQ_LAST(&lc->cells, layout_cells); + return (layout_find_bottomright(lc)); +} diff --git a/tmux.1 b/tmux.1 index bee32920..a188feaf 100644 --- a/tmux.1 +++ b/tmux.1 @@ -323,6 +323,16 @@ If neither a colon nor period appears, first attempts to use the argument as a pane index; if that fails, it is looked up as for .Ar target-window . +One of the strings +.Em top , +.Em bottom , +.Em left , +.Em right , +.Em top-left , +.Em top-right , +.Em bottom-left or +.Em bottom-right +may be used instead of a pane index. .Pp Multiple commands may be specified together as part of a .Em command sequence . diff --git a/tmux.h b/tmux.h index d73483a8..cf42a85c 100644 --- a/tmux.h +++ b/tmux.h @@ -1844,6 +1844,9 @@ u_int layout_set_next(struct window *); u_int layout_set_previous(struct window *); void layout_set_active_changed(struct window *); +/* layout-string.c */ +struct layout_cell *layout_find_string(struct window *, const char *); + /* window-clock.c */ extern const struct window_mode window_clock_mode;