mirror of
https://github.com/neovim/neovim.git
synced 2025-10-09 19:36:40 +00:00
vim-patch:9.0.1530: cursor moves to wrong line when 'foldmethod' is "diff"
Problem: Cursor moves to wrong line when 'foldmethod' is "diff". (Rick
Howe)
Solution: Adjust logic for scrolling. (Luuk van Baal, closes vim/vim#12364,
closes vim/vim#12218)
aa6ba308a1
This commit is contained in:
@@ -1318,14 +1318,6 @@ bool scrolldown(long line_count, int byfold)
|
|||||||
return moved;
|
return moved;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return TRUE if scrollup() will scroll by screen line rather than text line.
|
|
||||||
static int scrolling_screenlines(bool byfold)
|
|
||||||
{
|
|
||||||
return (curwin->w_p_wrap && curwin->w_p_sms)
|
|
||||||
|| (byfold && hasAnyFolding(curwin))
|
|
||||||
|| (curwin->w_p_diff && !curwin->w_p_wrap);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Scroll the current window up by "line_count" logical lines. "CTRL-E"
|
/// Scroll the current window up by "line_count" logical lines. "CTRL-E"
|
||||||
///
|
///
|
||||||
/// @param line_count number of lines to scroll
|
/// @param line_count number of lines to scroll
|
||||||
@@ -1336,7 +1328,7 @@ bool scrollup(long line_count, int byfold)
|
|||||||
linenr_T botline = curwin->w_botline;
|
linenr_T botline = curwin->w_botline;
|
||||||
int do_sms = curwin->w_p_wrap && curwin->w_p_sms;
|
int do_sms = curwin->w_p_wrap && curwin->w_p_sms;
|
||||||
|
|
||||||
if (scrolling_screenlines(byfold) || win_may_fill(curwin)) {
|
if (do_sms || (byfold && hasAnyFolding(curwin)) || win_may_fill(curwin)) {
|
||||||
int width1 = curwin->w_width_inner - curwin_col_off();
|
int width1 = curwin->w_width_inner - curwin_col_off();
|
||||||
int width2 = width1 + curwin_col_off2();
|
int width2 = width1 + curwin_col_off2();
|
||||||
unsigned size = 0;
|
unsigned size = 0;
|
||||||
@@ -1873,6 +1865,7 @@ void scroll_cursor_bot(int min_scroll, int set_topbot)
|
|||||||
int old_valid = curwin->w_valid;
|
int old_valid = curwin->w_valid;
|
||||||
int old_empty_rows = curwin->w_empty_rows;
|
int old_empty_rows = curwin->w_empty_rows;
|
||||||
linenr_T cln = curwin->w_cursor.lnum; // Cursor Line Number
|
linenr_T cln = curwin->w_cursor.lnum; // Cursor Line Number
|
||||||
|
int do_sms = curwin->w_p_wrap && curwin->w_p_sms;
|
||||||
|
|
||||||
if (set_topbot) {
|
if (set_topbot) {
|
||||||
bool set_skipcol = false;
|
bool set_skipcol = false;
|
||||||
@@ -1889,7 +1882,7 @@ void scroll_cursor_bot(int min_scroll, int set_topbot)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (used + loff.height > curwin->w_height_inner) {
|
if (used + loff.height > curwin->w_height_inner) {
|
||||||
if (curwin->w_p_sms && curwin->w_p_wrap) {
|
if (do_sms) {
|
||||||
// 'smoothscroll' and 'wrap' are set. The above line is
|
// 'smoothscroll' and 'wrap' are set. The above line is
|
||||||
// too long to show in its entirety, so we show just a part
|
// too long to show in its entirety, so we show just a part
|
||||||
// of it.
|
// of it.
|
||||||
@@ -1928,7 +1921,6 @@ void scroll_cursor_bot(int min_scroll, int set_topbot)
|
|||||||
used = plines_win_nofill(curwin, cln, true);
|
used = plines_win_nofill(curwin, cln, true);
|
||||||
|
|
||||||
int scrolled = 0;
|
int scrolled = 0;
|
||||||
int min_scrolled = 1;
|
|
||||||
// If the cursor is on or below botline, we will at least scroll by the
|
// If the cursor is on or below botline, we will at least scroll by the
|
||||||
// height of the cursor line, which is "used". Correct for empty lines,
|
// height of the cursor line, which is "used". Correct for empty lines,
|
||||||
// which are really part of botline.
|
// which are really part of botline.
|
||||||
@@ -1937,16 +1929,8 @@ void scroll_cursor_bot(int min_scroll, int set_topbot)
|
|||||||
if (cln == curwin->w_botline) {
|
if (cln == curwin->w_botline) {
|
||||||
scrolled -= curwin->w_empty_rows;
|
scrolled -= curwin->w_empty_rows;
|
||||||
}
|
}
|
||||||
min_scrolled = scrolled;
|
if (do_sms) {
|
||||||
if (curwin->w_p_sms && curwin->w_p_wrap) {
|
// 'smoothscroll' and 'wrap' are set.
|
||||||
// 'smoothscroll' and 'wrap' are set
|
|
||||||
if (cln > curwin->w_botline) {
|
|
||||||
// add screen lines below w_botline
|
|
||||||
for (linenr_T lnum = curwin->w_botline + 1; lnum <= cln; lnum++) {
|
|
||||||
min_scrolled += plines_win_nofill(curwin, lnum, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate how many screen lines the current top line of window
|
// Calculate how many screen lines the current top line of window
|
||||||
// occupies. If it is occupying more than the entire window, we
|
// occupies. If it is occupying more than the entire window, we
|
||||||
// need to scroll the additional clipped lines to scroll past the
|
// need to scroll the additional clipped lines to scroll past the
|
||||||
@@ -1965,7 +1949,6 @@ void scroll_cursor_bot(int min_scroll, int set_topbot)
|
|||||||
top_plines -= skip_lines;
|
top_plines -= skip_lines;
|
||||||
if (top_plines > curwin->w_height_inner) {
|
if (top_plines > curwin->w_height_inner) {
|
||||||
scrolled += (top_plines - curwin->w_height_inner);
|
scrolled += (top_plines - curwin->w_height_inner);
|
||||||
min_scrolled += (top_plines - curwin->w_height_inner);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2070,21 +2053,11 @@ void scroll_cursor_bot(int min_scroll, int set_topbot)
|
|||||||
// Otherwise put it at 1/2 of the screen.
|
// Otherwise put it at 1/2 of the screen.
|
||||||
if (line_count >= curwin->w_height_inner && line_count > min_scroll) {
|
if (line_count >= curwin->w_height_inner && line_count > min_scroll) {
|
||||||
scroll_cursor_halfway(false, true);
|
scroll_cursor_halfway(false, true);
|
||||||
} else {
|
} else if (line_count > 0) {
|
||||||
// With 'smoothscroll' scroll at least the height of the cursor line,
|
if (do_sms) {
|
||||||
// unless it would move the cursor.
|
scrollup(scrolled, true); // TODO(vim):
|
||||||
if (curwin->w_p_wrap && curwin->w_p_sms && line_count < min_scrolled
|
} else {
|
||||||
&& (curwin->w_cursor.lnum < curwin->w_topline
|
scrollup(line_count, true);
|
||||||
|| (curwin->w_virtcol - curwin->w_skipcol >=
|
|
||||||
curwin->w_width_inner - curwin_col_off()))) {
|
|
||||||
line_count = min_scrolled;
|
|
||||||
}
|
|
||||||
if (line_count > 0) {
|
|
||||||
if (scrolling_screenlines(true)) {
|
|
||||||
scrollup(scrolled, true); // TODO(vim):
|
|
||||||
} else {
|
|
||||||
scrollup(line_count, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
41
test/functional/legacy/normal_spec.lua
Normal file
41
test/functional/legacy/normal_spec.lua
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
local helpers = require('test.functional.helpers')(after_each)
|
||||||
|
local Screen = require('test.functional.ui.screen')
|
||||||
|
local clear = helpers.clear
|
||||||
|
local exec = helpers.exec
|
||||||
|
|
||||||
|
before_each(clear)
|
||||||
|
|
||||||
|
describe('normal', function()
|
||||||
|
-- oldtest: Test_normal_j_below_botline()
|
||||||
|
it([["j" does not skip lines when scrolling below botline and 'foldmethod' is not "manual"]], function()
|
||||||
|
local screen = Screen.new(40, 19)
|
||||||
|
screen:attach()
|
||||||
|
screen:set_default_attr_ids({{foreground = Screen.colors.Brown}})
|
||||||
|
exec([[
|
||||||
|
set number foldmethod=diff scrolloff=0
|
||||||
|
call setline(1, map(range(1, 9), 'repeat(v:val, 200)'))
|
||||||
|
norm Lj
|
||||||
|
]])
|
||||||
|
screen:expect([[
|
||||||
|
{1: 2 }222222222222222222222222222222222222|
|
||||||
|
{1: }222222222222222222222222222222222222|
|
||||||
|
{1: }222222222222222222222222222222222222|
|
||||||
|
{1: }222222222222222222222222222222222222|
|
||||||
|
{1: }222222222222222222222222222222222222|
|
||||||
|
{1: }22222222222222222222 |
|
||||||
|
{1: 3 }333333333333333333333333333333333333|
|
||||||
|
{1: }333333333333333333333333333333333333|
|
||||||
|
{1: }333333333333333333333333333333333333|
|
||||||
|
{1: }333333333333333333333333333333333333|
|
||||||
|
{1: }333333333333333333333333333333333333|
|
||||||
|
{1: }33333333333333333333 |
|
||||||
|
{1: 4 }^444444444444444444444444444444444444|
|
||||||
|
{1: }444444444444444444444444444444444444|
|
||||||
|
{1: }444444444444444444444444444444444444|
|
||||||
|
{1: }444444444444444444444444444444444444|
|
||||||
|
{1: }444444444444444444444444444444444444|
|
||||||
|
{1: }44444444444444444444 |
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
end)
|
||||||
|
end)
|
@@ -3993,4 +3993,22 @@ func Test_mouse_shape_after_cancelling_gr()
|
|||||||
call delete('Xmouseshapes')
|
call delete('Xmouseshapes')
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
" Test that "j" does not skip lines when scrolling below botline and
|
||||||
|
" 'foldmethod' is not "manual".
|
||||||
|
func Test_normal_j_below_botline()
|
||||||
|
CheckScreendump
|
||||||
|
|
||||||
|
let lines =<< trim END
|
||||||
|
set number foldmethod=diff scrolloff=0
|
||||||
|
call setline(1, map(range(1, 9), 'repeat(v:val, 200)'))
|
||||||
|
norm Lj
|
||||||
|
END
|
||||||
|
call writefile(lines, 'XNormalJBelowBotline', 'D')
|
||||||
|
let buf = RunVimInTerminal('-S XNormalJBelowBotline', #{rows: 19, cols: 40})
|
||||||
|
|
||||||
|
call VerifyScreenDump(buf, 'Test_normal_j_below_botline', {})
|
||||||
|
|
||||||
|
call StopVimInTerminal(buf)
|
||||||
|
endfunc
|
||||||
|
|
||||||
" vim: shiftwidth=2 sts=2 expandtab
|
" vim: shiftwidth=2 sts=2 expandtab
|
||||||
|
Reference in New Issue
Block a user