Skip to content

Commit

Permalink
fixup! feat(window/ui): add splitkeep option
Browse files Browse the repository at this point in the history
vim-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.
vim/vim@29ab524

vim-patch:9.0.0455: a few problems with 'splitscroll'

Problem:    A few problems with 'splitscroll'.
Solution:   Fix 'splitscroll' problems. (Luuk van Baal, closes vim/vim#11117)
vim/vim@5ed3917

vim-patch:9.0.0461: 'scroll' is not always updated

Problem:    'scroll' is not always updated.
Solution:   Call win_init_size() at the right place.
vim/vim@470a141

vim-patch:9.0.0465: cursor moves when cmdwin is closed when 'splitscroll' is off

Problem:    Cursor moves when cmdwin is closed when 'splitscroll' is off.
Solution:   Temporarily set 'splitscroll' when jumping back to the original
            window. (closes vim/vim#11128)
vim/vim@e697d48

vim-patch:9.0.0469: cursor moves if cmdwin is closed when 'splitscroll' is off

Problem:    Cursor moves if cmdwin is closed when 'splitscroll' is off.
Solution:   Skip win_fix_cursor if called when cmdwin is open or closing.
            (Luuk van Baal, closes vim/vim#11134)
vim/vim@3735f11

vim-patch:9.0.0478: test for 'splitscroll' takes too much time

Problem:    Test for 'splitscroll' takes too much time.
Solution:   Only test some of the combinations. (Luuk van Baal, closes vim/vim#11139)
vim/vim@594f9e0

vim-patch:9.0.0486: text scrolled with 'nosplitscroll', autocmd win and help

Problem:    Text scrolled with 'nosplitscroll', autocmd win opened and help
            window closed.
Solution:   Skip win_fix_scroll() in more situations. (Luuk van Baal,
            closes vim/vim#11150)
vim/vim@d5bc762

vim-patch:9.0.0505: various problems with 'nosplitscroll'

Problem:    Various problems with 'nosplitscroll'.
Solution:   Fix 'nosplitscroll' problems. (Luuk van Baal, closes vim/vim#11166)
vim/vim@faf1d41

vim-patch:9.0.0555: scrolling with 'nosplitscroll' in callback changing curwin

Problem:    Scrolling with 'nosplitscroll' in callback changing curwin.
Solution:   Invalidate w_cline_row in the right place. (Luuk van Baal,
            closes vim/vim#11185)
vim/vim@20e5856

vim-patch:9.0.0603: with 'nosplitscroll' folds are not handled correctly

Problem:    With 'nosplitscroll' folds are not handled correctly.
Solution:   Take care of closed folds when moving the cursor. (Luuk van Baal,
            closes vim/vim#11234)
vim/vim@7c1cbb6

vim-patch:9.0.0605: dump file missing

Problem:    Dump file missing.
Solution:   Add the missing dump file. (issue vim/vim#11234)
vim/vim@439a2ba

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 vim/vim#11258)
vim/vim@13ece2a

vim-patch:9.0.0667: ml_get error when 'splitkeep' is "screen"

Problem:    ml_get error when 'splitkeep' is "screen". (Marius Gedminas)
Solution:   Check the botline is not too large. (Luuk van Baal,
            closes vim/vim#11293, closes vim/vim#11292)
vim/vim@346823d
  • Loading branch information
zeertzjq committed Oct 6, 2022
1 parent 7e32d6b commit 669867a
Show file tree
Hide file tree
Showing 8 changed files with 236 additions and 220 deletions.
1 change: 1 addition & 0 deletions src/nvim/edit.c
Expand Up @@ -2597,6 +2597,7 @@ int cursor_up(long n, int upd_topline)
if (upd_topline) {
update_topline(curwin); // make sure curwin->w_topline is valid
}

return OK;
}

Expand Down
7 changes: 4 additions & 3 deletions src/nvim/globals.h
Expand Up @@ -1071,10 +1071,11 @@ EXTERN char windowsVersion[20] INIT(= { 0 });

EXTERN int exit_need_delay INIT(= 0);

// Skip win_fix_cursor() call for 'splitkeep' when cmdwin is closed.
///< Skip win_fix_cursor() call for 'splitkeep' when cmdwin is closed.
EXTERN bool skip_win_fix_cursor INIT(= false);
// Skip win_fix_scroll() call for 'splitkeep' when closing tab page.
///< Skip win_fix_scroll() call for 'splitkeep' when closing tab page.
EXTERN bool 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 bool skip_update_topline INIT(= false);

#endif // NVIM_GLOBALS_H
2 changes: 1 addition & 1 deletion src/nvim/option_defs.h
Expand Up @@ -729,7 +729,7 @@ EXTERN unsigned int tpf_flags; ///< flags from 'termpastefilter'
EXTERN char *p_tfu; ///< 'tagfunc'
EXTERN char *p_spc; ///< 'spellcapcheck'
EXTERN char *p_spf; ///< 'spellfile'
EXTERN char *p_spk; // 'splitkeep'
EXTERN char *p_spk; ///< 'splitkeep'
EXTERN char *p_spl; ///< 'spelllang'
EXTERN char *p_spo; // 'spelloptions'
EXTERN unsigned int spo_flags;
Expand Down
2 changes: 1 addition & 1 deletion src/nvim/optionstr.c
Expand Up @@ -1097,7 +1097,7 @@ char *did_set_string_option(int opt_idx, char **varp, char *oldval, char *errbuf
errmsg = e_invarg;
}
} else if (varp == &p_spk) { // 'splitkeep'
if (check_opt_strings(p_spk, p_spk_values, true) != OK) {
if (check_opt_strings(p_spk, p_spk_values, false) != OK) {
errmsg = e_invarg;
}
} else if (varp == &p_debug) { // 'debug'
Expand Down
30 changes: 17 additions & 13 deletions src/nvim/testdir/test_window_cmd.vim
@@ -1,5 +1,7 @@
" Tests for window cmd (:wincmd, :split, :vsplit, :resize and etc...)

source check.vim
source screendump.vim

func Test_window_cmd_ls0_with_split()
set ls=0
Expand Down Expand Up @@ -1504,7 +1506,9 @@ func Test_splitkeep_options()
let &laststatus = (run % 3)
let &splitbelow = (run % 3)
let &equalalways = (run % 2)
"let wsb = (run % 2) && &splitbelow
" Nvim: both windows have a winbar after splitting
" let wsb = (run % 2) && &splitbelow
let wsb = 0
let tl = (gui ? 0 : ((run % 5) ? 1 : 0))
let pos = !(run % 3) ? 'H' : ((run % 2) ? 'M' : 'L')
tabnew | tabonly! | redraw
Expand All @@ -1526,51 +1530,51 @@ func Test_splitkeep_options()
call assert_equal(1, line("w0"))
call assert_equal(&scroll, winheight(0) / 2)
wincmd j
call assert_equal(&spk == 'topline' ? 1 : win_screenpos(0)[0] - tl, line("w0"))
call assert_equal(&spk == 'topline' ? 1 : win_screenpos(0)[0] - tl - wsb, line("w0"))

" No scroll when resizing windows
wincmd k | resize +2 | redraw
call assert_equal(1, line("w0"))
wincmd j
call assert_equal(&spk == 'topline' ? 1 : win_screenpos(0)[0] - tl, line("w0"))
call assert_equal(&spk == 'topline' ? 1 : win_screenpos(0)[0] - tl - wsb, line("w0"))

" No scroll when dragging statusline
call win_move_statusline(1, -3)
call assert_equal(&spk == 'topline' ? 1 : win_screenpos(0)[0] - tl, line("w0"))
call assert_equal(&spk == 'topline' ? 1 : win_screenpos(0)[0] - tl - wsb, line("w0"))
wincmd k
call assert_equal(1, line("w0"))

" No scroll when changing shellsize
set lines+=2
call assert_equal(1, line("w0"))
wincmd j
call assert_equal(&spk == 'topline' ? 1 : win_screenpos(0)[0] - tl, line("w0"))
call assert_equal(&spk == 'topline' ? 1 : win_screenpos(0)[0] - tl - wsb, line("w0"))
set lines-=2
call assert_equal(&spk == 'topline' ? 1 : win_screenpos(0)[0] - tl, line("w0"))
call assert_equal(&spk == 'topline' ? 1 : win_screenpos(0)[0] - tl - wsb, line("w0"))
wincmd k
call assert_equal(1, line("w0"))

" No scroll when equalizing windows
wincmd =
call assert_equal(1, line("w0"))
wincmd j
call assert_equal(&spk == 'topline' ? 1 : win_screenpos(0)[0] - tl, line("w0"))
call assert_equal(&spk == 'topline' ? 1 : win_screenpos(0)[0] - tl - wsb, line("w0"))
wincmd k
call assert_equal(1, line("w0"))

" No scroll in windows split multiple times
vsplit | split | 4wincmd w
call assert_equal(&spk == 'topline' ? 1 : win_screenpos(0)[0] - tl, line("w0"))
call assert_equal(&spk == 'topline' ? 1 : win_screenpos(0)[0] - tl - wsb, line("w0"))
1wincmd w | quit | wincmd l | split
call assert_equal(&spk == 'topline' ? 1 : win_screenpos(0)[0] - tl, line("w0"))
call assert_equal(&spk == 'topline' ? 1 : win_screenpos(0)[0] - tl - wsb, line("w0"))
wincmd j
call assert_equal(&spk == 'topline' ? 1 : win_screenpos(0)[0] - tl, line("w0"))
call assert_equal(&spk == 'topline' ? 1 : win_screenpos(0)[0] - tl - wsb, line("w0"))

" No scroll in small window
2wincmd w | only | 5split | wincmd k
call assert_equal(1, line("w0"))
wincmd j
call assert_equal(&spk == 'topline' ? 1 : win_screenpos(0)[0] - tl, line("w0"))
call assert_equal(&spk == 'topline' ? 1 : win_screenpos(0)[0] - tl - wsb, line("w0"))

" No scroll for vertical split
quit | vsplit | wincmd l
Expand All @@ -1580,7 +1584,7 @@ func Test_splitkeep_options()

" No scroll in windows split and quit multiple times
quit | redraw | split | split | quit | redraw
call assert_equal(&spk == 'topline' ? 1 : win_screenpos(0)[0] - tl, line("w0"))
call assert_equal(&spk == 'topline' ? 1 : win_screenpos(0)[0] - tl - wsb, line("w0"))

" No scroll for new buffer
1wincmd w | only | copen | wincmd k
Expand All @@ -1605,7 +1609,7 @@ func Test_splitkeep_options()
only | execute "norm gg5\<C-e>" | split | wincmd k
call assert_equal(6, line("w0"))
wincmd j
call assert_equal(&spk == 'topline' ? 6 : 5 + win_screenpos(0)[0] - tl, line("w0"))
call assert_equal(&spk == 'topline' ? 6 : 5 + win_screenpos(0)[0] - tl - wsb, line("w0"))
endfor

tabnew | tabonly! | %bwipeout!
Expand Down
30 changes: 16 additions & 14 deletions src/nvim/window.c
Expand Up @@ -6081,12 +6081,12 @@ void set_fraction(win_T *wp)
}
}

// Handle scroll position for 'splitkeep'. Replaces scroll_to_fraction()
// call from win_set_inner_size(). Instead we iterate over all windows in a
// tabpage and calculate the new scroll position.
// TODO(luukvbaal): Ensure this also works with wrapped lines.
// Requires topline to be able to be set to a bufferline with some
// offset(row-wise scrolling/smoothscroll).
/// Handle scroll position for 'splitkeep'. Replaces scroll_to_fraction()
/// call from win_set_inner_size(). Instead we iterate over all windows in a
/// tabpage and calculate the new scroll position.
/// TODO(luukvbaal): Ensure this also works with wrapped lines.
/// Requires topline to be able to be set to a bufferline with some
/// offset(row-wise scrolling/smoothscroll).
void win_fix_scroll(int resize)
{
linenr_T lnum;
Expand All @@ -6095,14 +6095,14 @@ 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) {
// Determine botline needed to avoid scrolling and set cursor.
// 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) {
lnum = wp->w_cursor.lnum;
int diff = (wp->w_winrow - wp->w_prev_winrow)
+ (wp->w_height - wp->w_prev_height);
lnum = wp->w_cursor.lnum;
wp->w_cursor.lnum = wp->w_botline - 1;
// Add difference in height and row to botline.
// Add difference in height and row to botline.
if (diff > 0) {
cursor_down_inner(wp, diff);
} else {
Expand Down Expand Up @@ -6131,9 +6131,9 @@ 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, scroll to make valid instead.
/// 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, scroll to make valid instead.
static void win_fix_cursor(int normal)
{
win_T *wp = curwin;
Expand All @@ -6146,6 +6146,7 @@ static void win_fix_cursor(int normal)
return;
}

// Determine valid cursor range.
so = MIN(wp->w_height_inner / 2, so);
wp->w_cursor.lnum = wp->w_topline;
linenr_T top = cursor_down_inner(wp, so);
Expand All @@ -6160,7 +6161,8 @@ static void win_fix_cursor(int normal)
}

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('\'');
wp->w_cursor.lnum = nlnum;
} else {
Expand Down Expand Up @@ -6327,7 +6329,7 @@ void win_set_inner_size(win_T *wp, bool valid_cursor)

// There is no point in adjusting the scroll position when exiting. Some
// values might be invalid.
if (!exiting && valid_cursor && *p_spk == 'c') {
if (valid_cursor && !exiting && *p_spk == 'c') {
scroll_to_fraction(wp, prev_height);
}
redraw_later(wp, UPD_SOME_VALID);
Expand Down

0 comments on commit 669867a

Please sign in to comment.