1
0
forked from aniani/vim

patch 9.0.0647: the 'splitscroll' option is not a good name

Problem:    The 'splitscroll' option is not a good name.
Solution:   Rename 'splitscroll' to 'splitkeep' and make it a string option,
            also supporting "topline". (Luuk van Baal, closes #11258)
This commit is contained in:
Luuk van Baal 2022-10-03 15:28:08 +01:00 committed by Bram Moolenaar
parent 6b2d4ff714
commit 13ece2ae1d
21 changed files with 141 additions and 129 deletions

View File

@ -7518,24 +7518,28 @@ A jump table for the options with a short description can be found at |Q_op|.
When on, splitting a window will put the new window below the current When on, splitting a window will put the new window below the current
one. |:split| one. |:split|
*'splitkeep'* *'spk'
'splitkeep' 'spk' string (default "cursor")
global
The value of this option determines the scroll behavior when opening,
closing or resizing horizontal splits.
Possible values are:
cursor Keep the same relative cursor position.
screen Keep the text on the same screen line.
topline Keep the topline the same.
For the "screen" and "topline" values, the cursor position will be
changed when necessary. In this case, the jumplist will be populated
with the previous cursor position. For "screen", the text cannot always
be kept on the same screen line when 'wrap' is enabled.
*'splitright'* *'spr'* *'nosplitright'* *'nospr'* *'splitright'* *'spr'* *'nosplitright'* *'nospr'*
'splitright' 'spr' boolean (default off) 'splitright' 'spr' boolean (default off)
global global
When on, splitting a window will put the new window right of the When on, splitting a window will put the new window right of the
current one. |:vsplit| current one. |:vsplit|
*'splitscroll'* *'spsc'* *'nosplitscroll'* *'nospsc'*
'splitscroll' 'spsc' boolean (default on)
global
The value of this option determines the scroll behavior when opening,
closing or resizing horizontal splits. When "on", splitting a window
horizontally will keep the same relative cursor position in the old and
new window, as well windows that are resized. When "off", scrolling
will be avoided to stabilize the window content. Instead, the cursor
position will be changed when necessary. In this case, the jumplist
will be populated with the previous cursor position. Scrolling cannot
be guaranteed to be avoided when 'wrap' is enabled.
*'startofline'* *'sol'* *'nostartofline'* *'nosol'* *'startofline'* *'sol'* *'nostartofline'* *'nosol'*
'startofline' 'sol' boolean (default on) 'startofline' 'sol' boolean (default on)
global global

View File

@ -919,8 +919,8 @@ Short explanation of each option: *option-list*
'spelloptions' 'spo' options for spell checking 'spelloptions' 'spo' options for spell checking
'spellsuggest' 'sps' method(s) used to suggest spelling corrections 'spellsuggest' 'sps' method(s) used to suggest spelling corrections
'splitbelow' 'sb' new window from split is below the current one 'splitbelow' 'sb' new window from split is below the current one
'splitkeep' 'spk' determines scroll behavior for split windows
'splitright' 'spr' new window is put right of the current one 'splitright' 'spr' new window is put right of the current one
'splitscroll' 'spsc' determines scroll behavior for split windows
'startofline' 'sol' commands move cursor to first non-blank in line 'startofline' 'sol' commands move cursor to first non-blank in line
'statusline' 'stl' custom format for the status line 'statusline' 'stl' custom format for the status line
'suffixes' 'su' suffixes that are ignored with multiple match 'suffixes' 'su' suffixes that are ignored with multiple match

View File

@ -516,10 +516,10 @@ call <SID>AddOption("switchbuf", gettext("\"useopen\" and/or \"split\"; which wi
call <SID>OptionG("swb", &swb) call <SID>OptionG("swb", &swb)
call <SID>AddOption("splitbelow", gettext("a new window is put below the current one")) call <SID>AddOption("splitbelow", gettext("a new window is put below the current one"))
call <SID>BinOptionG("sb", &sb) call <SID>BinOptionG("sb", &sb)
call <SID>AddOption("splitkeep", gettext("determines scroll behavior for split windows"))
call <SID>BinOptionG("spk", &spk)
call <SID>AddOption("splitright", gettext("a new window is put right of the current one")) call <SID>AddOption("splitright", gettext("a new window is put right of the current one"))
call <SID>BinOptionG("spr", &spr) call <SID>BinOptionG("spr", &spr)
call <SID>AddOption("splitscroll", gettext("determines scroll behavior for split windows"))
call <SID>BinOptionG("spsc", &spsc)
call <SID>AddOption("scrollbind", gettext("this window scrolls together with other bound windows")) call <SID>AddOption("scrollbind", gettext("this window scrolls together with other bound windows"))
call append("$", "\t" .. s:local_to_window) call append("$", "\t" .. s:local_to_window)
call <SID>BinOptionL("scb") call <SID>BinOptionL("scb")

View File

@ -1975,10 +1975,10 @@ EXTERN int channel_need_redraw INIT(= FALSE);
EXTERN optmagic_T magic_overruled INIT(= OPTION_MAGIC_NOT_SET); EXTERN optmagic_T magic_overruled INIT(= OPTION_MAGIC_NOT_SET);
#ifdef FEAT_CMDWIN #ifdef FEAT_CMDWIN
// Skip win_fix_cursor() call for 'nosplitscroll' when cmdwin is closed. // Skip win_fix_cursor() call for 'splitkeep' when cmdwin is closed.
EXTERN int skip_win_fix_cursor INIT(= FALSE); EXTERN int skip_win_fix_cursor INIT(= FALSE);
#endif #endif
// Skip win_fix_scroll() call for 'nosplitscroll' when closing tab page. // Skip win_fix_scroll() call for 'splitkeep' when closing tab page.
EXTERN int skip_win_fix_scroll INIT(= FALSE); EXTERN int skip_win_fix_scroll INIT(= FALSE);
// Skip update_topline() call while executing win_fix_scroll(). // Skip update_topline() call while executing win_fix_scroll().
EXTERN int skip_update_topline INIT(= FALSE); EXTERN int skip_update_topline INIT(= FALSE);

View File

@ -219,6 +219,10 @@ update_topline(void)
long *so_ptr = curwin->w_p_so >= 0 ? &curwin->w_p_so : &p_so; long *so_ptr = curwin->w_p_so >= 0 ? &curwin->w_p_so : &p_so;
int save_so = *so_ptr; int save_so = *so_ptr;
// Cursor is updated instead when this is TRUE for 'splitkeep'.
if (skip_update_topline)
return;
// If there is no valid screen and when the window height is zero just use // If there is no valid screen and when the window height is zero just use
// the cursor line. // the cursor line.
if (!screen_valid(TRUE) || curwin->w_height == 0) if (!screen_valid(TRUE) || curwin->w_height == 0)
@ -1027,8 +1031,7 @@ curs_columns(
/* /*
* First make sure that w_topline is valid (after moving the cursor). * First make sure that w_topline is valid (after moving the cursor).
*/ */
if (!skip_update_topline) update_topline();
update_topline();
/* /*
* Next make sure that w_cline_row is valid. * Next make sure that w_cline_row is valid.

View File

@ -924,11 +924,11 @@ EXTERN char_u *p_spo; // 'spelloptions'
EXTERN char_u *p_sps; // 'spellsuggest' EXTERN char_u *p_sps; // 'spellsuggest'
#endif #endif
EXTERN int p_spr; // 'splitright' EXTERN int p_spr; // 'splitright'
EXTERN int p_spsc; // 'splitscroll'
EXTERN int p_sol; // 'startofline' EXTERN int p_sol; // 'startofline'
EXTERN char_u *p_su; // 'suffixes' EXTERN char_u *p_su; // 'suffixes'
EXTERN char_u *p_sws; // 'swapsync' EXTERN char_u *p_sws; // 'swapsync'
EXTERN char_u *p_swb; // 'switchbuf' EXTERN char_u *p_swb; // 'switchbuf'
EXTERN char_u *p_spk; // 'splitkeep'
EXTERN unsigned swb_flags; EXTERN unsigned swb_flags;
// Keep in sync with p_swb_values in optionstr.c // Keep in sync with p_swb_values in optionstr.c
#define SWB_USEOPEN 0x001 #define SWB_USEOPEN 0x001

View File

@ -2350,12 +2350,12 @@ static struct vimoption options[] =
{"splitbelow", "sb", P_BOOL|P_VI_DEF, {"splitbelow", "sb", P_BOOL|P_VI_DEF,
(char_u *)&p_sb, PV_NONE, (char_u *)&p_sb, PV_NONE,
{(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
{"splitkeep", "spk", P_STRING,
(char_u *)&p_spk, PV_NONE,
{(char_u *)"cursor", (char_u *)"cursor"} SCTX_INIT},
{"splitright", "spr", P_BOOL|P_VI_DEF, {"splitright", "spr", P_BOOL|P_VI_DEF,
(char_u *)&p_spr, PV_NONE, (char_u *)&p_spr, PV_NONE,
{(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, {(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
{"splitscroll", "spsc", P_BOOL,
(char_u *)&p_spsc, PV_NONE,
{(char_u *)TRUE, (char_u *)TRUE} SCTX_INIT},
{"startofline", "sol", P_BOOL|P_VI_DEF|P_VIM, {"startofline", "sol", P_BOOL|P_VI_DEF|P_VIM,
(char_u *)&p_sol, PV_NONE, (char_u *)&p_sol, PV_NONE,
{(char_u *)TRUE, (char_u *)0L} SCTX_INIT}, {(char_u *)TRUE, (char_u *)0L} SCTX_INIT},

View File

@ -46,6 +46,7 @@ static char *(p_ssop_values[]) = {"buffers", "winpos", "resize", "winsize",
#endif #endif
// Keep in sync with SWB_ flags in option.h // Keep in sync with SWB_ flags in option.h
static char *(p_swb_values[]) = {"useopen", "usetab", "split", "newtab", "vsplit", "uselast", NULL}; static char *(p_swb_values[]) = {"useopen", "usetab", "split", "newtab", "vsplit", "uselast", NULL};
static char *(p_spk_values[]) = {"cursor", "screen", "topline", NULL};
static char *(p_tc_values[]) = {"followic", "ignore", "match", "followscs", "smart", NULL}; static char *(p_tc_values[]) = {"followic", "ignore", "match", "followscs", "smart", NULL};
#if defined(FEAT_TOOLBAR) && !defined(FEAT_GUI_MSWIN) #if defined(FEAT_TOOLBAR) && !defined(FEAT_GUI_MSWIN)
static char *(p_toolbar_values[]) = {"text", "icons", "tooltips", "horiz", NULL}; static char *(p_toolbar_values[]) = {"text", "icons", "tooltips", "horiz", NULL};
@ -1683,6 +1684,13 @@ did_set_string_option(
errmsg = e_invalid_argument; errmsg = e_invalid_argument;
} }
// 'splitkeep'
else if (varp == &p_spk)
{
if (check_opt_strings(p_spk, p_spk_values, FALSE) != OK)
errmsg = e_invalid_argument;
}
// 'debug' // 'debug'
else if (varp == &p_debug) else if (varp == &p_debug)
{ {
@ -1722,7 +1730,7 @@ did_set_string_option(
int is_spellfile = varp == &(curwin->w_s->b_p_spf); int is_spellfile = varp == &(curwin->w_s->b_p_spf);
if ((is_spellfile && !valid_spellfile(*varp)) if ((is_spellfile && !valid_spellfile(*varp))
|| (!is_spellfile && !valid_spelllang(*varp))) || (!is_spellfile && !valid_spelllang(*varp)))
errmsg = e_invalid_argument; errmsg = e_invalid_argument;
else else
errmsg = did_set_spell_option(is_spellfile); errmsg = did_set_spell_option(is_spellfile);

View File

@ -3621,8 +3621,8 @@ struct window_S
int w_winrow; // first row of window in screen int w_winrow; // first row of window in screen
int w_height; // number of rows in window, excluding int w_height; // number of rows in window, excluding
// status/command/winbar line(s) // status/command/winbar line(s)
int w_prev_winrow; // previous winrow used for 'splitscroll' int w_prev_winrow; // previous winrow used for 'splitkeep'
int w_prev_height; // previous height used for 'splitscroll' int w_prev_height; // previous height used for 'splitkeep'
int w_status_height; // number of status lines (0 or 1) int w_status_height; // number of status lines (0 or 1)
int w_wincol; // Leftmost column of window in screen. int w_wincol; // Leftmost column of window in screen.

View File

@ -134,6 +134,7 @@ let test_values = {
\ 'spelllang': [['', 'xxx', 'sr@latin'], ['not&lang', "that\\\rthere"]], \ 'spelllang': [['', 'xxx', 'sr@latin'], ['not&lang', "that\\\rthere"]],
\ 'spelloptions': [['', 'camel'], ['xxx']], \ 'spelloptions': [['', 'camel'], ['xxx']],
\ 'spellsuggest': [['', 'best', 'double,33'], ['xxx']], \ 'spellsuggest': [['', 'best', 'double,33'], ['xxx']],
\ 'splitkeep': [['cursor', 'screen', 'topline'], ['xxx']],
\ 'switchbuf': [['', 'useopen', 'split,newtab'], ['xxx']], \ 'switchbuf': [['', 'useopen', 'split,newtab'], ['xxx']],
\ 'tagcase': [['smart', 'match'], ['', 'xxx', 'smart,match']], \ 'tagcase': [['smart', 'match'], ['', 'xxx', 'smart,match']],
\ 'term': [[], []], \ 'term': [[], []],

View File

@ -1632,31 +1632,29 @@ func Test_win_equal_last_status()
set laststatus& set laststatus&
endfunc endfunc
" Ensure no scrolling happens with 'nosplitscroll' for a sequence of " Test "screen" and "cursor" values for 'splitkeep' with a sequence of
" split operations for various options: with and without a winbar, " split operations for various options: with and without a winbar,
" tabline, for each possible value of 'laststatus', 'scrolloff', " tabline, for each possible value of 'laststatus', 'scrolloff',
" 'equalalways', and regardless of the cursor position. " 'equalalways', and with the cursor at the top, middle and bottom.
func Test_nosplitscroll_options() func Test_splitkeep_options()
set nowrap
set nosplitscroll
" disallow window resizing " disallow window resizing
let save_WS = &t_WS let save_WS = &t_WS
set t_WS= set t_WS=
let gui = has("gui_running") let gui = has("gui_running")
inoremap <expr> c "<cmd>copen<bar>wincmd k<CR>" inoremap <expr> c "<cmd>copen<bar>wincmd k<CR>"
for run in range(0, 10) for run in range(0, 20)
tabnew | tabonly! | redraw let &splitkeep = run > 10 ? 'topline' : 'screen'
let tabline = (gui ? 0 : ((run % 5) ? 1 : 0)) let &scrolloff = (!(run % 4) ? 0 : run)
let winbar_sb = (run % 2) && (run % 3) let &laststatus = (run % 3)
execute 'set scrolloff=' . (!(run % 4) ? 0 : run) let &splitbelow = (run % 3)
execute 'set laststatus=' . (run % 3) let &equalalways = (run % 2)
execute 'set ' . ((run % 2) ? 'equalalways' : 'noequalalways') let wsb = (run % 2) && &splitbelow
execute 'set ' . ((run % 3) ? 'splitbelow' : 'nosplitbelow') let tl = (gui ? 0 : ((run % 5) ? 1 : 0))
let pos = !(run % 3) ? 'H' : ((run % 2) ? 'M' : 'L')
tabnew | tabonly! | redraw
execute (run % 5) ? 'tabnew' : '' execute (run % 5) ? 'tabnew' : ''
execute (run % 2) ? 'nnoremenu 1.10 WinBar.Test :echo' : '' execute (run % 2) ? 'nnoremenu 1.10 WinBar.Test :echo' : ''
let pos = !(run % 3) ? 'H' : ((run % 2) ? 'M' : 'L')
call setline(1, range(1, 256)) call setline(1, range(1, 256))
" No scroll for restore_snapshot " No scroll for restore_snapshot
norm G norm G
@ -1672,17 +1670,17 @@ func Test_nosplitscroll_options()
call assert_equal(1, line("w0")) call assert_equal(1, line("w0"))
call assert_equal(&scroll, winheight(0) / 2) call assert_equal(&scroll, winheight(0) / 2)
wincmd j wincmd j
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0")) call assert_equal(&spk == 'topline' ? 1 : win_screenpos(0)[0] - tl - wsb, line("w0"))
" No scroll when resizing windows " No scroll when resizing windows
wincmd k | resize +2 wincmd k | resize +2 | redraw
call assert_equal(1, line("w0")) call assert_equal(1, line("w0"))
wincmd j wincmd j
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0")) call assert_equal(&spk == 'topline' ? 1 : win_screenpos(0)[0] - tl - wsb, line("w0"))
" No scroll when dragging statusline " No scroll when dragging statusline
call win_move_statusline(1, -3) call win_move_statusline(1, -3)
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0")) call assert_equal(&spk == 'topline' ? 1 : win_screenpos(0)[0] - tl - wsb, line("w0"))
wincmd k wincmd k
call assert_equal(1, line("w0")) call assert_equal(1, line("w0"))
@ -1690,9 +1688,9 @@ func Test_nosplitscroll_options()
set lines+=2 set lines+=2
call assert_equal(1, line("w0")) call assert_equal(1, line("w0"))
wincmd j wincmd j
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0")) call assert_equal(&spk == 'topline' ? 1 : win_screenpos(0)[0] - tl - wsb, line("w0"))
set lines-=2 set lines-=2
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0")) call assert_equal(&spk == 'topline' ? 1 : win_screenpos(0)[0] - tl - wsb, line("w0"))
wincmd k wincmd k
call assert_equal(1, line("w0")) call assert_equal(1, line("w0"))
@ -1700,23 +1698,23 @@ func Test_nosplitscroll_options()
wincmd = wincmd =
call assert_equal(1, line("w0")) call assert_equal(1, line("w0"))
wincmd j wincmd j
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0")) call assert_equal(&spk == 'topline' ? 1 : win_screenpos(0)[0] - tl - wsb, line("w0"))
wincmd k wincmd k
call assert_equal(1, line("w0")) call assert_equal(1, line("w0"))
" No scroll in windows split multiple times " No scroll in windows split multiple times
vsplit | split | 4wincmd w vsplit | split | 4wincmd w
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0")) call assert_equal(&spk == 'topline' ? 1 : win_screenpos(0)[0] - tl - wsb, line("w0"))
1wincmd w | quit | wincmd l | split 1wincmd w | quit | wincmd l | split
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0")) call assert_equal(&spk == 'topline' ? 1 : win_screenpos(0)[0] - tl - wsb, line("w0"))
wincmd j wincmd j
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0")) call assert_equal(&spk == 'topline' ? 1 : win_screenpos(0)[0] - tl - wsb, line("w0"))
" No scroll in small window " No scroll in small window
2wincmd w | only | 5split | wincmd k 2wincmd w | only | 5split | wincmd k
call assert_equal(1, line("w0")) call assert_equal(1, line("w0"))
wincmd j wincmd j
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0")) call assert_equal(&spk == 'topline' ? 1 : win_screenpos(0)[0] - tl - wsb, line("w0"))
" No scroll for vertical split " No scroll for vertical split
quit | vsplit | wincmd l quit | vsplit | wincmd l
@ -1725,8 +1723,8 @@ func Test_nosplitscroll_options()
call assert_equal(1, line("w0")) call assert_equal(1, line("w0"))
" No scroll in windows split and quit multiple times " No scroll in windows split and quit multiple times
quit | redraw | split | redraw | split | redraw | quit | redraw quit | redraw | split | split | quit | redraw
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0")) call assert_equal(&spk == 'topline' ? 1 : win_screenpos(0)[0] - tl - wsb, line("w0"))
" No scroll for new buffer " No scroll for new buffer
1wincmd w | only | copen | wincmd k 1wincmd w | only | copen | wincmd k
@ -1734,7 +1732,7 @@ func Test_nosplitscroll_options()
only only
call assert_equal(1, line("w0")) call assert_equal(1, line("w0"))
above copen | wincmd j above copen | wincmd j
call assert_equal(win_screenpos(0)[0] - tabline, line("w0")) call assert_equal(&spk == 'topline' ? 1 : win_screenpos(0)[0] - tl, line("w0"))
" No scroll when opening cmdwin, and no cursor move when closing cmdwin. " No scroll when opening cmdwin, and no cursor move when closing cmdwin.
only | norm ggL only | norm ggL
@ -1751,22 +1749,21 @@ func Test_nosplitscroll_options()
only | execute "norm gg5\<C-e>" | split | wincmd k only | execute "norm gg5\<C-e>" | split | wincmd k
call assert_equal(6, line("w0")) call assert_equal(6, line("w0"))
wincmd j wincmd j
call assert_equal(5 + win_screenpos(0)[0] - tabline - winbar_sb, line("w0")) call assert_equal(&spk == 'topline' ? 6 : 5 + win_screenpos(0)[0] - tl - wsb, line("w0"))
endfor endfor
tabnew | tabonly! | %bwipeout! tabnew | tabonly! | %bwipeout!
iunmap c iunmap c
set wrap&
set scrolloff& set scrolloff&
set splitbelow& set splitbelow&
set laststatus& set laststatus&
set equalalways& set equalalways&
set splitscroll& set splitkeep&
let &t_WS = save_WS let &t_WS = save_WS
endfunc endfunc
function Test_nosplitscroll_cmdwin_cursor_position() function Test_splitkeep_cmdwin_cursor_position()
set nosplitscroll set splitkeep=screen
call setline(1, range(&lines)) call setline(1, range(&lines))
" No scroll when cursor is at near bottom of window and cusor position " No scroll when cursor is at near bottom of window and cusor position
@ -1789,11 +1786,11 @@ function Test_nosplitscroll_cmdwin_cursor_position()
call assert_equal(1, col('.')) call assert_equal(1, col('.'))
%bwipeout! %bwipeout!
set splitscroll& set splitkeep&
endfunction endfunction
function Test_nosplitscroll_misc() function Test_splitkeep_misc()
set nosplitscroll set splitkeep=screen
set splitbelow set splitbelow
call setline(1, range(1, &lines)) call setline(1, range(1, &lines))
@ -1815,67 +1812,68 @@ function Test_nosplitscroll_misc()
%bwipeout! %bwipeout!
set splitbelow& set splitbelow&
set splitscroll& set splitkeep&
endfunc endfunc
function Test_nosplitscroll_callback() function Test_splitkeep_callback()
CheckScreendump CheckScreendump
let lines =<< trim END let lines =<< trim END
set nosplitscroll set splitkeep=screen
call setline(1, range(&lines)) call setline(1, range(&lines))
function WincmdCb(a, b) function C1(a, b)
split | wincmd p split | wincmd p
endfunction endfunction
function TermCb(a, b) function C2(a, b)
close | split close | split
endfunction endfunction
nnoremap t <cmd>call popup_create(term_start(&shell, { 'hidden': 1, 'exit_cb': 'TermCb' }), {})<CR> nn j <cmd>call job_start([&sh, &shcf, "true"], { 'exit_cb': 'C1' })<CR>
nnoremap j <cmd>call job_start([&shell, &shellcmdflag, "echo"], { 'exit_cb': 'WincmdCb' })<CR> nn t <cmd>call popup_create(term_start([&sh, &shcf, "true"],
\ { 'hidden': 1, 'exit_cb': 'C2' }), {})<CR>
END END
call writefile(lines, 'XTestNosplitscrollCallback', 'D') call writefile(lines, 'XTestSplitkeepCallback', 'D')
let buf = RunVimInTerminal('-S XTestNosplitscrollCallback', #{rows: 8}) let buf = RunVimInTerminal('-S XTestSplitkeepCallback', #{rows: 8})
call term_sendkeys(buf, "j") call term_sendkeys(buf, "j")
call VerifyScreenDump(buf, 'Test_nosplitscroll_callback_1', {}) call VerifyScreenDump(buf, 'Test_splitkeep_callback_1', {})
call term_sendkeys(buf, ":quit\<CR>Htexit\<CR>") call term_sendkeys(buf, ":quit\<CR>Ht")
call VerifyScreenDump(buf, 'Test_nosplitscroll_callback_2', {}) call VerifyScreenDump(buf, 'Test_splitkeep_callback_2', {})
call term_sendkeys(buf, ":set sb\<CR>:quit\<CR>Gj") call term_sendkeys(buf, ":set sb\<CR>:quit\<CR>Gj")
call VerifyScreenDump(buf, 'Test_nosplitscroll_callback_3', {}) call VerifyScreenDump(buf, 'Test_splitkeep_callback_3', {})
call term_sendkeys(buf, ":quit\<CR>Gtexit\<CR>") call term_sendkeys(buf, ":quit\<CR>Gt")
call VerifyScreenDump(buf, 'Test_nosplitscroll_callback_4', {}) call VerifyScreenDump(buf, 'Test_splitkeep_callback_4', {})
endfunc endfunc
function Test_nosplitscroll_fold() function Test_splitkeep_fold()
CheckScreendump CheckScreendump
let lines =<< trim END let lines =<< trim END
set nosplitscroll set splitkeep=screen
set foldmethod=marker set foldmethod=marker
set number set number
let line = 1 let line = 1
for n in range(1, &lines) for n in range(1, &lines)
call setline(line, ['int FuncName() {/*{{{*/', 1, 2, 3, 4, 5, '}/*}}}*/', call setline(line, ['int FuncName() {/*{{{*/', 1, 2, 3, 4, 5, '}/*}}}*/',
\ 'after fold']) \ 'after fold'])
let line += 8 let line += 8
endfor endfor
END END
call writefile(lines, 'XTestNosplitscrollFold', 'D') call writefile(lines, 'XTestSplitkeepFold', 'D')
let buf = RunVimInTerminal('-S XTestNosplitscrollFold', #{rows: 10}) let buf = RunVimInTerminal('-S XTestSplitkeepFold', #{rows: 10})
call term_sendkeys(buf, "L:wincmd s\<CR>") call term_sendkeys(buf, "L:wincmd s\<CR>")
call VerifyScreenDump(buf, 'Test_nosplitscroll_fold_1', {}) call VerifyScreenDump(buf, 'Test_splitkeep_fold_1', {})
call term_sendkeys(buf, ":quit\<CR>") call term_sendkeys(buf, ":quit\<CR>")
call VerifyScreenDump(buf, 'Test_nosplitscroll_fold_2', {}) call VerifyScreenDump(buf, 'Test_splitkeep_fold_2', {})
call term_sendkeys(buf, "H:below split\<CR>") call term_sendkeys(buf, "H:below split\<CR>")
call VerifyScreenDump(buf, 'Test_nosplitscroll_fold_3', {}) call VerifyScreenDump(buf, 'Test_splitkeep_fold_3', {})
call term_sendkeys(buf, ":wincmd k\<CR>:quit\<CR>") call term_sendkeys(buf, ":wincmd k\<CR>:quit\<CR>")
call VerifyScreenDump(buf, 'Test_nosplitscroll_fold_4', {}) call VerifyScreenDump(buf, 'Test_splitkeep_fold_4', {})
endfunction endfunction
" vim: shiftwidth=2 sts=2 expandtab " vim: shiftwidth=2 sts=2 expandtab

View File

@ -699,6 +699,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
647,
/**/ /**/
646, 646,
/**/ /**/

View File

@ -1325,7 +1325,7 @@ win_split_ins(
win_equal(wp, TRUE, win_equal(wp, TRUE,
(flags & WSP_VERT) ? (dir == 'v' ? 'b' : 'h') (flags & WSP_VERT) ? (dir == 'v' ? 'b' : 'h')
: dir == 'h' ? 'b' : 'v'); : dir == 'h' ? 'b' : 'v');
else if (!p_spsc && wp != aucmd_win) else if (*p_spk != 'c' && wp != aucmd_win)
win_fix_scroll(FALSE); win_fix_scroll(FALSE);
// Don't change the window height/width to 'winheight' / 'winwidth' if a // Don't change the window height/width to 'winheight' / 'winwidth' if a
@ -1411,7 +1411,7 @@ win_init(win_T *newp, win_T *oldp, int flags UNUSED)
newp->w_prevdir = (oldp->w_prevdir == NULL) newp->w_prevdir = (oldp->w_prevdir == NULL)
? NULL : vim_strsave(oldp->w_prevdir); ? NULL : vim_strsave(oldp->w_prevdir);
if (!p_spsc) if (*p_spk != 'c')
{ {
newp->w_botline = oldp->w_botline; newp->w_botline = oldp->w_botline;
newp->w_prev_height = oldp->w_height - WINBAR_HEIGHT(oldp); newp->w_prev_height = oldp->w_height - WINBAR_HEIGHT(oldp);
@ -1925,7 +1925,7 @@ win_equal(
win_equal_rec(next_curwin == NULL ? curwin : next_curwin, current, win_equal_rec(next_curwin == NULL ? curwin : next_curwin, current,
topframe, dir, 0, tabline_height(), topframe, dir, 0, tabline_height(),
(int)Columns, topframe->fr_height); (int)Columns, topframe->fr_height);
if (!p_spsc && next_curwin != aucmd_win) if (*p_spk != 'c' && next_curwin != aucmd_win)
win_fix_scroll(TRUE); win_fix_scroll(TRUE);
} }
@ -2733,7 +2733,7 @@ win_close(win_T *win, int free_buf)
else else
{ {
win_comp_pos(); win_comp_pos();
if (!p_spsc) if (*p_spk != 'c')
win_fix_scroll(FALSE); win_fix_scroll(FALSE);
} }
if (close_curwin) if (close_curwin)
@ -4931,7 +4931,7 @@ win_enter_ext(win_T *wp, int flags)
// Might need to scroll the old window before switching, e.g., when the // Might need to scroll the old window before switching, e.g., when the
// cursor was moved. // cursor was moved.
if (p_spsc) if (*p_spk == 'c')
update_topline(); update_topline();
// may have to copy the buffer options when 'cpo' contains 'S' // may have to copy the buffer options when 'cpo' contains 'S'
@ -4947,7 +4947,7 @@ win_enter_ext(win_T *wp, int flags)
check_cursor(); check_cursor();
if (!virtual_active()) if (!virtual_active())
curwin->w_cursor.coladd = 0; curwin->w_cursor.coladd = 0;
if (p_spsc) // assume cursor position needs updating. if (*p_spk == 'c') // assume cursor position needs updating
changed_line_abv_curs(); changed_line_abv_curs();
else else
win_fix_cursor(TRUE); win_fix_cursor(TRUE);
@ -5068,7 +5068,7 @@ static int last_win_id = LOWEST_WIN_ID - 1;
* FALSE. * FALSE.
*/ */
static win_T * static win_T *
win_alloc(win_T *after UNUSED, int hidden UNUSED) win_alloc(win_T *after, int hidden)
{ {
win_T *new_wp; win_T *new_wp;
@ -5480,7 +5480,7 @@ shell_new_rows(void)
compute_cmdrow(); compute_cmdrow();
curtab->tp_ch_used = p_ch; curtab->tp_ch_used = p_ch;
if (!p_spsc && !skip_win_fix_scroll) if (*p_spk != 'c' && !skip_win_fix_scroll)
win_fix_scroll(TRUE); win_fix_scroll(TRUE);
#if 0 #if 0
@ -5687,7 +5687,7 @@ win_setheight_win(int height, win_T *win)
msg_row = row; msg_row = row;
msg_col = 0; msg_col = 0;
if (!p_spsc) if (*p_spk != 'c')
win_fix_scroll(TRUE); win_fix_scroll(TRUE);
redraw_all_later(UPD_NOT_VALID); redraw_all_later(UPD_NOT_VALID);
@ -6218,7 +6218,7 @@ win_drag_status_line(win_T *dragwin, int offset)
p_ch = MAX(Rows - cmdline_row, 1); p_ch = MAX(Rows - cmdline_row, 1);
curtab->tp_ch_used = p_ch; curtab->tp_ch_used = p_ch;
if (!p_spsc) if (*p_spk != 'c')
win_fix_scroll(TRUE); win_fix_scroll(TRUE);
redraw_all_later(UPD_SOME_VALID); redraw_all_later(UPD_SOME_VALID);
@ -6348,7 +6348,7 @@ set_fraction(win_T *wp)
} }
/* /*
* Handle scroll position for 'nosplitscroll'. Replaces scroll_to_fraction() * Handle scroll position for 'splitkeep'. Replaces scroll_to_fraction()
* call from win_new_height(). Instead we iterate over all windows in a * call from win_new_height(). Instead we iterate over all windows in a
* tabpage and calculate the new scroll position. * tabpage and calculate the new scroll position.
* TODO: Ensure this also works with wrapped lines. * TODO: Ensure this also works with wrapped lines.
@ -6362,14 +6362,14 @@ win_fix_scroll(int resize)
win_T *wp; win_T *wp;
linenr_T lnum; linenr_T lnum;
skip_update_topline = TRUE; // avoid scrolling in curs_columns() skip_update_topline = TRUE;
FOR_ALL_WINDOWS(wp) FOR_ALL_WINDOWS(wp)
{ {
// Skip when window height has not changed. // Skip when window height has not changed.
if (wp->w_height != wp->w_prev_height) if (wp->w_height != wp->w_prev_height)
{ {
// If window has moved update botline to keep the same screenlines. // If window has moved update botline to keep the same screenlines.
if (wp->w_winrow != wp->w_prev_winrow) if (*p_spk == 's' && wp->w_winrow != wp->w_prev_winrow)
{ {
lnum = wp->w_cursor.lnum; lnum = wp->w_cursor.lnum;
diff = (wp->w_winrow - wp->w_prev_winrow) diff = (wp->w_winrow - wp->w_prev_winrow)
@ -6403,7 +6403,7 @@ win_fix_scroll(int resize)
} }
/* /*
* Make sure the cursor position is valid for 'nosplitscroll'. * Make sure the cursor position is valid for 'splitkeep'.
* If it is not, put the cursor position in the jumplist and move it. * If it is not, put the cursor position in the jumplist and move it.
* If we are not in normal mode, scroll to make valid instead. * If we are not in normal mode, scroll to make valid instead.
*/ */
@ -6413,9 +6413,9 @@ win_fix_cursor(int normal)
long so = get_scrolloff_value(); long so = get_scrolloff_value();
win_T *wp = curwin; win_T *wp = curwin;
linenr_T nlnum = 0; linenr_T nlnum = 0;
linenr_T lnum = wp->w_cursor.lnum; linenr_T lnum = wp->w_cursor.lnum;
linenr_T bot; linenr_T bot;
linenr_T top; linenr_T top;
if (wp->w_buffer->b_ml.ml_line_count < wp->w_height) if (wp->w_buffer->b_ml.ml_line_count < wp->w_height)
return; return;
@ -6429,25 +6429,23 @@ win_fix_cursor(int normal)
top = cursor_down_inner(wp, so); top = cursor_down_inner(wp, so);
wp->w_cursor.lnum = wp->w_botline - 1; wp->w_cursor.lnum = wp->w_botline - 1;
bot = cursor_up_inner(wp, so); bot = cursor_up_inner(wp, so);
wp->w_cursor.lnum = lnum;
// Check if cursor position is above or below valid cursor range. // Check if cursor position is above or below valid cursor range.
if (lnum > bot && (wp->w_botline - wp->w_buffer->b_ml.ml_line_count) != 1) if (lnum > bot && (wp->w_botline - wp->w_buffer->b_ml.ml_line_count) != 1)
nlnum = bot; nlnum = bot;
else if (lnum < top && wp->w_topline != 1) else if (lnum < top && wp->w_topline != 1)
nlnum = (so == wp->w_height / 2) ? bot : top; nlnum = (so == wp->w_height / 2) ? bot : top;
wp->w_cursor.lnum = lnum;
if (nlnum) // Cursor is invalid for current scroll position. if (nlnum) // Cursor is invalid for current scroll position.
{ {
if (normal) // Save to jumplist and set cursor to avoid scrolling. if (normal) // Save to jumplist and set cursor to avoid scrolling.
{ {
setmark('\''); setmark('\'');
wp->w_cursor.lnum = nlnum; wp->w_cursor.lnum = nlnum;
curs_columns(TRUE); // validate w_wrow
} }
else // Scroll instead when not in normal mode. else // Scroll instead when not in normal mode.
{ {
wp->w_fraction = 0.5 * FRACTION_MULT; wp->w_fraction = (nlnum == bot) ? FRACTION_MULT : 0;
scroll_to_fraction(wp, wp->w_prev_height); scroll_to_fraction(wp, wp->w_prev_height);
validate_botline_win(curwin); validate_botline_win(curwin);
} }
@ -6474,7 +6472,7 @@ win_new_height(win_T *wp, int height)
if (wp->w_height > 0) if (wp->w_height > 0)
{ {
if (wp == curwin && p_spsc) if (wp == curwin && *p_spk == 'c')
// w_wrow needs to be valid. When setting 'laststatus' this may // w_wrow needs to be valid. When setting 'laststatus' this may
// call win_new_height() recursively. // call win_new_height() recursively.
validate_cursor(); validate_cursor();
@ -6490,7 +6488,7 @@ win_new_height(win_T *wp, int height)
// There is no point in adjusting the scroll position when exiting. Some // There is no point in adjusting the scroll position when exiting. Some
// values might be invalid. // values might be invalid.
if (!exiting && p_spsc) if (!exiting && *p_spk == 'c')
scroll_to_fraction(wp, prev_height); scroll_to_fraction(wp, prev_height);
} }
@ -6604,7 +6602,7 @@ scroll_to_fraction(win_T *wp, int prev_height)
if (wp == curwin) if (wp == curwin)
{ {
if (p_spsc && get_scrolloff_value()) if (get_scrolloff_value())
update_topline(); update_topline();
curs_columns(FALSE); // validate w_wrow curs_columns(FALSE); // validate w_wrow
} }
@ -6627,15 +6625,13 @@ win_new_width(win_T *wp, int width)
wp->w_width = width < 0 ? 0 : width; wp->w_width = width < 0 ? 0 : width;
wp->w_lines_valid = 0; wp->w_lines_valid = 0;
changed_line_abv_curs_win(wp); changed_line_abv_curs_win(wp);
// Handled in win_fix_scroll() invalidate_botline_win(wp);
if (p_spsc) if (wp == curwin)
{ {
invalidate_botline_win(wp); skip_update_topline = (*p_spk != 'c');
if (wp == curwin) update_topline();
{ curs_columns(TRUE); // validate w_wrow
update_topline(); skip_update_topline = FALSE;
curs_columns(TRUE); // validate w_wrow
}
} }
redraw_win_later(wp, UPD_NOT_VALID); redraw_win_later(wp, UPD_NOT_VALID);
wp->w_redr_status = TRUE; wp->w_redr_status = TRUE;