diff options
author | Luuk van Baal <luukvbaal@gmail.com> | 2023-12-08 05:58:29 +0100 |
---|---|---|
committer | Lewis Russell <me@lewisr.dev> | 2023-12-08 15:42:18 +0000 |
commit | 2289ca273cdaad4248a6cd962bddcc956b296c18 (patch) | |
tree | f18c939b8c394a65e3cc82c826ec772dd042ca65 | |
parent | 808fbe67a81da028eed6607fa3f5d13547d72332 (diff) | |
download | rneovim-2289ca273cdaad4248a6cd962bddcc956b296c18.tar.gz rneovim-2289ca273cdaad4248a6cd962bddcc956b296c18.tar.bz2 rneovim-2289ca273cdaad4248a6cd962bddcc956b296c18.zip |
perf(column): avoid counting when max signs are removed from a range
-rw-r--r-- | src/nvim/decoration.c | 32 | ||||
-rw-r--r-- | src/nvim/drawscreen.c | 8 | ||||
-rw-r--r-- | test/functional/ui/decorations_spec.lua | 15 | ||||
-rw-r--r-- | test/functional/ui/sign_spec.lua | 7 |
4 files changed, 42 insertions, 20 deletions
diff --git a/src/nvim/decoration.c b/src/nvim/decoration.c index 20311d80e5..62cbd33186 100644 --- a/src/nvim/decoration.c +++ b/src/nvim/decoration.c @@ -792,17 +792,16 @@ DecorSignHighlight *decor_find_sign(DecorInline decor) } } -/// If "count" is greater than current max, set it and reset "max_count". static void buf_signcols_validate_row(buf_T *buf, int count, int add) { - int del = add < 0 ? -add : 0; + // If "count" is greater than current max, set it and reset "max_count". if (count > buf->b_signcols.max) { buf->b_signcols.max = count; buf->b_signcols.max_count = 0; buf->b_signcols.resized = true; } - /// Add sign of "add" to "max_count" - if (count == buf->b_signcols.max - del) { + // If row has or had "max" signs, adjust "max_count" with sign of "add". + if (count == buf->b_signcols.max - (add < 0 ? -add : 0)) { buf->b_signcols.max_count += (add > 0) - (add < 0); } } @@ -811,7 +810,12 @@ static void buf_signcols_validate_row(buf_T *buf, int count, int add) /// "b_signcols" accordingly. static void buf_signcols_validate_range(buf_T *buf, int row1, int row2, int add) { - int count = 0; // Number of signs on the current line + if (-add == buf->b_signcols.max) { + buf->b_signcols.max_count -= (row2 + 1 - row1); + return; // max signs were removed from the range, no need to count. + } + + int count = 0; // Number of signs on the current row int currow = row1; MTPair pair = { 0 }; MarkTreeIter itr[1]; @@ -847,8 +851,8 @@ static void buf_signcols_validate_range(buf_T *buf, int row1, int row2, int add) count++; if (mt_paired(mark)) { MTPos end = marktree_get_altpos(buf->b_marktree, mark, NULL); - for (int i = mark.pos.row; i < MIN(row2, end.row); i++) { - overlap[row2 - i]++; + for (int i = mark.pos.row + 1; i <= MIN(row2, end.row); i++) { + overlap[i - row1]++; } } } @@ -861,13 +865,17 @@ static void buf_signcols_validate_range(buf_T *buf, int row1, int row2, int add) int buf_signcols_validate(win_T *wp, buf_T *buf, bool stc_check) { + if (!map_size(buf->b_signcols.invalid)) { + return buf->b_signcols.max; + } + int start; SignRange range; map_foreach(buf->b_signcols.invalid, start, range, { - // Leave rest of the ranges invalid if max is already greater than - // configured maximum or resize is detected for 'statuscolumn' rebuild. - if ((!stc_check || buf->b_signcols.resized) - && (range.add > 0 && buf->b_signcols.max >= wp->w_maxscwidth)) { + // Leave rest of the ranges invalid if max is already at configured + // maximum or resize is detected for a 'statuscolumn' rebuild. + if ((stc_check && buf->b_signcols.resized) + || (!stc_check && range.add > 0 && buf->b_signcols.max >= wp->w_maxscwidth)) { return wp->w_maxscwidth; } buf_signcols_validate_range(buf, start, range.end, range.add); @@ -877,7 +885,7 @@ int buf_signcols_validate(win_T *wp, buf_T *buf, bool stc_check) if (buf->b_signcols.max_count == 0) { buf->b_signcols.max = 0; buf->b_signcols.resized = true; - buf_signcols_validate_range(buf, 0, buf->b_ml.ml_line_count, 0); + buf_signcols_validate_range(buf, 0, buf->b_ml.ml_line_count, 1); } map_clear(int, buf->b_signcols.invalid); diff --git a/src/nvim/drawscreen.c b/src/nvim/drawscreen.c index a436dd2766..314764d117 100644 --- a/src/nvim/drawscreen.c +++ b/src/nvim/drawscreen.c @@ -1195,15 +1195,13 @@ void comp_col(void) /// Redraw entire window "wp" if configured 'signcolumn' width changes. static bool win_redraw_signcols(win_T *wp) { + int width; bool rebuild_stc = false; buf_T *buf = wp->w_buffer; - int width = buf->b_signcols.max; if (wp->w_minscwidth <= SCL_NO) { if (*wp->w_p_stc) { - if (map_size(buf->b_signcols.invalid)) { - buf_signcols_validate(wp, buf, true); - } + buf_signcols_validate(wp, buf, true); if (buf->b_signcols.resized) { rebuild_stc = true; wp->w_nrwidth_line_count = 0; @@ -1212,7 +1210,7 @@ static bool win_redraw_signcols(win_T *wp) width = 0; } else if (wp->w_maxscwidth <= 1 && buf->b_signs_with_text >= (size_t)wp->w_maxscwidth) { width = wp->w_maxscwidth; - } else if (map_size(buf->b_signcols.invalid)) { + } else { width = buf_signcols_validate(wp, buf, false); } diff --git a/test/functional/ui/decorations_spec.lua b/test/functional/ui/decorations_spec.lua index a60562380a..925243054c 100644 --- a/test/functional/ui/decorations_spec.lua +++ b/test/functional/ui/decorations_spec.lua @@ -4989,6 +4989,21 @@ l5 | ]]} end) + + it('correct width with multiple overlapping signs', function() + screen:try_resize(20, 4) + insert(example_test3) + meths.buf_set_extmark(0, ns, 0, -1, {sign_text='S1', end_row=2}) + meths.buf_set_extmark(0, ns, 1, -1, {sign_text='S2', end_row=2}) + feed('gg') + + screen:expect{grid=[[ + S1{1: }^l1 | + S1S2l2 | + S1S2l3 | + | + ]]} + end) end) describe('decorations: virt_text', function() diff --git a/test/functional/ui/sign_spec.lua b/test/functional/ui/sign_spec.lua index b12e79bd42..1c0a6f663b 100644 --- a/test/functional/ui/sign_spec.lua +++ b/test/functional/ui/sign_spec.lua @@ -367,11 +367,12 @@ describe('Signs', function() | ]]} -- line deletion deletes signs. + command('3move1') command('2d') screen:expect([[ - {1:>>}{8:XX}{2: }{6: 1 }a | - {8:XX}{1:>>}WW{6: 2 }^c | - {2: }{6: 3 } | + {1:>>}{8:XX}{6: 1 }a | + {8:XX}{1:>>}{6: 2 }^b | + {2: }{6: 3 } | {0:~ }| {0:~ }| {0:~ }| |