From 06292baadcc8747b9aee0bf1ea3960df84119b01 Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 21 Aug 2024 05:03:13 +0000 Subject: [PATCH] Add mirrored versions of the main-horizontal and main-vertical layouts where the main pane is bottom or right instead of top or left, from Sherwyn Sen. --- key-bindings.c | 2 + layout-set.c | 200 +++++++++++++++++++++++++++++++++++++++++++++++++ status.c | 5 +- tmux.1 | 38 +++++++--- 4 files changed, 231 insertions(+), 14 deletions(-) diff --git a/key-bindings.c b/key-bindings.c index eaf05f02..86da8018 100644 --- a/key-bindings.c +++ b/key-bindings.c @@ -413,6 +413,8 @@ key_bindings_init(void) "bind -N 'Set the main-horizontal layout' M-3 { select-layout main-horizontal }", "bind -N 'Set the main-vertical layout' M-4 { select-layout main-vertical }", "bind -N 'Select the tiled layout' M-5 { select-layout tiled }", + "bind -N 'Set the main-horizontal-mirrored layout' M-6 { select-layout main-horizontal-mirrored }", + "bind -N 'Set the main-vertical-mirrored layout' M-7 { select-layout main-vertical-mirrored }", "bind -N 'Select the next window with an alert' M-n { next-window -a }", "bind -N 'Rotate through the panes in reverse' M-o { rotate-window -D }", "bind -N 'Select the previous window with an alert' M-p { previous-window -a }", diff --git a/layout-set.c b/layout-set.c index c702817d..cc2e74bf 100644 --- a/layout-set.c +++ b/layout-set.c @@ -31,7 +31,9 @@ static void layout_set_even_h(struct window *); static void layout_set_even_v(struct window *); static void layout_set_main_h(struct window *); +static void layout_set_main_h_mirrored(struct window *); static void layout_set_main_v(struct window *); +static void layout_set_main_v_mirrored(struct window *); static void layout_set_tiled(struct window *); static const struct { @@ -41,7 +43,9 @@ static const struct { { "even-horizontal", layout_set_even_h }, { "even-vertical", layout_set_even_v }, { "main-horizontal", layout_set_main_h }, + { "main-horizontal-mirrored", layout_set_main_h_mirrored }, { "main-vertical", layout_set_main_v }, + { "main-vertical-mirrored", layout_set_main_v_mirrored }, { "tiled", layout_set_tiled }, }; @@ -279,6 +283,104 @@ layout_set_main_h(struct window *w) server_redraw_window(w); } +static void +layout_set_main_h_mirrored(struct window *w) +{ + struct window_pane *wp; + struct layout_cell *lc, *lcmain, *lcother, *lcchild; + u_int n, mainh, otherh, sx, sy; + char *cause; + const char *s; + + layout_print_cell(w->layout_root, __func__, 1); + + /* Get number of panes. */ + n = window_count_panes(w); + if (n <= 1) + return; + n--; /* take off main pane */ + + /* Find available height - take off one line for the border. */ + sy = w->sy - 1; + + /* Get the main pane height. */ + s = options_get_string(w->options, "main-pane-height"); + mainh = args_string_percentage(s, 0, sy, sy, &cause); + if (cause != NULL) { + mainh = 24; + free(cause); + } + + /* Work out the other pane height. */ + if (mainh + PANE_MINIMUM >= sy) { + if (sy <= PANE_MINIMUM + PANE_MINIMUM) + mainh = PANE_MINIMUM; + else + mainh = sy - PANE_MINIMUM; + otherh = PANE_MINIMUM; + } else { + s = options_get_string(w->options, "other-pane-height"); + otherh = args_string_percentage(s, 0, sy, sy, &cause); + if (cause != NULL || otherh == 0) { + otherh = sy - mainh; + free(cause); + } else if (otherh > sy || sy - otherh < mainh) + otherh = sy - mainh; + else + mainh = sy - otherh; + } + + /* Work out what width is needed. */ + sx = (n * (PANE_MINIMUM + 1)) - 1; + if (sx < w->sx) + sx = w->sx; + + /* Free old tree and create a new root. */ + layout_free(w); + lc = w->layout_root = layout_create_cell(NULL); + layout_set_size(lc, sx, mainh + otherh + 1, 0, 0); + layout_make_node(lc, LAYOUT_TOPBOTTOM); + + /* Create the other pane. */ + lcother = layout_create_cell(lc); + layout_set_size(lcother, sx, otherh, 0, 0); + if (n == 1) { + wp = TAILQ_NEXT(TAILQ_FIRST(&w->panes), entry); + layout_make_leaf(lcother, wp); + TAILQ_INSERT_TAIL(&lc->cells, lcother, entry); + } else { + layout_make_node(lcother, LAYOUT_LEFTRIGHT); + TAILQ_INSERT_TAIL(&lc->cells, lcother, entry); + + /* Add the remaining panes as children. */ + TAILQ_FOREACH(wp, &w->panes, entry) { + if (wp == TAILQ_FIRST(&w->panes)) + continue; + lcchild = layout_create_cell(lcother); + layout_set_size(lcchild, PANE_MINIMUM, otherh, 0, 0); + layout_make_leaf(lcchild, wp); + TAILQ_INSERT_TAIL(&lcother->cells, lcchild, entry); + } + layout_spread_cell(w, lcother); + } + + /* Create the main pane. */ + lcmain = layout_create_cell(lc); + layout_set_size(lcmain, sx, mainh, 0, 0); + layout_make_leaf(lcmain, TAILQ_FIRST(&w->panes)); + TAILQ_INSERT_TAIL(&lc->cells, lcmain, entry); + + /* Fix cell offsets. */ + layout_fix_offsets(w); + layout_fix_panes(w, NULL); + + layout_print_cell(w->layout_root, __func__, 1); + + window_resize(w, lc->sx, lc->sy, -1, -1); + notify_window("window-layout-changed", w); + server_redraw_window(w); +} + static void layout_set_main_v(struct window *w) { @@ -377,6 +479,104 @@ layout_set_main_v(struct window *w) server_redraw_window(w); } +static void +layout_set_main_v_mirrored(struct window *w) +{ + struct window_pane *wp; + struct layout_cell *lc, *lcmain, *lcother, *lcchild; + u_int n, mainw, otherw, sx, sy; + char *cause; + const char *s; + + layout_print_cell(w->layout_root, __func__, 1); + + /* Get number of panes. */ + n = window_count_panes(w); + if (n <= 1) + return; + n--; /* take off main pane */ + + /* Find available width - take off one line for the border. */ + sx = w->sx - 1; + + /* Get the main pane width. */ + s = options_get_string(w->options, "main-pane-width"); + mainw = args_string_percentage(s, 0, sx, sx, &cause); + if (cause != NULL) { + mainw = 80; + free(cause); + } + + /* Work out the other pane width. */ + if (mainw + PANE_MINIMUM >= sx) { + if (sx <= PANE_MINIMUM + PANE_MINIMUM) + mainw = PANE_MINIMUM; + else + mainw = sx - PANE_MINIMUM; + otherw = PANE_MINIMUM; + } else { + s = options_get_string(w->options, "other-pane-width"); + otherw = args_string_percentage(s, 0, sx, sx, &cause); + if (cause != NULL || otherw == 0) { + otherw = sx - mainw; + free(cause); + } else if (otherw > sx || sx - otherw < mainw) + otherw = sx - mainw; + else + mainw = sx - otherw; + } + + /* Work out what height is needed. */ + sy = (n * (PANE_MINIMUM + 1)) - 1; + if (sy < w->sy) + sy = w->sy; + + /* Free old tree and create a new root. */ + layout_free(w); + lc = w->layout_root = layout_create_cell(NULL); + layout_set_size(lc, mainw + otherw + 1, sy, 0, 0); + layout_make_node(lc, LAYOUT_LEFTRIGHT); + + /* Create the other pane. */ + lcother = layout_create_cell(lc); + layout_set_size(lcother, otherw, sy, 0, 0); + if (n == 1) { + wp = TAILQ_NEXT(TAILQ_FIRST(&w->panes), entry); + layout_make_leaf(lcother, wp); + TAILQ_INSERT_TAIL(&lc->cells, lcother, entry); + } else { + layout_make_node(lcother, LAYOUT_TOPBOTTOM); + TAILQ_INSERT_TAIL(&lc->cells, lcother, entry); + + /* Add the remaining panes as children. */ + TAILQ_FOREACH(wp, &w->panes, entry) { + if (wp == TAILQ_FIRST(&w->panes)) + continue; + lcchild = layout_create_cell(lcother); + layout_set_size(lcchild, otherw, PANE_MINIMUM, 0, 0); + layout_make_leaf(lcchild, wp); + TAILQ_INSERT_TAIL(&lcother->cells, lcchild, entry); + } + layout_spread_cell(w, lcother); + } + + /* Create the main pane. */ + lcmain = layout_create_cell(lc); + layout_set_size(lcmain, mainw, sy, 0, 0); + layout_make_leaf(lcmain, TAILQ_FIRST(&w->panes)); + TAILQ_INSERT_TAIL(&lc->cells, lcmain, entry); + + /* Fix cell offsets. */ + layout_fix_offsets(w); + layout_fix_panes(w, NULL); + + layout_print_cell(w->layout_root, __func__, 1); + + window_resize(w, lc->sx, lc->sy, -1, -1); + notify_window("window-layout-changed", w); + server_redraw_window(w); +} + void layout_set_tiled(struct window *w) { diff --git a/status.c b/status.c index d0b4e3b5..9096dbec 100644 --- a/status.c +++ b/status.c @@ -1626,8 +1626,9 @@ status_prompt_complete_list(u_int *size, const char *s, int at_start) struct options_entry *o; struct options_array_item *a; const char *layouts[] = { - "even-horizontal", "even-vertical", "main-horizontal", - "main-vertical", "tiled", NULL + "even-horizontal", "even-vertical", + "main-horizontal", "main-horizontal-mirrored", + "main-vertical", "main-vertical-mirrored", "tiled", NULL }; *size = 0; diff --git a/tmux.1 b/tmux.1 index 9ab65993..920f8e9f 100644 --- a/tmux.1 +++ b/tmux.1 @@ -370,8 +370,10 @@ Enter copy mode and scroll one page up. Change to the pane above, below, to the left, or to the right of the current pane. .It M-1 to M-5 -Arrange panes in one of the five preset layouts: even-horizontal, -even-vertical, main-horizontal, main-vertical, or tiled. +Arrange panes in one of the seven preset layouts: +even-horizontal, even-vertical, +main-horizontal, main-horizontal-mirrored, +main-vertical, main-vertical, or tiled. .It Space Arrange the current window in the next preset layout. .It M-n @@ -2162,14 +2164,20 @@ are spread from left to right in the leftover space at the bottom. Use the .Em main-pane-height window option to specify the height of the top pane. -.It Ic main-vertical -Similar to +.It Ic main-horizontal-mirrored +The same as .Ic main-horizontal -but the large pane is placed on the left and the others spread from top to -bottom along the right. -See the +but mirrored so the main pane is at the bottom of the window. +.It Ic main-vertical +A large (main) pane is shown on the left of the window and the remaining panes +are spread from top to bottom in the leftover space on the right. +Use the .Em main-pane-width -window option. +window option to specify the width of the left pane. +.It Ic main-vertical-mirrored +The same as +.Ic main-vertical +but mirrored so the main pane is on the right of the window. .It Ic tiled Panes are spread out as evenly as possible over the window in both rows and columns. @@ -4483,9 +4491,11 @@ Set the character used to fill areas of the terminal unused by a window. .It Ic main-pane-height Ar height .It Ic main-pane-width Ar width Set the width or height of the main (left or top) pane in the -.Ic main-horizontal +.Ic main-horizontal, +.Ic main-horizontal-mirrored, +.Ic main-vertical, or -.Ic main-vertical +.Ic main-vertical-mirrored layouts. If suffixed by .Ql % , @@ -4559,7 +4569,9 @@ An interval of zero disables the monitoring. .It Ic other-pane-height Ar height Set the height of the other panes (not the main pane) in the .Ic main-horizontal -layout. +and +.Ic main-horizontal-mirrored +layouts. If this option is set to 0 (the default), it will have no effect. If both the .Ic main-pane-height @@ -4576,7 +4588,9 @@ Like .Ic other-pane-height , but set the width of other panes in the .Ic main-vertical -layout. +and +.Ic main-vertical-mirrored +layouts. .Pp .It Ic pane-active-border-style Ar style Set the pane border style for the currently active pane.