mirror of
https://github.com/neovim/neovim
synced 2025-07-19 10:41:48 +00:00
perf(column): only invalidate lines affected by added sign
This commit is contained in:
committed by
Lewis Russell
parent
584c6c25cc
commit
f4001d27ef
@ -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));
|
buf = xcalloc(1, sizeof(buf_T));
|
||||||
// init b: variables
|
// init b: variables
|
||||||
buf->b_vars = tv_dict_alloc();
|
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);
|
init_var_dict(buf->b_vars, &buf->b_bufvar, VAR_SCOPE);
|
||||||
buf_init_changedtick(buf);
|
buf_init_changedtick(buf);
|
||||||
}
|
}
|
||||||
@ -4026,88 +4026,64 @@ char *buf_spname(buf_T *buf)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Invalidate the signcolumn if needed after deleting
|
/// Invalidate the signcolumn if needed after deleting a sign ranging from line1 to line2.
|
||||||
/// 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
|
|
||||||
void buf_signcols_del_check(buf_T *buf, linenr_T line1, linenr_T 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;
|
linenr_T sent = buf->b_signcols.sentinel;
|
||||||
|
|
||||||
if (sent >= line1 && sent <= line2) {
|
if (sent >= line1 && sent <= line2) {
|
||||||
// Only invalidate when removing signs at the sentinel line.
|
// When removed sign overlaps the sentinel line, entire buffer needs to be checked.
|
||||||
buf->b_signcols.valid = false;
|
buf->b_signcols.sentinel = buf->b_signcols.size = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Re-calculate the signcolumn after adding a sign.
|
/// Invalidate the signcolumn if needed after adding a sign ranging from line1 to line2.
|
||||||
///
|
|
||||||
/// @param buf buffer to check
|
|
||||||
/// @param added sign being added
|
|
||||||
void buf_signcols_add_check(buf_T *buf, linenr_T line1, linenr_T 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) {
|
if (!buf->b_signcols.sentinel) {
|
||||||
buf->b_signcols.valid = false;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
linenr_T sent = buf->b_signcols.sentinel;
|
linenr_T sent = buf->b_signcols.sentinel;
|
||||||
|
|
||||||
if (sent >= line1 && sent <= line2) {
|
if (sent >= line1 && sent <= line2) {
|
||||||
|
// If added sign overlaps sentinel line, increment without invalidating.
|
||||||
if (buf->b_signcols.size == buf->b_signcols.max) {
|
if (buf->b_signcols.size == buf->b_signcols.max) {
|
||||||
buf->b_signcols.max++;
|
buf->b_signcols.max++;
|
||||||
}
|
}
|
||||||
buf->b_signcols.size++;
|
buf->b_signcols.size++;
|
||||||
redraw_buf_later(buf, UPD_NOT_VALID);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int signcols = decor_signcols(buf, line1 - 1, line2 - 1, SIGN_SHOW_MAX);
|
if (line1 < buf->b_signcols.invalid_top) {
|
||||||
|
buf->b_signcols.invalid_top = line1;
|
||||||
if (signcols > buf->b_signcols.size) {
|
}
|
||||||
buf->b_signcols.size = signcols;
|
if (line2 > buf->b_signcols.invalid_bot) {
|
||||||
buf->b_signcols.max = signcols;
|
buf->b_signcols.invalid_bot = line2;
|
||||||
redraw_buf_later(buf, UPD_NOT_VALID);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int buf_signcols(buf_T *buf, int max)
|
int buf_signcols(buf_T *buf, int max)
|
||||||
{
|
{
|
||||||
// The maximum can be determined from 'signcolumn' which is window scoped so
|
if (!buf->b_signs_with_text) {
|
||||||
// need to invalidate signcols if the maximum is greater than the previous
|
buf->b_signcols.size = 0;
|
||||||
// (valid) maximum.
|
} else if (max <= 1 && buf->b_signs_with_text >= (size_t)max) {
|
||||||
if (buf->b_signcols.max && max > buf->b_signcols.max) {
|
buf->b_signcols.size = max;
|
||||||
buf->b_signcols.valid = false;
|
} 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!buf->b_signcols.valid) {
|
if (buf->b_signcols.invalid_bot) {
|
||||||
buf->b_signcols.sentinel = 0;
|
decor_validate_signcols(buf, max);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
buf->b_signcols.max = max;
|
buf->b_signcols.max = max;
|
||||||
buf->b_signcols.valid = true;
|
buf->b_signcols.invalid_top = MAXLNUM;
|
||||||
}
|
buf->b_signcols.invalid_bot = 0;
|
||||||
|
|
||||||
return buf->b_signcols.size;
|
return buf->b_signcols.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -706,9 +706,10 @@ struct file_buffer {
|
|||||||
|
|
||||||
struct {
|
struct {
|
||||||
int size; // last calculated number of sign columns
|
int size; // last calculated number of sign columns
|
||||||
bool valid; // calculated sign columns is valid
|
int max; // maximum value size is valid for.
|
||||||
linenr_T sentinel; // a line number which is holding up the signcolumn
|
linenr_T sentinel; // a line number which is holding up the signcolumn
|
||||||
int max; // Maximum value size is valid for.
|
linenr_T invalid_top; // first invalid line number that needs to be checked
|
||||||
|
linenr_T invalid_bot; // last invalid line number that needs to be checked
|
||||||
} b_signcols;
|
} b_signcols;
|
||||||
|
|
||||||
Terminal *terminal; // Terminal instance associated with the buffer
|
Terminal *terminal; // Terminal instance associated with the buffer
|
||||||
|
@ -791,22 +791,15 @@ DecorSignHighlight *decor_find_sign(DecorInline decor)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the maximum required amount of sign columns needed between row and
|
// Increase the signcolumn size and update the sentinel line if necessary for
|
||||||
// end_row.
|
// the invalidated range.
|
||||||
int decor_signcols(buf_T *buf, int row, int end_row, int max)
|
void decor_validate_signcols(buf_T *buf, int max)
|
||||||
{
|
{
|
||||||
if (max <= 1 && buf->b_signs_with_text >= (size_t)max) {
|
|
||||||
return max;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buf->b_signs_with_text == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int signcols = 0; // highest value of count
|
int signcols = 0; // highest value of count
|
||||||
|
int currow = buf->b_signcols.invalid_top - 1;
|
||||||
// TODO(bfredl): only need to use marktree_itr_get_overlap once.
|
// TODO(bfredl): only need to use marktree_itr_get_overlap once.
|
||||||
// then we can process both start and end events and update state for each row
|
// then we can process both start and end events and update state for each row
|
||||||
for (int currow = row; currow <= end_row; currow++) {
|
for (; currow < buf->b_signcols.invalid_bot; currow++) {
|
||||||
MarkTreeIter itr[1];
|
MarkTreeIter itr[1];
|
||||||
if (!marktree_itr_get_overlap(buf->b_marktree, currow, 0, itr)) {
|
if (!marktree_itr_get_overlap(buf->b_marktree, currow, 0, itr)) {
|
||||||
continue;
|
continue;
|
||||||
@ -832,17 +825,16 @@ int decor_signcols(buf_T *buf, int row, int end_row, int max)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (count > signcols) {
|
if (count > signcols) {
|
||||||
if (count > buf->b_signcols.size) {
|
if (count >= buf->b_signcols.size) {
|
||||||
|
buf->b_signcols.size = count;
|
||||||
buf->b_signcols.sentinel = currow + 1;
|
buf->b_signcols.sentinel = currow + 1;
|
||||||
}
|
}
|
||||||
if (count >= max) {
|
if (count >= max) {
|
||||||
return max;
|
return;
|
||||||
}
|
}
|
||||||
signcols = count;
|
signcols = count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return signcols;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void decor_redraw_end(DecorState *state)
|
void decor_redraw_end(DecorState *state)
|
||||||
|
@ -606,10 +606,12 @@ int update_screen(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Reset 'statuscolumn' if there is no dedicated signcolumn but it is invalid.
|
// Reset 'statuscolumn' if there is no dedicated signcolumn but it is invalid.
|
||||||
if (*wp->w_p_stc != NUL && !wp->w_buffer->b_signcols.valid && wp->w_minscwidth <= SCL_NO) {
|
if (*wp->w_p_stc != NUL && wp->w_minscwidth <= SCL_NO
|
||||||
|
&& (wp->w_buffer->b_signcols.invalid_bot || !wp->w_buffer->b_signcols.sentinel)) {
|
||||||
wp->w_nrwidth_line_count = 0;
|
wp->w_nrwidth_line_count = 0;
|
||||||
wp->w_valid &= ~VALID_WCOL;
|
wp->w_valid &= ~VALID_WCOL;
|
||||||
wp->w_redr_type = UPD_NOT_VALID;
|
wp->w_redr_type = UPD_NOT_VALID;
|
||||||
|
wp->w_buffer->b_signcols.invalid_bot = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -618,11 +620,6 @@ int update_screen(void)
|
|||||||
screen_search_hl.rm.regprog = NULL;
|
screen_search_hl.rm.regprog = NULL;
|
||||||
|
|
||||||
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
|
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 && wp->w_minscwidth <= SCL_NO) {
|
|
||||||
buf_signcols(wp->w_buffer, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wp->w_redr_type == UPD_CLEAR && wp->w_floating && wp->w_grid_alloc.chars) {
|
if (wp->w_redr_type == UPD_CLEAR && wp->w_floating && wp->w_grid_alloc.chars) {
|
||||||
grid_invalidate(&wp->w_grid_alloc);
|
grid_invalidate(&wp->w_grid_alloc);
|
||||||
wp->w_redr_type = UPD_NOT_VALID;
|
wp->w_redr_type = UPD_NOT_VALID;
|
||||||
@ -1213,6 +1210,7 @@ static void redraw_win_signcol(win_T *wp)
|
|||||||
wp->w_scwidth = win_signcol_count(wp);
|
wp->w_scwidth = win_signcol_count(wp);
|
||||||
if (wp->w_scwidth != scwidth) {
|
if (wp->w_scwidth != scwidth) {
|
||||||
changed_line_abv_curs_win(wp);
|
changed_line_abv_curs_win(wp);
|
||||||
|
redraw_later(wp, UPD_NOT_VALID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -467,6 +467,27 @@ describe('Signs', function()
|
|||||||
{0:~ }|
|
{0:~ }|
|
||||||
|
|
|
|
||||||
]])
|
]])
|
||||||
|
-- should not increase size because sign with existing id is moved
|
||||||
|
command('sign place 4 line=1 name=pietSearch buffer=1')
|
||||||
|
screen:expect_unchanged()
|
||||||
|
command('sign unplace 4')
|
||||||
|
screen:expect([[
|
||||||
|
{1:>>>>>>}{6: 1 }a |
|
||||||
|
{2: }{6: 2 }b |
|
||||||
|
{2: }{6: 3 }c |
|
||||||
|
{2: }{6: 4 }^ |
|
||||||
|
{0:~ }|
|
||||||
|
{0:~ }|
|
||||||
|
{0:~ }|
|
||||||
|
{0:~ }|
|
||||||
|
{0:~ }|
|
||||||
|
{0:~ }|
|
||||||
|
{0:~ }|
|
||||||
|
{0:~ }|
|
||||||
|
{0:~ }|
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
command('sign place 4 line=1 name=pietSearch buffer=1')
|
||||||
-- should keep the column at maximum size when signs are
|
-- should keep the column at maximum size when signs are
|
||||||
-- exceeding the maximum
|
-- exceeding the maximum
|
||||||
command('sign place 5 line=1 name=pietSearch buffer=1')
|
command('sign place 5 line=1 name=pietSearch buffer=1')
|
||||||
|
Reference in New Issue
Block a user