aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/buffer.c
diff options
context:
space:
mode:
authorLuuk van Baal <luukvbaal@gmail.com>2023-11-28 05:40:18 +0100
committerLewis Russell <me@lewisr.dev>2023-11-29 10:17:15 +0000
commitf4001d27efae44c6c07678ad2c72eed5f1a25ea8 (patch)
treecbcbeb8bdccd1d56860ef94ee30f669602624611 /src/nvim/buffer.c
parent584c6c25ccfc5d13ffa0a4bd6efa467beb3987fe (diff)
downloadrneovim-f4001d27efae44c6c07678ad2c72eed5f1a25ea8.tar.gz
rneovim-f4001d27efae44c6c07678ad2c72eed5f1a25ea8.tar.bz2
rneovim-f4001d27efae44c6c07678ad2c72eed5f1a25ea8.zip
perf(column): only invalidate lines affected by added sign
Diffstat (limited to 'src/nvim/buffer.c')
-rw-r--r--src/nvim/buffer.c80
1 files changed, 28 insertions, 52 deletions
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index 4d553cc91f..e6bedca232 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -1844,7 +1844,7 @@ buf_T *buflist_new(char *ffname_arg, char *sfname_arg, linenr_T lnum, int flags)
buf = xcalloc(1, sizeof(buf_T));
// init b: variables
buf->b_vars = tv_dict_alloc();
- buf->b_signcols.valid = false;
+ buf->b_signcols.sentinel = 0;
init_var_dict(buf->b_vars, &buf->b_bufvar, VAR_SCOPE);
buf_init_changedtick(buf);
}
@@ -4026,88 +4026,64 @@ char *buf_spname(buf_T *buf)
return NULL;
}
-/// Invalidate the signcolumn if needed after deleting
-/// signs between line1 and line2 (inclusive).
-///
-/// @param buf buffer to check
-/// @param line1 start of region being deleted
-/// @param line2 end of region being deleted
+/// Invalidate the signcolumn if needed after deleting a sign ranging from line1 to line2.
void buf_signcols_del_check(buf_T *buf, linenr_T line1, linenr_T line2)
{
- if (!buf->b_signcols.valid) {
- return;
- }
-
- if (!buf->b_signcols.sentinel) {
- buf->b_signcols.valid = false;
- return;
- }
-
linenr_T sent = buf->b_signcols.sentinel;
-
if (sent >= line1 && sent <= line2) {
- // Only invalidate when removing signs at the sentinel line.
- buf->b_signcols.valid = false;
+ // When removed sign overlaps the sentinel line, entire buffer needs to be checked.
+ buf->b_signcols.sentinel = buf->b_signcols.size = 0;
}
}
-/// Re-calculate the signcolumn after adding a sign.
-///
-/// @param buf buffer to check
-/// @param added sign being added
+/// Invalidate the signcolumn if needed after adding a sign ranging from line1 to line2.
void buf_signcols_add_check(buf_T *buf, linenr_T line1, linenr_T line2)
{
- if (!buf->b_signcols.valid) {
- return;
- }
-
if (!buf->b_signcols.sentinel) {
- buf->b_signcols.valid = false;
return;
}
linenr_T sent = buf->b_signcols.sentinel;
-
if (sent >= line1 && sent <= line2) {
+ // If added sign overlaps sentinel line, increment without invalidating.
if (buf->b_signcols.size == buf->b_signcols.max) {
buf->b_signcols.max++;
}
buf->b_signcols.size++;
- redraw_buf_later(buf, UPD_NOT_VALID);
return;
}
- int signcols = decor_signcols(buf, line1 - 1, line2 - 1, SIGN_SHOW_MAX);
-
- if (signcols > buf->b_signcols.size) {
- buf->b_signcols.size = signcols;
- buf->b_signcols.max = signcols;
- redraw_buf_later(buf, UPD_NOT_VALID);
+ if (line1 < buf->b_signcols.invalid_top) {
+ buf->b_signcols.invalid_top = line1;
+ }
+ if (line2 > buf->b_signcols.invalid_bot) {
+ buf->b_signcols.invalid_bot = line2;
}
}
int buf_signcols(buf_T *buf, int max)
{
- // The maximum can be determined from 'signcolumn' which is window scoped so
- // need to invalidate signcols if the maximum is greater than the previous
- // (valid) maximum.
- if (buf->b_signcols.max && max > buf->b_signcols.max) {
- buf->b_signcols.valid = false;
- }
-
- if (!buf->b_signcols.valid) {
- buf->b_signcols.sentinel = 0;
- int signcols = decor_signcols(buf, 0, (int)buf->b_ml.ml_line_count - 1, max);
- // Check if we need to redraw
- if (signcols != buf->b_signcols.size) {
- buf->b_signcols.size = signcols;
- redraw_buf_later(buf, UPD_NOT_VALID);
+ if (!buf->b_signs_with_text) {
+ buf->b_signcols.size = 0;
+ } else if (max <= 1 && buf->b_signs_with_text >= (size_t)max) {
+ buf->b_signcols.size = max;
+ } else {
+ linenr_T sent = buf->b_signcols.sentinel;
+ if (!sent || max > buf->b_signcols.max) {
+ // Recheck if the window scoped maximum 'signcolumn' is greater than the
+ // previous maximum or if there is no sentinel line yet.
+ buf->b_signcols.invalid_top = sent ? sent : 1;
+ buf->b_signcols.invalid_bot = sent ? sent : buf->b_ml.ml_line_count;
}
- buf->b_signcols.max = max;
- buf->b_signcols.valid = true;
+ if (buf->b_signcols.invalid_bot) {
+ decor_validate_signcols(buf, max);
+ }
}
+ buf->b_signcols.max = max;
+ buf->b_signcols.invalid_top = MAXLNUM;
+ buf->b_signcols.invalid_bot = 0;
return buf->b_signcols.size;
}