mirror of
https://github.com/macvim-dev/macvim.git
synced 2026-06-11 15:37:29 +02:00
Merge remote-tracking branch 'vim/master'
This commit is contained in:
+10
-4
@@ -195,7 +195,7 @@ foldlevel({lnum}) Number fold level at {lnum}
|
||||
foldtext() String line displayed for closed fold
|
||||
foldtextresult({lnum}) String text for closed fold at {lnum}
|
||||
foreground() Number bring the Vim window to the foreground
|
||||
fullcommand({name}) String get full command from {name}
|
||||
fullcommand({name} [, {vim9}]) String get full command from {name}
|
||||
funcref({name} [, {arglist}] [, {dict}])
|
||||
Funcref reference to function {name}
|
||||
function({name} [, {arglist}] [, {dict}])
|
||||
@@ -2967,14 +2967,20 @@ foreground() Move the Vim window to the foreground. Useful when sent from
|
||||
{only in the Win32, Motif and GTK GUI versions and the
|
||||
Win32 console version}
|
||||
|
||||
fullcommand({name}) *fullcommand()*
|
||||
fullcommand({name} [, {vim9}]) *fullcommand()*
|
||||
Get the full command name from a short abbreviated command
|
||||
name; see |20.2| for details on command abbreviations.
|
||||
|
||||
The string argument {name} may start with a `:` and can
|
||||
include a [range], these are skipped and not returned.
|
||||
Returns an empty string if a command doesn't exist or if it's
|
||||
ambiguous (for user-defined commands).
|
||||
Returns an empty string if a command doesn't exist, if it's
|
||||
ambiguous (for user-defined commands) or cannot be shortened
|
||||
this way. |vim9-no-shorten|
|
||||
|
||||
Without the {vim9} argument uses the current script version.
|
||||
If {vim9} is present and FALSE then legacy script rules are
|
||||
used. When {vim9} is present and TRUE then Vim9 rules are
|
||||
used, e.g. "en" is not a short form of "endif".
|
||||
|
||||
For example `fullcommand('s')`, `fullcommand('sub')`,
|
||||
`fullcommand(':%substitute')` all return "substitute".
|
||||
|
||||
@@ -2108,6 +2108,9 @@ au BufNewFile,BufRead */.config/upstart/*.override setf upstart
|
||||
" Vala
|
||||
au BufNewFile,BufRead *.vala setf vala
|
||||
|
||||
" VDF
|
||||
au BufNewFile,BufRead *.vdf setf vdf
|
||||
|
||||
" VDM
|
||||
au BufRead,BufNewFile *.vdmpp,*.vpp setf vdmpp
|
||||
au BufRead,BufNewFile *.vdmrt setf vdmrt
|
||||
|
||||
+1
-1
@@ -515,7 +515,7 @@ call <SID>AddOption("splitbelow", gettext("a new window is put below the current
|
||||
call <SID>BinOptionG("sb", &sb)
|
||||
call <SID>AddOption("splitright", gettext("a new window is put right of the current one"))
|
||||
call <SID>BinOptionG("spr", &spr)
|
||||
call <SID>AddOption("splitscroll", gettext("determines scroll behavior when spliting windows"))
|
||||
call <SID>AddOption("splitscroll", gettext("determines scroll behavior for split windows"))
|
||||
call <SID>BinOptionG("spsc", &spsc)
|
||||
call <SID>AddOption("scrollbind", gettext("this window scrolls together with other bound windows"))
|
||||
call append("$", "\t" .. s:local_to_window)
|
||||
|
||||
+1
-1
@@ -4258,7 +4258,7 @@ objects/vim9type.o: vim9type.c vim.h protodef.h auto/config.h feature.h os_unix.
|
||||
os_mac.h ascii.h keymap.h termdefs.h macros.h option.h beval.h \
|
||||
proto/gui_beval.pro structs.h regexp.h gui.h libvterm/include/vterm.h \
|
||||
libvterm/include/vterm_keycodes.h alloc.h ex_cmds.h spell.h proto.h \
|
||||
globals.h errors.h
|
||||
globals.h errors.h vim9.h
|
||||
objects/viminfo.o: viminfo.c vim.h protodef.h auto/config.h feature.h os_unix.h \
|
||||
os_mac.h ascii.h keymap.h termdefs.h macros.h option.h beval.h \
|
||||
proto/gui_beval.pro structs.h regexp.h gui.h libvterm/include/vterm.h \
|
||||
|
||||
+1
-1
@@ -1853,7 +1853,7 @@ static funcentry_T global_functions[] =
|
||||
ret_string, f_foldtextresult},
|
||||
{"foreground", 0, 0, 0, NULL,
|
||||
ret_void, f_foreground},
|
||||
{"fullcommand", 1, 1, FEARG_1, arg1_string,
|
||||
{"fullcommand", 1, 2, FEARG_1, arg2_string_bool,
|
||||
ret_string, f_fullcommand},
|
||||
{"funcref", 1, 3, FEARG_1, arg3_any_list_dict,
|
||||
ret_func_unknown, f_funcref},
|
||||
|
||||
+23
-7
@@ -4054,20 +4054,31 @@ cmd_exists(char_u *name)
|
||||
void
|
||||
f_fullcommand(typval_T *argvars, typval_T *rettv)
|
||||
{
|
||||
exarg_T ea;
|
||||
char_u *name;
|
||||
char_u *p;
|
||||
exarg_T ea;
|
||||
char_u *name;
|
||||
char_u *p;
|
||||
int vim9script = in_vim9script();
|
||||
int save_cmod_flags = cmdmod.cmod_flags;
|
||||
|
||||
rettv->v_type = VAR_STRING;
|
||||
rettv->vval.v_string = NULL;
|
||||
|
||||
if (in_vim9script() && check_for_string_arg(argvars, 0) == FAIL)
|
||||
if (in_vim9script()
|
||||
&& (check_for_string_arg(argvars, 0) == FAIL
|
||||
|| check_for_opt_bool_arg(argvars, 1) == FAIL))
|
||||
return;
|
||||
|
||||
name = argvars[0].vval.v_string;
|
||||
if (name == NULL)
|
||||
return;
|
||||
|
||||
if (argvars[1].v_type != VAR_UNKNOWN)
|
||||
{
|
||||
vim9script = tv_get_bool(&argvars[1]);
|
||||
cmdmod.cmod_flags &= ~(CMOD_VIM9CMD | CMOD_LEGACY);
|
||||
cmdmod.cmod_flags |= vim9script ? CMOD_VIM9CMD : CMOD_LEGACY;
|
||||
}
|
||||
|
||||
while (*name == ':')
|
||||
name++;
|
||||
name = skip_range(name, TRUE, NULL);
|
||||
@@ -4075,10 +4086,13 @@ f_fullcommand(typval_T *argvars, typval_T *rettv)
|
||||
ea.cmd = (*name == '2' || *name == '3') ? name + 1 : name;
|
||||
ea.cmdidx = (cmdidx_T)0;
|
||||
ea.addr_count = 0;
|
||||
++emsg_silent; // don't complain about using "en" in Vim9 script
|
||||
p = find_ex_command(&ea, NULL, NULL, NULL);
|
||||
--emsg_silent;
|
||||
if (p == NULL || ea.cmdidx == CMD_SIZE)
|
||||
return;
|
||||
if (in_vim9script())
|
||||
goto theend;
|
||||
|
||||
if (vim9script)
|
||||
{
|
||||
int res;
|
||||
|
||||
@@ -4087,12 +4101,14 @@ f_fullcommand(typval_T *argvars, typval_T *rettv)
|
||||
--emsg_silent;
|
||||
|
||||
if (res == FAIL)
|
||||
return;
|
||||
goto theend;
|
||||
}
|
||||
|
||||
rettv->vval.v_string = vim_strsave(IS_USER_CMDIDX(ea.cmdidx)
|
||||
? get_user_command_name(ea.useridx, ea.cmdidx)
|
||||
: cmdnames[ea.cmdidx].cmd_name);
|
||||
theend:
|
||||
cmdmod.cmod_flags = save_cmod_flags;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
+19
-9
@@ -470,19 +470,29 @@ check_top_offset(void)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update w_curswant.
|
||||
*/
|
||||
void
|
||||
update_curswant_force(void)
|
||||
{
|
||||
validate_virtcol();
|
||||
curwin->w_curswant = curwin->w_virtcol
|
||||
#ifdef FEAT_PROP_POPUP
|
||||
- curwin->w_virtcol_first_char
|
||||
#endif
|
||||
;
|
||||
curwin->w_set_curswant = FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update w_curswant if w_set_curswant is set.
|
||||
*/
|
||||
void
|
||||
update_curswant(void)
|
||||
{
|
||||
if (curwin->w_set_curswant)
|
||||
{
|
||||
validate_virtcol();
|
||||
curwin->w_curswant = curwin->w_virtcol
|
||||
#ifdef FEAT_PROP_POPUP
|
||||
- curwin->w_virtcol_first_char
|
||||
#endif
|
||||
;
|
||||
curwin->w_set_curswant = FALSE;
|
||||
}
|
||||
update_curswant_force();
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+29
-19
@@ -5503,9 +5503,8 @@ nv_visual(cmdarg_T *cap)
|
||||
{
|
||||
if (resel_VIsual_line_count <= 1)
|
||||
{
|
||||
validate_virtcol();
|
||||
curwin->w_curswant = curwin->w_virtcol
|
||||
+ resel_VIsual_vcol * cap->count0 - 1;
|
||||
update_curswant_force();
|
||||
curwin->w_curswant += resel_VIsual_vcol * cap->count0 - 1;
|
||||
}
|
||||
else
|
||||
curwin->w_curswant = resel_VIsual_vcol;
|
||||
@@ -5518,9 +5517,8 @@ nv_visual(cmdarg_T *cap)
|
||||
}
|
||||
else if (VIsual_mode == Ctrl_V)
|
||||
{
|
||||
validate_virtcol();
|
||||
curwin->w_curswant = curwin->w_virtcol
|
||||
+ resel_VIsual_vcol * cap->count0 - 1;
|
||||
update_curswant_force();
|
||||
curwin->w_curswant += + resel_VIsual_vcol * cap->count0 - 1;
|
||||
coladvance(curwin->w_curswant);
|
||||
}
|
||||
else
|
||||
@@ -5747,13 +5745,19 @@ nv_g_home_m_cmd(cmdarg_T *cap)
|
||||
cap->oap->inclusive = FALSE;
|
||||
if (curwin->w_p_wrap && curwin->w_width != 0)
|
||||
{
|
||||
int width1 = curwin->w_width - curwin_col_off();
|
||||
int width2 = width1 + curwin_col_off2();
|
||||
int width1 = curwin->w_width - curwin_col_off();
|
||||
int width2 = width1 + curwin_col_off2();
|
||||
int virtcol;
|
||||
|
||||
validate_virtcol();
|
||||
virtcol = curwin->w_virtcol
|
||||
#ifdef FEAT_PROP_POPUP
|
||||
- curwin->w_virtcol_first_char
|
||||
#endif
|
||||
;
|
||||
i = 0;
|
||||
if (curwin->w_virtcol >= (colnr_T)width1 && width2 > 0)
|
||||
i = (curwin->w_virtcol - width1) / width2 * width2 + width1;
|
||||
if (virtcol >= (colnr_T)width1 && width2 > 0)
|
||||
i = (virtcol - width1) / width2 * width2 + width1;
|
||||
}
|
||||
else
|
||||
i = curwin->w_leftcol;
|
||||
@@ -5827,24 +5831,32 @@ nv_g_dollar_cmd(cmdarg_T *cap)
|
||||
{
|
||||
int width1 = curwin->w_width - col_off;
|
||||
int width2 = width1 + curwin_col_off2();
|
||||
int virtcol;
|
||||
|
||||
validate_virtcol();
|
||||
virtcol = curwin->w_virtcol
|
||||
#ifdef FEAT_PROP_POPUP
|
||||
- curwin->w_virtcol_first_char
|
||||
#endif
|
||||
;
|
||||
i = width1 - 1;
|
||||
if (curwin->w_virtcol >= (colnr_T)width1)
|
||||
i += ((curwin->w_virtcol - width1) / width2 + 1)
|
||||
if (virtcol >= (colnr_T)width1)
|
||||
i += ((virtcol - width1) / width2 + 1)
|
||||
* width2;
|
||||
coladvance((colnr_T)i);
|
||||
|
||||
// Make sure we stick in this column.
|
||||
validate_virtcol();
|
||||
curwin->w_curswant = curwin->w_virtcol;
|
||||
curwin->w_set_curswant = FALSE;
|
||||
update_curswant_force();
|
||||
if (curwin->w_cursor.col > 0 && curwin->w_p_wrap)
|
||||
{
|
||||
// Check for landing on a character that got split at
|
||||
// the end of the line. We do not want to advance to
|
||||
// the next screen line.
|
||||
if (curwin->w_virtcol > (colnr_T)i)
|
||||
if (curwin->w_virtcol
|
||||
#ifdef FEAT_PROP_POPUP
|
||||
- curwin->w_virtcol_first_char
|
||||
#endif
|
||||
> (colnr_T)i)
|
||||
--curwin->w_cursor.col;
|
||||
}
|
||||
}
|
||||
@@ -5872,9 +5884,7 @@ nv_g_dollar_cmd(cmdarg_T *cap)
|
||||
}
|
||||
|
||||
// Make sure we stick in this column.
|
||||
validate_virtcol();
|
||||
curwin->w_curswant = curwin->w_virtcol;
|
||||
curwin->w_set_curswant = FALSE;
|
||||
update_curswant_force();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1173,6 +1173,8 @@ op_replace(oparg_T *oap, int c)
|
||||
|
||||
while (LTOREQ_POS(curwin->w_cursor, oap->end))
|
||||
{
|
||||
int done = FALSE;
|
||||
|
||||
n = gchar_cursor();
|
||||
if (n != NUL)
|
||||
{
|
||||
@@ -1186,6 +1188,7 @@ op_replace(oparg_T *oap, int c)
|
||||
if (curwin->w_cursor.lnum == oap->end.lnum)
|
||||
oap->end.col += new_byte_len - old_byte_len;
|
||||
replace_character(c);
|
||||
done = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1204,10 +1207,15 @@ op_replace(oparg_T *oap, int c)
|
||||
if (curwin->w_cursor.lnum == oap->end.lnum)
|
||||
getvpos(&oap->end, end_vcol);
|
||||
}
|
||||
PBYTE(curwin->w_cursor, c);
|
||||
// with "coladd" set may move to just after a TAB
|
||||
if (gchar_cursor() != NUL)
|
||||
{
|
||||
PBYTE(curwin->w_cursor, c);
|
||||
done = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (virtual_op && curwin->w_cursor.lnum == oap->end.lnum)
|
||||
if (!done && virtual_op && curwin->w_cursor.lnum == oap->end.lnum)
|
||||
{
|
||||
int virtcols = oap->end.coladd;
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
void redraw_for_cursorline(win_T *wp);
|
||||
void update_topline_redraw(void);
|
||||
void update_topline(void);
|
||||
void update_curswant_force(void);
|
||||
void update_curswant(void);
|
||||
void check_cursor_moved(win_T *wp);
|
||||
void changed_window_setting(void);
|
||||
|
||||
@@ -16,7 +16,7 @@ int func_is_global(ufunc_T *ufunc);
|
||||
int func_requires_g_prefix(ufunc_T *ufunc);
|
||||
int func_name_refcount(char_u *name);
|
||||
void func_clear_free(ufunc_T *fp, int force);
|
||||
int copy_func(char_u *lambda, char_u *global, ectx_T *ectx);
|
||||
int copy_lambda_to_global_func(char_u *lambda, char_u *global, short loop_var_idx, short loop_var_count, ectx_T *ectx);
|
||||
int funcdepth_increment(void);
|
||||
void funcdepth_decrement(void);
|
||||
int funcdepth_get(void);
|
||||
|
||||
@@ -11,6 +11,8 @@ char_u *compile_for(char_u *arg_start, cctx_T *cctx);
|
||||
char_u *compile_endfor(char_u *arg, cctx_T *cctx);
|
||||
char_u *compile_while(char_u *arg, cctx_T *cctx);
|
||||
char_u *compile_endwhile(char_u *arg, cctx_T *cctx);
|
||||
short get_loop_var_info(cctx_T *cctx, short *loop_var_idx);
|
||||
int get_loop_var_idx(cctx_T *cctx);
|
||||
char_u *compile_continue(char_u *arg, cctx_T *cctx);
|
||||
char_u *compile_break(char_u *arg, cctx_T *cctx);
|
||||
char_u *compile_block(char_u *arg, cctx_T *cctx);
|
||||
|
||||
@@ -9,7 +9,7 @@ void restore_current_ectx(ectx_T *ectx);
|
||||
int add_defer_function(char_u *name, int argcount, typval_T *argvars);
|
||||
char_u *char_from_string(char_u *str, varnumber_T index);
|
||||
char_u *string_slice(char_u *str, varnumber_T first, varnumber_T last, int exclusive);
|
||||
int fill_partial_and_closure(partial_T *pt, ufunc_T *ufunc, ectx_T *ectx);
|
||||
int fill_partial_and_closure(partial_T *pt, ufunc_T *ufunc, short loop_var_idx, short loop_var_count, ectx_T *ectx);
|
||||
int may_load_script(int sid, int *loaded);
|
||||
typval_T *lookup_debug_var(char_u *name);
|
||||
int may_break_in_function(ufunc_T *ufunc);
|
||||
|
||||
@@ -31,7 +31,7 @@ int generate_CHECKLEN(cctx_T *cctx, int min_len, int more_OK);
|
||||
int generate_STORE(cctx_T *cctx, isntype_T isn_type, int idx, char_u *name);
|
||||
int generate_STORENR(cctx_T *cctx, int idx, varnumber_T value);
|
||||
int generate_LOAD(cctx_T *cctx, isntype_T isn_type, int idx, char_u *name, type_T *type);
|
||||
int generate_LOADOUTER(cctx_T *cctx, int idx, int nesting, type_T *type);
|
||||
int generate_LOADOUTER(cctx_T *cctx, int idx, int nesting, int loop_idx, type_T *type);
|
||||
int generate_LOADV(cctx_T *cctx, char_u *name);
|
||||
int generate_UNLET(cctx_T *cctx, isntype_T isn_type, char_u *name, int forceit);
|
||||
int generate_LOCKCONST(cctx_T *cctx);
|
||||
@@ -40,7 +40,7 @@ int generate_VIM9SCRIPT(cctx_T *cctx, isntype_T isn_type, int sid, int idx, type
|
||||
int generate_NEWLIST(cctx_T *cctx, int count, int use_null);
|
||||
int generate_NEWDICT(cctx_T *cctx, int count, int use_null);
|
||||
int generate_FUNCREF(cctx_T *cctx, ufunc_T *ufunc, isn_T **isnp);
|
||||
int generate_NEWFUNC(cctx_T *cctx, char_u *lambda_name, char_u *func_name);
|
||||
int generate_NEWFUNC(cctx_T *cctx, char_u *lambda_name, char_u *func_name, short loop_var_idx, short loop_var_count);
|
||||
int generate_DEF(cctx_T *cctx, char_u *name, size_t len);
|
||||
int generate_JUMP(cctx_T *cctx, jumpwhen_T when, int where);
|
||||
int generate_WHILE(cctx_T *cctx, int funcref_idx);
|
||||
|
||||
+2
-2
@@ -1817,14 +1817,14 @@ static regsubmatch_T rsm; // can only be used when can_f_submatch is TRUE
|
||||
* call_func() by vim_regsub_both().
|
||||
*/
|
||||
static int
|
||||
fill_submatch_list(int argc UNUSED, typval_T *argv, int argskip, int argcount)
|
||||
fill_submatch_list(int argc UNUSED, typval_T *argv, int argskip, ufunc_T *fp)
|
||||
{
|
||||
listitem_T *li;
|
||||
int i;
|
||||
char_u *s;
|
||||
typval_T *listarg = argv + argskip;
|
||||
|
||||
if (argcount == argskip)
|
||||
if (!has_varargs(fp) && fp->uf_args.ga_len <= argskip)
|
||||
// called function doesn't take a submatches argument
|
||||
return argskip;
|
||||
|
||||
|
||||
+15
-7
@@ -1656,7 +1656,7 @@ typedef enum {
|
||||
|
||||
/*
|
||||
* Structure to hold info for a user function.
|
||||
* When adding a field check copy_func().
|
||||
* When adding a field check copy_lambda_to_global_func().
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
@@ -1741,7 +1741,8 @@ typedef struct
|
||||
#define FC_NOARGS 0x200 // no a: variables in lambda
|
||||
#define FC_VIM9 0x400 // defined in vim9 script file
|
||||
#define FC_CFUNC 0x800 // defined as Lua C func
|
||||
#define FC_COPY 0x1000 // copy of another function by copy_func()
|
||||
#define FC_COPY 0x1000 // copy of another function by
|
||||
// copy_lambda_to_global_func()
|
||||
#define FC_LAMBDA 0x2000 // one line "return {expr}"
|
||||
|
||||
#define MAX_FUNC_ARGS 20 // maximum number of function arguments
|
||||
@@ -2052,13 +2053,13 @@ typedef struct
|
||||
|
||||
// Struct passed between functions dealing with function call execution.
|
||||
//
|
||||
// "argv_func", when not NULL, can be used to fill in arguments only when the
|
||||
// "fe_argv_func", when not NULL, can be used to fill in arguments only when the
|
||||
// invoked function uses them. It is called like this:
|
||||
// new_argcount = argv_func(current_argcount, argv, partial_argcount,
|
||||
// called_func_argcount)
|
||||
// new_argcount = fe_argv_func(current_argcount, argv, partial_argcount,
|
||||
// called_func)
|
||||
//
|
||||
typedef struct {
|
||||
int (* fe_argv_func)(int, typval_T *, int, int);
|
||||
int (* fe_argv_func)(int, typval_T *, int, ufunc_T *);
|
||||
linenr_T fe_firstline; // first line of range
|
||||
linenr_T fe_lastline; // last line of range
|
||||
int *fe_doesrange; // if not NULL: return: function handled range
|
||||
@@ -2096,10 +2097,17 @@ struct funcstack_S
|
||||
|
||||
typedef struct outer_S outer_T;
|
||||
struct outer_S {
|
||||
garray_T *out_stack; // stack from outer scope
|
||||
garray_T *out_stack; // stack from outer scope, or a copy
|
||||
// containing only arguments and local vars
|
||||
int out_frame_idx; // index of stack frame in out_stack
|
||||
outer_T *out_up; // outer scope of outer scope or NULL
|
||||
partial_T *out_up_partial; // partial owning out_up or NULL
|
||||
|
||||
garray_T *out_loop_stack; // stack from outer scope, or a copy
|
||||
// containing only vars inside the loop
|
||||
short out_loop_var_idx; // first variable defined in a loop
|
||||
// in out_loop_stack
|
||||
short out_loop_var_count; // number of variables defined in a loop
|
||||
};
|
||||
|
||||
struct partial_S
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
|f+0&#ffff4012|i|r|s|t| |t|h|i|n|g| |a|b|o|v|e| @42
|
||||
|s+0&#ffd7ff255|e|c|o|n|d| |t|h|i|n|g| |a|b|o|v|e| @41
|
||||
|o+0&#ffffff0|n|e| |t|w>o| @52
|
||||
|t|h|r|e@1| |f|o|u|r| @49
|
||||
@3|a+0&#ffff4012|n|o|t|h|e|r| |t|h|i|n|g| @43
|
||||
|f+0&#ffffff0|i|v|e| |s|i|x| @51
|
||||
|~+0#4040ff13&| @58
|
||||
|~| @58
|
||||
| +0#0000000&@41|1|,|7|-|1|2|7| @6|A|l@1|
|
||||
@@ -0,0 +1,9 @@
|
||||
|f+0&#ffff4012|i|r|s|t| |t|h|i|n|g| |a|b|o|v|e| @42
|
||||
|s+0&#ffd7ff255|e|c|o|n|d| |t|h|i|n|g| |a|b|o|v|e| @41
|
||||
>o+0&#ffffff0|n|e| |t|w|o| @52
|
||||
|t|h|r|e@1| |f|o|u|r| @49
|
||||
@3|a+0&#ffff4012|n|o|t|h|e|r| |t|h|i|n|g| @43
|
||||
|f+0&#ffffff0|i|v|e| |s|i|x| @51
|
||||
|~+0#4040ff13&| @58
|
||||
|~| @58
|
||||
| +0#0000000&@41|1|,|1|-|1|2|1| @6|A|l@1|
|
||||
@@ -662,6 +662,9 @@ func Test_fullcommand()
|
||||
\ '3match': 'match',
|
||||
\ 'aboveleft': 'aboveleft',
|
||||
\ 'abo': 'aboveleft',
|
||||
\ 'en': 'endif',
|
||||
\ 'end': 'endif',
|
||||
\ 'endi': 'endif',
|
||||
\ 's': 'substitute',
|
||||
\ '5s': 'substitute',
|
||||
\ ':5s': 'substitute',
|
||||
|
||||
@@ -595,6 +595,7 @@ let s:filename_checks = {
|
||||
\ 'usw2kagtlog': ['usw2kagt.log', 'USW2KAGT.LOG', 'usw2kagt.file.log', 'USW2KAGT.FILE.LOG', 'file.usw2kagt.log', 'FILE.USW2KAGT.LOG'],
|
||||
\ 'vala': ['file.vala'],
|
||||
\ 'vb': ['file.sba', 'file.vb', 'file.vbs', 'file.dsm', 'file.ctl'],
|
||||
\ 'vdf': ['file.vdf'],
|
||||
\ 'vdmpp': ['file.vpp', 'file.vdmpp'],
|
||||
\ 'vdmrt': ['file.vdmrt'],
|
||||
\ 'vdmsl': ['file.vdm', 'file.vdmsl'],
|
||||
|
||||
@@ -439,20 +439,28 @@ endfunc
|
||||
func SubReplacer(text, submatches)
|
||||
return a:text .. a:submatches[0] .. a:text
|
||||
endfunc
|
||||
func SubReplacerVar(text, ...)
|
||||
return a:text .. a:1[0] .. a:text
|
||||
endfunc
|
||||
def SubReplacerVar9(text: string, ...args: list<list<string>>): string
|
||||
return text .. args[0][0] .. text
|
||||
enddef
|
||||
func SubReplacer20(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18, t19, submatches)
|
||||
return a:t3 .. a:submatches[0] .. a:t11
|
||||
endfunc
|
||||
|
||||
func Test_substitute_partial()
|
||||
call assert_equal('1foo2foo3', substitute('123', '2', function('SubReplacer', ['foo']), 'g'))
|
||||
call assert_equal('1foo2foo3', substitute('123', '2', function('SubReplacer', ['foo']), 'g'))
|
||||
call assert_equal('1foo2foo3', substitute('123', '2', function('SubReplacerVar', ['foo']), 'g'))
|
||||
call assert_equal('1foo2foo3', substitute('123', '2', function('SubReplacerVar9', ['foo']), 'g'))
|
||||
|
||||
" 19 arguments plus one is just OK
|
||||
let Replacer = function('SubReplacer20', repeat(['foo'], 19))
|
||||
call assert_equal('1foo2foo3', substitute('123', '2', Replacer, 'g'))
|
||||
" 19 arguments plus one is just OK
|
||||
let Replacer = function('SubReplacer20', repeat(['foo'], 19))
|
||||
call assert_equal('1foo2foo3', substitute('123', '2', Replacer, 'g'))
|
||||
|
||||
" 20 arguments plus one is too many
|
||||
let Replacer = function('SubReplacer20', repeat(['foo'], 20))
|
||||
call assert_fails("call substitute('123', '2', Replacer, 'g')", 'E118:')
|
||||
" 20 arguments plus one is too many
|
||||
let Replacer = function('SubReplacer20', repeat(['foo'], 20))
|
||||
call assert_fails("call substitute('123', '2', Replacer, 'g')", 'E118:')
|
||||
endfunc
|
||||
|
||||
func Test_substitute_float()
|
||||
|
||||
@@ -2869,6 +2869,11 @@ func Test_props_with_text_above()
|
||||
let buf = RunVimInTerminal('-S XscriptPropsWithTextAbove', #{rows: 9, cols: 60})
|
||||
call VerifyScreenDump(buf, 'Test_prop_with_text_above_1', {})
|
||||
|
||||
call term_sendkeys(buf, "ggg$")
|
||||
call VerifyScreenDump(buf, 'Test_prop_with_text_above_1a', {})
|
||||
call term_sendkeys(buf, "g0")
|
||||
call VerifyScreenDump(buf, 'Test_prop_with_text_above_1b', {})
|
||||
|
||||
call term_sendkeys(buf, "ggI")
|
||||
call VerifyScreenDump(buf, 'Test_prop_with_text_above_2', {})
|
||||
call term_sendkeys(buf, "inserted \<Esc>")
|
||||
|
||||
@@ -1530,6 +1530,13 @@ def Test_fullcommand()
|
||||
assert_equal('scriptnames', fullcommand('scr'))
|
||||
assert_equal('', fullcommand('scg'))
|
||||
fullcommand('')->assert_equal('')
|
||||
|
||||
assert_equal('', fullcommand('en'))
|
||||
legacy call assert_equal('endif', fullcommand('en'))
|
||||
assert_equal('endif', fullcommand('en', 0))
|
||||
legacy call assert_equal('endif', fullcommand('en', 0))
|
||||
assert_equal('', fullcommand('en', 1))
|
||||
legacy call assert_equal('', fullcommand('en', 1))
|
||||
enddef
|
||||
|
||||
def Test_funcref()
|
||||
|
||||
@@ -400,11 +400,10 @@ def Test_block_local_vars()
|
||||
|
||||
# need to execute this with a separate Vim instance to avoid the current
|
||||
# context gets garbage collected.
|
||||
writefile(lines, 'Xscript')
|
||||
writefile(lines, 'Xscript', 'D')
|
||||
g:RunVim([], [], '-S Xscript')
|
||||
assert_equal(['ok'], readfile('Xdidit'))
|
||||
|
||||
delete('Xscript')
|
||||
delete('Xdidit')
|
||||
enddef
|
||||
|
||||
@@ -991,13 +990,12 @@ def Test_cnext_works_in_catch()
|
||||
writefile([getqflist({idx: 0}).idx], 'Xcncresult')
|
||||
qall
|
||||
END
|
||||
writefile(lines, 'XCatchCnext')
|
||||
writefile(lines, 'XCatchCnext', 'D')
|
||||
g:RunVim([], [], '--clean -S XCatchCnext')
|
||||
assert_equal(['1'], readfile('Xcncresult'))
|
||||
|
||||
delete('Xcncfile1')
|
||||
delete('Xcncfile2')
|
||||
delete('XCatchCnext')
|
||||
delete('Xcncresult')
|
||||
enddef
|
||||
|
||||
@@ -1015,9 +1013,8 @@ def Test_nocatch_throw_silenced()
|
||||
enddef
|
||||
silent! Func()
|
||||
END
|
||||
writefile(lines, 'XthrowSilenced')
|
||||
writefile(lines, 'XthrowSilenced', 'D')
|
||||
source XthrowSilenced
|
||||
delete('XthrowSilenced')
|
||||
enddef
|
||||
|
||||
def DeletedFunc(): list<any>
|
||||
@@ -1473,7 +1470,7 @@ def Test_vim9script_reload_delfunc()
|
||||
END
|
||||
|
||||
# FuncNo() is defined
|
||||
writefile(first_lines + withno_lines, 'Xreloaded.vim')
|
||||
writefile(first_lines + withno_lines, 'Xreloaded.vim', 'D')
|
||||
source Xreloaded.vim
|
||||
g:DoCheck(true)
|
||||
|
||||
@@ -1486,8 +1483,6 @@ def Test_vim9script_reload_delfunc()
|
||||
writefile(first_lines + withno_lines, 'Xreloaded.vim')
|
||||
source Xreloaded.vim
|
||||
g:DoCheck(false)
|
||||
|
||||
delete('Xreloaded.vim')
|
||||
enddef
|
||||
|
||||
def Test_vim9script_reload_delvar()
|
||||
@@ -1496,7 +1491,7 @@ def Test_vim9script_reload_delvar()
|
||||
vim9script
|
||||
var name = 'string'
|
||||
END
|
||||
writefile(lines, 'XreloadVar.vim')
|
||||
writefile(lines, 'XreloadVar.vim', 'D')
|
||||
source XreloadVar.vim
|
||||
|
||||
# now write the script using the same variable locally - works
|
||||
@@ -1508,8 +1503,6 @@ def Test_vim9script_reload_delvar()
|
||||
END
|
||||
writefile(lines, 'XreloadVar.vim')
|
||||
source XreloadVar.vim
|
||||
|
||||
delete('XreloadVar.vim')
|
||||
enddef
|
||||
|
||||
def Test_func_redefine_error()
|
||||
@@ -1520,7 +1513,7 @@ def Test_func_redefine_error()
|
||||
'enddef',
|
||||
'Func()',
|
||||
]
|
||||
writefile(lines, 'Xtestscript.vim')
|
||||
writefile(lines, 'Xtestscript.vim', 'D')
|
||||
|
||||
for count in range(3)
|
||||
try
|
||||
@@ -1531,8 +1524,6 @@ def Test_func_redefine_error()
|
||||
assert_match('function <SNR>\d\+_Func, line 1', v:throwpoint)
|
||||
endtry
|
||||
endfor
|
||||
|
||||
delete('Xtestscript.vim')
|
||||
enddef
|
||||
|
||||
def Test_func_redefine_fails()
|
||||
@@ -2035,9 +2026,8 @@ def Test_for_outside_of_function()
|
||||
endfor
|
||||
assert_equal(' loop 1 loop 2 loop 3', result)
|
||||
END
|
||||
writefile(lines, 'Xvim9for.vim')
|
||||
writefile(lines, 'Xvim9for.vim', 'D')
|
||||
source Xvim9for.vim
|
||||
delete('Xvim9for.vim')
|
||||
enddef
|
||||
|
||||
def Test_for_skipped_block()
|
||||
@@ -2271,6 +2261,18 @@ def Test_for_loop_with_closure()
|
||||
END
|
||||
v9.CheckDefAndScriptSuccess(lines)
|
||||
|
||||
# also works when the loop variable is used only once halfway the loops
|
||||
lines =<< trim END
|
||||
var Clo: func
|
||||
for i in range(5)
|
||||
if i == 3
|
||||
Clo = () => i
|
||||
endif
|
||||
endfor
|
||||
assert_equal(4, Clo())
|
||||
END
|
||||
v9.CheckDefAndScriptSuccess(lines)
|
||||
|
||||
# using a local variable set to the loop variable in a closure results in the
|
||||
# value at that moment
|
||||
lines =<< trim END
|
||||
@@ -3330,12 +3332,11 @@ def Test_finish()
|
||||
finish
|
||||
g:res = 'three'
|
||||
END
|
||||
writefile(lines, 'Xfinished')
|
||||
writefile(lines, 'Xfinished', 'D')
|
||||
source Xfinished
|
||||
assert_equal('two', g:res)
|
||||
|
||||
unlet g:res
|
||||
delete('Xfinished')
|
||||
enddef
|
||||
|
||||
def Test_forward_declaration()
|
||||
@@ -3349,14 +3350,13 @@ def Test_forward_declaration()
|
||||
theVal = 'else'
|
||||
g:laterVal = GetValue()
|
||||
END
|
||||
writefile(lines, 'Xforward')
|
||||
writefile(lines, 'Xforward', 'D')
|
||||
source Xforward
|
||||
assert_equal('something', g:initVal)
|
||||
assert_equal('else', g:laterVal)
|
||||
|
||||
unlet g:initVal
|
||||
unlet g:laterVal
|
||||
delete('Xforward')
|
||||
enddef
|
||||
|
||||
def Test_declare_script_var_in_func()
|
||||
@@ -3408,7 +3408,7 @@ func Test_vim9script_not_global()
|
||||
echo 'local'
|
||||
enddef
|
||||
END
|
||||
call writefile(vim9lines, 'Xvim9script.vim')
|
||||
call writefile(vim9lines, 'Xvim9script.vim', 'D')
|
||||
source Xvim9script.vim
|
||||
try
|
||||
echo g:var
|
||||
@@ -3428,8 +3428,6 @@ func Test_vim9script_not_global()
|
||||
catch /E117:/
|
||||
" caught
|
||||
endtry
|
||||
|
||||
call delete('Xvim9script.vim')
|
||||
endfunc
|
||||
|
||||
def Test_vim9_copen()
|
||||
@@ -3459,7 +3457,7 @@ def Test_error_in_autoload_script()
|
||||
var save_rtp = &rtp
|
||||
var dir = getcwd() .. '/Xruntime'
|
||||
&rtp = dir
|
||||
mkdir(dir .. '/autoload', 'p')
|
||||
mkdir(dir .. '/autoload', 'pR')
|
||||
|
||||
var lines =<< trim END
|
||||
vim9script noclear
|
||||
@@ -3492,12 +3490,11 @@ def Test_error_in_autoload_script()
|
||||
v9.CheckScriptSuccess(lines)
|
||||
|
||||
&rtp = save_rtp
|
||||
delete(dir, 'rf')
|
||||
enddef
|
||||
|
||||
def Test_error_in_autoload_script_foldexpr()
|
||||
var save_rtp = &rtp
|
||||
mkdir('Xvim/autoload', 'p')
|
||||
mkdir('Xvim/autoload', 'pR')
|
||||
&runtimepath = 'Xvim'
|
||||
|
||||
var lines =<< trim END
|
||||
@@ -3515,8 +3512,6 @@ def Test_error_in_autoload_script_foldexpr()
|
||||
redraw
|
||||
END
|
||||
v9.CheckScriptFailure(lines, 'E684: List index out of range: 0')
|
||||
|
||||
delete('Xvim', 'rf')
|
||||
enddef
|
||||
|
||||
def Test_invalid_sid()
|
||||
@@ -3529,16 +3524,14 @@ def Test_invalid_sid()
|
||||
enddef
|
||||
|
||||
def Test_restoring_cpo()
|
||||
writefile(['vim9script', 'set nocp'], 'Xsourced')
|
||||
writefile(['call writefile(["done"], "Xdone")', 'quit!'], 'Xclose')
|
||||
writefile(['vim9script', 'set nocp'], 'Xsourced', 'D')
|
||||
writefile(['call writefile(["done"], "Xdone")', 'quit!'], 'Xclose', 'D')
|
||||
if g:RunVim([], [], '-u NONE +"set cpo+=a" -S Xsourced -S Xclose')
|
||||
assert_equal(['done'], readfile('Xdone'))
|
||||
endif
|
||||
delete('Xsourced')
|
||||
delete('Xclose')
|
||||
delete('Xdone')
|
||||
|
||||
writefile(['vim9script', 'g:cpoval = &cpo'], 'XanotherScript')
|
||||
writefile(['vim9script', 'g:cpoval = &cpo'], 'XanotherScript', 'D')
|
||||
set cpo=aABceFsMny>
|
||||
edit XanotherScript
|
||||
so %
|
||||
@@ -3551,7 +3544,6 @@ def Test_restoring_cpo()
|
||||
assert_equal('aABceFsMny>', &cpo)
|
||||
assert_equal('aABceFsMny>', g:cpoval)
|
||||
|
||||
delete('XanotherScript')
|
||||
set cpo&vim
|
||||
unlet g:cpoval
|
||||
|
||||
@@ -3559,7 +3551,7 @@ def Test_restoring_cpo()
|
||||
# 'cpo' is not restored in main vimrc
|
||||
var save_HOME = $HOME
|
||||
$HOME = getcwd() .. '/Xhome'
|
||||
mkdir('Xhome')
|
||||
mkdir('Xhome', 'R')
|
||||
var lines =<< trim END
|
||||
vim9script
|
||||
writefile(['before: ' .. &cpo], 'Xrporesult')
|
||||
@@ -3571,14 +3563,14 @@ def Test_restoring_cpo()
|
||||
lines =<< trim END
|
||||
call writefile(['later: ' .. &cpo], 'Xrporesult', 'a')
|
||||
END
|
||||
writefile(lines, 'Xlegacy')
|
||||
writefile(lines, 'Xlegacy', 'D')
|
||||
|
||||
lines =<< trim END
|
||||
vim9script
|
||||
call writefile(['vim9: ' .. &cpo], 'Xrporesult', 'a')
|
||||
qa
|
||||
END
|
||||
writefile(lines, 'Xvim9')
|
||||
writefile(lines, 'Xvim9', 'D')
|
||||
|
||||
var cmd = g:GetVimCommand() .. " -S Xlegacy -S Xvim9"
|
||||
cmd = substitute(cmd, '-u NONE', '', '')
|
||||
@@ -3591,9 +3583,6 @@ def Test_restoring_cpo()
|
||||
'vim9: aABceFs'], readfile('Xrporesult'))
|
||||
|
||||
$HOME = save_HOME
|
||||
delete('Xhome', 'rf')
|
||||
delete('Xlegacy')
|
||||
delete('Xvim9')
|
||||
delete('Xrporesult')
|
||||
endif
|
||||
enddef
|
||||
@@ -3611,7 +3600,7 @@ def Run_test_no_redraw_when_restoring_cpo()
|
||||
export def Func()
|
||||
enddef
|
||||
END
|
||||
mkdir('Xnordir/autoload', 'p')
|
||||
mkdir('Xnordir/autoload', 'pR')
|
||||
writefile(lines, 'Xnordir/autoload/script.vim')
|
||||
|
||||
lines =<< trim END
|
||||
@@ -3621,7 +3610,7 @@ def Run_test_no_redraw_when_restoring_cpo()
|
||||
au CmdlineEnter : ++once timer_start(0, (_) => script#Func())
|
||||
setline(1, 'some text')
|
||||
END
|
||||
writefile(lines, 'XTest_redraw_cpo')
|
||||
writefile(lines, 'XTest_redraw_cpo', 'D')
|
||||
var buf = g:RunVimInTerminal('-S XTest_redraw_cpo', {'rows': 6})
|
||||
term_sendkeys(buf, "V:")
|
||||
g:VerifyScreenDump(buf, 'Test_vim9_no_redraw', {})
|
||||
@@ -3629,8 +3618,6 @@ def Run_test_no_redraw_when_restoring_cpo()
|
||||
# clean up
|
||||
term_sendkeys(buf, "\<Esc>u")
|
||||
g:StopVimInTerminal(buf)
|
||||
delete('XTest_redraw_cpo')
|
||||
delete('Xnordir', 'rf')
|
||||
enddef
|
||||
|
||||
func Test_reject_declaration()
|
||||
@@ -3731,8 +3718,8 @@ def Run_Test_define_func_at_command_line()
|
||||
call writefile(['errors: ' .. string(v:errors)], 'Xdidcmd')
|
||||
endfunc
|
||||
END
|
||||
writefile([''], 'Xdidcmd')
|
||||
writefile(lines, 'XcallFunc')
|
||||
writefile([''], 'Xdidcmd', 'D')
|
||||
writefile(lines, 'XcallFunc', 'D')
|
||||
var buf = g:RunVimInTerminal('-S XcallFunc', {rows: 6})
|
||||
# define Afunc() on the command line
|
||||
term_sendkeys(buf, ":def Afunc()\<CR>Bfunc()\<CR>enddef\<CR>")
|
||||
@@ -3740,8 +3727,6 @@ def Run_Test_define_func_at_command_line()
|
||||
g:WaitForAssert(() => assert_equal(['errors: []'], readfile('Xdidcmd')))
|
||||
|
||||
call g:StopVimInTerminal(buf)
|
||||
delete('XcallFunc')
|
||||
delete('Xdidcmd')
|
||||
enddef
|
||||
|
||||
def Test_script_var_scope()
|
||||
@@ -3869,9 +3854,8 @@ def Test_no_unknown_error_after_error()
|
||||
sleep 10m
|
||||
endfor
|
||||
END
|
||||
writefile(lines, 'Xdef')
|
||||
writefile(lines, 'Xdef', 'D')
|
||||
assert_fails('so Xdef', ['E684:', 'E1012:'])
|
||||
delete('Xdef')
|
||||
enddef
|
||||
|
||||
def InvokeNormal()
|
||||
@@ -3914,7 +3898,7 @@ def Test_script_var_gone_when_sourced_twice()
|
||||
name = arg
|
||||
enddef
|
||||
END
|
||||
writefile(lines, 'XscriptTwice.vim')
|
||||
writefile(lines, 'XscriptTwice.vim', 'D')
|
||||
so XscriptTwice.vim
|
||||
assert_equal('thename', g:GetName())
|
||||
g:SetName('newname')
|
||||
@@ -3925,7 +3909,6 @@ def Test_script_var_gone_when_sourced_twice()
|
||||
|
||||
delfunc g:GetName
|
||||
delfunc g:SetName
|
||||
delete('XscriptTwice.vim')
|
||||
unlet g:guard
|
||||
enddef
|
||||
|
||||
@@ -4102,7 +4085,7 @@ def Run_Test_debug_with_lambda()
|
||||
breakadd func Func
|
||||
Func()
|
||||
END
|
||||
writefile(lines, 'XdebugFunc')
|
||||
writefile(lines, 'XdebugFunc', 'D')
|
||||
var buf = g:RunVimInTerminal('-S XdebugFunc', {rows: 6, wait_for_ruler: 0})
|
||||
g:WaitForAssert(() => assert_match('^>', term_getline(buf, 6)))
|
||||
|
||||
@@ -4110,7 +4093,6 @@ def Run_Test_debug_with_lambda()
|
||||
g:WaitForAssert(() => assert_match('\[0\]', term_getline(buf, 5)))
|
||||
|
||||
g:StopVimInTerminal(buf)
|
||||
delete('XdebugFunc')
|
||||
enddef
|
||||
|
||||
func Test_debug_running_out_of_lines()
|
||||
@@ -4138,7 +4120,7 @@ def Run_Test_debug_running_out_of_lines()
|
||||
breakadd func Crash
|
||||
Crash()
|
||||
END
|
||||
writefile(lines, 'XdebugFunc')
|
||||
writefile(lines, 'XdebugFunc', 'D')
|
||||
var buf = g:RunVimInTerminal('-S XdebugFunc', {rows: 6, wait_for_ruler: 0})
|
||||
g:WaitForAssert(() => assert_match('^>', term_getline(buf, 6)))
|
||||
|
||||
@@ -4150,7 +4132,6 @@ def Run_Test_debug_running_out_of_lines()
|
||||
g:TermWait(buf)
|
||||
|
||||
g:StopVimInTerminal(buf)
|
||||
delete('XdebugFunc')
|
||||
enddef
|
||||
|
||||
def Test_ambigous_command_error()
|
||||
@@ -4239,7 +4220,7 @@ def Test_profile_with_lambda()
|
||||
writefile([result], 'Xdidprofile')
|
||||
endtry
|
||||
END
|
||||
writefile(lines, 'Xprofile.vim')
|
||||
writefile(lines, 'Xprofile.vim', 'D')
|
||||
call system(g:GetVimCommand()
|
||||
.. ' --clean'
|
||||
.. ' -c "so Xprofile.vim"'
|
||||
@@ -4250,7 +4231,6 @@ def Test_profile_with_lambda()
|
||||
assert_true(filereadable('Xprofile.log'))
|
||||
delete('Xdidprofile')
|
||||
delete('Xprofile.log')
|
||||
delete('Xprofile.vim')
|
||||
enddef
|
||||
|
||||
func Test_misplaced_type()
|
||||
@@ -4323,10 +4303,8 @@ def Test_substitute_cmd()
|
||||
assert_equal('otherthing', getline(1))
|
||||
bwipe!
|
||||
END
|
||||
writefile(lines, 'Xvim9lines')
|
||||
writefile(lines, 'Xvim9lines', 'D')
|
||||
source Xvim9lines
|
||||
|
||||
delete('Xvim9lines')
|
||||
enddef
|
||||
|
||||
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
|
||||
|
||||
@@ -572,4 +572,18 @@ func Test_virtualedit_mouse()
|
||||
set virtualedit&
|
||||
endfunc
|
||||
|
||||
" this was replacing the NUL at the end of the line
|
||||
func Test_virtualedit_replace_after_tab()
|
||||
new
|
||||
s/\v/ 0
|
||||
set ve=all
|
||||
let @" = ''
|
||||
sil! norm vPvr0
|
||||
|
||||
call assert_equal("\t0", getline(1))
|
||||
set ve&
|
||||
bwipe!
|
||||
endfunc
|
||||
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
||||
+100
-107
@@ -1637,127 +1637,119 @@ endfunc
|
||||
func Test_splitscroll_with_splits()
|
||||
set nowrap
|
||||
set nosplitscroll
|
||||
|
||||
" disallow window resizing
|
||||
let save_WS = &t_WS
|
||||
set t_WS=
|
||||
|
||||
let gui = has("gui_running")
|
||||
inoremap c <cmd>:copen<CR>
|
||||
for winbar in [0, 1]
|
||||
for sb in [0, 1]
|
||||
for ea in [0, 1]
|
||||
for tab in [0, 1]
|
||||
for so in [0, 5]
|
||||
for ls in range(0, 2)
|
||||
for pos in ["H", "M", "L"]
|
||||
tabnew | tabonly! | redraw
|
||||
let tabline = (gui ? 0 : (tab ? 1 : 0))
|
||||
let winbar_sb = (sb ? winbar : 0)
|
||||
execute 'set scrolloff=' . so
|
||||
execute 'set laststatus=' . ls
|
||||
execute 'set ' . (ea ? 'equalalways' : 'noequalalways')
|
||||
execute 'set ' . (sb ? 'splitbelow' : 'nosplitbelow')
|
||||
execute tab ? 'tabnew' : ''
|
||||
execute winbar ? 'nnoremenu 1.10 WinBar.Test :echo' : ''
|
||||
call setline(1, range(1, 256))
|
||||
" No scroll for restore_snapshot
|
||||
norm G
|
||||
try
|
||||
copen | close | colder
|
||||
catch /E380/
|
||||
endtry
|
||||
call assert_equal(257 - winheight(0), line("w0"))
|
||||
inoremap <expr> c "<cmd>copen<bar>wincmd k<CR>"
|
||||
for run in range(0, 10)
|
||||
tabnew | tabonly! | redraw
|
||||
let tabline = (gui ? 0 : ((run % 5) ? 1 : 0))
|
||||
let winbar_sb = (run % 2) && (run % 3)
|
||||
execute 'set scrolloff=' . !(run % 3) ? 0 : run
|
||||
execute 'set laststatus=' . (run % 3)
|
||||
execute 'set ' . ((run % 2) ? 'equalalways' : 'noequalalways')
|
||||
execute 'set ' . ((run % 3) ? 'splitbelow' : 'nosplitbelow')
|
||||
execute (run % 5) ? 'tabnew' : ''
|
||||
execute (run % 2) ? 'nnoremenu 1.10 WinBar.Test :echo' : ''
|
||||
let pos = !(run % 3) ? 'H' : ((run % 2) ? 'M' : 'L')
|
||||
call setline(1, range(1, 256))
|
||||
" No scroll for restore_snapshot
|
||||
norm G
|
||||
try
|
||||
copen | close | colder
|
||||
catch /E380/
|
||||
endtry
|
||||
call assert_equal(257 - winheight(0), line("w0"))
|
||||
|
||||
" No scroll for firstwin horizontal split
|
||||
execute 'norm gg' . pos
|
||||
split | redraw | wincmd k
|
||||
call assert_equal(1, line("w0"))
|
||||
call assert_equal(&scroll, winheight(0) / 2)
|
||||
wincmd j
|
||||
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0"))
|
||||
" No scroll for firstwin horizontal split
|
||||
execute 'norm gg' . pos
|
||||
split | redraw | wincmd k
|
||||
call assert_equal(1, line("w0"))
|
||||
call assert_equal(&scroll, winheight(0) / 2)
|
||||
wincmd j
|
||||
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0"))
|
||||
|
||||
" No scroll when resizing windows
|
||||
wincmd k | resize +2
|
||||
call assert_equal(1, line("w0"))
|
||||
wincmd j
|
||||
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0"))
|
||||
" No scroll when resizing windows
|
||||
wincmd k | resize +2
|
||||
call assert_equal(1, line("w0"))
|
||||
wincmd j
|
||||
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0"))
|
||||
|
||||
" No scroll when dragging statusline
|
||||
call win_move_statusline(1, -3)
|
||||
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0"))
|
||||
wincmd k
|
||||
call assert_equal(1, line("w0"))
|
||||
" No scroll when dragging statusline
|
||||
call win_move_statusline(1, -3)
|
||||
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, 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(win_screenpos(0)[0] - tabline - winbar_sb, line("w0"))
|
||||
set lines-=2
|
||||
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, 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(win_screenpos(0)[0] - tabline - winbar_sb, line("w0"))
|
||||
set lines-=2
|
||||
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, 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(win_screenpos(0)[0] - tabline - winbar_sb, 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(win_screenpos(0)[0] - tabline - winbar_sb, line("w0"))
|
||||
wincmd k
|
||||
call assert_equal(1, line("w0"))
|
||||
|
||||
" No scroll in windows split multiple times
|
||||
vsplit | split | 4wincmd w
|
||||
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0"))
|
||||
1wincmd w | quit | wincmd l | split
|
||||
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0"))
|
||||
wincmd j
|
||||
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0"))
|
||||
" No scroll in windows split multiple times
|
||||
vsplit | split | 4wincmd w
|
||||
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0"))
|
||||
1wincmd w | quit | wincmd l | split
|
||||
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0"))
|
||||
wincmd j
|
||||
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0"))
|
||||
|
||||
" No scroll in small window
|
||||
2wincmd w | only | 5split | wincmd k
|
||||
call assert_equal(1, line("w0"))
|
||||
wincmd j
|
||||
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0"))
|
||||
" No scroll in small window
|
||||
2wincmd w | only | 5split | wincmd k
|
||||
call assert_equal(1, line("w0"))
|
||||
wincmd j
|
||||
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0"))
|
||||
|
||||
" No scroll for vertical split
|
||||
quit | vsplit | wincmd l
|
||||
call assert_equal(1, line("w0"))
|
||||
wincmd h
|
||||
call assert_equal(1, line("w0"))
|
||||
" No scroll for vertical split
|
||||
quit | vsplit | wincmd l
|
||||
call assert_equal(1, line("w0"))
|
||||
wincmd h
|
||||
call assert_equal(1, line("w0"))
|
||||
|
||||
" No scroll in windows split and quit multiple times
|
||||
quit | redraw | split | redraw | split | redraw | quit | redraw
|
||||
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0"))
|
||||
" No scroll in windows split and quit multiple times
|
||||
quit | redraw | split | redraw | split | redraw | quit | redraw
|
||||
call assert_equal(win_screenpos(0)[0] - tabline - winbar_sb, line("w0"))
|
||||
|
||||
" No scroll for new buffer
|
||||
1wincmd w | only | copen | wincmd k
|
||||
call assert_equal(1, line("w0"))
|
||||
only
|
||||
call assert_equal(1, line("w0"))
|
||||
above copen | wincmd j
|
||||
call assert_equal(win_screenpos(0)[0] - tabline, line("w0"))
|
||||
" No scroll for new buffer
|
||||
1wincmd w | only | copen | wincmd k
|
||||
call assert_equal(1, line("w0"))
|
||||
only
|
||||
call assert_equal(1, line("w0"))
|
||||
above copen | wincmd j
|
||||
call assert_equal(win_screenpos(0)[0] - tabline, line("w0"))
|
||||
|
||||
" No scroll when opening cmdwin, and no cursor move when closing
|
||||
" cmdwin.
|
||||
only | norm ggL
|
||||
let curpos = getcurpos()
|
||||
norm q:
|
||||
call assert_equal(1, line("w0"))
|
||||
call assert_equal(curpos, getcurpos())
|
||||
" No scroll when opening cmdwin, and no cursor move when closing cmdwin.
|
||||
only | norm ggL
|
||||
let curpos = getcurpos()
|
||||
norm q:
|
||||
call assert_equal(1, line("w0"))
|
||||
call assert_equal(curpos, getcurpos())
|
||||
|
||||
" Scroll when cursor becomes invalid in insert mode
|
||||
norm Lic
|
||||
wincmd k | only
|
||||
call assert_notequal(1, line("w0"))
|
||||
" Scroll when cursor becomes invalid in insert mode
|
||||
norm Lic
|
||||
call assert_equal(curpos, getcurpos())
|
||||
|
||||
" No scroll when topline not equal to 1
|
||||
execute "norm gg5\<C-e>" | split | wincmd k
|
||||
call assert_equal(6, line("w0"))
|
||||
wincmd j
|
||||
call assert_equal(5 + win_screenpos(0)[0] - tabline - winbar_sb, line("w0"))
|
||||
endfor
|
||||
endfor
|
||||
endfor
|
||||
endfor
|
||||
endfor
|
||||
endfor
|
||||
" No scroll when topline not equal to 1
|
||||
only | execute "norm gg5\<C-e>" | split | wincmd k
|
||||
call assert_equal(6, line("w0"))
|
||||
wincmd j
|
||||
call assert_equal(5 + win_screenpos(0)[0] - tabline - winbar_sb, line("w0"))
|
||||
endfor
|
||||
|
||||
tabnew | tabonly! | %bwipeout!
|
||||
@@ -1768,6 +1760,7 @@ func Test_splitscroll_with_splits()
|
||||
set laststatus&
|
||||
set equalalways&
|
||||
set splitscroll&
|
||||
let &t_WS = save_WS
|
||||
endfunc
|
||||
|
||||
function Test_nosplitscroll_cmdwin_cursor_position()
|
||||
|
||||
+9
-3
@@ -2452,7 +2452,12 @@ func_clear_free(ufunc_T *fp, int force)
|
||||
* This is for when a compiled function defines a global function.
|
||||
*/
|
||||
int
|
||||
copy_func(char_u *lambda, char_u *global, ectx_T *ectx)
|
||||
copy_lambda_to_global_func(
|
||||
char_u *lambda,
|
||||
char_u *global,
|
||||
short loop_var_idx,
|
||||
short loop_var_count,
|
||||
ectx_T *ectx)
|
||||
{
|
||||
ufunc_T *ufunc = find_func_even_dead(lambda, FFED_IS_GLOBAL);
|
||||
ufunc_T *fp = NULL;
|
||||
@@ -2519,7 +2524,8 @@ copy_func(char_u *lambda, char_u *global, ectx_T *ectx)
|
||||
|
||||
if (pt == NULL)
|
||||
goto failed;
|
||||
if (fill_partial_and_closure(pt, ufunc, ectx) == FAIL)
|
||||
if (fill_partial_and_closure(pt, ufunc, loop_var_idx, loop_var_count,
|
||||
ectx) == FAIL)
|
||||
{
|
||||
vim_free(pt);
|
||||
goto failed;
|
||||
@@ -3644,7 +3650,7 @@ call_func(
|
||||
if (funcexe->fe_argv_func != NULL)
|
||||
// postponed filling in the arguments, do it now
|
||||
argcount = funcexe->fe_argv_func(argcount, argvars,
|
||||
argv_clear, fp->uf_args.ga_len);
|
||||
argv_clear, fp);
|
||||
|
||||
if (funcexe->fe_basetv != NULL)
|
||||
{
|
||||
|
||||
@@ -718,6 +718,28 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
483,
|
||||
/**/
|
||||
482,
|
||||
/**/
|
||||
481,
|
||||
/**/
|
||||
480,
|
||||
/**/
|
||||
479,
|
||||
/**/
|
||||
478,
|
||||
/**/
|
||||
477,
|
||||
/**/
|
||||
476,
|
||||
/**/
|
||||
475,
|
||||
/**/
|
||||
474,
|
||||
/**/
|
||||
473,
|
||||
/**/
|
||||
472,
|
||||
/**/
|
||||
|
||||
+20
-4
@@ -354,16 +354,29 @@ typedef struct {
|
||||
int ul_forceit; // forceit flag
|
||||
} unlet_T;
|
||||
|
||||
// extra arguments for funcref_T
|
||||
typedef struct {
|
||||
char_u *fre_func_name; // function name for legacy function
|
||||
short fre_loop_var_idx; // index of first variable inside loop
|
||||
short fre_loop_var_count; // number of variables inside loop
|
||||
} funcref_extra_T;
|
||||
|
||||
// arguments to ISN_FUNCREF
|
||||
typedef struct {
|
||||
int fr_dfunc_idx; // function index for :def function
|
||||
char_u *fr_func_name; // function name for legacy function
|
||||
int fr_dfunc_idx; // function index for :def function
|
||||
funcref_extra_T *fr_extra; // optional extra information
|
||||
} funcref_T;
|
||||
|
||||
// arguments to ISN_NEWFUNC
|
||||
typedef struct {
|
||||
char_u *nf_lambda; // name of the lambda already defined
|
||||
char_u *nf_global; // name of the global function to be created
|
||||
char_u *nfa_lambda; // name of the lambda already defined
|
||||
char_u *nfa_global; // name of the global function to be created
|
||||
short nfa_loop_var_idx; // index of first variable inside loop
|
||||
short nfa_loop_var_count; // number of variables inside loop
|
||||
} newfuncarg_T;
|
||||
|
||||
typedef struct {
|
||||
newfuncarg_T *nf_arg;
|
||||
} newfunc_T;
|
||||
|
||||
// arguments to ISN_CHECKLEN
|
||||
@@ -401,6 +414,8 @@ typedef struct {
|
||||
int outer_depth; // nesting level, stack frames to go up
|
||||
} isn_outer_T;
|
||||
|
||||
#define OUTER_LOOP_DEPTH -9 // used for outer_depth for loop variables
|
||||
|
||||
// arguments to ISN_SUBSTITUTE
|
||||
typedef struct {
|
||||
char_u *subs_cmd; // :s command
|
||||
@@ -677,6 +692,7 @@ typedef struct {
|
||||
char_u *lv_name;
|
||||
type_T *lv_type;
|
||||
int lv_idx; // index of the variable on the stack
|
||||
int lv_loop_idx; // index of first variable inside a loop or -1
|
||||
int lv_from_outer; // nesting level, using ctx_outer scope
|
||||
int lv_const; // when TRUE cannot be assigned to
|
||||
int lv_arg; // when TRUE this is an argument
|
||||
|
||||
@@ -1245,6 +1245,49 @@ compile_endwhile(char_u *arg, cctx_T *cctx)
|
||||
return arg;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the current information about variables declared inside a loop.
|
||||
* Returns zero if there are none, otherwise the count.
|
||||
* "loop_var_idx" is then set to the index of the first variable.
|
||||
*/
|
||||
short
|
||||
get_loop_var_info(cctx_T *cctx, short *loop_var_idx)
|
||||
{
|
||||
scope_T *scope = cctx->ctx_scope;
|
||||
int start_local_count;
|
||||
|
||||
while (scope != NULL && scope->se_type != WHILE_SCOPE
|
||||
&& scope->se_type != FOR_SCOPE)
|
||||
scope = scope->se_outer;
|
||||
if (scope == NULL)
|
||||
return 0;
|
||||
|
||||
if (scope->se_type == WHILE_SCOPE)
|
||||
start_local_count = scope->se_u.se_while.ws_local_count;
|
||||
else
|
||||
start_local_count = scope->se_u.se_for.fs_local_count;
|
||||
if (cctx->ctx_locals.ga_len > start_local_count)
|
||||
{
|
||||
*loop_var_idx = (short)start_local_count;
|
||||
return (short)(cctx->ctx_locals.ga_len - start_local_count);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the index of the first variable in a loop, if any.
|
||||
* Returns -1 if none.
|
||||
*/
|
||||
int
|
||||
get_loop_var_idx(cctx_T *cctx)
|
||||
{
|
||||
short loop_var_idx;
|
||||
|
||||
if (get_loop_var_info(cctx, &loop_var_idx) > 0)
|
||||
return loop_var_idx;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* compile "continue"
|
||||
*/
|
||||
|
||||
+4
-2
@@ -54,6 +54,7 @@ lookup_local(char_u *name, size_t len, lvar_T *lvar, cctx_T *cctx)
|
||||
{
|
||||
*lvar = *lvp;
|
||||
lvar->lv_from_outer = 0;
|
||||
lvar->lv_loop_idx = get_loop_var_idx(cctx);
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
@@ -954,7 +955,8 @@ compile_nested_function(exarg_T *eap, cctx_T *cctx, garray_T *lines_to_free)
|
||||
// recursive call.
|
||||
if (is_global)
|
||||
{
|
||||
r = generate_NEWFUNC(cctx, lambda_name, func_name);
|
||||
// TODO: loop variable index and count
|
||||
r = generate_NEWFUNC(cctx, lambda_name, func_name, 0, 0);
|
||||
func_name = NULL;
|
||||
lambda_name = NULL;
|
||||
}
|
||||
@@ -1193,7 +1195,7 @@ generate_loadvar(
|
||||
{
|
||||
if (lvar->lv_from_outer > 0)
|
||||
generate_LOADOUTER(cctx, lvar->lv_idx, lvar->lv_from_outer,
|
||||
type);
|
||||
lvar->lv_loop_idx, type);
|
||||
else
|
||||
generate_LOAD(cctx, ISN_LOAD, lvar->lv_idx, NULL, type);
|
||||
}
|
||||
|
||||
+93
-34
@@ -673,6 +673,9 @@ handle_closure_in_use(ectx_T *ectx, int free_arguments)
|
||||
if (closure_count == 0)
|
||||
return OK; // no funcrefs created
|
||||
|
||||
// Compute "top": the first entry in the stack used by the function.
|
||||
// This is the first argument (after that comes the stack frame and then
|
||||
// the local variables).
|
||||
argcount = ufunc_argcount(dfunc->df_ufunc);
|
||||
top = ectx->ec_frame_idx - argcount;
|
||||
|
||||
@@ -740,6 +743,7 @@ handle_closure_in_use(ectx_T *ectx, int free_arguments)
|
||||
else
|
||||
copy_tv(tv, stack + idx);
|
||||
}
|
||||
// Skip the stack frame.
|
||||
// Move the local variables.
|
||||
for (idx = 0; idx < dfunc->df_varcount; ++idx)
|
||||
{
|
||||
@@ -770,10 +774,17 @@ handle_closure_in_use(ectx_T *ectx, int free_arguments)
|
||||
- closure_count + idx];
|
||||
if (pt->pt_refcount > 1)
|
||||
{
|
||||
int prev_frame_idx = pt->pt_outer.out_frame_idx;
|
||||
|
||||
++funcstack->fs_refcount;
|
||||
pt->pt_funcstack = funcstack;
|
||||
pt->pt_outer.out_stack = &funcstack->fs_ga;
|
||||
pt->pt_outer.out_frame_idx = ectx->ec_frame_idx - top;
|
||||
|
||||
// TODO: drop this, should be done at ISN_ENDLOOP
|
||||
pt->pt_outer.out_loop_stack = &funcstack->fs_ga;
|
||||
pt->pt_outer.out_loop_var_idx -=
|
||||
prev_frame_idx - pt->pt_outer.out_frame_idx;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1814,7 +1825,12 @@ call_eval_func(
|
||||
* needed, especially when it is used as a closure.
|
||||
*/
|
||||
int
|
||||
fill_partial_and_closure(partial_T *pt, ufunc_T *ufunc, ectx_T *ectx)
|
||||
fill_partial_and_closure(
|
||||
partial_T *pt,
|
||||
ufunc_T *ufunc,
|
||||
short loop_var_idx,
|
||||
short loop_var_count,
|
||||
ectx_T *ectx)
|
||||
{
|
||||
pt->pt_func = ufunc;
|
||||
pt->pt_refcount = 1;
|
||||
@@ -1839,6 +1855,14 @@ fill_partial_and_closure(partial_T *pt, ufunc_T *ufunc, ectx_T *ectx)
|
||||
}
|
||||
}
|
||||
|
||||
// The closure may need to find variables defined inside a loop. A
|
||||
// new reference is made every time, ISN_ENDLOOP will check if they
|
||||
// are actually used.
|
||||
pt->pt_outer.out_loop_stack = &ectx->ec_stack;
|
||||
pt->pt_outer.out_loop_var_idx = ectx->ec_frame_idx + STACK_FRAME_SIZE
|
||||
+ loop_var_idx;
|
||||
pt->pt_outer.out_loop_var_count = loop_var_count;
|
||||
|
||||
// If the function currently executing returns and the closure is still
|
||||
// being referenced, we need to make a copy of the context (arguments
|
||||
// and local variables) so that the closure can use it later.
|
||||
@@ -1853,8 +1877,8 @@ fill_partial_and_closure(partial_T *pt, ufunc_T *ufunc, ectx_T *ectx)
|
||||
++(((typval_T *)ectx->ec_stack.ga_data) + ectx->ec_frame_idx
|
||||
+ STACK_FRAME_SIZE + dfunc->df_varcount)->vval.v_number;
|
||||
|
||||
((partial_T **)ectx->ec_funcrefs.ga_data)
|
||||
[ectx->ec_funcrefs.ga_len] = pt;
|
||||
((partial_T **)ectx->ec_funcrefs.ga_data)[ectx->ec_funcrefs.ga_len]
|
||||
= pt;
|
||||
++pt->pt_refcount;
|
||||
++ectx->ec_funcrefs.ga_len;
|
||||
}
|
||||
@@ -3610,9 +3634,15 @@ exec_instructions(ectx_T *ectx)
|
||||
iemsg("LOADOUTER depth more than scope levels");
|
||||
goto theend;
|
||||
}
|
||||
tv = ((typval_T *)outer->out_stack->ga_data)
|
||||
+ outer->out_frame_idx + STACK_FRAME_SIZE
|
||||
+ iptr->isn_arg.outer.outer_idx;
|
||||
if (depth == OUTER_LOOP_DEPTH)
|
||||
// variable declared in loop
|
||||
tv = ((typval_T *)outer->out_loop_stack->ga_data)
|
||||
+ outer->out_loop_var_idx
|
||||
+ iptr->isn_arg.outer.outer_idx;
|
||||
else
|
||||
tv = ((typval_T *)outer->out_stack->ga_data)
|
||||
+ outer->out_frame_idx + STACK_FRAME_SIZE
|
||||
+ iptr->isn_arg.outer.outer_idx;
|
||||
if (iptr->isn_type == ISN_LOADOUTER)
|
||||
{
|
||||
if (GA_GROW_FAILS(&ectx->ec_stack, 1))
|
||||
@@ -3913,9 +3943,10 @@ exec_instructions(ectx_T *ectx)
|
||||
// push a partial, a reference to a compiled function
|
||||
case ISN_FUNCREF:
|
||||
{
|
||||
partial_T *pt = ALLOC_CLEAR_ONE(partial_T);
|
||||
ufunc_T *ufunc;
|
||||
funcref_T *funcref = &iptr->isn_arg.funcref;
|
||||
partial_T *pt = ALLOC_CLEAR_ONE(partial_T);
|
||||
ufunc_T *ufunc;
|
||||
funcref_T *funcref = &iptr->isn_arg.funcref;
|
||||
funcref_extra_T *extra = funcref->fr_extra;
|
||||
|
||||
if (pt == NULL)
|
||||
goto theend;
|
||||
@@ -3924,7 +3955,7 @@ exec_instructions(ectx_T *ectx)
|
||||
vim_free(pt);
|
||||
goto theend;
|
||||
}
|
||||
if (funcref->fr_func_name == NULL)
|
||||
if (extra == NULL || extra->fre_func_name == NULL)
|
||||
{
|
||||
dfunc_T *pt_dfunc = ((dfunc_T *)def_functions.ga_data)
|
||||
+ funcref->fr_dfunc_idx;
|
||||
@@ -3932,16 +3963,17 @@ exec_instructions(ectx_T *ectx)
|
||||
ufunc = pt_dfunc->df_ufunc;
|
||||
}
|
||||
else
|
||||
{
|
||||
ufunc = find_func(funcref->fr_func_name, FALSE);
|
||||
}
|
||||
ufunc = find_func(extra->fre_func_name, FALSE);
|
||||
if (ufunc == NULL)
|
||||
{
|
||||
SOURCING_LNUM = iptr->isn_lnum;
|
||||
iemsg("ufunc unexpectedly NULL for FUNCREF");
|
||||
goto theend;
|
||||
}
|
||||
if (fill_partial_and_closure(pt, ufunc, ectx) == FAIL)
|
||||
if (fill_partial_and_closure(pt, ufunc,
|
||||
extra == NULL ? 0 : extra->fre_loop_var_idx,
|
||||
extra == NULL ? 0 : extra->fre_loop_var_count,
|
||||
ectx) == FAIL)
|
||||
goto theend;
|
||||
tv = STACK_TV_BOT(0);
|
||||
++ectx->ec_stack.ga_len;
|
||||
@@ -3954,10 +3986,11 @@ exec_instructions(ectx_T *ectx)
|
||||
// Create a global function from a lambda.
|
||||
case ISN_NEWFUNC:
|
||||
{
|
||||
newfunc_T *newfunc = &iptr->isn_arg.newfunc;
|
||||
newfuncarg_T *arg = iptr->isn_arg.newfunc.nf_arg;
|
||||
|
||||
if (copy_func(newfunc->nf_lambda, newfunc->nf_global,
|
||||
ectx) == FAIL)
|
||||
if (copy_lambda_to_global_func(arg->nfa_lambda,
|
||||
arg->nfa_global, arg->nfa_loop_var_idx,
|
||||
arg->nfa_loop_var_count, ectx) == FAIL)
|
||||
goto theend;
|
||||
}
|
||||
break;
|
||||
@@ -5520,7 +5553,7 @@ call_def_function(
|
||||
ufunc_T *base_ufunc = dfunc->df_ufunc;
|
||||
|
||||
// "uf_partial" is on the ufunc that "df_ufunc" points to, as is done
|
||||
// by copy_func().
|
||||
// by copy_lambda_to_global_func().
|
||||
if (partial != NULL || base_ufunc->uf_partial != NULL)
|
||||
{
|
||||
ectx.ec_outer_ref = ALLOC_CLEAR_ONE(outer_ref_T);
|
||||
@@ -5880,15 +5913,20 @@ list_instructions(char *pfx, isn_T *instr, int instr_count, ufunc_T *ufunc)
|
||||
break;
|
||||
case ISN_LOADOUTER:
|
||||
{
|
||||
if (iptr->isn_arg.outer.outer_idx < 0)
|
||||
isn_outer_T *outer = &iptr->isn_arg.outer;
|
||||
|
||||
if (outer->outer_idx < 0)
|
||||
smsg("%s%4d LOADOUTER level %d arg[%d]", pfx, current,
|
||||
iptr->isn_arg.outer.outer_depth,
|
||||
iptr->isn_arg.outer.outer_idx
|
||||
outer->outer_depth,
|
||||
outer->outer_idx
|
||||
+ STACK_FRAME_SIZE);
|
||||
else if (outer->outer_depth == OUTER_LOOP_DEPTH)
|
||||
smsg("%s%4d LOADOUTER level 1 $%d in loop",
|
||||
pfx, current, outer->outer_idx);
|
||||
else
|
||||
smsg("%s%4d LOADOUTER level %d $%d", pfx, current,
|
||||
iptr->isn_arg.outer.outer_depth,
|
||||
iptr->isn_arg.outer.outer_idx);
|
||||
outer->outer_depth,
|
||||
outer->outer_idx);
|
||||
}
|
||||
break;
|
||||
case ISN_LOADV:
|
||||
@@ -5971,9 +6009,16 @@ list_instructions(char *pfx, isn_T *instr, int instr_count, ufunc_T *ufunc)
|
||||
iptr->isn_arg.number);
|
||||
break;
|
||||
case ISN_STOREOUTER:
|
||||
smsg("%s%4d STOREOUTER level %d $%d", pfx, current,
|
||||
iptr->isn_arg.outer.outer_depth,
|
||||
iptr->isn_arg.outer.outer_idx);
|
||||
{
|
||||
isn_outer_T *outer = &iptr->isn_arg.outer;
|
||||
|
||||
if (outer->outer_depth == OUTER_LOOP_DEPTH)
|
||||
smsg("%s%4d STOREOUTER level 1 $%d in loop",
|
||||
pfx, current, outer->outer_idx);
|
||||
else
|
||||
smsg("%s%4d STOREOUTER level %d $%d", pfx, current,
|
||||
outer->outer_depth, outer->outer_idx);
|
||||
}
|
||||
break;
|
||||
case ISN_STOREV:
|
||||
smsg("%s%4d STOREV v:%s", pfx, current,
|
||||
@@ -6190,27 +6235,41 @@ list_instructions(char *pfx, isn_T *instr, int instr_count, ufunc_T *ufunc)
|
||||
break;
|
||||
case ISN_FUNCREF:
|
||||
{
|
||||
funcref_T *funcref = &iptr->isn_arg.funcref;
|
||||
char_u *name;
|
||||
funcref_T *funcref = &iptr->isn_arg.funcref;
|
||||
funcref_extra_T *extra = funcref->fr_extra;
|
||||
char_u *name;
|
||||
|
||||
if (funcref->fr_func_name == NULL)
|
||||
if (extra == NULL || extra->fre_func_name == NULL)
|
||||
{
|
||||
dfunc_T *df = ((dfunc_T *)def_functions.ga_data)
|
||||
+ funcref->fr_dfunc_idx;
|
||||
name = df->df_ufunc->uf_name;
|
||||
}
|
||||
else
|
||||
name = funcref->fr_func_name;
|
||||
smsg("%s%4d FUNCREF %s", pfx, current, name);
|
||||
name = extra->fre_func_name;
|
||||
if (extra == NULL || extra->fre_loop_var_count == 0)
|
||||
smsg("%s%4d FUNCREF %s", pfx, current, name);
|
||||
else
|
||||
smsg("%s%4d FUNCREF %s var $%d - $%d", pfx, current,
|
||||
name,
|
||||
extra->fre_loop_var_idx,
|
||||
extra->fre_loop_var_idx
|
||||
+ extra->fre_loop_var_count - 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case ISN_NEWFUNC:
|
||||
{
|
||||
newfunc_T *newfunc = &iptr->isn_arg.newfunc;
|
||||
newfuncarg_T *arg = iptr->isn_arg.newfunc.nf_arg;
|
||||
|
||||
smsg("%s%4d NEWFUNC %s %s", pfx, current,
|
||||
newfunc->nf_lambda, newfunc->nf_global);
|
||||
if (arg->nfa_loop_var_count == 0)
|
||||
smsg("%s%4d NEWFUNC %s %s", pfx, current,
|
||||
arg->nfa_lambda, arg->nfa_global);
|
||||
else
|
||||
smsg("%s%4d NEWFUNC %s %s var $%d - $%d", pfx, current,
|
||||
arg->nfa_lambda, arg->nfa_global,
|
||||
arg->nfa_loop_var_idx,
|
||||
arg->nfa_loop_var_idx + arg->nfa_loop_var_count - 1);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
+4
-1
@@ -496,6 +496,7 @@ compile_load(
|
||||
int idx;
|
||||
int gen_load = FALSE;
|
||||
int gen_load_outer = 0;
|
||||
int outer_loop_idx = -1;
|
||||
|
||||
name = vim_strnsave(*arg, end - *arg);
|
||||
if (name == NULL)
|
||||
@@ -520,6 +521,7 @@ compile_load(
|
||||
{
|
||||
type = lvar.lv_type;
|
||||
idx = lvar.lv_idx;
|
||||
outer_loop_idx = lvar.lv_loop_idx;
|
||||
if (lvar.lv_from_outer != 0)
|
||||
gen_load_outer = lvar.lv_from_outer;
|
||||
else
|
||||
@@ -544,7 +546,8 @@ compile_load(
|
||||
res = generate_LOAD(cctx, ISN_LOAD, idx, NULL, type);
|
||||
if (gen_load_outer > 0)
|
||||
{
|
||||
res = generate_LOADOUTER(cctx, idx, gen_load_outer, type);
|
||||
res = generate_LOADOUTER(cctx, idx,
|
||||
gen_load_outer, outer_loop_idx, type);
|
||||
cctx->ctx_outer_used = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
+94
-27
@@ -916,15 +916,25 @@ generate_STORE(cctx_T *cctx, isntype_T isn_type, int idx, char_u *name)
|
||||
* Generate an ISN_STOREOUTER instruction.
|
||||
*/
|
||||
static int
|
||||
generate_STOREOUTER(cctx_T *cctx, int idx, int level)
|
||||
generate_STOREOUTER(cctx_T *cctx, int idx, int level, int loop_idx)
|
||||
{
|
||||
isn_T *isn;
|
||||
|
||||
RETURN_OK_IF_SKIP(cctx);
|
||||
if ((isn = generate_instr_drop(cctx, ISN_STOREOUTER, 1)) == NULL)
|
||||
return FAIL;
|
||||
isn->isn_arg.outer.outer_idx = idx;
|
||||
isn->isn_arg.outer.outer_depth = level;
|
||||
if (level == 1 && loop_idx >= 0 && idx >= loop_idx)
|
||||
{
|
||||
// Store a variable defined in a loop. A copy will be made at the end
|
||||
// of the loop. TODO: how about deeper nesting?
|
||||
isn->isn_arg.outer.outer_idx = idx - loop_idx;
|
||||
isn->isn_arg.outer.outer_depth = OUTER_LOOP_DEPTH;
|
||||
}
|
||||
else
|
||||
{
|
||||
isn->isn_arg.outer.outer_idx = idx;
|
||||
isn->isn_arg.outer.outer_depth = level;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
@@ -999,6 +1009,7 @@ generate_LOADOUTER(
|
||||
cctx_T *cctx,
|
||||
int idx,
|
||||
int nesting,
|
||||
int loop_idx,
|
||||
type_T *type)
|
||||
{
|
||||
isn_T *isn;
|
||||
@@ -1006,8 +1017,18 @@ generate_LOADOUTER(
|
||||
RETURN_OK_IF_SKIP(cctx);
|
||||
if ((isn = generate_instr_type2(cctx, ISN_LOADOUTER, type, type)) == NULL)
|
||||
return FAIL;
|
||||
isn->isn_arg.outer.outer_idx = idx;
|
||||
isn->isn_arg.outer.outer_depth = nesting;
|
||||
if (nesting == 1 && loop_idx >= 0 && idx >= loop_idx)
|
||||
{
|
||||
// Load a variable defined in a loop. A copy will be made at the end
|
||||
// of the loop. TODO: how about deeper nesting?
|
||||
isn->isn_arg.outer.outer_idx = idx - loop_idx;
|
||||
isn->isn_arg.outer.outer_depth = OUTER_LOOP_DEPTH;
|
||||
}
|
||||
else
|
||||
{
|
||||
isn->isn_arg.outer.outer_idx = idx;
|
||||
isn->isn_arg.outer.outer_depth = nesting;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
@@ -1186,20 +1207,39 @@ generate_NEWDICT(cctx_T *cctx, int count, int use_null)
|
||||
/*
|
||||
* Generate an ISN_FUNCREF instruction.
|
||||
* "isnp" is set to the instruction, so that fr_dfunc_idx can be set later.
|
||||
* If variables were declared inside a loop "loop_var_idx" is the index of the
|
||||
* first one and "loop_var_count" the number of variables declared.
|
||||
*/
|
||||
int
|
||||
generate_FUNCREF(cctx_T *cctx, ufunc_T *ufunc, isn_T **isnp)
|
||||
generate_FUNCREF(
|
||||
cctx_T *cctx,
|
||||
ufunc_T *ufunc,
|
||||
isn_T **isnp)
|
||||
{
|
||||
isn_T *isn;
|
||||
type_T *type;
|
||||
isn_T *isn;
|
||||
type_T *type;
|
||||
funcref_extra_T *extra;
|
||||
short loop_var_idx;
|
||||
short loop_var_count;
|
||||
|
||||
RETURN_OK_IF_SKIP(cctx);
|
||||
if ((isn = generate_instr(cctx, ISN_FUNCREF)) == NULL)
|
||||
return FAIL;
|
||||
if (isnp != NULL)
|
||||
*isnp = isn;
|
||||
|
||||
loop_var_count = get_loop_var_info(cctx, &loop_var_idx);
|
||||
if (ufunc->uf_def_status == UF_NOT_COMPILED || loop_var_count > 0)
|
||||
{
|
||||
extra = ALLOC_CLEAR_ONE(funcref_extra_T);
|
||||
if (extra == NULL)
|
||||
return FAIL;
|
||||
isn->isn_arg.funcref.fr_extra = extra;
|
||||
extra->fre_loop_var_idx = loop_var_idx;
|
||||
extra->fre_loop_var_count = loop_var_count;
|
||||
}
|
||||
if (ufunc->uf_def_status == UF_NOT_COMPILED)
|
||||
isn->isn_arg.funcref.fr_func_name = vim_strsave(ufunc->uf_name);
|
||||
extra->fre_func_name = vim_strsave(ufunc->uf_name);
|
||||
else
|
||||
isn->isn_arg.funcref.fr_dfunc_idx = ufunc->uf_dfunc_idx;
|
||||
cctx->ctx_has_closure = 1;
|
||||
@@ -1221,7 +1261,12 @@ generate_FUNCREF(cctx_T *cctx, ufunc_T *ufunc, isn_T **isnp)
|
||||
* consumed.
|
||||
*/
|
||||
int
|
||||
generate_NEWFUNC(cctx_T *cctx, char_u *lambda_name, char_u *func_name)
|
||||
generate_NEWFUNC(
|
||||
cctx_T *cctx,
|
||||
char_u *lambda_name,
|
||||
char_u *func_name,
|
||||
short loop_var_idx,
|
||||
short loop_var_count)
|
||||
{
|
||||
isn_T *isn;
|
||||
int ret = OK;
|
||||
@@ -1232,9 +1277,19 @@ generate_NEWFUNC(cctx_T *cctx, char_u *lambda_name, char_u *func_name)
|
||||
ret = FAIL;
|
||||
else
|
||||
{
|
||||
isn->isn_arg.newfunc.nf_lambda = lambda_name;
|
||||
isn->isn_arg.newfunc.nf_global = func_name;
|
||||
return OK;
|
||||
newfuncarg_T *arg = ALLOC_CLEAR_ONE(newfuncarg_T);
|
||||
|
||||
if (arg == NULL)
|
||||
ret = FAIL;
|
||||
else
|
||||
{
|
||||
isn->isn_arg.newfunc.nf_arg = arg;
|
||||
arg->nfa_lambda = lambda_name;
|
||||
arg->nfa_global = func_name;
|
||||
arg->nfa_loop_var_idx = loop_var_idx;
|
||||
arg->nfa_loop_var_count = loop_var_count;
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
vim_free(lambda_name);
|
||||
@@ -2123,7 +2178,7 @@ generate_store_lhs(cctx_T *cctx, lhs_T *lhs, int instr_count, int is_decl)
|
||||
}
|
||||
else if (lhs->lhs_lvar->lv_from_outer > 0)
|
||||
generate_STOREOUTER(cctx, lhs->lhs_lvar->lv_idx,
|
||||
lhs->lhs_lvar->lv_from_outer);
|
||||
lhs->lhs_lvar->lv_from_outer, lhs->lhs_lvar->lv_loop_idx);
|
||||
else
|
||||
generate_STORE(cctx, ISN_STORE, lhs->lhs_lvar->lv_idx, NULL);
|
||||
}
|
||||
@@ -2226,22 +2281,28 @@ delete_instr(isn_T *isn)
|
||||
|
||||
case ISN_FUNCREF:
|
||||
{
|
||||
if (isn->isn_arg.funcref.fr_func_name == NULL)
|
||||
funcref_T *funcref = &isn->isn_arg.funcref;
|
||||
funcref_extra_T *extra = funcref->fr_extra;
|
||||
|
||||
if (extra == NULL || extra->fre_func_name == NULL)
|
||||
{
|
||||
dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
|
||||
+ isn->isn_arg.funcref.fr_dfunc_idx;
|
||||
+ funcref->fr_dfunc_idx;
|
||||
ufunc_T *ufunc = dfunc->df_ufunc;
|
||||
|
||||
if (ufunc != NULL && func_name_refcount(ufunc->uf_name))
|
||||
func_ptr_unref(ufunc);
|
||||
}
|
||||
else
|
||||
if (extra != NULL)
|
||||
{
|
||||
char_u *name = isn->isn_arg.funcref.fr_func_name;
|
||||
char_u *name = extra->fre_func_name;
|
||||
|
||||
if (name != NULL)
|
||||
{
|
||||
func_unref(name);
|
||||
vim_free(isn->isn_arg.funcref.fr_func_name);
|
||||
vim_free(name);
|
||||
}
|
||||
vim_free(extra);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -2259,17 +2320,23 @@ delete_instr(isn_T *isn)
|
||||
|
||||
case ISN_NEWFUNC:
|
||||
{
|
||||
char_u *lambda = isn->isn_arg.newfunc.nf_lambda;
|
||||
ufunc_T *ufunc = find_func_even_dead(lambda, FFED_IS_GLOBAL);
|
||||
newfuncarg_T *arg = isn->isn_arg.newfunc.nf_arg;
|
||||
|
||||
if (ufunc != NULL)
|
||||
if (arg != NULL)
|
||||
{
|
||||
unlink_def_function(ufunc);
|
||||
func_ptr_unref(ufunc);
|
||||
}
|
||||
ufunc_T *ufunc = find_func_even_dead(
|
||||
arg->nfa_lambda, FFED_IS_GLOBAL);
|
||||
|
||||
vim_free(lambda);
|
||||
vim_free(isn->isn_arg.newfunc.nf_global);
|
||||
if (ufunc != NULL)
|
||||
{
|
||||
unlink_def_function(ufunc);
|
||||
func_ptr_unref(ufunc);
|
||||
}
|
||||
|
||||
vim_free(arg->nfa_lambda);
|
||||
vim_free(arg->nfa_global);
|
||||
vim_free(arg);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@@ -20,6 +20,11 @@
|
||||
# include <float.h>
|
||||
#endif
|
||||
|
||||
// When not generating protos this is included in proto.h
|
||||
#ifdef PROTO
|
||||
# include "vim9.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Allocate memory for a type_T and add the pointer to type_gap, so that it can
|
||||
* be easily freed later.
|
||||
|
||||
+6
-3
@@ -6409,7 +6409,6 @@ win_fix_scroll(int resize)
|
||||
static void
|
||||
win_fix_cursor(int normal)
|
||||
{
|
||||
int top = FALSE;
|
||||
win_T *wp = curwin;
|
||||
long so = get_scrolloff_value();
|
||||
linenr_T nlnum = 0;
|
||||
@@ -6424,7 +6423,7 @@ win_fix_cursor(int normal)
|
||||
so = MIN(wp->w_height / 2, so);
|
||||
// Check if cursor position is above topline or below botline.
|
||||
if (wp->w_cursor.lnum < (wp->w_topline + so) && wp->w_topline != 1)
|
||||
top = nlnum = MIN(wp->w_topline + so, wp->w_buffer->b_ml.ml_line_count);
|
||||
nlnum = MIN(wp->w_topline + so, wp->w_buffer->b_ml.ml_line_count);
|
||||
else if (wp->w_cursor.lnum > (wp->w_botline - so - 1)
|
||||
&& (wp->w_botline - wp->w_buffer->b_ml.ml_line_count) != 1)
|
||||
nlnum = MAX(wp->w_botline - so - 1, 1);
|
||||
@@ -6442,7 +6441,11 @@ win_fix_cursor(int normal)
|
||||
}
|
||||
else
|
||||
{ // Ensure cursor stays visible if we are not in normal mode.
|
||||
wp->w_fraction = top ? 0 : FRACTION_MULT;
|
||||
wp->w_fraction = 0.5 * FRACTION_MULT;
|
||||
// Make sure cursor is closer to topline than botline.
|
||||
if (so == wp->w_height / 2
|
||||
&& nlnum - wp->w_topline > wp->w_botline - 1 - nlnum)
|
||||
wp->w_fraction++;
|
||||
scroll_to_fraction(wp, wp->w_prev_height);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user