diff options
author | Luuk van Baal <luukvbaal@gmail.com> | 2023-11-20 02:27:16 +0100 |
---|---|---|
committer | Lewis Russell <me@lewisr.dev> | 2023-11-21 09:38:32 +0000 |
commit | 585eeacb24e1aa0fed978e46063de100b16b8bdf (patch) | |
tree | 023df9778c072cef7fa36d4b23ed96d5a9dc2997 /src | |
parent | fec5e3ab247bcc1ced67f1d0aa7fa10f694f933b (diff) | |
download | rneovim-585eeacb24e1aa0fed978e46063de100b16b8bdf.tar.gz rneovim-585eeacb24e1aa0fed978e46063de100b16b8bdf.tar.bz2 rneovim-585eeacb24e1aa0fed978e46063de100b16b8bdf.zip |
refactor(sign): store 'signcolumn' width range when it is set
Problem: Minimum and maximum signcolumn width is determined each redraw.
Solution: Determine and store 'signcolumn' range when option is set.
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/buffer_defs.h | 2 | ||||
-rw-r--r-- | src/nvim/decoration.c | 6 | ||||
-rw-r--r-- | src/nvim/drawline.c | 2 | ||||
-rw-r--r-- | src/nvim/drawscreen.c | 7 | ||||
-rw-r--r-- | src/nvim/option.c | 45 | ||||
-rw-r--r-- | src/nvim/option_vars.h | 3 | ||||
-rw-r--r-- | src/nvim/optionstr.c | 58 |
7 files changed, 55 insertions, 68 deletions
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index 039484d2e2..21cbefdb90 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -1206,6 +1206,8 @@ struct window_S { int w_nrwidth; // width of 'number' and 'relativenumber' // column being used int w_scwidth; // width of 'signcolumn' + int w_minscwidth; // minimum width or SCL_NO/SCL_NUM + int w_maxscwidth; // maximum width or SCL_NO/SCL_NUM // === end of cached values === diff --git a/src/nvim/decoration.c b/src/nvim/decoration.c index 48dffea24b..b784d8bea3 100644 --- a/src/nvim/decoration.c +++ b/src/nvim/decoration.c @@ -442,7 +442,9 @@ void decor_redraw_signs(win_T *wp, buf_T *buf, int row, SignTextAttrs sattrs[], int *cul_id, int *num_id) { MarkTreeIter itr[1]; - if (!buf->b_signs || !marktree_itr_get_overlap(buf->b_marktree, row, 0, itr)) { + if (!buf->b_signs + || wp->w_minscwidth == SCL_NO + || !marktree_itr_get_overlap(buf->b_marktree, row, 0, itr)) { return; } @@ -471,7 +473,7 @@ void decor_redraw_signs(win_T *wp, buf_T *buf, int row, SignTextAttrs sattrs[], } if (kv_size(signs)) { - int width = (*wp->w_p_scl == 'n' && *(wp->w_p_scl + 1) == 'u') ? 1 : wp->w_scwidth; + int width = wp->w_minscwidth == SCL_NUM ? 1 : wp->w_scwidth; int idx = MIN(width, num_text) - 1; qsort((void *)&kv_A(signs, 0), kv_size(signs), sizeof(MTKey), sign_cmp); diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index 5813dada28..c1d4e55fe5 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -561,7 +561,7 @@ static void handle_lnum_col(win_T *wp, winlinevars_T *wlv, int sign_num_attr, in && !((has_cpo_n && !wp->w_p_bri) && wp->w_skipcol > 0 && wlv->lnum == wp->w_topline)) { // If 'signcolumn' is set to 'number' and a sign is present in "lnum", // then display the sign instead of the line number. - if (*wp->w_p_scl == 'n' && *(wp->w_p_scl + 1) == 'u' && wlv->sattrs[0].text) { + if (wp->w_minscwidth == SCL_NUM && wlv->sattrs[0].text) { get_sign_display_info(true, wp, wlv, 0, sign_cul_attr); } else { // Draw the line number (empty space after wrapping). diff --git a/src/nvim/drawscreen.c b/src/nvim/drawscreen.c index 7a9c5eb588..fee2f288f6 100644 --- a/src/nvim/drawscreen.c +++ b/src/nvim/drawscreen.c @@ -606,7 +606,7 @@ int update_screen(void) } // Reset 'statuscolumn' if there is no dedicated signcolumn but it is invalid. - if (*wp->w_p_stc != NUL && !wp->w_buffer->b_signcols.valid && win_no_signcol(wp)) { + if (*wp->w_p_stc != NUL && !wp->w_buffer->b_signcols.valid && wp->w_minscwidth <= SCL_NO) { wp->w_nrwidth_line_count = 0; wp->w_valid &= ~VALID_WCOL; wp->w_redr_type = UPD_NOT_VALID; @@ -619,7 +619,7 @@ int update_screen(void) FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { // Validate b_signcols if there is no dedicated signcolumn but 'statuscolumn' is set. - if (*wp->w_p_stc != NUL && win_no_signcol(wp)) { + if (*wp->w_p_stc != NUL && wp->w_minscwidth <= SCL_NO) { buf_signcols(wp->w_buffer, 0); } @@ -2632,8 +2632,7 @@ int number_width(win_T *wp) // If 'signcolumn' is set to 'number' and there is a sign to display, then // the minimal width for the number column is 2. - if (n < 2 && wp->w_buffer->b_signs_with_text - && (*wp->w_p_scl == 'n' && *(wp->w_p_scl + 1) == 'u')) { + if (n < 2 && wp->w_buffer->b_signs_with_text && wp->w_minscwidth == SCL_NUM) { n = 2; } diff --git a/src/nvim/option.c b/src/nvim/option.c index a920912452..0fae498b25 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -2245,6 +2245,7 @@ static const char *did_set_number_relativenumber(optset_T *args) // When 'relativenumber'/'number' is changed and 'statuscolumn' is set, reset width. win->w_nrwidth_line_count = 0; } + check_signcolumn(win); return NULL; } @@ -4861,6 +4862,7 @@ void didset_window_options(win_T *wp, bool valid_cursor) parse_winhl_opt(wp); // sets w_hl_needs_update also for w_p_winbl check_blending(wp); set_winbar_win(wp, false, valid_cursor); + check_signcolumn(wp); wp->w_grid_alloc.blending = wp->w_p_winbl > 0; } @@ -6170,49 +6172,12 @@ bool fish_like_shell(void) /// buffer signs and on user configuration. int win_signcol_count(win_T *wp) { - return win_signcol_configured(wp); -} - -/// Return true when window "wp" has no sign column. -bool win_no_signcol(win_T *wp) -{ - const char *scl = wp->w_p_scl; - return (*scl == 'n' && (*(scl + 1) == 'o' || (*(scl + 1) == 'u' - && (wp->w_p_nu || wp->w_p_rnu)))); -} - -/// Return the number of requested sign columns, based on user / configuration. -int win_signcol_configured(win_T *wp) -{ - const char *scl = wp->w_p_scl; - - if (win_no_signcol(wp)) { + if (wp->w_minscwidth <= SCL_NO) { return 0; } - // yes or yes - if (!strncmp(scl, "yes:", 4)) { - // Fixed amount of columns - return scl[4] - '0'; - } - if (*scl == 'y') { - return 1; - } - - int minimum = 0, maximum = 1; - - if (!strncmp(scl, "auto:", 5)) { - // Variable depending on a configuration - maximum = scl[5] - '0'; - // auto:<NUM>-<NUM> - if (strlen(scl) == 8 && *(scl + 6) == '-') { - minimum = maximum; - maximum = scl[7] - '0'; - } - } - - int needed_signcols = buf_signcols(wp->w_buffer, maximum); - int ret = MAX(minimum, MIN(maximum, needed_signcols)); + int needed_signcols = buf_signcols(wp->w_buffer, wp->w_maxscwidth); + int ret = MAX(wp->w_minscwidth, MIN(wp->w_maxscwidth, needed_signcols)); assert(ret <= SIGN_SHOW_MAX); return ret; } diff --git a/src/nvim/option_vars.h b/src/nvim/option_vars.h index 0193e43de7..ce65750d78 100644 --- a/src/nvim/option_vars.h +++ b/src/nvim/option_vars.h @@ -947,3 +947,6 @@ enum { #define MAX_NUMBERWIDTH 20 // used for 'numberwidth' and 'statuscolumn' #define TABSTOP_MAX 9999 + +#define SCL_NO -1 // 'signcolumn' set to "no" +#define SCL_NUM -2 // 'signcolumn' set to "number" diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c index 000fbaba95..56f44788b0 100644 --- a/src/nvim/optionstr.c +++ b/src/nvim/optionstr.c @@ -388,34 +388,53 @@ static bool valid_filetype(const char *val) return valid_name(val, ".-_"); } -/// Handle setting 'signcolumn' for value 'val' +/// Handle setting 'signcolumn' for value 'val'. Store minimum and maximum width. /// /// @return OK when the value is valid, FAIL otherwise -static int check_signcolumn(char *val) +int check_signcolumn(win_T *wp) { + char *val = wp->w_p_scl; if (*val == NUL) { return FAIL; } - // check for basic match + if (check_opt_strings(val, p_scl_values, false) == OK) { + if (!strncmp(val, "no", 2)) { // no + wp->w_minscwidth = wp->w_maxscwidth = SCL_NO; + } else if (!strncmp(val, "nu", 2) && (wp->w_p_nu || wp->w_p_rnu)) { // number + wp->w_minscwidth = wp->w_maxscwidth = SCL_NUM; + } else if (!strncmp(val, "yes:", 4)) { // yes:<NUM> + wp->w_minscwidth = wp->w_maxscwidth = val[4] - '0'; + } else if (*val == 'y') { // yes + wp->w_minscwidth = wp->w_maxscwidth = 1; + } else if (!strncmp(val, "auto:", 5)) { // auto:<NUM> + wp->w_minscwidth = 0; + wp->w_maxscwidth = val[5] - '0'; + } else { // auto + wp->w_minscwidth = 0; + wp->w_maxscwidth = 1; + } return OK; } - // check for 'auto:<NUMBER>-<NUMBER>' - if (strlen(val) == 8 - && !strncmp(val, "auto:", 5) - && ascii_isdigit(val[5]) - && val[6] == '-' - && ascii_isdigit(val[7])) { - int min = val[5] - '0'; - int max = val[7] - '0'; - if (min < 1 || max < 2 || min > 8 || max > 9 || min >= max) { - return FAIL; - } - return OK; + if (strncmp(val, "auto:", 5) != 0 + || strlen(val) != 8 + || !ascii_isdigit(val[5]) + || val[6] != '-' + || !ascii_isdigit(val[7])) { + return FAIL; } - return FAIL; + // auto:<NUM>-<NUM> + int min = val[5] - '0'; + int max = val[7] - '0'; + if (min < 1 || max < 2 || min > 8 || min >= max) { + return FAIL; + } + + wp->w_minscwidth = min; + wp->w_maxscwidth = max; + return OK; } /// Check validity of options with the 'statusline' format. @@ -2072,16 +2091,13 @@ int expand_set_showcmdloc(optexpand_T *args, int *numMatches, char ***matches) const char *did_set_signcolumn(optset_T *args) { win_T *win = (win_T *)args->os_win; - char **varp = (char **)args->os_varp; const char *oldval = args->os_oldval.string.data; - if (check_signcolumn(*varp) != OK) { + if (check_signcolumn(win) != OK) { return e_invarg; } // When changing the 'signcolumn' to or from 'number', recompute the // width of the number column if 'number' or 'relativenumber' is set. - if (((*oldval == 'n' && *(oldval + 1) == 'u') - || (*win->w_p_scl == 'n' && *(win->w_p_scl + 1) == 'u')) - && (win->w_p_nu || win->w_p_rnu)) { + if ((*oldval == 'n' && *(oldval + 1) == 'u') || win->w_minscwidth == SCL_NUM) { win->w_nrwidth_line_count = 0; } return NULL; |