Skip to content

Commit 29ab524

Browse files
luukvbaalbrammool
authored andcommitted
patch 9.0.0445: when opening/closing window text moves up/down
Problem: When opening/closing window text moves up/down. Solution: Add the 'splitscroll' option. When off text will keep its position as much as possible.
1 parent 9510d22 commit 29ab524

File tree

10 files changed

+287
-10
lines changed

10 files changed

+287
-10
lines changed

runtime/doc/options.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7499,6 +7499,18 @@ A jump table for the options with a short description can be found at |Q_op|.
74997499
When on, splitting a window will put the new window right of the
75007500
current one. |:vsplit|
75017501

7502+
*'splitscroll'* *'spsc'* *'nosplitscroll'* *'nospsc'*
7503+
'splitscroll' 'spsc' boolean (default on)
7504+
global
7505+
The value of this option determines the scroll behavior when opening,
7506+
closing or resizing horizontal splits. When "on", splitting a window
7507+
horizontally will keep the same relative cursor position in the old and
7508+
new window, as well windows that are resized. When "off", scrolling
7509+
will be avoided to stabilize the window content. Instead, the cursor
7510+
position will be changed when necessary. In this case, the jumplist
7511+
will be populated with the previous cursor position. Scrolling cannot
7512+
be guaranteed to be avoided when 'wrap' is enabled.
7513+
75027514
*'startofline'* *'sol'* *'nostartofline'* *'nosol'*
75037515
'startofline' 'sol' boolean (default on)
75047516
global

runtime/doc/quickref.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -919,6 +919,7 @@ Short explanation of each option: *option-list*
919919
'spellsuggest' 'sps' method(s) used to suggest spelling corrections
920920
'splitbelow' 'sb' new window from split is below the current one
921921
'splitright' 'spr' new window is put right of the current one
922+
'splitscroll' 'spsc' determines scroll behavior when splitting windows
922923
'startofline' 'sol' commands move cursor to first non-blank in line
923924
'statusline' 'stl' custom format for the status line
924925
'suffixes' 'su' suffixes that are ignored with multiple match

