diff options
author | hashinclude <pulkitg10@gmail.com> | 2019-05-07 09:17:05 +0200 |
---|---|---|
committer | Justin M. Keyes <justinkz@gmail.com> | 2019-05-07 09:17:37 +0200 |
commit | 400ee59247eae62990baf30c7802bc8effb3704a (patch) | |
tree | 6ca5b263ddcac4e48d4e803cc226e83b4ceee798 | |
parent | b3adfa03b70fd5ecbe485488c10ee952ec811d93 (diff) | |
download | rneovim-400ee59247eae62990baf30c7802bc8effb3704a.tar.gz rneovim-400ee59247eae62990baf30c7802bc8effb3704a.tar.bz2 rneovim-400ee59247eae62990baf30c7802bc8effb3704a.zip |
API: fix cursor position when lines are added #9961
Restore code removed in #9674.
-rw-r--r-- | src/nvim/api/buffer.c | 21 | ||||
-rw-r--r-- | test/functional/api/buffer_spec.lua | 35 |
2 files changed, 56 insertions, 0 deletions
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index da4db60ad6..4a0b8d13d0 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -474,6 +474,7 @@ void nvim_buf_set_lines(uint64_t channel_id, false); changed_lines((linenr_T)start, 0, (linenr_T)end, (long)extra, true); + fix_cursor((linenr_T)start, (linenr_T)end, (linenr_T)extra); end: for (size_t i = 0; i < new_len; i++) { @@ -1106,6 +1107,26 @@ free_exit: return 0; } +// Check if deleting lines made the cursor position invalid. +// Changed lines from `lo` to `hi`; added `extra` lines (negative if deleted). +static void fix_cursor(linenr_T lo, linenr_T hi, linenr_T extra) +{ + if (curwin->w_cursor.lnum >= lo) { + // Adjust cursor position if it's in/after the changed lines. + if (curwin->w_cursor.lnum >= hi) { + curwin->w_cursor.lnum += extra; + check_cursor_col(); + } else if (extra < 0) { + curwin->w_cursor.lnum = lo; + check_cursor(); + } else { + check_cursor_col(); + } + changed_cline_bef_curs(); + } + invalidate_botline(); +} + // Normalizes 0-based indexes to buffer line numbers static int64_t normalize_index(buf_T *buf, int64_t index, bool *oob) { diff --git a/test/functional/api/buffer_spec.lua b/test/functional/api/buffer_spec.lua index d26cb0dbb3..9d6cfb99ab 100644 --- a/test/functional/api/buffer_spec.lua +++ b/test/functional/api/buffer_spec.lua @@ -39,6 +39,41 @@ describe('api/buf', function() eq(1, curbuf_depr('line_count')) end) + it('cursor position is maintained after lines are inserted #9961', function() + -- replace the buffer contents with these three lines. + request('nvim_buf_set_lines', 0, 0, -1, 1, {"line1", "line2", "line3", "line4"}) + -- Set the current cursor to {3, 2}. + curwin('set_cursor', {3, 2}) + + -- add 2 lines and delete 1 line above the current cursor position. + request('nvim_buf_set_lines', 0, 1, 2, 1, {"line5", "line6"}) + -- check the current set of lines in the buffer. + eq({"line1", "line5", "line6", "line3", "line4"}, buffer('get_lines', 0, 0, -1, 1)) + -- cursor should be moved below by 1 line. + eq({4, 2}, curwin('get_cursor')) + + -- add a line after the current cursor position. + request('nvim_buf_set_lines', 0, 5, 5, 1, {"line7"}) + -- check the current set of lines in the buffer. + eq({"line1", "line5", "line6", "line3", "line4", "line7"}, buffer('get_lines', 0, 0, -1, 1)) + -- cursor position is unchanged. + eq({4, 2}, curwin('get_cursor')) + + -- overwrite current cursor line. + request('nvim_buf_set_lines', 0, 3, 5, 1, {"line8", "line9"}) + -- check the current set of lines in the buffer. + eq({"line1", "line5", "line6", "line8", "line9", "line7"}, buffer('get_lines', 0, 0, -1, 1)) + -- cursor position is unchanged. + eq({4, 2}, curwin('get_cursor')) + + -- delete current cursor line. + request('nvim_buf_set_lines', 0, 3, 5, 1, {}) + -- check the current set of lines in the buffer. + eq({"line1", "line5", "line6", "line7"}, buffer('get_lines', 0, 0, -1, 1)) + -- cursor position is unchanged. + eq({4, 2}, curwin('get_cursor')) + end) + it('line_count has defined behaviour for unloaded buffers', function() -- we'll need to know our bufnr for when it gets unloaded local bufnr = curbuf('get_number') |