Skip to content

Commit

Permalink
Make scrolloff and sidescrolloff global-local
Browse files Browse the repository at this point in the history
It was noticed, that sidescrolloff and scrolloff options behave
differently in comparison to other global-local window options like
'listchars'

So make those two behave like other global-local options.

Add a few tests to make sure all global-local window options behave
similar

fixes vim#12956
  • Loading branch information
chrisbra committed Jul 6, 2023
1 parent d392a74 commit 9f4f198
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 4 deletions.
6 changes: 6 additions & 0 deletions runtime/doc/options.txt
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,12 @@ used. Thus it does the same as: >
Note: In the future more global options can be made |global-local|. Using
":setlocal" on a global option might work differently then.

*window-global-local*
One special feature are |global-local| window options. Those options are not
only local to the window, but in addition to the buffer inside the window.
Each buffer remembers uses its own local version of that option value, so when
you edit the same buffer in a different window, it carries along and re-uses
the window-local options.

*option-value-function*
Some options ('completefunc', 'imactivatefunc', 'imstatusfunc', 'omnifunc',
Expand Down
2 changes: 2 additions & 0 deletions src/option.c
Original file line number Diff line number Diff line change
Expand Up @@ -6652,6 +6652,8 @@ copy_winopt(winopt_T *from, winopt_T *to)
to->wo_sms = from->wo_sms;
to->wo_crb = from->wo_crb;
to->wo_crb_save = from->wo_crb_save;
to->wo_siso = from->wo_siso;
to->wo_so = from->wo_so;
#ifdef FEAT_SPELL
to->wo_spell = from->wo_spell;
#endif
Expand Down
6 changes: 4 additions & 2 deletions src/structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,10 @@ typedef struct
char_u *wo_scl;
# define w_p_scl w_onebuf_opt.wo_scl // 'signcolumn'
#endif
long wo_siso;
# define w_p_siso w_onebuf_opt.wo_siso // 'sidescrolloff' local value
long wo_so;
# define w_p_so w_onebuf_opt.wo_so // 'scrolloff' local value
#ifdef FEAT_TERMINAL
char_u *wo_twk;
# define w_p_twk w_onebuf_opt.wo_twk // 'termwinkey'
Expand Down Expand Up @@ -3977,8 +3981,6 @@ struct window_S
int *w_p_cc_cols; // array of columns to highlight or NULL
char_u w_p_culopt_flags; // flags for cursorline highlighting
#endif
long w_p_siso; // 'sidescrolloff' local value
long w_p_so; // 'scrolloff' local value

#ifdef FEAT_LINEBREAK
int w_briopt_min; // minimum width for breakindent
Expand Down
85 changes: 85 additions & 0 deletions src/testdir/test_options.vim
Original file line number Diff line number Diff line change
Expand Up @@ -1689,4 +1689,89 @@ func Test_string_option_revert_on_failure()
bw!
endfunc

func Test_set_option_window_global_local()
new Xbuffer1
let [ _gso, _lso ] = [ &g:scrolloff, &l:scrolloff ]
setlocal scrolloff=2
setglobal scrolloff=3
setl modified
" A new buffer has its own window-local options
hide enew
call assert_equal(-1, &l:scrolloff)
call assert_equal(3, &g:scrolloff)
" A new window opened with its own buffer-local options
new
call assert_equal(-1, &l:scrolloff)
call assert_equal(3, &g:scrolloff)
" Re-open Xbuffer1 and it should use
" the previous set window-local options
b Xbuffer1
call assert_equal(2, &l:scrolloff)
call assert_equal(3, &g:scrolloff)
bw!
bw!
let &g:scrolloff = _gso
endfunc

func GetGlobalLocalWindowOptions()
new
sil! r $VIMRUNTIME/doc/options.txt
" Filter for global or local to window
v/^'.*'.*\n.*global or local to window |global-local/d
" get option value and type
sil %s/^'\([^']*\)'.*'\s\+\(\w\+\)\s\+(default \%(\(".*"\|\d\+\|empty\)\).*/\1 \2 \3/g
sil %s/empty/""/g
" split the result
let result=getline(1,'$')->map({_, val -> split(val, ' ')})
bw!
return result
endfunc

func Test_set_option_window_global_local_all()
new Xbuffer2

let optionlist = GetGlobalLocalWindowOptions()
for [opt, type, default] in optionlist
let _old = eval('&g:' .. opt)
if type == 'string'
if opt == 'fillchars'
exe 'setl ' .. opt .. '=vert:+'
exe 'setg ' .. opt .. '=vert:+,fold:+'
elseif opt == 'listchars'
exe 'setl ' .. opt .. '=tab:>>'
exe 'setg ' .. opt .. '=tab:++'
elseif opt == 'virtualedit'
exe 'setl ' .. opt .. '=all'
exe 'setg ' .. opt .. '=block'
else
exe 'setl ' .. opt .. '=Local'
exe 'setg ' .. opt .. '=Global'
endif
elseif type == 'number'
exe 'setl ' .. opt .. '=5'
exe 'setg ' .. opt .. '=10'
endif
setl modified
hide enew
if type == 'string'
call assert_equal('', eval('&l:' .. opt))
if opt == 'fillchars'
call assert_equal('vert:+,fold:+', eval('&g:' .. opt), 'option:' .. opt)
elseif opt == 'listchars'
call assert_equal('tab:++', eval('&g:' .. opt), 'option:' .. opt)
elseif opt == 'virtualedit'
call assert_equal('block', eval('&g:' .. opt), 'option:' .. opt)
else
call assert_equal('Global', eval('&g:' .. opt), 'option:' .. opt)
endif
elseif type == 'number'
call assert_equal(-1, eval('&l:' .. opt), 'option:' .. opt)
call assert_equal(10, eval('&g:' .. opt), 'option:' .. opt)
endif
bw!
exe 'let &g:' .. opt .. '=' .. default
endfor
bw!
endfunc

" vim: shiftwidth=2 sts=2 expandtab
4 changes: 2 additions & 2 deletions src/window.c
Original file line number Diff line number Diff line change
Expand Up @@ -5546,8 +5546,8 @@ win_alloc(win_T *after, int hidden)
new_wp->w_scbind_pos = 1;

// use global option value for global-local options
new_wp->w_p_so = -1;
new_wp->w_p_siso = -1;
new_wp->w_allbuf_opt.wo_so = new_wp->w_p_so = -1;
new_wp->w_allbuf_opt.wo_siso = new_wp->w_p_siso = -1;

// We won't calculate w_fraction until resizing the window
new_wp->w_fraction = 0;
Expand Down

0 comments on commit 9f4f198

Please sign in to comment.