runtime/optwin.vim

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,8 @@ call <SID>AddOption("splitbelow", gettext("a new window is put below the current
515515
call <SID>BinOptionG("sb", &sb)
516516
call <SID>AddOption("splitright", gettext("a new window is put right of the current one"))
517517
call <SID>BinOptionG("spr", &spr)
518+
call <SID>AddOption("splitscroll", gettext("determines scroll behavior when spliting windows"))
519+
call <SID>BinOptionG("spsc", &spsc)
518520
call <SID>AddOption("scrollbind", gettext("this window scrolls together with other bound windows"))
519521
call append("$", "\t" .. s:local_to_window)
520522
call <SID>BinOptionL("scb")

src/move.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -981,7 +981,8 @@ curs_columns(
981981
/*
982982
* First make sure that w_topline is valid (after moving the cursor).
983983
*/
984-
update_topline();
984+
if (p_spsc)
985+
update_topline();
985986

986987
/*
987988
* Next make sure that w_cline_row is valid.

src/option.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -924,6 +924,7 @@ EXTERN char_u *p_spo; // 'spelloptions'
924924
EXTERN char_u *p_sps; // 'spellsuggest'
925925
#endif
926926
EXTERN int p_spr; // 'splitright'
927+
EXTERN int p_spsc; // 'splitscroll'
927928
EXTERN int p_sol; // 'startofline'
928929
EXTERN char_u *p_su; // 'suffixes'
929930
EXTERN char_u *p_sws; // 'swapsync'

src/optiondefs.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2349,6 +2349,9 @@ static struct vimoption options[] =
23492349
{"splitright", "spr", P_BOOL|P_VI_DEF,
23502350
(char_u *)&p_spr, PV_NONE,
23512351
{(char_u *)FALSE, (char_u *)0L} SCTX_INIT},
2352+
{"splitscroll", "spsc", P_BOOL,
2353+
(char_u *)&p_spsc, PV_NONE,
2354+
{(char_u *)TRUE, (char_u *)TRUE} SCTX_INIT},
23522355
{"startofline", "sol", P_BOOL|P_VI_DEF|P_VIM,
23532356
(char_u *)&p_sol, PV_NONE,
23542357
{(char_u *)TRUE, (char_u *)0L} SCTX_INIT},

src/structs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3570,6 +3570,8 @@ struct window_S
35703570
int w_winrow; // first row of window in screen
35713571
int w_height; // number of rows in window, excluding
35723572
// status/command/winbar line(s)
3573+
int w_prev_winrow; // previous winrow used for 'splitscroll'
3574+
int w_prev_height; // previous height used for 'splitscroll'
35733575

35743576
int w_status_height; // number of status lines (0 or 1)
35753577
int w_wincol; // Leftmost column of window in screen.

src/testdir/test_window_cmd.vim

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1631,5 +1631,133 @@ func Test_win_equal_last_status()
16311631
set laststatus&
16321632
endfunc
16331633

1634+
" Ensure no scrolling happens with 'nosplitscroll' with and without a
1635+
" winbar, tabline, for each possible value of 'laststatus', 'scrolloff',
1636+
" 'equalalways', and regardless of the cursor position.
1637+
func Test_splitscroll_with_splits()
1638+
set nowrap
1639+
set nosplitscroll
1640+
let gui = has("gui_running")
1641+
inoremap c <cmd>:copen<CR>
1642+
for winbar in [0, 1]
1643+
for sb in [0, 1]
1644+
for ea in [0, 1]
1645+
for tab in [0, 1]
1646+
for so in [0, 5]
1647+
for ls in range(0, 2)
1648+
for pos in ["H", "M", "L"]
1649+
let tabline = (gui ? 0 : (tab ? 1 : 0))
1650+
let winbar_sb = (sb ? winbar : 0)
1651+
execute 'set scrolloff=' . so
1652+
execute 'set laststatus=' . ls
1653+
execute 'set ' . (ea ? 'equalalways' : 'noequalalways')
1654+
execute 'set ' . (sb ? 'splitbelow' : 'nosplitbelow')
1655+
execute tab ? 'tabnew' : ''
1656+
execute winbar ? 'nnoremenu 1.10 WinBar.Test :echo' : ''
1657+
call setline(1, range(1, 256))
1658+
execute 'norm gg' . pos
1659+
" No scroll for vertical split and quit
1660+
vsplit | quit
1661+
call assert_equal(1, line("w0"))
1662+
1663+
" No scroll for horizontal split
1664+
split | redraw! | wincmd k
1665+
call assert_equal(1, line("w0"))
1666+
1667+
" No scroll when resizing windows
1668+
resize +2
1669+
call assert_equal(1, line("w0"))
1670+
wincmd j
1671+
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0"))
1672+
1673+
" No scroll when dragging statusline
1674+
call win_move_statusline(1, -3)
1675+
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0"))
1676+
wincmd k
1677+
call assert_equal(1, line("w0"))
1678+
1679+
" No scroll when changing shellsize
1680+
set lines+=2
1681+
call assert_equal(1, line("w0"))
1682+
wincmd j
1683+
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0"))
1684+
set lines-=2
1685+
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0"))
1686+
wincmd k
1687+
call assert_equal(1, line("w0"))
1688+
1689+
" No scroll when equalizing windows
1690+
wincmd =
1691+
call assert_equal(1, line("w0"))
1692+
wincmd j
1693+
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0"))
1694+
wincmd k
1695+
call assert_equal(1, line("w0"))
1696+
1697+
" No scroll in windows split multiple times
1698+
vsplit | split | 4wincmd w
1699+
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0"))
1700+
1wincmd w | quit | wincmd l | split
1701+
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0"))
1702+
wincmd j
1703+
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0"))
1704+
1705+
" No scroll in small window
1706+
2wincmd w | only | 5split | wincmd k
1707+
call assert_equal(1, line("w0"))
1708+
wincmd j
1709+
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0"))
1710+
1711+
" No scroll for vertical split
1712+
quit | vsplit | wincmd l
1713+
call assert_equal(1, line("w0"))
1714+
wincmd h
1715+
call assert_equal(1, line("w0"))
1716+
1717+
" No scroll in windows split and quit multiple times
1718+
quit | split | split | quit
1719+
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0"))
1720+
1721+
" No scroll for new buffer
1722+
1wincmd w | only | copen | wincmd k
1723+
call assert_equal(1, line("w0"))
1724+
only
1725+
call assert_equal(1, line("w0"))
1726+
above copen | wincmd j
1727+
call assert_equal(win_screenpos(0)[0] - tabline, line("w0"))
1728+
1729+
" No scroll when opening cmdwin
1730+
only | norm ggLq:
1731+
call assert_equal(1, line("w0"))
1732+
1733+
" Scroll when cursor becomes invalid in insert mode
1734+
norm Lic
1735+
wincmd k | only
1736+
call assert_notequal(1, line("w0"))
1737+
1738+
" No scroll when topline not equal to 1
1739+
execute "norm gg5\<C-e>" | split | wincmd k
1740+
call assert_equal(6, line("w0"))
1741+
wincmd j
1742+
call assert_equal(5 + win_screenpos(0)[0] - tabline - winbar_sb, line("w0"))
1743+
only
1744+
endfor
1745+
endfor
1746+
endfor
1747+
tabonly!
1748+
endfor
1749+
endfor
1750+
endfor
1751+
endfor
1752+
1753+
tabnew | tabonly! | %bwipeout!
1754+
iunmap c
1755+
set wrap&
1756+
set scrolloff&
1757+
set splitbelow&
1758+
set laststatus&
1759+
set equalalways&
1760+
set splitscroll&
1761+
endfunc
16341762

16351763
" vim: shiftwidth=2 sts=2 expandtab

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -703,6 +703,8 @@ static char *(features[]) =
703703

704704
static int included_patches[] =
705705
{ /* Add new patch number below this line */
706+
/**/
707+
445,
706708
/**/
707709
444,
708710
/**/

0 commit comments

Comments
 (0)