fix(api): better topline adjustments in nvim_buf_set_lines

Some more reasonable defaults for topline:
  - if topline was replaced with another line, that now becomes topline
  - if line was inserted just before topline, display it. This is more
    similar to the previous API behavior.
This commit is contained in:
bfredl 2023-08-28 11:35:09 +02:00
parent 794981d9be
commit 0a81ec14a4
3 changed files with 144 additions and 5 deletions

View File

@ -464,7 +464,8 @@ void nvim_buf_set_lines(uint64_t channel_id, Buffer buffer, Integer start, Integ
// Adjust marks. Invalidate any which lie in the
// changed range, and move any in the remainder of the buffer.
mark_adjust_buf(buf, (linenr_T)start, (linenr_T)(end - 1), MAXLNUM, (linenr_T)extra,
linenr_T adjust = end > start ? MAXLNUM : 0;
mark_adjust_buf(buf, (linenr_T)start, (linenr_T)(end - 1), adjust, (linenr_T)extra,
true, true, kExtmarkNOOP);
extmark_splice(buf, (int)start - 1, 0, (int)(end - start), 0,
@ -711,7 +712,8 @@ void nvim_buf_set_text(uint64_t channel_id, Buffer buffer, Integer start_row, In
// Adjust marks. Invalidate any which lie in the
// changed range, and move any in the remainder of the buffer.
// Do not adjust any cursors. need to use column-aware logic (below)
mark_adjust_buf(buf, (linenr_T)start_row, (linenr_T)end_row, MAXLNUM, (linenr_T)extra,
linenr_T adjust = end_row >= start_row ? MAXLNUM : 0;
mark_adjust_buf(buf, (linenr_T)start_row, (linenr_T)end_row, adjust, (linenr_T)extra,
true, true, kExtmarkNOOP);
extmark_splice(buf, (int)start_row - 1, (colnr_T)start_col,

View File

@ -1249,7 +1249,8 @@ void mark_adjust_buf(buf_T *buf, linenr_T line1, linenr_T line2, linenr_T amount
if (line1 <= 1) {
win->w_topline = 1;
} else {
win->w_topline = line1 - 1;
// api: if the deleted region was replaced with new contents, display that
win->w_topline = (by_api && amount_after > line1 - line2 - 1) ? line1 : line1 - 1;
}
} else if (win->w_topline > line1) {
// keep topline on the same line, unless inserting just
@ -1257,7 +1258,9 @@ void mark_adjust_buf(buf_T *buf, linenr_T line1, linenr_T line2, linenr_T amount
win->w_topline += amount;
}
win->w_topfill = 0;
} else if (amount_after && win->w_topline > line2) {
// api: display new line if inserted right at topline
// TODO(bfredl): maybe always?
} else if (amount_after && win->w_topline > line2 + (by_api ? 1 : 0)) {
win->w_topline += amount_after;
win->w_topfill = 0;
}

View File

@ -182,8 +182,8 @@ describe('api/buf', function()
{2:[No Name] }|
|
]]}
meths.buf_set_lines(buf, 0, 2, true, {"aaabbb"})
meths.buf_set_lines(buf, 0, 2, true, {"aaabbb"})
screen:expect{grid=[[
|
{1:~ }|
@ -198,6 +198,72 @@ describe('api/buf', function()
{2:[No Name] [+] }|
|
]]}
-- replacing topline keeps it the topline
meths.buf_set_lines(buf, 3, 4, true, {"wwweeee"})
screen:expect{grid=[[
|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{3:[No Name] }|
wwweeee |
xxx |
yyy |
^zzz |
{2:[No Name] [+] }|
|
]]}
-- inserting just before topline does not scroll up if cursor would be moved
meths.buf_set_lines(buf, 3, 3, true, {"mmm"})
screen:expect{grid=[[
|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{3:[No Name] }|
wwweeee |
xxx |
yyy |
^zzz |
{2:[No Name] [+] }|
|
]], unchanged=true}
meths.win_set_cursor(0, {7, 0})
screen:expect{grid=[[
|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{3:[No Name] }|
wwweeee |
xxx |
^yyy |
zzz |
{2:[No Name] [+] }|
|
]]}
meths.buf_set_lines(buf, 4, 4, true, {"mmmeeeee"})
screen:expect{grid=[[
|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{3:[No Name] }|
mmmeeeee |
wwweeee |
xxx |
^yyy |
{2:[No Name] [+] }|
|
]]}
end)
it('of non-current window', function()
@ -237,6 +303,40 @@ describe('api/buf', function()
{3:[No Name] [+] }|
|
]]}
-- replacing topline keeps it the topline
meths.buf_set_lines(buf, 3, 4, true, {"wwweeee"})
screen:expect{grid=[[
^ |
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{2:[No Name] }|
wwweeee |
xxx |
yyy |
zzz |
{3:[No Name] [+] }|
|
]]}
-- inserting just before topline scrolls up
meths.buf_set_lines(buf, 3, 3, true, {"mmm"})
screen:expect{grid=[[
^ |
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{2:[No Name] }|
mmm |
wwweeee |
xxx |
yyy |
{3:[No Name] [+] }|
|
]]}
end)
it('of split windows with same buffer', function()
@ -277,6 +377,40 @@ describe('api/buf', function()
{3:[No Name] [+] }|
|
]]}
-- replacing topline keeps it the topline
meths.buf_set_lines(buf, 3, 4, true, {"wwweeee"})
screen:expect{grid=[[
^aaabbb |
ccc |
ddd |
wwweeee |
xxx |
{2:[No Name] [+] }|
wwweeee |
xxx |
yyy |
zzz |
{3:[No Name] [+] }|
|
]]}
-- inserting just before topline scrolls up
meths.buf_set_lines(buf, 3, 3, true, {"mmm"})
screen:expect{grid=[[
^aaabbb |
ccc |
ddd |
mmm |
wwweeee |
{2:[No Name] [+] }|
mmm |
wwweeee |
xxx |
yyy |
{3:[No Name] [+] }|
|
]]}
end)
end)