aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbfredl <bjorn.linse@gmail.com>2023-08-28 11:35:09 +0200
committerbfredl <bjorn.linse@gmail.com>2023-08-29 09:26:15 +0200
commit0a81ec14a4c006822509b06396871509140b7a79 (patch)
tree3455796f8c48fe8c5f202fe3044580c8fe7d8930
parent794981d9bed7048fb3ee1ada38fcf1ebdace4c53 (diff)
downloadrneovim-0a81ec14a4c006822509b06396871509140b7a79.tar.gz
rneovim-0a81ec14a4c006822509b06396871509140b7a79.tar.bz2
rneovim-0a81ec14a4c006822509b06396871509140b7a79.zip
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.
-rw-r--r--src/nvim/api/buffer.c6
-rw-r--r--src/nvim/mark.c7
-rw-r--r--test/functional/api/buffer_spec.lua136
3 files changed, 144 insertions, 5 deletions
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c
index d36f0dd050..b8cb09ceb3 100644
--- a/src/nvim/api/buffer.c
+++ b/src/nvim/api/buffer.c
@@ -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,
diff --git a/src/nvim/mark.c b/src/nvim/mark.c
index 584a6c5827..39fc623676 100644
--- a/src/nvim/mark.c
+++ b/src/nvim/mark.c
@@ -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;
}
diff --git a/test/functional/api/buffer_spec.lua b/test/functional/api/buffer_spec.lua
index 73a8749682..aea1f359e6 100644
--- a/test/functional/api/buffer_spec.lua
+++ b/test/functional/api/buffer_spec.lua
@@ -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)