From 6f04866044e7482c20bd28abd876d173093fa6ac Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Mon, 22 Mar 2010 19:07:52 +0000 Subject: [PATCH] Support up, down, left, right movement through panes with -UDLR flags to select-pane. Also REMOVE the up- and down-pane commands: equivalent behaviour is now available using -t :.+ and -t :.-. --- Makefile | 4 +- cmd-down-pane.c | 60 ------------------------- cmd-select-pane.c | 41 +++++++++++++++-- cmd-up-pane.c | 60 ------------------------- cmd.c | 20 +++++++-- key-bindings.c | 8 ++-- tmux.1 | 30 ++++++++----- tmux.h | 4 ++ window.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 194 insertions(+), 143 deletions(-) delete mode 100644 cmd-down-pane.c delete mode 100644 cmd-up-pane.c diff --git a/Makefile b/Makefile index 574f4b48..be0051ef 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ SRCS= attributes.c cfg.c client.c clock.c \ cmd-break-pane.c cmd-choose-session.c cmd-choose-window.c \ cmd-clear-history.c cmd-clock-mode.c cmd-command-prompt.c \ cmd-confirm-before.c cmd-copy-buffer.c cmd-copy-mode.c \ - cmd-delete-buffer.c cmd-detach-client.c cmd-down-pane.c \ + cmd-delete-buffer.c cmd-detach-client.c \ cmd-find-window.c cmd-generic.c cmd-has-session.c cmd-kill-pane.c \ cmd-kill-server.c cmd-kill-session.c cmd-kill-window.c \ cmd-last-window.c cmd-link-window.c cmd-list-buffers.c \ @@ -28,7 +28,7 @@ SRCS= attributes.c cfg.c client.c clock.c \ cmd-run-shell.c cmd-suspend-client.c cmd-swap-pane.c cmd-swap-window.c \ cmd-switch-client.c cmd-unbind-key.c cmd-unlink-window.c \ cmd-set-environment.c cmd-show-environment.c cmd-choose-client.c \ - cmd-up-pane.c cmd-display-message.c cmd-display-panes.c \ + cmd-display-message.c cmd-display-panes.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 \ diff --git a/cmd-down-pane.c b/cmd-down-pane.c deleted file mode 100644 index a065a6e9..00000000 --- a/cmd-down-pane.c +++ /dev/null @@ -1,60 +0,0 @@ -/* $OpenBSD$ */ - -/* - * 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 "tmux.h" - -/* - * Move down a pane. - */ - -int cmd_down_pane_exec(struct cmd *, struct cmd_ctx *); - -const struct cmd_entry cmd_down_pane_entry = { - "down-pane", "downp", - CMD_TARGET_WINDOW_USAGE, - 0, "", - cmd_target_init, - cmd_target_parse, - cmd_down_pane_exec, - cmd_target_free, - cmd_target_print -}; - -int -cmd_down_pane_exec(struct cmd *self, struct cmd_ctx *ctx) -{ - struct cmd_target_data *data = self->data; - struct winlink *wl; - struct window *w; - - if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) - return (-1); - w = wl->window; - - do { - w->active = TAILQ_NEXT(w->active, entry); - if (w->active == NULL) - w->active = TAILQ_FIRST(&w->panes); - } while (!window_pane_visible(w->active)); - server_status_window(wl->window); - server_redraw_window_borders(wl->window); - - return (0); -} diff --git a/cmd-select-pane.c b/cmd-select-pane.c index 956ed912..b5defa2e 100644 --- a/cmd-select-pane.c +++ b/cmd-select-pane.c @@ -24,19 +24,40 @@ * Select pane. */ +void cmd_select_pane_init(struct cmd *, int); int cmd_select_pane_exec(struct cmd *, struct cmd_ctx *); const struct cmd_entry cmd_select_pane_entry = { "select-pane", "selectp", - CMD_TARGET_PANE_USAGE, - 0, "", - cmd_target_init, + "[-DLRU] " CMD_TARGET_PANE_USAGE, + 0, "DLRU", + cmd_select_pane_init, cmd_target_parse, cmd_select_pane_exec, cmd_target_free, cmd_target_print }; +void +cmd_select_pane_init(struct cmd *self, int key) +{ + struct cmd_target_data *data; + + cmd_target_init(self, key); + data = self->data; + + if (key == KEYC_UP) + cmd_set_flag(&data->chflags, 'U'); + if (key == KEYC_DOWN) + cmd_set_flag(&data->chflags, 'D'); + if (key == KEYC_LEFT) + cmd_set_flag(&data->chflags, 'L'); + if (key == KEYC_RIGHT) + cmd_set_flag(&data->chflags, 'R'); + if (key == 'o') + data->target = xstrdup(":.+"); +} + int cmd_select_pane_exec(struct cmd *self, struct cmd_ctx *ctx) { @@ -51,6 +72,20 @@ cmd_select_pane_exec(struct cmd *self, struct cmd_ctx *ctx) ctx->error(ctx, "pane not visible: %s", data->target); return (-1); } + + if (cmd_check_flag(data->chflags, 'L')) + wp = window_pane_find_left(wp); + else if (cmd_check_flag(data->chflags, 'R')) + wp = window_pane_find_right(wp); + else if (cmd_check_flag(data->chflags, 'U')) + wp = window_pane_find_up(wp); + else if (cmd_check_flag(data->chflags, 'D')) + wp = window_pane_find_down(wp); + if (wp == NULL) { + ctx->error(ctx, "pane not found"); + return (-1); + } + window_set_active_pane(wl->window, wp); server_status_window(wl->window); server_redraw_window_borders(wl->window); diff --git a/cmd-up-pane.c b/cmd-up-pane.c deleted file mode 100644 index 62fe76be..00000000 --- a/cmd-up-pane.c +++ /dev/null @@ -1,60 +0,0 @@ -/* $OpenBSD$ */ - -/* - * 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 "tmux.h" - -/* - * Move up a pane. - */ - -int cmd_up_pane_exec(struct cmd *, struct cmd_ctx *); - -const struct cmd_entry cmd_up_pane_entry = { - "up-pane", "upp", - CMD_TARGET_WINDOW_USAGE, - 0, "", - cmd_target_init, - cmd_target_parse, - cmd_up_pane_exec, - cmd_target_free, - cmd_target_print -}; - -int -cmd_up_pane_exec(struct cmd *self, struct cmd_ctx *ctx) -{ - struct cmd_target_data *data = self->data; - struct winlink *wl; - struct window *w; - - if ((wl = cmd_find_window(ctx, data->target, NULL)) == NULL) - return (-1); - w = wl->window; - - do { - w->active = TAILQ_PREV(w->active, window_panes, entry); - if (w->active == NULL) - w->active = TAILQ_LAST(&w->panes, window_panes); - } while (!window_pane_visible(w->active)); - server_status_window(wl->window); - server_redraw_window_borders(wl->window); - - return (0); -} diff --git a/cmd.c b/cmd.c index 6163d78a..09b58adf 100644 --- a/cmd.c +++ b/cmd.c @@ -45,7 +45,6 @@ const struct cmd_entry *cmd_table[] = { &cmd_detach_client_entry, &cmd_display_message_entry, &cmd_display_panes_entry, - &cmd_down_pane_entry, &cmd_find_window_entry, &cmd_has_session_entry, &cmd_if_shell_entry, @@ -109,7 +108,6 @@ const struct cmd_entry *cmd_table[] = { &cmd_switch_client_entry, &cmd_unbind_key_entry, &cmd_unlink_window_entry, - &cmd_up_pane_entry, NULL }; @@ -955,15 +953,29 @@ cmd_find_pane(struct cmd_ctx *ctx, return (wl); lookup_string: + /* Try as next or previous pane. */ + if (paneptr[0] == '+' && paneptr[1] == '\0') { + *wpp = TAILQ_NEXT(wl->window->active, entry); + if (*wpp == NULL) + *wpp = TAILQ_FIRST(&wl->window->panes); + return (wl); + } + if (paneptr[0] == '-' && paneptr[1] == '\0') { + *wpp = TAILQ_PREV(wl->window->active, window_panes, entry); + if (*wpp == NULL) + *wpp = TAILQ_LAST(&wl->window->panes, window_panes); + return (wl); + } + /* Try pane string description. */ - if ((lc = layout_find_string(s->curw->window, paneptr)) == NULL) { + if ((lc = layout_find_string(wl->window, paneptr)) == NULL) { ctx->error(ctx, "can't find pane: %s", paneptr); goto error; } *wpp = lc->wp; xfree(winptr); - return (s->curw); + return (wl); no_period: /* Try as a pane number alone. */ diff --git a/key-bindings.c b/key-bindings.c index c08ac942..2eb5327c 100644 --- a/key-bindings.c +++ b/key-bindings.c @@ -136,7 +136,7 @@ key_bindings_init(void) { 'i', 0, &cmd_display_message_entry }, { 'l', 0, &cmd_last_window_entry }, { 'n', 0, &cmd_next_window_entry }, - { 'o', 0, &cmd_down_pane_entry }, + { 'o', 0, &cmd_select_pane_entry }, { 'p', 0, &cmd_previous_window_entry }, { 'q', 0, &cmd_display_panes_entry }, { 'r', 0, &cmd_refresh_client_entry }, @@ -155,8 +155,10 @@ key_bindings_init(void) { 'n' | KEYC_ESCAPE, 0, &cmd_next_window_entry }, { 'o' | KEYC_ESCAPE, 0, &cmd_rotate_window_entry }, { 'p' | KEYC_ESCAPE, 0, &cmd_previous_window_entry }, - { KEYC_UP, 0, &cmd_up_pane_entry }, - { KEYC_DOWN, 0, &cmd_down_pane_entry }, + { KEYC_UP, 1, &cmd_select_pane_entry }, + { KEYC_DOWN, 1, &cmd_select_pane_entry }, + { KEYC_LEFT, 1, &cmd_select_pane_entry }, + { KEYC_RIGHT, 1, &cmd_select_pane_entry }, { KEYC_UP | KEYC_ESCAPE, 1, &cmd_resize_pane_entry }, { KEYC_DOWN | KEYC_ESCAPE, 1, &cmd_resize_pane_entry }, { KEYC_LEFT | KEYC_ESCAPE, 1, &cmd_resize_pane_entry }, diff --git a/tmux.1 b/tmux.1 index 6d24fd53..92738dc5 100644 --- a/tmux.1 +++ b/tmux.1 @@ -336,6 +336,11 @@ 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 . +A +.Ql + +or +.Ql - +indicate the next or previous pane index, respectively. One of the strings .Em top , .Em bottom , @@ -727,10 +732,8 @@ command (bound to and .Ql C-right by default), the current pane may be changed with the -.Ic up-pane -and -.Ic down-pane -commands and the +.Ic select-pane +command and the .Ic rotate-window and .Ic swap-pane @@ -859,9 +862,6 @@ While the indicator is on screen, a pane may be selected with the to .Ql 9 keys. -.It Ic down-pane Op Fl t Ar target-pane -.D1 (alias: Ic downp ) -Change the active pane to the next pane (higher index). .It Xo Ic find-window .Op Fl t Ar target-window .Ar match-string @@ -1103,12 +1103,23 @@ Choose a specific layout for a window. If .Ar layout-name is not given, the last layout used (if any) is reapplied. -.It Ic select-pane Op Fl t Ar target-pane +.It Xo Ic select-pane +.Op Fl DLRU +.Op Fl t Ar target-pane +.Xc .D1 (alias: Ic selectp ) Make pane .Ar target-pane the active pane in window .Ar target-window . +If one of +.Fl D , +.Fl L , +.Fl R , +or +.Fl U +is used, respectively the pane below, to the left, to the right, or above the +target pane is used. .It Ic select-window Op Fl t Ar target-window .D1 (alias: Ic selectw ) Select the window at @@ -1184,9 +1195,6 @@ if .Fl k is specified and the window is linked to only one session, it is unlinked and destroyed. -.It Ic up-pane Op Fl t Ar target-pane -.D1 (alias: Ic upp ) -Change the active pane to the previous pane (lower index). .El .Sh KEY BINDINGS .Nm diff --git a/tmux.h b/tmux.h index 45fc18d9..23288425 100644 --- a/tmux.h +++ b/tmux.h @@ -1832,6 +1832,10 @@ void window_pane_mouse(struct window_pane *, int window_pane_visible(struct window_pane *); char *window_pane_search( struct window_pane *, const char *, u_int *); +struct window_pane *window_pane_find_up(struct window_pane *); +struct window_pane *window_pane_find_down(struct window_pane *); +struct window_pane *window_pane_find_left(struct window_pane *); +struct window_pane *window_pane_find_right(struct window_pane *); /* layout.c */ struct layout_cell *layout_create_cell(struct layout_cell *); diff --git a/window.c b/window.c index 1a41c11a..7f2eac8d 100644 --- a/window.c +++ b/window.c @@ -827,3 +827,113 @@ window_pane_search(struct window_pane *wp, const char *searchstr, u_int *lineno) xfree(newsearchstr); return (msg); } + +/* Find the pane directly above another. */ +struct window_pane * +window_pane_find_up(struct window_pane *wp) +{ + struct window_pane *wp2; + u_int left, top; + + if (wp == NULL || !window_pane_visible(wp)) + return (NULL); + + top = wp->yoff; + if (top == 0) + top = wp->window->sy + 1; + left = wp->xoff; + + TAILQ_FOREACH(wp2, &wp->window->panes, entry) { + if (!window_pane_visible(wp2)) + continue; + if (wp2->yoff + wp2->sy + 1 != top) + continue; + if (left >= wp2->xoff && left <= wp2->xoff + wp2->sx) + return (wp2); + } + return (NULL); +} + +/* Find the pane directly below another. */ +struct window_pane * +window_pane_find_down(struct window_pane *wp) +{ + struct window_pane *wp2; + u_int left, bottom; + + if (wp == NULL || !window_pane_visible(wp)) + return (NULL); + + bottom = wp->yoff + wp->sy + 1; + if (bottom >= wp->window->sy) + bottom = 0; + left = wp->xoff; + + TAILQ_FOREACH(wp2, &wp->window->panes, entry) { + if (!window_pane_visible(wp2)) + continue; + if (wp2->yoff != bottom) + continue; + if (left >= wp2->xoff && left <= wp2->xoff + wp2->sx) + return (wp2); + } + return (NULL); +} + +/* + * Find the pane directly to the left of another, adjacent to the left side and + * containing the top edge. + */ +struct window_pane * +window_pane_find_left(struct window_pane *wp) +{ + struct window_pane *wp2; + u_int left, top; + + if (wp == NULL || !window_pane_visible(wp)) + return (NULL); + + left = wp->xoff; + if (left == 0) + left = wp->window->sx + 1; + top = wp->yoff; + + TAILQ_FOREACH(wp2, &wp->window->panes, entry) { + if (!window_pane_visible(wp2)) + continue; + if (wp2->xoff + wp2->sx + 1 != left) + continue; + if (top >= wp2->yoff && top <= wp2->yoff + wp2->sy) + return (wp2); + } + return (NULL); +} + +/* + * Find the pane directly to the right of another, that is adjacent to the + * right edge and including the top edge. + */ +struct window_pane * +window_pane_find_right(struct window_pane *wp) +{ + struct window_pane *wp2; + u_int right, top; + + if (wp == NULL || !window_pane_visible(wp)) + return (NULL); + + right = wp->xoff + wp->sx + 1; + if (right >= wp->window->sx) + right = 0; + top = wp->yoff; + + TAILQ_FOREACH(wp2, &wp->window->panes, entry) { + if (!window_pane_visible(wp2)) + continue; + if (wp2->xoff != right) + continue; + if (top >= wp2->yoff && top <= wp2->yoff + wp2->sy) + return (wp2); + } + return (NULL); +}