0
0
mirror of https://github.com/vim/vim.git synced 2025-08-23 19:34:27 -04:00

patch 8.2.3900: it is not easy to use a script-local function for an option

Problem:    It is not easy to use a script-local function for an option.
Solution:   recognize s: and <SID> at the start of the expression. (Yegappan
            Lakshmanan, closes #9401)
This commit is contained in:
Yegappan Lakshmanan 2021-12-26 10:51:39 +00:00 committed by Bram Moolenaar
parent ec86520f94
commit 8bb65f230d
13 changed files with 265 additions and 8 deletions

View File

@ -398,6 +398,11 @@ mode, so that a CTRL-Z doesn't end the text on DOS.
The `redraw!` command may not be needed, depending on whether executing a
shell command shows something on the display or not.
If the 'diffexpr' expression starts with s: or |<SID>|, then it is replaced
with the script ID (|local-function|). Example: >
set diffexpr=s:MyDiffExpr()
set diffexpr=<SID>SomeDiffExpr()
<
*E810* *E97*
Vim will do a test if the diff output looks alright. If it doesn't, you will
get an error message. Possible causes:
@ -449,4 +454,9 @@ evaluating 'patchexpr'. This hopefully avoids that files in the current
directory are accidentally patched. Vim will also delete files starting with
v:fname_in and ending in ".rej" and ".orig".
If the 'patchexpr' expression starts with s: or |<SID>|, then it is replaced
with the script ID (|local-function|). Example: >
set patchexpr=s:MyPatchExpr()
set patchexpr=<SID>SomePatchExpr()
<
vim:tw=78:ts=8:noet:ft=help:norl:

View File

@ -121,6 +121,11 @@ method can be very slow!
Try to avoid the "=", "a" and "s" return values, since Vim often has to search
backwards for a line for which the fold level is defined. This can be slow.
If the 'foldexpr' expression starts with s: or |<SID>|, then it is replaced
with the script ID (|local-function|). Example: >
set foldexpr=s:MyFoldExpr()
set foldexpr=<SID>SomeFoldExpr()
<
An example of using "a1" and "s1": For a multi-line C comment, a line
containing "/*" would return "a1" to start a fold, and a line containing "*/"
would return "s1" to end the fold after that line: >
@ -543,6 +548,8 @@ A closed fold is indicated with a '+'.
These characters can be changed with the 'fillchars' option.
These characters can be changed with the 'fillchars' option.
Where the fold column is too narrow to display all nested folds, digits are
shown to indicate the nesting level.

View File

@ -1225,6 +1225,11 @@ A jump table for the options with a short description can be found at |Q_op|.
Vim does not try to send a message to an external debugger (Netbeans
or Sun Workshop).
If the expression starts with s: or |<SID>|, then it is replaced with
the script ID (|local-function|). Example: >
set bexpr=s:MyBalloonExpr()
set bexpr=<SID>SomeBalloonExpr()
<
The expression will be evaluated in the |sandbox| when set from a
modeline, see |sandbox-option|.
This option cannot be set in a modeline when 'modelineexpr' is off.
@ -3596,6 +3601,11 @@ A jump table for the options with a short description can be found at |Q_op|.
When the expression evaluates to non-zero Vim will fall back to using
the internal format mechanism.
If the expression starts with s: or |<SID>|, then it is replaced with
the script ID (|local-function|). Example: >
set formatexpr=s:MyFormatExpr()
set formatexpr=<SID>SomeFormatExpr()
<
The expression will be evaluated in the |sandbox| when set from a
modeline, see |sandbox-option|. That stops the option from working,
since changing the buffer text is not allowed.
@ -4438,6 +4448,11 @@ A jump table for the options with a short description can be found at |Q_op|.
found. Allows doing "gf" on the name after an 'include' statement.
Also used for |<cfile>|.
If the expression starts with s: or |<SID>|, then it is replaced with
the script ID (|local-function|). Example: >
set includeexpr=s:MyIncludeExpr(v:fname)
set includeexpr=<SID>SomeIncludeExpr(v:fname)
<
The expression will be evaluated in the |sandbox| when set from a
modeline, see |sandbox-option|.
This option cannot be set in a modeline when 'modelineexpr' is off.
@ -4511,6 +4526,11 @@ A jump table for the options with a short description can be found at |Q_op|.
The expression is evaluated with |v:lnum| set to the line number for
which the indent is to be computed. The cursor is also in this line
when the expression is evaluated (but it may be moved around).
If the expression starts with s: or |<SID>|, then it is replaced with
the script ID (|local-function|). Example: >
set indentexpr=s:MyIndentExpr()
set indentexpr=<SID>SomeIndentExpr()
<
The expression must return the number of spaces worth of indent. It
can return "-1" to keep the current indent (this means 'autoindent' is
used for the indent).

View File

@ -174,6 +174,11 @@ an error message. In that case Vim will delete the file. In the default
value for non-MS-Windows a trick is used: Adding "v:shell_error" will result
in a non-zero number when the system() call fails.
If the expression starts with s: or |<SID>|, then it is replaced with the
script ID (|local-function|). Example: >
set printexpr=s:MyPrintFile()
set printexpr=<SID>SomePrintFile()
<
This option cannot be set from a |modeline| or in the |sandbox|, for security
reasons.

View File

@ -2026,14 +2026,6 @@ ambw_end:
newFoldLevel();
}
}
# ifdef FEAT_EVAL
// 'foldexpr'
else if (varp == &curwin->w_p_fde)
{
if (foldmethodIsExpr(curwin))
foldUpdateAll(curwin);
}
# endif
// 'foldmarker'
else if (gvarp == &curwin->w_allbuf_opt.wo_fmr)
{
@ -2307,6 +2299,89 @@ ambw_end:
# endif
#endif
#ifdef FEAT_EVAL
// '*expr' options
else if (
# ifdef FEAT_BEVAL
varp == &p_bexpr ||
# endif
# ifdef FEAT_DIFF
varp == &p_dex ||
# endif
# ifdef FEAT_FOLDING
varp == &curwin->w_p_fde ||
# endif
gvarp == &p_fex ||
# ifdef FEAT_FIND_ID
gvarp == &p_inex ||
# endif
# ifdef FEAT_CINDENT
gvarp == &p_inde ||
# endif
# ifdef FEAT_DIFF
varp == &p_pex ||
# endif
# ifdef FEAT_POSTSCRIPT
varp == &p_pexpr ||
# endif
FALSE
)
{
char_u **p_opt = NULL;
char_u *name;
// If the option value starts with <SID> or s:, then replace that with
// the script identifier.
# ifdef FEAT_BEVAL
if (varp == &p_bexpr) // 'balloonexpr'
p_opt = (opt_flags & OPT_LOCAL) ? &curbuf->b_p_bexpr : &p_bexpr;
# endif
# ifdef FEAT_DIFF
if (varp == &p_dex) // 'diffexpr'
p_opt = &p_dex;
# endif
# ifdef FEAT_FOLDING
if(varp == &curwin->w_p_fde) // 'foldexpr'
p_opt = &curwin->w_p_fde;
# endif
if (gvarp == &p_fex) // 'formatexpr'
p_opt = &curbuf->b_p_fex;
# ifdef FEAT_FIND_ID
if (gvarp == &p_inex) // 'includeexpr'
p_opt = &curbuf->b_p_inex;
# endif
# ifdef FEAT_CINDENT
if (gvarp == &p_inde) // 'indentexpr'
p_opt = &curbuf->b_p_inde;
# endif
# ifdef FEAT_DIFF
if (varp == &p_pex) // 'patchexpr'
p_opt = &p_pex;
# endif
# ifdef FEAT_POSTSCRIPT
if (varp == &p_pexpr) // 'printexpr'
p_opt = &p_pexpr;
# endif
if (p_opt != NULL)
{
name = get_scriptlocal_funcname(*p_opt);
if (name != NULL)
{
if (new_value_alloced)
free_string_option(*p_opt);
*p_opt = name;
new_value_alloced = TRUE;
}
}
# ifdef FEAT_FOLDING
if (varp == &curwin->w_p_fde && foldmethodIsExpr(curwin))
foldUpdateAll(curwin);
# endif
}
#endif
#ifdef FEAT_COMPL_FUNC
// 'completefunc'
else if (gvarp == &p_cfu)

View File

@ -681,8 +681,19 @@ func Test_diffexpr()
set diffexpr=NewDiffFunc()
call assert_fails('windo diffthis', ['E117:', 'E97:'])
diffoff!
" Using a script-local function
func s:NewDiffExpr()
endfunc
set diffexpr=s:NewDiffExpr()
call assert_equal(expand('<SID>') .. 'NewDiffExpr()', &diffexpr)
set diffexpr=<SID>NewDiffExpr()
call assert_equal(expand('<SID>') .. 'NewDiffExpr()', &diffexpr)
%bwipe!
set diffexpr& diffopt&
delfunc DiffExpr
delfunc s:NewDiffExpr
endfunc
func Test_diffpatch()
@ -1216,10 +1227,19 @@ func Test_patchexpr()
call assert_equal(2, winnr('$'))
call assert_true(&diff)
" Using a script-local function
func s:NewPatchExpr()
endfunc
set patchexpr=s:NewPatchExpr()
call assert_equal(expand('<SID>') .. 'NewPatchExpr()', &patchexpr)
set patchexpr=<SID>NewPatchExpr()
call assert_equal(expand('<SID>') .. 'NewPatchExpr()', &patchexpr)
call delete('Xinput')
call delete('Xdiff')
set patchexpr&
delfunc TPatch
delfunc s:NewPatchExpr
%bwipe!
endfunc

View File

@ -324,6 +324,16 @@ func Test_edit_11_indentexpr()
set cinkeys&vim indentkeys&vim
set nocindent indentexpr=
delfu Do_Indent
" Using a script-local function
func s:NewIndentExpr()
endfunc
set indentexpr=s:NewIndentExpr()
call assert_equal(expand('<SID>') .. 'NewIndentExpr()', &indentexpr)
set indentexpr=<SID>NewIndentExpr()
call assert_equal(expand('<SID>') .. 'NewIndentExpr()', &indentexpr)
set indentexpr&
bw!
endfunc

View File

@ -1382,4 +1382,30 @@ func Test_fold_jump()
bw!
endfunc
" Test for using a script-local function for 'foldexpr'
func Test_foldexpr_scriptlocal_func()
func! s:FoldFunc()
let g:FoldLnum = v:lnum
endfunc
new | only
call setline(1, 'abc')
let g:FoldLnum = 0
set foldmethod=expr foldexpr=s:FoldFunc()
redraw!
call assert_equal(expand('<SID>') .. 'FoldFunc()', &foldexpr)
call assert_equal(1, g:FoldLnum)
set foldmethod& foldexpr=
bw!
new | only
call setline(1, 'abc')
let g:FoldLnum = 0
set foldmethod=expr foldexpr=<SID>FoldFunc()
redraw!
call assert_equal(expand('<SID>') .. 'FoldFunc()', &foldexpr)
call assert_equal(1, g:FoldLnum)
set foldmethod& foldexpr=
delfunc s:FoldFunc
bw!
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@ -217,4 +217,30 @@ func Test_gf_includeexpr()
delfunc IncFunc
endfunc
" Test for using a script-local function for 'includeexpr'
func Test_includeexpr_scriptlocal_func()
func! s:IncludeFunc()
let g:IncludeFname = v:fname
return ''
endfunc
set includeexpr=s:IncludeFunc()
call assert_equal(expand('<SID>') .. 'IncludeFunc()', &includeexpr)
new | only
call setline(1, 'TestFile1')
let g:IncludeFname = ''
call assert_fails('normal! gf', 'E447:')
call assert_equal('TestFile1', g:IncludeFname)
bw!
set includeexpr=<SID>IncludeFunc()
call assert_equal(expand('<SID>') .. 'IncludeFunc()', &includeexpr)
new | only
call setline(1, 'TestFile2')
let g:IncludeFname = ''
call assert_fails('normal! gf', 'E447:')
call assert_equal('TestFile2', g:IncludeFname)
set includeexpr&
delfunc s:IncludeFunc
bw!
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@ -258,6 +258,15 @@ func Test_set_balloonexpr()
setl balloonexpr&
call assert_equal('', &balloonexpr)
delfunc MyBalloonExpr
" Using a script-local function
func s:NewBalloonExpr()
endfunc
set balloonexpr=s:NewBalloonExpr()
call assert_equal(expand('<SID>') .. 'NewBalloonExpr()', &balloonexpr)
set balloonexpr=<SID>NewBalloonExpr()
call assert_equal(expand('<SID>') .. 'NewBalloonExpr()', &balloonexpr)
delfunc s:NewBalloonExpr
bwipe!
" Multiline support

View File

@ -125,6 +125,14 @@ func Test_printexpr()
set printexpr=PrintFails(v:fname_in)
call assert_fails('hardcopy', 'E365:')
" Using a script-local function
func s:NewPrintExpr()
endfunc
set printexpr=s:NewPrintExpr()
call assert_equal(expand('<SID>') .. 'NewPrintExpr()', &printexpr)
set printexpr=<SID>NewPrintExpr()
call assert_equal(expand('<SID>') .. 'NewPrintExpr()', &printexpr)
set printexpr&
bwipe
endfunc

View File

@ -253,6 +253,45 @@ func Test_normal_formatexpr_returns_nonzero()
close!
endfunc
" Test for using a script-local function for 'formatexpr'
func Test_formatexpr_scriptlocal_func()
func! s:Format()
let g:FormatArgs = [v:lnum, v:count]
endfunc
set formatexpr=s:Format()
call assert_equal(expand('<SID>') .. 'Format()', &formatexpr)
new | only
call setline(1, range(1, 40))
let g:FormatArgs = []
normal! 2GVjgq
call assert_equal([2, 2], g:FormatArgs)
bw!
set formatexpr=<SID>Format()
call assert_equal(expand('<SID>') .. 'Format()', &formatexpr)
new | only
call setline(1, range(1, 40))
let g:FormatArgs = []
normal! 4GVjgq
call assert_equal([4, 2], g:FormatArgs)
bw!
let &formatexpr = 's:Format()'
new | only
call setline(1, range(1, 40))
let g:FormatArgs = []
normal! 6GVjgq
call assert_equal([6, 2], g:FormatArgs)
bw!
let &formatexpr = '<SID>Format()'
new | only
call setline(1, range(1, 40))
let g:FormatArgs = []
normal! 8GVjgq
call assert_equal([8, 2], g:FormatArgs)
setlocal formatexpr=
delfunc s:Format
bw!
endfunc
" basic test for formatprg
func Test_normal06_formatprg()
" only test on non windows platform

View File

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