# HG changeset patch # User Bram Moolenaar # Date 1642783504 -3600 # Node ID e11682ba8c805522adfd981ed7f670cfdc970f78 # Parent 685e831a281a6097c5de683d6f91218efb1e72ef patch 8.2.4173: cannot use an import in 'foldexpr' Commit: https://github.com/vim/vim/commit/e70dd11ef41f69bd5e94f630194e6b3c4f3f2102 Author: Bram Moolenaar Date: Fri Jan 21 16:31:11 2022 +0000 patch 8.2.4173: cannot use an import in 'foldexpr' Problem: Cannot use an import in 'foldexpr'. Solution: Set the script context to where 'foldexpr' was set. (closes https://github.com/vim/vim/issues/9584) Fix that the script context was not set for all buffers. diff --git a/src/eval.c b/src/eval.c --- a/src/eval.c +++ b/src/eval.c @@ -772,7 +772,7 @@ call_func_retlist( return rettv.vval.v_list; } -#ifdef FEAT_FOLDING +#if defined(FEAT_FOLDING) || defined(PROTO) /* * Evaluate "arg", which is 'foldexpr'. * Note: caller must set "curwin" to match "arg". @@ -780,14 +780,19 @@ call_func_retlist( * give error messages. */ int -eval_foldexpr(char_u *arg, int *cp) +eval_foldexpr(win_T *wp, int *cp) { + char_u *arg; typval_T tv; varnumber_T retval; char_u *s; + sctx_T saved_sctx = current_sctx; int use_sandbox = was_set_insecurely((char_u *)"foldexpr", OPT_LOCAL); + arg = wp->w_p_fde; + current_sctx = wp->w_p_script_ctx[WV_FDE]; + ++emsg_off; if (use_sandbox) ++sandbox; @@ -818,6 +823,7 @@ eval_foldexpr(char_u *arg, int *cp) --sandbox; --textwinlock; clear_evalarg(&EVALARG_EVALUATE, NULL); + current_sctx = saved_sctx; return (int)retval; } diff --git a/src/fold.c b/src/fold.c --- a/src/fold.c +++ b/src/fold.c @@ -3307,7 +3307,7 @@ foldlevelExpr(fline_T *flp) // KeyTyped may be reset to 0 when calling a function which invokes // do_cmdline(). To make 'foldopen' work correctly restore KeyTyped. save_keytyped = KeyTyped; - n = eval_foldexpr(flp->wp->w_p_fde, &c); + n = eval_foldexpr(flp->wp, &c); KeyTyped = save_keytyped; switch (c) diff --git a/src/option.c b/src/option.c --- a/src/option.c +++ b/src/option.c @@ -2604,7 +2604,13 @@ set_option_sctx_idx(int opt_idx, int opt if (indir & PV_BUF) curbuf->b_p_script_ctx[indir & PV_MASK] = new_script_ctx; else if (indir & PV_WIN) + { curwin->w_p_script_ctx[indir & PV_MASK] = new_script_ctx; + if (both) + // also setting the "all buffers" value + curwin->w_allbuf_opt.wo_script_ctx[indir & PV_MASK] = + new_script_ctx; + } } } diff --git a/src/proto/eval.pro b/src/proto/eval.pro --- a/src/proto/eval.pro +++ b/src/proto/eval.pro @@ -18,11 +18,9 @@ char_u *eval_to_string_safe(char_u *arg, varnumber_T eval_to_number(char_u *expr); typval_T *eval_expr(char_u *arg, exarg_T *eap); int call_vim_function(char_u *func, int argc, typval_T *argv, typval_T *rettv); -varnumber_T call_func_retnr(char_u *func, int argc, typval_T *argv); -int call_func_noret(char_u *func, int argc, typval_T *argv); void *call_func_retstr(char_u *func, int argc, typval_T *argv); void *call_func_retlist(char_u *func, int argc, typval_T *argv); -int eval_foldexpr(char_u *arg, int *cp); +int eval_foldexpr(win_T *wp, int *cp); char_u *get_lval(char_u *name, typval_T *rettv, lval_T *lp, int unlet, int skip, int flags, int fne_flags); void clear_lval(lval_T *lp); void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, int flags, char_u *op, int var_idx); diff --git a/src/structs.h b/src/structs.h --- a/src/structs.h +++ b/src/structs.h @@ -3695,6 +3695,8 @@ struct window_S */ winopt_T w_onebuf_opt; winopt_T w_allbuf_opt; + // transform a pointer to a "onebuf" option into a "allbuf" option +#define GLOBAL_WO(p) ((char *)p + sizeof(winopt_T)) // A few options have local flags for P_INSECURE. #ifdef FEAT_STL_OPT @@ -3718,9 +3720,6 @@ struct window_S int w_briopt_list; // additional indent for lists #endif - // transform a pointer to a "onebuf" option into a "allbuf" option -#define GLOBAL_WO(p) ((char *)p + sizeof(winopt_T)) - long w_scbind_pos; #ifdef FEAT_EVAL diff --git a/src/testdir/test_vim9_import.vim b/src/testdir/test_vim9_import.vim --- a/src/testdir/test_vim9_import.vim +++ b/src/testdir/test_vim9_import.vim @@ -673,6 +673,45 @@ def Test_use_autoload_import_in_insert_c &rtp = save_rtp enddef +def Test_use_autoload_import_in_fold_expression() + mkdir('Xdir/autoload', 'p') + var save_rtp = &rtp + exe 'set rtp^=' .. getcwd() .. '/Xdir' + + var lines =<< trim END + vim9script + export def Expr(): string + return getline(v:lnum) =~ '^#' ? '>1' : '1' + enddef + g:fold_loaded = 'yes' + END + writefile(lines, 'Xdir/autoload/fold.vim') + + lines =<< trim END + vim9script + import autoload 'fold.vim' + &foldexpr = 'fold.Expr()' + &foldmethod = 'expr' + &debug = 'throw' + END + new + setline(1, ['# one', 'text', '# two', 'text']) + g:fold_loaded = 'no' + CheckScriptSuccess(lines) + assert_equal('no', g:fold_loaded) + redraw + assert_equal('yes', g:fold_loaded) + + # Check that script context of 'foldexpr' is copied to another buffer. + edit! otherfile + redraw + + set foldexpr= foldmethod& + bwipe! + delete('Xdir', 'rf') + &rtp = save_rtp +enddef + def Test_export_fails() CheckScriptFailure(['export var some = 123'], 'E1042:') CheckScriptFailure(['vim9script', 'export var g:some'], 'E1022:') diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -751,6 +751,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 4173, +/**/ 4172, /**/ 4171,