From de5163a634374d64f98a79afafe0c2a526c21a04 Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 22 Apr 2020 06:57:13 +0000 Subject: [PATCH 1/2] Change so main-pane-width and height can be given as a percentage. --- arguments.c | 27 +++++++++++++++++---------- layout-set.c | 43 +++++++++++++++++++++++++++++++++---------- options-table.c | 24 ++++++++---------------- tmux.1 | 6 ++++++ tmux.h | 2 ++ 5 files changed, 66 insertions(+), 36 deletions(-) diff --git a/arguments.c b/arguments.c index 5b882ea1..547cec00 100644 --- a/arguments.c +++ b/arguments.c @@ -352,22 +352,29 @@ long long args_percentage(struct args *args, u_char ch, long long minval, long long maxval, long long curval, char **cause) { - const char *errstr; - long long ll; + const char *value; struct args_entry *entry; - struct args_value *value; - size_t valuelen; - char *copy; if ((entry = args_find(args, ch)) == NULL) { *cause = xstrdup("missing"); return (0); } - value = TAILQ_LAST(&entry->values, args_values); - valuelen = strlen(value->value); + value = TAILQ_LAST(&entry->values, args_values)->value; + return (args_string_percentage(value, minval, maxval, curval, cause)); +} - if (value->value[valuelen - 1] == '%') { - copy = xstrdup(value->value); +/* Convert a string to a number which may be a percentage. */ +long long +args_string_percentage(const char *value, long long minval, long long maxval, + long long curval, char **cause) +{ + const char *errstr; + long long ll; + size_t valuelen = strlen(value); + char *copy; + + if (value[valuelen - 1] == '%') { + copy = xstrdup(value); copy[valuelen - 1] = '\0'; ll = strtonum(copy, 0, 100, &errstr); @@ -386,7 +393,7 @@ args_percentage(struct args *args, u_char ch, long long minval, return (0); } } else { - ll = strtonum(value->value, minval, maxval, &errstr); + ll = strtonum(value, minval, maxval, &errstr); if (errstr != NULL) { *cause = xstrdup(errstr); return (0); diff --git a/layout-set.c b/layout-set.c index f712b059..9ef28416 100644 --- a/layout-set.c +++ b/layout-set.c @@ -18,6 +18,7 @@ #include +#include #include #include "tmux.h" @@ -186,6 +187,8 @@ layout_set_main_h(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); @@ -198,8 +201,15 @@ layout_set_main_h(struct window *w) /* Find available height - take off one line for the border. */ sy = w->sy - 1; - /* Get the main pane height and work out the other pane height. */ - mainh = options_get_number(w->options, "main-pane-height"); + /* 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; @@ -207,10 +217,12 @@ layout_set_main_h(struct window *w) mainh = sy - PANE_MINIMUM; otherh = PANE_MINIMUM; } else { - otherh = options_get_number(w->options, "other-pane-height"); - if (otherh == 0) + 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; - else if (otherh > sy || sy - otherh < mainh) + free(cause); + } else if (otherh > sy || sy - otherh < mainh) otherh = sy - mainh; else mainh = sy - otherh; @@ -273,6 +285,8 @@ layout_set_main_v(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); @@ -285,8 +299,15 @@ layout_set_main_v(struct window *w) /* Find available width - take off one line for the border. */ sx = w->sx - 1; - /* Get the main pane width and work out the other pane width. */ - mainw = options_get_number(w->options, "main-pane-width"); + /* 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; @@ -294,10 +315,12 @@ layout_set_main_v(struct window *w) mainw = sx - PANE_MINIMUM; otherw = PANE_MINIMUM; } else { - otherw = options_get_number(w->options, "other-pane-width"); - if (otherw == 0) + 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; - else if (otherw > sx || sx - otherw < mainw) + free(cause); + } else if (otherw > sx || sx - otherw < mainw) otherw = sx - mainw; else mainw = sx - otherw; diff --git a/options-table.c b/options-table.c index 6537e2c9..23e5af6f 100644 --- a/options-table.c +++ b/options-table.c @@ -647,19 +647,15 @@ const struct options_table_entry options_table[] = { }, { .name = "main-pane-height", - .type = OPTIONS_TABLE_NUMBER, + .type = OPTIONS_TABLE_STRING, .scope = OPTIONS_TABLE_WINDOW, - .minimum = 1, - .maximum = INT_MAX, - .default_num = 24 + .default_str = "24" }, { .name = "main-pane-width", - .type = OPTIONS_TABLE_NUMBER, + .type = OPTIONS_TABLE_STRING, .scope = OPTIONS_TABLE_WINDOW, - .minimum = 1, - .maximum = INT_MAX, - .default_num = 80 + .default_str = "80" }, { .name = "mode-keys", @@ -696,19 +692,15 @@ const struct options_table_entry options_table[] = { }, { .name = "other-pane-height", - .type = OPTIONS_TABLE_NUMBER, + .type = OPTIONS_TABLE_STRING, .scope = OPTIONS_TABLE_WINDOW, - .minimum = 0, - .maximum = INT_MAX, - .default_num = 0 + .default_str = "0" }, { .name = "other-pane-width", - .type = OPTIONS_TABLE_NUMBER, + .type = OPTIONS_TABLE_STRING, .scope = OPTIONS_TABLE_WINDOW, - .minimum = 0, - .maximum = INT_MAX, - .default_num = 0 + .default_str = "0" }, { .name = "pane-active-border-style", diff --git a/tmux.1 b/tmux.1 index e54817d5..b99fcb62 100644 --- a/tmux.1 +++ b/tmux.1 @@ -3711,6 +3711,9 @@ Set the width or height of the main (left or top) pane in the or .Ic main-vertical layouts. +If suffixed by +.Ql % , +this is a percentage of the window size. .Pp .It Xo Ic mode-keys .Op Ic vi | emacs @@ -3764,6 +3767,9 @@ and .Ic other-pane-height options are set, the main pane will grow taller to make the other panes the specified height, but will never shrink to do so. +If suffixed by +.Ql % , +this is a percentage of the window size. .Pp .It Ic other-pane-width Ar width Like diff --git a/tmux.h b/tmux.h index 3fe32b50..8561f11d 100644 --- a/tmux.h +++ b/tmux.h @@ -2043,6 +2043,8 @@ long long args_strtonum(struct args *, u_char, long long, long long, char **); long long args_percentage(struct args *, u_char, long long, long long, long long, char **); +long long args_string_percentage(const char *, long long, long long, + long long, char **); /* cmd-find.c */ int cmd_find_target(struct cmd_find_state *, struct cmdq_item *, From b72498c4ff0566d377a4757d1393817627c281ec Mon Sep 17 00:00:00 2001 From: nicm Date: Wed, 22 Apr 2020 08:48:44 +0000 Subject: [PATCH 2/2] Update the cursor position when deleting lines from screens without history, GitHub issue 2173. --- screen.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/screen.c b/screen.c index 129cfc2d..f416ac37 100644 --- a/screen.c +++ b/screen.c @@ -48,7 +48,7 @@ struct screen_title_entry { }; TAILQ_HEAD(screen_titles, screen_title_entry); -static void screen_resize_y(struct screen *, u_int, int); +static void screen_resize_y(struct screen *, u_int, int, u_int *); static void screen_reflow(struct screen *, u_int, u_int *, u_int *); /* Free titles stack. */ @@ -254,7 +254,7 @@ screen_resize_cursor(struct screen *s, u_int sx, u_int sy, int reflow, reflow = 0; if (sy != screen_size_y(s)) - screen_resize_y(s, sy, eat_empty); + screen_resize_y(s, sy, eat_empty, cy); if (reflow) screen_reflow(s, sx, cx, cy); @@ -281,7 +281,7 @@ screen_resize(struct screen *s, u_int sx, u_int sy, int reflow) } static void -screen_resize_y(struct screen *s, u_int sy, int eat_empty) +screen_resize_y(struct screen *s, u_int sy, int eat_empty, u_int *cy) { struct grid *gd = s->grid; u_int needed, available, oldy, i; @@ -330,6 +330,7 @@ screen_resize_y(struct screen *s, u_int sy, int eat_empty) if (available > needed) available = needed; grid_view_delete_lines(gd, 0, available, 8); + (*cy) -= available; } }