diff options
author | zeertzjq <zeertzjq@outlook.com> | 2023-08-21 08:58:18 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-08-21 08:58:18 +0800 |
commit | a2a226170d178086592967f23c39112811178f0c (patch) | |
tree | 4f6e662c7968a674192ef1b60ac7d42099239040 | |
parent | 694814cdd54ac245d1f4d2c28dce7e9132fcb616 (diff) | |
download | rneovim-a2a226170d178086592967f23c39112811178f0c.tar.gz rneovim-a2a226170d178086592967f23c39112811178f0c.tar.bz2 rneovim-a2a226170d178086592967f23c39112811178f0c.zip |
vim-patch:9.0.1772: Cursor may be adjusted in 'splitkeep'ed windows (#24811)
Problem: Cursor is adjusted in window that did not change in size by
'splitkeep'.
Solution: Only check that cursor position is valid in a window that
has changed in size.
closes: vim/vim#12509
https://github.com/vim/vim/commit/16af913eeefb288ce968fb87e09a597413861900
Co-authored-by: Luuk van Baal <luukvbaal@gmail.com>
-rw-r--r-- | src/nvim/buffer_defs.h | 1 | ||||
-rw-r--r-- | src/nvim/window.c | 16 | ||||
-rw-r--r-- | test/functional/legacy/window_cmd_spec.lua | 55 | ||||
-rw-r--r-- | test/old/testdir/test_window_cmd.vim | 27 |
4 files changed, 95 insertions, 4 deletions
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index ca1f791d28..0a7c742798 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -1194,6 +1194,7 @@ struct window_S { int w_hsep_height; // Number of horizontal separator rows (0 or 1) int w_vsep_width; // Number of vertical separator columns (0 or 1). pos_save_T w_save_cursor; // backup of cursor pos and topline + bool w_do_win_fix_cursor; // if true cursor may be invalid int w_winrow_off; ///< offset from winrow to the inner window area int w_wincol_off; ///< offset from wincol to the inner window area diff --git a/src/nvim/window.c b/src/nvim/window.c index e933390363..175a79568c 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -6465,6 +6465,10 @@ void win_fix_scroll(int resize) FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { // Skip when window height has not changed or when floating. if (!wp->w_floating && wp->w_height != wp->w_prev_height) { + // Cursor position in this window may now be invalid. It is kept + // potentially invalid until the window is made the current window. + wp->w_do_win_fix_cursor = true; + // If window has moved update botline to keep the same screenlines. if (*p_spk == 's' && wp->w_winrow != wp->w_prev_winrow && wp->w_botline - 1 <= wp->w_buffer->b_ml.ml_line_count) { @@ -6488,6 +6492,7 @@ void win_fix_scroll(int resize) } else if (wp == curwin) { wp->w_valid &= ~VALID_CROW; } + invalidate_botline_win(wp); validate_botline(wp); } @@ -6505,16 +6510,19 @@ void win_fix_scroll(int resize) /// Make sure the cursor position is valid for 'splitkeep'. /// If it is not, put the cursor position in the jumplist and move it. -/// If we are not in normal mode ("normal" is zero), make it valid by scrolling +/// If we are not in normal mode ("normal" is false), make it valid by scrolling /// instead. -static void win_fix_cursor(int normal) +static void win_fix_cursor(bool normal) { win_T *wp = curwin; - if (skip_win_fix_cursor || wp->w_buffer->b_ml.ml_line_count < wp->w_height) { + if (skip_win_fix_cursor + || !wp->w_do_win_fix_cursor + || wp->w_buffer->b_ml.ml_line_count < wp->w_height_inner) { return; } + wp->w_do_win_fix_cursor = false; // Determine valid cursor range. int so = MIN(wp->w_height_inner / 2, get_scrolloff_value(wp)); linenr_T lnum = wp->w_cursor.lnum; @@ -6533,7 +6541,7 @@ static void win_fix_cursor(int normal) if (lnum > bot && (wp->w_botline - wp->w_buffer->b_ml.ml_line_count) != 1) { nlnum = bot; } else if (lnum < top && wp->w_topline != 1) { - nlnum = (so == wp->w_height / 2) ? bot : top; + nlnum = (so == wp->w_height_inner / 2) ? bot : top; } if (nlnum != 0) { // Cursor is invalid for current scroll position. diff --git a/test/functional/legacy/window_cmd_spec.lua b/test/functional/legacy/window_cmd_spec.lua index 373a9c7163..979b46ae47 100644 --- a/test/functional/legacy/window_cmd_spec.lua +++ b/test/functional/legacy/window_cmd_spec.lua @@ -43,6 +43,61 @@ describe('splitkeep', function() screen:attach() end) + -- oldtest: Test_splitkeep_cursor() + it('does not adjust cursor in window that did not change size', function() + screen:try_resize(75, 8) + -- FIXME: bottom window is different without the "vsplit | close" + exec([[ + vsplit | close + set scrolloff=5 + set splitkeep=screen + autocmd CursorMoved * wincmd p | wincmd p + call setline(1, range(1, 200)) + func CursorEqualize() + call cursor(100, 1) + wincmd = + endfunc + wincmd s + call CursorEqualize() + ]]) + + screen:expect([[ + 99 | + ^100 | + 101 | + [No Name] [+] | + 5 | + 6 | + [No Name] [+] | + | + ]]) + + feed('j') + screen:expect([[ + 100 | + ^101 | + 102 | + [No Name] [+] | + 5 | + 6 | + [No Name] [+] | + | + ]]) + + command('set scrolloff=0') + feed('G') + screen:expect([[ + 198 | + 199 | + ^200 | + [No Name] [+] | + 5 | + 6 | + [No Name] [+] | + | + ]]) + end) + -- oldtest: Test_splitkeep_callback() it('does not scroll when split in callback', function() exec([[ diff --git a/test/old/testdir/test_window_cmd.vim b/test/old/testdir/test_window_cmd.vim index 7d4932a2b5..bd4cb44b2b 100644 --- a/test/old/testdir/test_window_cmd.vim +++ b/test/old/testdir/test_window_cmd.vim @@ -1805,6 +1805,33 @@ func Test_splitkeep_misc() set splitkeep& endfunc +func Test_splitkeep_cursor() + CheckScreendump + let lines =<< trim END + set splitkeep=screen + autocmd CursorMoved * wincmd p | wincmd p + call setline(1, range(1, 200)) + func CursorEqualize() + call cursor(100, 1) + wincmd = + endfunc + wincmd s + call CursorEqualize() + END + call writefile(lines, 'XTestSplitkeepCallback', 'D') + let buf = RunVimInTerminal('-S XTestSplitkeepCallback', #{rows: 8}) + + call VerifyScreenDump(buf, 'Test_splitkeep_cursor_1', {}) + + call term_sendkeys(buf, "j") + call VerifyScreenDump(buf, 'Test_splitkeep_cursor_2', {}) + + call term_sendkeys(buf, ":set scrolloff=0\<CR>G") + call VerifyScreenDump(buf, 'Test_splitkeep_cursor_3', {}) + + call StopVimInTerminal(buf) +endfunc + func Test_splitkeep_callback() CheckScreendump let lines =<< trim END |