vim-patch:9.0.1710: scrolloff options work slightly different

Problem: sidescrolloff and scrolloff options work slightly
         different than other global-local options
Solution: Make it behave consistent for all global-local options

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. Also add some
extra documentation for a few special local-window options.

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

closes: vim/vim#12956
closes: vim/vim#12643

4a8eb6e7a9

Co-authored-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
zeertzjq 2023-08-23 16:32:15 +08:00
parent 99265d099c
commit 0ba27bb51d
7 changed files with 162 additions and 17 deletions

View File

@ -189,6 +189,8 @@ opt+=val" the expansion is done before the adding or removing.
Handling of local options *local-options*
Note: The following also applies to |global-local| options.
Some of the options only apply to a window or buffer. Each window or buffer
has its own copy of this option, thus each can have its own value. This
allows you to set 'list' in one window but not in another. And set
@ -238,6 +240,30 @@ The options local to a window are remembered for each buffer. This also
happens when the buffer is not loaded, but they are lost when the buffer is
wiped out |:bwipe|.
Special local window options *special-local-window-option*
The following local window options won't be copied over when new windows are
created, thus they behave slightly differently:
Option Reason ~
'previewwindow' there can only be a single one
'scroll' specific to existing window
'winfixheight' specific to existing window
'winfixwidth' specific to existing window
Special local buffer options *special-local-buffer-option*
The following local buffer options won't be copied over when new buffers are
created, thus they behave slightly differently:
Option Reason ~
'filetype' explicitly set by autocommands
'syntax' explicitly set by autocommands
'bufhidden' denote |special-buffers|
'buftype' denote |special-buffers|
'readonly' will be detected automatically
'modified' will be detected automatically
*:setl* *:setlocal*
:setl[ocal][!] ... Like ":set" but set only the value local to the
current buffer or window. Not all options have a
@ -311,7 +337,6 @@ 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.
*option-value-function*
Some options ('completefunc', 'omnifunc', 'operatorfunc', 'quickfixtextfunc',
'tagfunc' and 'thesaurusfunc') are set to a function name or a function
@ -1070,7 +1095,7 @@ A jump table for the options with a short description can be found at |Q_op|.
*'bufhidden'* *'bh'*
'bufhidden' 'bh' string (default "")
local to buffer
local to buffer |special-local-buffer-option|
This option specifies what happens when a buffer is no longer
displayed in a window:
<empty> follow the global 'hidden' option
@ -1102,7 +1127,7 @@ A jump table for the options with a short description can be found at |Q_op|.
*'buftype'* *'bt'* *E382*
'buftype' 'bt' string (default "")
local to buffer
local to buffer |special-local-buffer-option|
The value of this option specifies the type of a buffer:
<empty> normal buffer
acwrite buffer will always be written with |BufWriteCmd|s
@ -2408,7 +2433,7 @@ A jump table for the options with a short description can be found at |Q_op|.
*'filetype'* *'ft'*
'filetype' 'ft' string (default "")
local to buffer
local to buffer |special-local-buffer-option|
When this option is set, the FileType autocommand event is triggered.
All autocommands that match with the value of this option will be
executed. Thus the value of 'filetype' is used in place of the file
@ -4084,7 +4109,7 @@ A jump table for the options with a short description can be found at |Q_op|.
*'modified'* *'mod'* *'nomodified'* *'nomod'*
'modified' 'mod' boolean (default off)
local to buffer
local to buffer |special-local-buffer-option|
When on, the buffer is considered to be modified. This option is set
when:
1. A change was made to the text since it was last written. Using the
@ -4532,7 +4557,7 @@ A jump table for the options with a short description can be found at |Q_op|.
*'previewwindow'* *'pvw'* *'nopreviewwindow'* *'nopvw'* *E590*
'previewwindow' 'pvw' boolean (default off)
local to window
local to window |special-local-window-option|
Identifies the preview window. Only one window can have this option
set. It's normally not set directly, but by using one of the commands
|:ptag|, |:pedit|, etc.
@ -4602,7 +4627,7 @@ A jump table for the options with a short description can be found at |Q_op|.
*'readonly'* *'ro'* *'noreadonly'* *'noro'*
'readonly' 'ro' boolean (default off)
local to buffer
local to buffer |special-local-buffer-option|
If on, writes fail unless you use a '!'. Protects you from
accidentally overwriting a file. Default on when Vim is started
in read-only mode ("vim -R") or when the executable is called "view".
@ -4864,7 +4889,7 @@ A jump table for the options with a short description can be found at |Q_op|.
*'scroll'* *'scr'*
'scroll' 'scr' number (default half the window height)
local to window
local to window |special-local-window-option|
Number of lines to scroll with CTRL-U and CTRL-D commands. Will be
set to half the number of lines in the window when the window size
changes. This may happen when enabling the |status-line| or
@ -6214,7 +6239,7 @@ A jump table for the options with a short description can be found at |Q_op|.
*'syntax'* *'syn'*
'syntax' 'syn' string (default "")
local to buffer
local to buffer |special-local-buffer-option|
When this option is set, the syntax with this name is loaded, unless
syntax highlighting has been switched off with ":syntax off".
Otherwise this option does not always reflect the current syntax (the
@ -7081,7 +7106,7 @@ A jump table for the options with a short description can be found at |Q_op|.
*'winfixheight'* *'wfh'* *'nowinfixheight'* *'nowfh'*
'winfixheight' 'wfh' boolean (default off)
local to window
local to window |special-local-window-option|
Keep the window height when windows are opened or closed and
'equalalways' is set. Also for |CTRL-W_=|. Set by default for the
|preview-window| and |quickfix-window|.
@ -7089,7 +7114,7 @@ A jump table for the options with a short description can be found at |Q_op|.
*'winfixwidth'* *'wfw'* *'nowinfixwidth'* *'nowfw'*
'winfixwidth' 'wfw' boolean (default off)
local to window
local to window |special-local-window-option|
Keep the window width when windows are opened or closed and
'equalalways' is set. Also for |CTRL-W_=|.
The width may be changed anyway when running out of room.

View File

@ -542,6 +542,36 @@ local function scope_to_doc(s)
return 'global or '..m[s[2]]..' |global-local|'
end
-- @param o vim.option_meta
-- @return string
local function scope_more_doc(o)
if
vim.list_contains({
'previewwindow',
'scroll',
'winfixheight',
'winfixwidth',
}, o.full_name)
then
return ' |special-local-window-option|'
end
if
vim.list_contains({
'bufhidden',
'buftype',
'filetype',
'modified',
'readonly',
'syntax',
}, o.full_name)
then
return ' |special-local-buffer-option|'
end
return ''
end
--- @return table<string,vim.option_meta>
local function get_option_meta()
local opts = require('src/nvim/options').options
@ -624,7 +654,7 @@ local function render_option_doc(_f, opt, write)
write(string.format('%s\t%s', name_str, otype))
end
write('\t\t\t'..scope_to_doc(opt.scope))
write('\t\t\t'..scope_to_doc(opt.scope)..scope_more_doc(opt))
for _, l in ipairs(split(opt.desc)) do
if l == '<' or l:match('^<%s') then
write(l)

View File

@ -230,6 +230,10 @@ typedef struct {
#define w_p_crb_save w_onebuf_opt.wo_crb_save
char *wo_scl;
#define w_p_scl w_onebuf_opt.wo_scl // 'signcolumn'
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
char *wo_winhl;
#define w_p_winhl w_onebuf_opt.wo_winhl // 'winhighlight'
char *wo_lcs;
@ -1321,8 +1325,6 @@ struct window_S {
uint32_t w_p_fdt_flags; // flags for 'foldtext'
int *w_p_cc_cols; // array of columns to highlight or NULL
uint8_t w_p_culopt_flags; // flags for cursorline highlighting
long w_p_siso; // 'sidescrolloff' local value
long w_p_so; // 'scrolloff' local value
int w_briopt_min; // minimum width for breakindent
int w_briopt_shift; // additional shift for breakindent

View File

@ -4702,6 +4702,8 @@ void 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;
to->wo_spell = from->wo_spell;
to->wo_cuc = from->wo_cuc;
to->wo_cul = from->wo_cul;

View File

@ -5132,8 +5132,8 @@ static win_T *win_alloc(win_T *after, bool hidden)
new_wp->w_ns_hl = -1;
// use global option 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;

View File

@ -1548,7 +1548,7 @@ describe('lua stdlib', function()
eq(100, funcs.luaeval "vim.wo.scrolloff")
exec_lua [[
vim.wo[0][0].scrolloff = 200
vim.cmd "split"
vim.cmd "enew"
]]
eq(100, funcs.luaeval "vim.wo.scrolloff")
end)

View File

@ -1682,4 +1682,90 @@ 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, ' ')})
let result = getline(1, '$')->map({_, val -> matchlist(val, '\([^ ]\+\) \+\([^ ]\+\) \+\(.*\)')[1:3]})
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