Merge remote-tracking branch 'vim/master'

This commit is contained in:
ichizok
2022-01-19 14:44:58 +09:00
29 changed files with 697 additions and 228 deletions
+2
View File
@@ -5247,6 +5247,8 @@ maparg({name} [, {mode} [, {abbr} [, {dict}]]]) *maparg()*
(|mapmode-ic|)
"sid" The script local ID, used for <sid> mappings
(|<SID>|).
"scriptversion" The version of the script. 999999 for
|Vim9| script.
"lnum" The line number in "sid", zero if unknown.
"nowait" Do not wait for other, longer mappings.
(|:map-<nowait>|).
+6 -4
View File
@@ -365,12 +365,11 @@ For writing a Vim script, see chapter 41 of the user manual |usr_41.txt|.
Vim version, or update Vim to a newer version. See
|vimscript-version| for what changed between versions.
:vim9s[cript] [noclear] [autoload] *:vim9s* *:vim9script*
:vim9s[cript] [noclear] *:vim9s* *:vim9script*
Marks a script file as containing |Vim9-script|
commands. Also see |vim9-namespace|.
Must be the first command in the file.
For [noclear] see |vim9-reload|.
For [autoload] see |vim9-autoload|.
Without the |+eval| feature this changes the syntax
for some commands.
See |:vim9cmd| for executing one command with Vim9
@@ -378,8 +377,11 @@ For writing a Vim script, see chapter 41 of the user manual |usr_41.txt|.
*:scr* *:scriptnames*
:scr[iptnames] List all sourced script names, in the order they were
first sourced. The number is used for the script ID
|<SID>|.
first encountered. The number is used for the script
ID |<SID>|.
For a script that was used with `import autoload` but
was not actually sourced yet an "A" is shown after the
script ID.
{not available when compiled without the |+eval|
feature}
+8 -7
View File
@@ -1,4 +1,4 @@
*vim9.txt* For Vim version 8.2. Last change: 2022 Jan 15
*vim9.txt* For Vim version 8.2. Last change: 2022 Jan 18
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -1523,17 +1523,18 @@ actually needed. Using the autoload mechanism is recommended:
directory.
2. In the autoload script put the bulk of the code. >
vim9script autoload
vim9script
export def Stuff(arg: string)
...
< This goes in .../autoload/for/search.vim.
Adding "autoload" to `:vim9script` has the effect that "for#search#" will
be prefixed to every exported item. The prefix is obtained from the file
name, as you would to manually in a legacy autoload script. Thus the
exported function can be found with "for#search#Stuff", but you would
normally use `import autoload` and not need to specify the prefix.
Putting the "search.vim" script under the "/autoload/for/" directory has
the effect that "for#search#" will be prefixed to every exported item. The
prefix is obtained from the file name, as you would to manually in a
legacy autoload script. Thus the exported function can be found with
"for#search#Stuff", but you would normally use `import autoload` and not
use the prefix.
You can split up the functionality and import other scripts from the
autoload script as you like. This way you can share code between plugins.
+9 -6
View File
@@ -508,7 +508,8 @@ NETBEANS_LIB = WSock32.lib Ws2_32.lib
# gdi32.lib and comdlg32.lib for printing support
# ole32.lib and uuid.lib are needed for FEAT_SHORTCUT
CON_LIB = oldnames.lib kernel32.lib advapi32.lib shell32.lib gdi32.lib \
comdlg32.lib ole32.lib netapi32.lib uuid.lib /machine:$(CPU)
comdlg32.lib ole32.lib netapi32.lib uuid.lib user32.lib \
/machine:$(CPU)
!if "$(DELAYLOAD)" == "yes"
CON_LIB = $(CON_LIB) /DELAYLOAD:comdlg32.dll /DELAYLOAD:ole32.dll DelayImp.lib
!endif
@@ -671,6 +672,7 @@ CFLAGS = $(CFLAGS) /fsanitize=address
!endif
!ifdef NODEBUG
VIM = vim
! if "$(OPTIMIZE)" == "SPACE"
OPTFLAG = /O1
@@ -701,7 +703,9 @@ LIBC = msvcrt.lib
LIBC = libcmt.lib
CFLAGS = $(CFLAGS) /Zl /MT
! endif
!else # DEBUG
VIM = vimd
! if ("$(CPU)" == "i386") || ("$(CPU)" == "ix86")
DEBUGINFO = /ZI
@@ -721,6 +725,7 @@ LIBC = $(LIBC) msvcrtd.lib
LIBC = $(LIBC) libcmtd.lib
CFLAGS = $(CFLAGS) /Zl /MTd
! endif
!endif # DEBUG
!if "$(CL)" == "/D_USING_V110_SDK71_"
@@ -910,9 +915,7 @@ GUI_OBJ = \
$(OUTDIR)\gui_beval.obj \
$(OUTDIR)\gui_w32.obj
GUI_LIB = \
gdi32.lib version.lib $(IME_LIB) \
winspool.lib comctl32.lib advapi32.lib shell32.lib netapi32.lib \
/machine:$(CPU)
version.lib $(IME_LIB) winspool.lib comctl32.lib
!else
SUBSYSTEM = console
CUI_INCL = iscygpty.h
@@ -1320,11 +1323,11 @@ conflags = $(conflags) /map /mapinfo:lines
!ENDIF
LINKARGS1 = $(linkdebug) $(conflags)
LINKARGS2 = $(CON_LIB) $(GUI_LIB) $(NODEFAULTLIB) $(LIBC) $(OLE_LIB) user32.lib \
LINKARGS2 = $(CON_LIB) $(GUI_LIB) $(NODEFAULTLIB) $(LIBC) $(OLE_LIB) \
$(LUA_LIB) $(MZSCHEME_LIB) $(PERL_LIB) $(PYTHON_LIB) $(PYTHON3_LIB) $(RUBY_LIB) \
$(TCL_LIB) $(SOUND_LIB) $(NETBEANS_LIB) $(XPM_LIB) $(SOD_LIB) $(LINK_PDB)
# Report link time code generation progress if used.
# Report link time code generation progress if used.
!ifdef NODEBUG
! if $(MSVC_MAJOR) >= 8
! if "$(OPTIMIZE)" != "SPACE"
+22 -10
View File
@@ -5321,6 +5321,12 @@ esac
if test "x$features" = "xtiny" -o "x$features" = "xsmall"; then
has_eval=no
else
has_eval=yes
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking --with-compiledby argument" >&5
$as_echo_n "checking --with-compiledby argument... " >&6; }
@@ -5398,7 +5404,7 @@ fi
$as_echo "$enable_luainterp" >&6; }
if test "$enable_luainterp" = "yes" -o "$enable_luainterp" = "dynamic"; then
if test "x$features" = "xtiny" -o "x$features" = "xsmall"; then
if test "$has_eval" = "no"; then
as_fn_error $? "cannot use Lua with tiny or small features" "$LINENO" 5
fi
@@ -6182,7 +6188,7 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_perlinterp" >&5
$as_echo "$enable_perlinterp" >&6; }
if test "$enable_perlinterp" = "yes" -o "$enable_perlinterp" = "dynamic"; then
if test "x$features" = "xtiny" -o "x$features" = "xsmall"; then
if test "$has_eval" = "no"; then
as_fn_error $? "cannot use Perl with tiny or small features" "$LINENO" 5
fi
@@ -6400,7 +6406,7 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_pythoninterp" >&5
$as_echo "$enable_pythoninterp" >&6; }
if test "$enable_pythoninterp" = "yes" -o "$enable_pythoninterp" = "dynamic"; then
if test "x$features" = "xtiny" -o "x$features" = "xsmall"; then
if test "$has_eval" = "no"; then
as_fn_error $? "cannot use Python with tiny or small features" "$LINENO" 5
fi
@@ -6758,7 +6764,7 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_python3interp" >&5
$as_echo "$enable_python3interp" >&6; }
if test "$enable_python3interp" = "yes" -o "$enable_python3interp" = "dynamic"; then
if test "x$features" = "xtiny" -o "x$features" = "xsmall"; then
if test "$has_eval" = "no"; then
as_fn_error $? "cannot use Python with tiny or small features" "$LINENO" 5
fi
@@ -7731,7 +7737,7 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_rubyinterp" >&5
$as_echo "$enable_rubyinterp" >&6; }
if test "$enable_rubyinterp" = "yes" -o "$enable_rubyinterp" = "dynamic"; then
if test "x$features" = "xtiny" -o "x$features" = "xsmall"; then
if test "$has_eval" = "no"; then
as_fn_error $? "cannot use Ruby with tiny or small features" "$LINENO" 5
fi
@@ -7936,7 +7942,7 @@ else
fi
if test "$enable_netbeans" = "yes"; then
if test "x$features" = "xtiny" -o "x$features" = "xsmall"; then
if test "$has_eval" = "no"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: cannot use NetBeans with tiny or small features" >&5
$as_echo "cannot use NetBeans with tiny or small features" >&6; }
enable_netbeans="no"
@@ -7959,7 +7965,7 @@ else
fi
if test "$enable_channel" = "yes"; then
if test "x$features" = "xtiny" -o "x$features" = "xsmall"; then
if test "$has_eval" = "no"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: cannot use channels with tiny or small features" >&5
$as_echo "cannot use channels with tiny or small features" >&6; }
enable_channel="no"
@@ -8263,7 +8269,7 @@ else
fi
if test "$enable_terminal" = "yes" || test "$enable_terminal" = "auto" -a "x$features" = "xhuge" ; then
if test "x$features" = "xtiny" -o "x$features" = "xsmall"; then
if test "$has_eval" = "no"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: cannot use terminal emulator with tiny or small features" >&5
$as_echo "cannot use terminal emulator with tiny or small features" >&6; }
enable_terminal="no"
@@ -13280,8 +13286,14 @@ $as_echo "Defaulting to no" >&6; }
enable_canberra="no"
fi
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_canberra" >&5
if test "$enable_canberra" = "yes" -a "$has_eval" = "no"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: cannot use sound with tiny or small features" >&5
$as_echo "cannot use sound with tiny or small features" >&6; }
enable_canberra="no"
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_canberra" >&5
$as_echo "$enable_canberra" >&6; }
fi
fi
if test "$enable_canberra" = "yes"; then
if test "x$PKG_CONFIG" != "xno"; then
@@ -13296,7 +13308,7 @@ if test "$enable_canberra" = "yes"; then
$as_echo_n "checking for libcanberra... " >&6; }
ac_save_CFLAGS="$CFLAGS"
ac_save_LIBS="$LIBS"
if `echo "$CFLAGS" | grep -v "$canberra_cflags" >/dev/null`; then
if `echo "$CFLAGS" | grep -v "$canberra_cflags" 2>/dev/null`; then
CFLAGS="$CFLAGS $canberra_cflags"
fi
LIBS="$LIBS $canberra_lib"
+21 -10
View File
@@ -579,6 +579,12 @@ esac
AC_SUBST(dovimdiff)
AC_SUBST(dogvimdiff)
if test "x$features" = "xtiny" -o "x$features" = "xsmall"; then
has_eval=no
else
has_eval=yes
fi
AC_MSG_CHECKING(--with-compiledby argument)
AC_ARG_WITH(compiledby, [ --with-compiledby=NAME name to show in :version message],
compiledby="$withval"; AC_MSG_RESULT($withval),
@@ -624,7 +630,7 @@ AC_ARG_ENABLE(luainterp,
AC_MSG_RESULT($enable_luainterp)
if test "$enable_luainterp" = "yes" -o "$enable_luainterp" = "dynamic"; then
if test "x$features" = "xtiny" -o "x$features" = "xsmall"; then
if test "$has_eval" = "no"; then
AC_MSG_ERROR([cannot use Lua with tiny or small features])
fi
@@ -1122,7 +1128,7 @@ AC_ARG_ENABLE(perlinterp,
[enable_perlinterp="no"])
AC_MSG_RESULT($enable_perlinterp)
if test "$enable_perlinterp" = "yes" -o "$enable_perlinterp" = "dynamic"; then
if test "x$features" = "xtiny" -o "x$features" = "xsmall"; then
if test "$has_eval" = "no"; then
AC_MSG_ERROR([cannot use Perl with tiny or small features])
fi
AC_SUBST(vi_cv_path_perl)
@@ -1282,7 +1288,7 @@ AC_ARG_ENABLE(pythoninterp,
[enable_pythoninterp="no"])
AC_MSG_RESULT($enable_pythoninterp)
if test "$enable_pythoninterp" = "yes" -o "$enable_pythoninterp" = "dynamic"; then
if test "x$features" = "xtiny" -o "x$features" = "xsmall"; then
if test "$has_eval" = "no"; then
AC_MSG_ERROR([cannot use Python with tiny or small features])
fi
@@ -1527,7 +1533,7 @@ AC_ARG_ENABLE(python3interp,
[enable_python3interp="no"])
AC_MSG_RESULT($enable_python3interp)
if test "$enable_python3interp" = "yes" -o "$enable_python3interp" = "dynamic"; then
if test "x$features" = "xtiny" -o "x$features" = "xsmall"; then
if test "$has_eval" = "no"; then
AC_MSG_ERROR([cannot use Python with tiny or small features])
fi
@@ -2074,7 +2080,7 @@ AC_ARG_ENABLE(rubyinterp,
[enable_rubyinterp="no"])
AC_MSG_RESULT($enable_rubyinterp)
if test "$enable_rubyinterp" = "yes" -o "$enable_rubyinterp" = "dynamic"; then
if test "x$features" = "xtiny" -o "x$features" = "xsmall"; then
if test "$has_eval" = "no"; then
AC_MSG_ERROR([cannot use Ruby with tiny or small features])
fi
@@ -2213,7 +2219,7 @@ AC_ARG_ENABLE(netbeans,
[ --disable-netbeans Disable NetBeans integration support.],
, [enable_netbeans="yes"])
if test "$enable_netbeans" = "yes"; then
if test "x$features" = "xtiny" -o "x$features" = "xsmall"; then
if test "$has_eval" = "no"; then
AC_MSG_RESULT([cannot use NetBeans with tiny or small features])
enable_netbeans="no"
else
@@ -2228,7 +2234,7 @@ AC_ARG_ENABLE(channel,
[ --disable-channel Disable process communication support.],
, [enable_channel="yes"])
if test "$enable_channel" = "yes"; then
if test "x$features" = "xtiny" -o "x$features" = "xsmall"; then
if test "$has_eval" = "no"; then
AC_MSG_RESULT([cannot use channels with tiny or small features])
enable_channel="no"
else
@@ -2336,7 +2342,7 @@ AC_ARG_ENABLE(terminal,
[ --enable-terminal Enable terminal emulation support.],
, [enable_terminal="auto"])
if test "$enable_terminal" = "yes" || test "$enable_terminal" = "auto" -a "x$features" = "xhuge" ; then
if test "x$features" = "xtiny" -o "x$features" = "xsmall"; then
if test "$has_eval" = "no"; then
AC_MSG_RESULT([cannot use terminal emulator with tiny or small features])
enable_terminal="no"
else
@@ -3979,7 +3985,12 @@ if test "$enable_canberra" = "maybe"; then
enable_canberra="no"
fi
else
AC_MSG_RESULT($enable_canberra)
if test "$enable_canberra" = "yes" -a "$has_eval" = "no"; then
AC_MSG_RESULT([cannot use sound with tiny or small features])
enable_canberra="no"
else
AC_MSG_RESULT($enable_canberra)
fi
fi
if test "$enable_canberra" = "yes"; then
if test "x$PKG_CONFIG" != "xno"; then
@@ -3993,7 +4004,7 @@ if test "$enable_canberra" = "yes"; then
AC_MSG_CHECKING(for libcanberra)
ac_save_CFLAGS="$CFLAGS"
ac_save_LIBS="$LIBS"
if `echo "$CFLAGS" | grep -v "$canberra_cflags" >/dev/null`; then
if `echo "$CFLAGS" | grep -v "$canberra_cflags" 2>/dev/null`; then
CFLAGS="$CFLAGS $canberra_cflags"
fi
LIBS="$LIBS $canberra_lib"
+1 -2
View File
@@ -3213,8 +3213,7 @@ EXTERN char e_cannot_import_dot_vim_without_using_as[]
INIT(= N_("E1261: Cannot import .vim without using \"as\""));
EXTERN char e_cannot_import_same_script_twice_str[]
INIT(= N_("E1262: Cannot import the same script twice: %s"));
EXTERN char e_using_autoload_in_script_not_under_autoload_directory[]
INIT(= N_("E1263: Using autoload in a script not under an autoload directory"));
// E1263 unused
EXTERN char e_autoload_import_cannot_use_absolute_or_relative_path[]
INIT(= N_("E1264: Autoload import cannot use absolute or relative path: %s"));
EXTERN char e_cannot_use_partial_here[]
+77 -42
View File
@@ -625,6 +625,63 @@ eval_expr(char_u *arg, exarg_T *eap)
return tv;
}
/*
* "*arg" points to what can be a function name in the form of "import.Name" or
* "Funcref". Return the name of the function. Set "tofree" to something that
* was allocated.
* If "verbose" is FALSE no errors are given.
* Return NULL for any failure.
*/
static char_u *
deref_function_name(
char_u **arg,
char_u **tofree,
evalarg_T *evalarg,
int verbose)
{
typval_T ref;
char_u *name = *arg;
ref.v_type = VAR_UNKNOWN;
if (eval7(arg, &ref, evalarg, FALSE) == FAIL)
return NULL;
if (*skipwhite(*arg) != NUL)
{
if (verbose)
semsg(_(e_trailing_characters_str), *arg);
name = NULL;
}
else if (ref.v_type == VAR_FUNC && ref.vval.v_string != NULL)
{
name = ref.vval.v_string;
ref.vval.v_string = NULL;
*tofree = name;
}
else if (ref.v_type == VAR_PARTIAL && ref.vval.v_partial != NULL)
{
if (ref.vval.v_partial->pt_argc > 0
|| ref.vval.v_partial->pt_dict != NULL)
{
if (verbose)
emsg(_(e_cannot_use_partial_here));
name = NULL;
}
else
{
name = vim_strsave(partial_name(ref.vval.v_partial));
*tofree = name;
}
}
else
{
if (verbose)
semsg(_(e_not_callable_type_str), name);
name = NULL;
}
clear_tv(&ref);
return name;
}
/*
* Call some Vim script function and return the result in "*rettv".
* Uses argv[0] to argv[argc - 1] for the function arguments. argv[argc]
@@ -640,15 +697,29 @@ call_vim_function(
{
int ret;
funcexe_T funcexe;
char_u *arg;
char_u *name;
char_u *tofree = NULL;
rettv->v_type = VAR_UNKNOWN; // clear_tv() uses this
CLEAR_FIELD(funcexe);
funcexe.fe_firstline = curwin->w_cursor.lnum;
funcexe.fe_lastline = curwin->w_cursor.lnum;
funcexe.fe_evaluate = TRUE;
ret = call_func(func, -1, rettv, argc, argv, &funcexe);
// The name might be "import.Func" or "Funcref".
arg = func;
++emsg_off;
name = deref_function_name(&arg, &tofree, &EVALARG_EVALUATE, FALSE);
--emsg_off;
if (name == NULL)
name = func;
ret = call_func(name, -1, rettv, argc, argv, &funcexe);
if (ret == FAIL)
clear_tv(rettv);
vim_free(tofree);
return ret;
}
@@ -3979,57 +4050,21 @@ eval_method(
if (**arg != '(' && alias == NULL
&& (paren = vim_strchr(*arg, '(')) != NULL)
{
typval_T ref;
char_u *deref;
*arg = name;
*paren = NUL;
ref.v_type = VAR_UNKNOWN;
if (eval7(arg, &ref, evalarg, FALSE) == FAIL)
deref = deref_function_name(arg, &tofree, evalarg, verbose);
if (deref == NULL)
{
*arg = name + len;
ret = FAIL;
}
else if (*skipwhite(*arg) != NUL)
{
if (verbose)
semsg(_(e_trailing_characters_str), *arg);
ret = FAIL;
}
else if (ref.v_type == VAR_FUNC && ref.vval.v_string != NULL)
{
name = ref.vval.v_string;
ref.vval.v_string = NULL;
tofree = name;
len = STRLEN(name);
}
else if (ref.v_type == VAR_PARTIAL && ref.vval.v_partial != NULL)
{
if (ref.vval.v_partial->pt_argc > 0
|| ref.vval.v_partial->pt_dict != NULL)
{
emsg(_(e_cannot_use_partial_here));
ret = FAIL;
}
else
{
name = vim_strsave(partial_name(ref.vval.v_partial));
tofree = name;
if (name == NULL)
{
ret = FAIL;
name = *arg;
}
else
len = STRLEN(name);
}
}
else
{
if (verbose)
semsg(_(e_not_callable_type_str), name);
ret = FAIL;
name = deref;
len = STRLEN(name);
}
clear_tv(&ref);
*paren = '(';
}
+11 -8
View File
@@ -248,14 +248,6 @@ vim_tcl_init(char *arg)
#endif
}
#if defined(EXITFREE) || defined(PROTO)
void
vim_tcl_finalize(void)
{
Tcl_Finalize();
}
#endif
#if defined(DYNAMIC_TCL) || defined(PROTO)
static int stubs_initialized = FALSE;
@@ -285,6 +277,17 @@ tcl_enabled(int verbose)
}
return stubs_initialized;
}
#endif
#if defined(EXITFREE) || defined(PROTO)
void
vim_tcl_finalize(void)
{
# ifdef DYNAMIC_TCL
if (stubs_initialized)
# endif
Tcl_Finalize();
}
#endif
void
+29 -10
View File
@@ -222,11 +222,12 @@ map_add(
#ifdef FEAT_EVAL
int expr,
scid_T sid, // -1 to use current_sctx
int scriptversion,
linenr_T lnum,
#endif
int simplified)
{
mapblock_T *mp = ALLOC_ONE(mapblock_T);
mapblock_T *mp = ALLOC_CLEAR_ONE(mapblock_T);
if (mp == NULL)
return FAIL;
@@ -259,11 +260,11 @@ map_add(
mp->m_simplified = simplified;
#ifdef FEAT_EVAL
mp->m_expr = expr;
if (sid >= 0)
if (sid > 0)
{
mp->m_script_ctx.sc_sid = sid;
mp->m_script_ctx.sc_lnum = lnum;
mp->m_script_ctx.sc_version = in_vim9script() ? SCRIPT_VERSION_VIM9 : 0;
mp->m_script_ctx.sc_version = scriptversion;
}
else
{
@@ -844,7 +845,7 @@ do_map(
if (map_add(map_table, abbr_table, keys, rhs, orig_rhs,
noremap, nowait, silent, mode, abbrev,
#ifdef FEAT_EVAL
expr, /* sid */ -1, /* lnum */ 0,
expr, /* sid */ -1, /* scriptversion */ 0, /* lnum */ 0,
#endif
did_simplify && keyround == 1) == FAIL)
{
@@ -1515,6 +1516,12 @@ check_abbr(
}
if (mp != NULL)
{
int noremap;
int silent;
#ifdef FEAT_EVAL
int expr;
#endif
// Found a match:
// Insert the rest of the abbreviation in typebuf.tb_buf[].
// This goes from end to start.
@@ -1567,8 +1574,14 @@ check_abbr(
// insert the last typed char
(void)ins_typebuf(tb, 1, 0, TRUE, mp->m_silent);
}
// copy values here, calling eval_map_expr() may make "mp" invalid!
noremap = mp->m_noremap;
silent = mp->m_silent;
#ifdef FEAT_EVAL
if (mp->m_expr)
expr = mp->m_expr;
if (expr)
s = eval_map_expr(mp, c);
else
#endif
@@ -1576,11 +1589,11 @@ check_abbr(
if (s != NULL)
{
// insert the to string
(void)ins_typebuf(s, mp->m_noremap, 0, TRUE, mp->m_silent);
(void)ins_typebuf(s, noremap, 0, TRUE, silent);
// no abbrev. for these chars
typebuf.tb_no_abbr_cnt += (int)STRLEN(s) + j + 1;
#ifdef FEAT_EVAL
if (mp->m_expr)
if (expr)
vim_free(s);
#endif
}
@@ -1590,7 +1603,7 @@ check_abbr(
if (has_mbyte)
len = clen; // Delete characters instead of bytes
while (len-- > 0) // delete the from string
(void)ins_typebuf(tb, 1, 0, TRUE, mp->m_silent);
(void)ins_typebuf(tb, 1, 0, TRUE, silent);
return TRUE;
}
}
@@ -1601,6 +1614,7 @@ check_abbr(
/*
* Evaluate the RHS of a mapping or abbreviations and take care of escaping
* special characters.
* Careful: after this "mp" will be invalid if the mapping was deleted.
*/
char_u *
eval_map_expr(
@@ -2289,6 +2303,8 @@ get_maparg(typval_T *argvars, typval_T *rettv, int exact)
dict_add_number(dict, "expr", mp->m_expr ? 1L : 0L);
dict_add_number(dict, "silent", mp->m_silent ? 1L : 0L);
dict_add_number(dict, "sid", (long)mp->m_script_ctx.sc_sid);
dict_add_number(dict, "scriptversion",
(long)mp->m_script_ctx.sc_version);
dict_add_number(dict, "lnum", (long)mp->m_script_ctx.sc_lnum);
dict_add_number(dict, "buffer", (long)buffer_local);
dict_add_number(dict, "nowait", mp->m_nowait ? 1L : 0L);
@@ -2358,6 +2374,7 @@ f_mapset(typval_T *argvars, typval_T *rettv UNUSED)
int silent;
int buffer;
scid_T sid;
int scriptversion;
linenr_T lnum;
mapblock_T **map_table = maphash;
mapblock_T **abbr_table = &first_abbr;
@@ -2403,6 +2420,7 @@ f_mapset(typval_T *argvars, typval_T *rettv UNUSED)
expr = dict_get_number(d, (char_u *)"expr") != 0;
silent = dict_get_number(d, (char_u *)"silent") != 0;
sid = dict_get_number(d, (char_u *)"sid");
scriptversion = dict_get_number(d, (char_u *)"scriptversion");
lnum = dict_get_number(d, (char_u *)"lnum");
buffer = dict_get_number(d, (char_u *)"buffer");
nowait = dict_get_number(d, (char_u *)"nowait") != 0;
@@ -2433,10 +2451,11 @@ f_mapset(typval_T *argvars, typval_T *rettv UNUSED)
vim_free(arg);
(void)map_add(map_table, abbr_table, lhsraw, rhs, orig_rhs, noremap,
nowait, silent, mode, is_abbr, expr, sid, lnum, 0);
nowait, silent, mode, is_abbr, expr, sid, scriptversion, lnum, 0);
if (lhsrawalt != NULL)
(void)map_add(map_table, abbr_table, lhsrawalt, rhs, orig_rhs, noremap,
nowait, silent, mode, is_abbr, expr, sid, lnum, 1);
nowait, silent, mode, is_abbr, expr, sid, scriptversion,
lnum, 1);
vim_free(keys_buf);
vim_free(arg_buf);
}
+1 -1
View File
@@ -2909,7 +2909,6 @@ mch_parse_cmd(char_u *cmd, int use_shcf, char ***argv, int *argc)
return OK;
}
# if defined(FEAT_JOB_CHANNEL) || defined(PROTO)
/*
* Build "argv[argc]" from the string "cmd".
* "argv[argc]" is set to NULL;
@@ -2936,6 +2935,7 @@ build_argv_from_string(char_u *cmd, char ***argv, int *argc)
return OK;
}
# if defined(FEAT_JOB_CHANNEL) || defined(PROTO)
/*
* Build "argv[argc]" from the list "l".
* "argv[argc]" is set to NULL;
+26 -14
View File
@@ -536,24 +536,29 @@ block_insert(
if (b_insert)
{
off = (*mb_head_off)(oldp, oldp + offset + spaces);
spaces -= off;
count -= off;
}
else
{
off = (*mb_off_next)(oldp, oldp + offset);
offset += off;
// spaces fill the gap, the character that's at the edge moves
// right
off = (*mb_head_off)(oldp, oldp + offset);
offset -= off;
}
spaces -= off;
count -= off;
}
if (spaces < 0) // can happen when the cursor was moved
spaces = 0;
newp = alloc(STRLEN(oldp) + s_len + count + 1);
// Make sure the allocated size matches what is actually copied below.
newp = alloc(STRLEN(oldp) + spaces + s_len
+ (spaces > 0 && !bdp->is_short ? ts_val - spaces : 0)
+ count + 1);
if (newp == NULL)
continue;
// copy up to shifted part
mch_memmove(newp, oldp, (size_t)(offset));
mch_memmove(newp, oldp, (size_t)offset);
oldp += offset;
// insert pre-padding
@@ -564,14 +569,21 @@ block_insert(
mch_memmove(newp + startcol, s, (size_t)s_len);
offset += s_len;
if (spaces && !bdp->is_short)
if (spaces > 0 && !bdp->is_short)
{
// insert post-padding
vim_memset(newp + offset + spaces, ' ', (size_t)(ts_val - spaces));
// We're splitting a TAB, don't copy it.
oldp++;
// We allowed for that TAB, remember this now
count++;
if (*oldp == TAB)
{
// insert post-padding
vim_memset(newp + offset + spaces, ' ',
(size_t)(ts_val - spaces));
// we're splitting a TAB, don't copy it
oldp++;
// We allowed for that TAB, remember this now
count++;
}
else
// Not a TAB, no extra spaces
count = spaces;
}
if (spaces > 0)
@@ -1598,7 +1610,7 @@ op_insert(oparg_T *oap, long count1)
oap->start_vcol = t;
}
else if (oap->op_type == OP_APPEND
&& oap->end.col + oap->end.coladd
&& oap->start.col + oap->start.coladd
>= curbuf->b_op_start_orig.col
+ curbuf->b_op_start_orig.coladd)
{
+14 -4
View File
@@ -1648,12 +1648,22 @@ ex_scriptnames(exarg_T *eap)
}
for (i = 1; i <= script_items.ga_len && !got_int; ++i)
if (SCRIPT_ITEM(i)->sn_name != NULL)
{
scriptitem_T *si = SCRIPT_ITEM(i);
if (si->sn_name != NULL)
{
home_replace(NULL, SCRIPT_ITEM(i)->sn_name,
NameBuff, MAXPATHL, TRUE);
smsg("%3d: %s", i, NameBuff);
home_replace(NULL, si->sn_name, NameBuff, MAXPATHL, TRUE);
vim_snprintf((char *)IObuff, IOSIZE, "%3d%s: %s",
i,
si->sn_state == SN_STATE_NOT_LOADED ? " A" : "",
NameBuff);
msg_putchar('\n');
msg_outtrans(IObuff);
out_flush(); // output one line at a time
ui_breakcheck();
}
}
}
# if defined(BACKSLASH_IN_FILENAME) || defined(PROTO)
+8 -4
View File
@@ -18,26 +18,30 @@ func Test_maparg()
call assert_equal("is<F4>foo", maparg('foo<C-V>'))
call assert_equal({'silent': 0, 'noremap': 0, 'script': 0, 'lhs': 'foo<C-V>',
\ 'lhsraw': "foo\x80\xfc\x04V", 'lhsrawalt': "foo\x16",
\ 'mode': ' ', 'nowait': 0, 'expr': 0, 'sid': sid, 'lnum': lnum + 1,
\ 'mode': ' ', 'nowait': 0, 'expr': 0, 'sid': sid, 'scriptversion': 1,
\ 'lnum': lnum + 1,
\ 'rhs': 'is<F4>foo', 'buffer': 0},
\ maparg('foo<C-V>', '', 0, 1))
call assert_equal({'silent': 1, 'noremap': 1, 'script': 1, 'lhs': 'bar',
\ 'lhsraw': 'bar', 'mode': 'v',
\ 'nowait': 0, 'expr': 1, 'sid': sid, 'lnum': lnum + 2,
\ 'nowait': 0, 'expr': 1, 'sid': sid, 'scriptversion': 1,
\ 'lnum': lnum + 2,
\ 'rhs': 'isbar', 'buffer': 1},
\ 'bar'->maparg('', 0, 1))
let lnum = expand('<sflnum>')
map <buffer> <nowait> foo bar
call assert_equal({'silent': 0, 'noremap': 0, 'script': 0, 'lhs': 'foo',
\ 'lhsraw': 'foo', 'mode': ' ',
\ 'nowait': 1, 'expr': 0, 'sid': sid, 'lnum': lnum + 1, 'rhs': 'bar',
\ 'nowait': 1, 'expr': 0, 'sid': sid, 'scriptversion': 1,
\ 'lnum': lnum + 1, 'rhs': 'bar',
\ 'buffer': 1},
\ maparg('foo', '', 0, 1))
let lnum = expand('<sflnum>')
tmap baz foo
call assert_equal({'silent': 0, 'noremap': 0, 'script': 0, 'lhs': 'baz',
\ 'lhsraw': 'baz', 'mode': 't',
\ 'nowait': 0, 'expr': 0, 'sid': sid, 'lnum': lnum + 1, 'rhs': 'foo',
\ 'nowait': 0, 'expr': 0, 'sid': sid, 'scriptversion': 1,
\ 'lnum': lnum + 1, 'rhs': 'foo',
\ 'buffer': 0},
\ maparg('baz', 't', 0, 1))
+13 -1
View File
@@ -704,6 +704,11 @@ func Test_mapcomplete()
mapclear
endfunc
func GetAbbrText()
unabbr hola
return 'hello'
endfunc
" Test for <expr> in abbreviation
func Test_expr_abbr()
new
@@ -719,7 +724,14 @@ func Test_expr_abbr()
call assert_equal('', getline(1))
unabbr <expr> hte
close!
" evaluating the expression deletes the abbreviation
abbr <expr> hola GetAbbrText()
call assert_equal('GetAbbrText()', maparg('hola', 'i', '1'))
call feedkeys("ahola \<Esc>", 'xt')
call assert_equal('hello ', getline('.'))
call assert_equal('', maparg('hola', 'i', '1'))
bwipe!
endfunc
" Test for storing mappings in different modes in a vimrc file
+4
View File
@@ -23,6 +23,10 @@ func Test_scriptnames()
bwipe
call delete('Xscripting')
let msgs = execute('messages')
scriptnames
call assert_equal(msgs, execute('messages'))
endfunc
" vim: shiftwidth=2 sts=2 expandtab
+2 -2
View File
@@ -589,10 +589,10 @@ func Test_command_list()
\ execute('command DoCmd'))
" Test output in verbose mode.
command! DoCmd :
command! -nargs=+ -complete=customlist,SomeFunc DoCmd :ls
call assert_match("^\n"
\ .. " Name Args Address Complete Definition\n"
\ .. " DoCmd 0 :\n"
\ .. " DoCmd + customlist,SomeFunc :ls\n"
\ .. "\tLast set from .*/test_usercommands.vim line \\d\\+$",
\ execute('verbose command DoCmd'))
+1
View File
@@ -2278,6 +2278,7 @@ def Test_maparg()
nowait: 0,
expr: 0,
sid: SID(),
scriptversion: 999999,
rhs: 'bar',
buffer: 0})
unmap foo
+76 -42
View File
@@ -1717,7 +1717,7 @@ let g:dict_one = #{one: 1}
let $TESTVAR = 'testvar'
" type casts
def Test_expr7t()
def Test_expr7()
var lines =<< trim END
var ls: list<string> = ['a', <string>g:string_empty]
var ln: list<number> = [<number>g:anint, <number>g:thefour]
@@ -1743,7 +1743,7 @@ def Test_expr7t()
enddef
" test low level expression
def Test_expr7_number()
def Test_expr8_number()
# number constant
var lines =<< trim END
assert_equal(0, 0)
@@ -1756,7 +1756,7 @@ def Test_expr7_number()
CheckDefAndScriptSuccess(lines)
enddef
def Test_expr7_float()
def Test_expr8_float()
# float constant
if !has('float')
MissingFeature 'float'
@@ -1771,7 +1771,7 @@ def Test_expr7_float()
endif
enddef
def Test_expr7_blob()
def Test_expr8_blob()
# blob constant
var lines =<< trim END
assert_equal(g:blob_empty, 0z)
@@ -1803,7 +1803,7 @@ def Test_expr7_blob()
CheckDefAndScriptFailure(["var x = 0z123"], 'E973:', 1)
enddef
def Test_expr7_string()
def Test_expr8_string()
# string constant
var lines =<< trim END
assert_equal(g:string_empty, '')
@@ -1820,7 +1820,7 @@ def Test_expr7_string()
CheckDefAndScriptFailure(["var x = 'abc"], 'E115:', 1)
enddef
def Test_expr7_vimvar()
def Test_expr8_vimvar()
v:errors = []
var errs: list<string> = v:errors
CheckDefFailure(['var errs: list<number> = v:errors'], 'E1012:')
@@ -1845,7 +1845,7 @@ def Test_expr7_vimvar()
bwipe!
enddef
def Test_expr7_special()
def Test_expr8_special()
# special constant
var lines =<< trim END
assert_equal(g:special_true, true)
@@ -1882,7 +1882,7 @@ def Test_expr7_special()
CheckDefAndScriptFailure(['v:none = 22'], 'E46:', 1)
enddef
def Test_expr7_list()
def Test_expr8_list()
# list
var lines =<< trim END
assert_equal(g:list_empty, [])
@@ -1955,7 +1955,7 @@ def Test_expr7_list()
CheckDefAndScriptFailure(lines + ['echo numbers[a :b]'], 'E1004:', 4)
enddef
def Test_expr7_list_vim9script()
def Test_expr8_list_vim9script()
var lines =<< trim END
var l = [
11,
@@ -2043,7 +2043,7 @@ def LambdaUsingArg(x: number): func
x == 2
enddef
def Test_expr7_lambda()
def Test_expr8_lambda()
var lines =<< trim END
var La = () => 'result'
# comment
@@ -2129,7 +2129,7 @@ def Test_expr7_lambda()
CheckDefAndScriptSuccess(lines)
enddef
def Test_expr7_lambda_block()
def Test_expr8_lambda_block()
var lines =<< trim END
var Func = (s: string): string => {
return 'hello ' .. s
@@ -2209,7 +2209,7 @@ def NewLambdaUsingArg(x: number): func
x == 2
enddef
def Test_expr7_new_lambda()
def Test_expr8_new_lambda()
var lines =<< trim END
var La = () => 'result'
assert_equal('result', La())
@@ -2294,7 +2294,7 @@ def Test_expr7_new_lambda()
CheckDefAndScriptFailure(['var Fx = (a) => [0', ' 1]'], 'E696:', 2)
enddef
def Test_expr7_lambda_vim9script()
def Test_expr8_lambda_vim9script()
var lines =<< trim END
var v = 10->((a) =>
a
@@ -2313,7 +2313,7 @@ def Test_expr7_lambda_vim9script()
CheckDefAndScriptSuccess(lines)
enddef
def Test_expr7_funcref()
def Test_expr8_funcref()
var lines =<< trim END
def RetNumber(): number
return 123
@@ -2350,7 +2350,7 @@ enddef
let g:test_space_dict = {'': 'empty', ' ': 'space'}
let g:test_hash_dict = #{one: 1, two: 2}
def Test_expr7_dict()
def Test_expr8_dict()
# dictionary
var lines =<< trim END
assert_equal(g:dict_empty, {})
@@ -2461,7 +2461,7 @@ def Test_expr7_dict()
CheckDefExecAndScriptFailure(['{}[getftype("file")]'], 'E716: Key not present in Dictionary: ""', 1)
enddef
def Test_expr7_dict_vim9script()
def Test_expr8_dict_vim9script()
var lines =<< trim END
var d = {
['one']:
@@ -2592,7 +2592,7 @@ def Test_expr7_dict_vim9script()
CheckScriptSuccess(lines)
enddef
def Test_expr7_dict_in_block()
def Test_expr8_dict_in_block()
var lines =<< trim END
vim9script
command MyCommand {
@@ -2615,7 +2615,7 @@ def Test_expr7_dict_in_block()
delcommand YourCommand
enddef
def Test_expr7_call_2bool()
def Test_expr8_call_2bool()
var lines =<< trim END
vim9script
@@ -2663,7 +2663,7 @@ def Test_expr_member()
CheckDefExecAndScriptFailure(["var d: dict<number>", "d = g:list_empty"], 'E1012: Type mismatch; expected dict<number> but got list<unknown>', 2)
enddef
def Test_expr7_any_index_slice()
def Test_expr8_any_index_slice()
var lines =<< trim END
# getting the one member should clear the list only after getting the item
assert_equal('bbb', ['aaa', 'bbb', 'ccc'][1])
@@ -2817,7 +2817,7 @@ def SetSomeVar()
b:someVar = &fdm
enddef
def Test_expr7_option()
def Test_expr8_option()
var lines =<< trim END
# option
set ts=11
@@ -2844,7 +2844,7 @@ def Test_expr7_option()
CheckDefAndScriptSuccess(lines)
enddef
def Test_expr7_environment()
def Test_expr8_environment()
var lines =<< trim END
# environment variable
assert_equal('testvar', $TESTVAR)
@@ -2856,7 +2856,7 @@ def Test_expr7_environment()
CheckDefAndScriptFailure(["$"], ['E1002:', 'E15:'], 1)
enddef
def Test_expr7_register()
def Test_expr8_register()
var lines =<< trim END
@a = 'register a'
assert_equal('register a', @a)
@@ -2882,7 +2882,7 @@ def Test_expr7_register()
enddef
" This is slow when run under valgrind.
def Test_expr7_namespace()
def Test_expr8_namespace()
var lines =<< trim END
g:some_var = 'some'
assert_equal('some', get(g:, 'some_var'))
@@ -2911,7 +2911,7 @@ def Test_expr7_namespace()
CheckDefAndScriptSuccess(lines)
enddef
def Test_expr7_namespace_loop_def()
def Test_expr8_namespace_loop_def()
var lines =<< trim END
# check using g: in a for loop more than DO_NOT_FREE_CNT times
var exists = 0
@@ -2930,8 +2930,8 @@ def Test_expr7_namespace_loop_def()
enddef
" NOTE: this is known to be slow. To skip use:
" :let $TEST_SKIP_PAT = 'Test_expr7_namespace_loop_script'
def Test_expr7_namespace_loop_script()
" :let $TEST_SKIP_PAT = 'Test_expr8_namespace_loop_script'
def Test_expr8_namespace_loop_script()
var lines =<< trim END
vim9script
# check using g: in a for loop more than DO_NOT_FREE_CNT times
@@ -2950,7 +2950,7 @@ def Test_expr7_namespace_loop_script()
CheckScriptSuccess(lines)
enddef
def Test_expr7_parens()
def Test_expr8_parens()
# (expr)
var lines =<< trim END
assert_equal(4, (6 * 4) / 6)
@@ -2982,7 +2982,7 @@ def Test_expr7_parens()
CheckDefAndScriptSuccess(lines)
enddef
def Test_expr7_negate_add()
def Test_expr8_negate_add()
var lines =<< trim END
assert_equal(-99, -99)
assert_equal(-99, - 99)
@@ -3031,7 +3031,7 @@ def LegacyReturn(): string
legacy return #{key: 'ok'}.key
enddef
def Test_expr7_legacy_script()
def Test_expr8_legacy_script()
var lines =<< trim END
let s:legacy = 'legacy'
def GetLocal(): string
@@ -3065,7 +3065,7 @@ def s:Echo4Arg(arg: any): string
return arg
enddef
def Test_expr7_call()
def Test_expr8_call()
var lines =<< trim END
assert_equal('yes', 'yes'->Echo())
assert_equal(true, !range(5)->empty())
@@ -3098,7 +3098,7 @@ def Test_expr7_call()
delete('Xruntime', 'rf')
enddef
def Test_expr7_method_call()
def Test_expr8_method_call()
var lines =<< trim END
new
setline(1, ['first', 'last'])
@@ -3175,7 +3175,7 @@ def Test_expr7_method_call()
CheckDefExecFailure(lines, 'E1013:')
enddef
def Test_expr7_method_call_linebreak()
def Test_expr8_method_call_linebreak()
# this was giving an error when skipping over the expression
var lines =<< trim END
vim9script
@@ -3191,8 +3191,42 @@ def Test_expr7_method_call_linebreak()
CheckScriptSuccess(lines)
enddef
def Test_expr8_method_call_import()
var lines =<< trim END
vim9script
export def Square(items: list<number>): list<number>
return map(items, (_, i) => i * i)
enddef
END
call writefile(lines, 'Xsquare.vim')
def Test_expr7_not()
lines =<< trim END
vim9script
import './Xsquare.vim'
def Test(): list<number>
return range(5)
->Xsquare.Square()
->map((_, i) => i * 10)
enddef
assert_equal([0, 10, 40, 90, 160], Test())
END
CheckScriptSuccess(lines)
lines =<< trim END
vim9script
import './Xsquare.vim'
echo range(5)->Xsquare.NoSuchFunc()
END
CheckScriptFailure(lines, 'E1048: Item not found in script: NoSuchFunc')
delete('Xsquare.vim')
enddef
def Test_expr8_not()
var lines =<< trim END
assert_equal(true, !'')
assert_equal(true, ![])
@@ -3244,7 +3278,7 @@ enddef
let g:anumber = 42
def Test_expr7_negate()
def Test_expr8_negate()
var lines =<< trim END
var nr = 1
assert_equal(-1, -nr)
@@ -3253,7 +3287,7 @@ def Test_expr7_negate()
CheckDefAndScriptSuccess(lines)
enddef
func Test_expr7_fails()
func Test_expr8_fails()
call CheckDefFailure(["var x = (12"], "E1097:", 3)
call CheckScriptFailure(['vim9script', "var x = (12"], 'E110:', 2)
@@ -3313,7 +3347,7 @@ func CallMe2(one, two)
return a:one .. a:two
endfunc
def Test_expr7_trailing()
def Test_expr8_trailing()
var lines =<< trim END
# user function call
assert_equal(123, g:CallMe(123))
@@ -3349,7 +3383,7 @@ def Test_expr7_trailing()
CheckDefAndScriptSuccess(lines)
enddef
def Test_expr7_string_subscript()
def Test_expr8_string_subscript()
var lines =<< trim END
var text = 'abcdef'
assert_equal('f', text[-1])
@@ -3448,7 +3482,7 @@ def Test_expr7_string_subscript()
CheckDefAndScriptFailure(lines, ['E1012: Type mismatch; expected number but got string', 'E1030: Using a String as a Number: "2"'], 1)
enddef
def Test_expr7_list_subscript()
def Test_expr8_list_subscript()
var lines =<< trim END
var list = [0, 1, 2, 3, 4]
assert_equal(0, list[0])
@@ -3491,7 +3525,7 @@ def Test_expr7_list_subscript()
CheckDefAndScriptSuccess(lines)
enddef
def Test_expr7_dict_subscript()
def Test_expr8_dict_subscript()
var lines =<< trim END
var l = [{lnum: 2}, {lnum: 1}]
var res = l[0].lnum > l[1].lnum
@@ -3512,7 +3546,7 @@ def Test_expr7_dict_subscript()
CheckDefAndScriptSuccess(lines)
enddef
def Test_expr7_blob_subscript()
def Test_expr8_blob_subscript()
var lines =<< trim END
var b = 0z112233
assert_equal(0x11, b[0])
@@ -3524,7 +3558,7 @@ def Test_expr7_blob_subscript()
CheckDefAndScriptSuccess(lines)
enddef
def Test_expr7_subscript_linebreak()
def Test_expr8_subscript_linebreak()
var lines =<< trim END
var range = range(
3)
@@ -3567,7 +3601,7 @@ def Test_expr7_subscript_linebreak()
CheckDefAndScriptFailure(lines, ['E1127:', 'E116:'], 2)
enddef
func Test_expr7_trailing_fails()
func Test_expr8_trailing_fails()
call CheckDefAndScriptFailure(['var l = [2]', 'l->((ll) => add(ll, 8))'], 'E107:', 2)
call CheckDefAndScriptFailure(['var l = [2]', 'l->((ll) => add(ll, 8)) ()'], 'E274:', 2)
endfunc
+14
View File
@@ -341,6 +341,20 @@ def Test_return_something()
ReturnString()->assert_equal('string')
ReturnNumber()->assert_equal(123)
assert_fails('ReturnGlobal()', 'E1012: Type mismatch; expected number but got string', '', 1, 'ReturnGlobal')
var lines =<< trim END
vim9script
def Msg()
echomsg 'in Msg()...'
enddef
def Func()
return Msg()
enddef
defcompile
END
CheckScriptFailure(lines, 'E1096:')
enddef
def Test_check_argument_type()
+193 -9
View File
@@ -580,6 +580,29 @@ def Test_use_import_in_mapping()
nunmap <F3>
enddef
def Test_use_import_in_completion()
var lines =<< trim END
vim9script
export def Complete(..._): list<string>
return ['abcd']
enddef
END
writefile(lines, 'Xscript.vim')
lines =<< trim END
vim9script
import './Xscript.vim'
command -nargs=1 -complete=customlist,Xscript.Complete Cmd echo 'ok'
feedkeys(":Cmd ab\<Tab>\<C-B>#\<CR>", 'xnt')
assert_equal('#Cmd abcd', @:)
END
CheckScriptSuccess(lines)
delcommand Cmd
delete('Xscript.vim')
enddef
def Test_export_fails()
CheckScriptFailure(['export var some = 123'], 'E1042:')
CheckScriptFailure(['vim9script', 'export var g:some'], 'E1022:')
@@ -1173,9 +1196,9 @@ def Test_vim9script_autoload()
var save_rtp = &rtp
exe 'set rtp^=' .. getcwd() .. '/Xdir'
# when using "vim9script autoload" prefix is not needed
# when the path has "/autoload/" prefix is not needed
var lines =<< trim END
vim9script autoload
vim9script
g:prefixed_loaded += 1
export def Gettest(): string
@@ -1233,13 +1256,147 @@ def Test_vim9script_autoload()
&rtp = save_rtp
enddef
def Test_import_autoload_not_exported()
mkdir('Xdir/autoload', 'p')
var save_rtp = &rtp
exe 'set rtp^=' .. getcwd() .. '/Xdir'
# error when using an item that is not exported from an autoload script
var exportLines =<< trim END
vim9script
var notExported = 123
def NotExport()
echo 'nop'
enddef
END
writefile(exportLines, 'Xdir/autoload/notExport1.vim')
var lines =<< trim END
vim9script
import autoload 'notExport1.vim'
echo notExport1.notFound
END
CheckScriptFailure(lines, 'E1048: Item not found in script: notFound')
lines =<< trim END
vim9script
import autoload 'notExport1.vim'
echo notExport1.notExported
END
CheckScriptFailure(lines, 'E1049: Item not exported in script: notExported')
lines =<< trim END
vim9script
import autoload 'notExport1.vim'
echo notExport1.NotFunc()
END
CheckScriptFailure(lines, 'E1048: Item not found in script: NotFunc')
lines =<< trim END
vim9script
import autoload 'notExport1.vim'
echo notExport1.NotExport()
END
CheckScriptFailure(lines, 'E1049: Item not exported in script: NotExport')
lines =<< trim END
vim9script
import autoload 'notExport1.vim'
echo 'text'->notExport1.NotFunc()
END
CheckScriptFailure(lines, 'E1048: Item not found in script: NotFunc')
lines =<< trim END
vim9script
import autoload 'notExport1.vim'
echo 'text'->notExport1.NotExport()
END
CheckScriptFailure(lines, 'E1049: Item not exported in script: NotExport')
# using a :def function we use a different autoload script every time so that
# the function is compiled without the script loaded
writefile(exportLines, 'Xdir/autoload/notExport2.vim')
lines =<< trim END
vim9script
import autoload 'notExport2.vim'
def Testit()
echo notExport2.notFound
enddef
Testit()
END
CheckScriptFailure(lines, 'E1048: Item not found in script: notExport2#notFound')
writefile(exportLines, 'Xdir/autoload/notExport3.vim')
lines =<< trim END
vim9script
import autoload 'notExport3.vim'
def Testit()
echo notExport3.notExported
enddef
Testit()
END
# don't get E1049 because it is too complicated to figure out
CheckScriptFailure(lines, 'E1048: Item not found in script: notExport3#notExported')
writefile(exportLines, 'Xdir/autoload/notExport4.vim')
lines =<< trim END
vim9script
import autoload 'notExport4.vim'
def Testit()
echo notExport4.NotFunc()
enddef
Testit()
END
CheckScriptFailure(lines, 'E117: Unknown function: notExport4#NotFunc')
writefile(exportLines, 'Xdir/autoload/notExport5.vim')
lines =<< trim END
vim9script
import autoload 'notExport5.vim'
def Testit()
echo notExport5.NotExport()
enddef
Testit()
END
CheckScriptFailure(lines, 'E117: Unknown function: notExport5#NotExport')
writefile(exportLines, 'Xdir/autoload/notExport6.vim')
lines =<< trim END
vim9script
import autoload 'notExport6.vim'
def Testit()
echo 'text'->notExport6.NotFunc()
enddef
Testit()
END
CheckScriptFailure(lines, 'E117: Unknown function: notExport6#NotFunc')
writefile(exportLines, 'Xdir/autoload/notExport7.vim')
lines =<< trim END
vim9script
import autoload 'notExport7.vim'
def Testit()
echo 'text'->notExport7.NotExport()
enddef
Testit()
END
CheckScriptFailure(lines, 'E117: Unknown function: notExport7#NotExport')
delete('Xdir', 'rf')
&rtp = save_rtp
enddef
def Test_vim9script_autoload_call()
mkdir('Xdir/autoload', 'p')
var save_rtp = &rtp
exe 'set rtp^=' .. getcwd() .. '/Xdir'
var lines =<< trim END
vim9script autoload
vim9script
export def RetArg(arg: string): string
return arg
enddef
export def Getother()
g:result = 'other'
@@ -1250,6 +1407,13 @@ def Test_vim9script_autoload_call()
lines =<< trim END
vim9script
import autoload 'another.vim'
# compile this before 'another.vim' is loaded
def CallAnother()
assert_equal('foo', 'foo'->another.RetArg())
enddef
CallAnother()
call another.Getother()
assert_equal('other', g:result)
END
@@ -1266,7 +1430,7 @@ def Test_import_autoload_postponed()
exe 'set rtp^=' .. getcwd() .. '/Xdir'
var lines =<< trim END
vim9script autoload
vim9script
g:loaded_postponed = 'true'
export var variable = 'bla'
@@ -1303,7 +1467,7 @@ def Test_import_autoload_override()
test_override('autoload', 1)
var lines =<< trim END
vim9script autoload
vim9script
g:loaded_override = 'true'
export var variable = 'bla'
@@ -1338,7 +1502,7 @@ def Test_autoload_mapping()
exe 'set rtp^=' .. getcwd() .. '/Xdir'
var lines =<< trim END
vim9script autoload
vim9script
g:toggle_loaded = 'yes'
@@ -1363,10 +1527,12 @@ def Test_autoload_mapping()
CheckScriptSuccess(lines)
assert_false(exists("g:toggle_loaded"))
assert_false(exists("g:toggle_called"))
assert_match('\d A: \f*[/\\]toggle.vim', execute('scriptnames'))
feedkeys("tt", 'xt')
assert_equal('yes', g:toggle_loaded)
assert_equal('yes', g:toggle_called)
assert_match('\d: \f*[/\\]toggle.vim', execute('scriptnames'))
feedkeys("xx", 'xt')
assert_equal('yes', g:doit_called)
@@ -1387,7 +1553,13 @@ def Test_vim9script_autoload_fails()
vim9script autoload
var n = 0
END
CheckScriptFailure(lines, 'E1263:')
CheckScriptFailure(lines, 'E475: Invalid argument: autoload')
lines =<< trim END
vim9script noclear noclear
var n = 0
END
CheckScriptFailure(lines, 'E983: Duplicate argument: noclear')
enddef
def Test_import_autoload_fails()
@@ -1399,9 +1571,21 @@ def Test_import_autoload_fails()
lines =<< trim END
vim9script
import autoload 'doesNotExist.vim'
import autoload './doesNotExist.vim'
END
CheckScriptFailure(lines, 'E1264:')
lines =<< trim END
vim9script
import autoload '/dir/doesNotExist.vim'
END
CheckScriptFailure(lines, 'E1264:')
lines =<< trim END
vim9script
import autoload 'doesNotExist.vim'
END
CheckScriptFailure(lines, 'E1053: Could not import "doesNotExist.vim"')
enddef
" test disassembling an auto-loaded function starting with "debug"
@@ -1468,7 +1652,7 @@ enddef
" test using a autoloaded file that is case sensitive
def Test_vim9_autoload_case_sensitive()
var lines =<< trim END
vim9script autoload
vim9script
export def CaseSensitive(): string
return 'done'
enddef
+11
View File
@@ -1278,6 +1278,17 @@ func Test_visual_block_ctrl_w_f()
au! BufNew
endfunc
func Test_visual_block_append_invalid_char()
" this was going over the end of the line
set isprint=@,161-255
new
call setline(1, [' let xxx', 'xxxxxˆ', 'xxxxxxxxxxx'])
exe "normal 0\<C-V>jjA-\<Esc>"
call assert_equal([' - let xxx', 'xxxxx -ˆ', 'xxxxxxxx-xxx'], getline(1, 3))
bwipe!
set isprint&
endfunc
func Test_visual_reselect_with_count()
" this was causing an illegal memory access
let lines =<< trim END
+9
View File
@@ -548,6 +548,15 @@ uc_list(char_u *name, size_t name_len)
{
STRCPY(IObuff + len, command_complete[j].name);
len += (int)STRLEN(IObuff + len);
#ifdef FEAT_EVAL
if (p_verbose > 0 && cmd->uc_compl_arg != NULL
&& STRLEN(cmd->uc_compl_arg) < 200)
{
IObuff[len] = ',';
STRCPY(IObuff + len + 1, cmd->uc_compl_arg);
len += (int)STRLEN(IObuff + len);
}
#endif
break;
}
+16 -4
View File
@@ -3119,18 +3119,30 @@ free_all_functions(void)
/*
* Return TRUE if "name" looks like a builtin function name: starts with a
* lower case letter and doesn't contain AUTOLOAD_CHAR or ':'.
* lower case letter, doesn't contain AUTOLOAD_CHAR or ':', no "." after the
* name.
* "len" is the length of "name", or -1 for NUL terminated.
*/
int
builtin_function(char_u *name, int len)
{
char_u *p;
int i;
if (!ASCII_ISLOWER(name[0]) || name[1] == ':')
return FALSE;
p = vim_strchr(name, AUTOLOAD_CHAR);
return p == NULL || (len > 0 && p > name + len);
for (i = 0; name[i] != NUL && (len < 0 || i < len); ++i)
{
if (name[i] == AUTOLOAD_CHAR)
return FALSE;
if (!eval_isnamec(name[i]))
{
// "name.something" is not a builtin function
if (name[i] == '.')
return FALSE;
break;
}
}
return TRUE;
}
int
+46
View File
@@ -765,6 +765,52 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
4141,
/**/
4140,
/**/
4139,
/**/
4138,
/**/
4137,
/**/
4136,
/**/
4135,
/**/
4134,
/**/
4133,
/**/
4132,
/**/
4131,
/**/
4130,
/**/
4129,
/**/
4128,
/**/
4127,
/**/
4126,
/**/
4125,
/**/
4124,
/**/
4123,
/**/
4122,
/**/
4121,
/**/
4120,
/**/
4119,
/**/
4118,
/**/
+5 -7
View File
@@ -2196,6 +2196,11 @@ compile_return(char_u *arg, int check_return_type, int legacy, cctx_T *cctx)
if (*p != NUL && *p != '|' && *p != '\n')
{
if (cctx->ctx_ufunc->uf_ret_type->tt_type == VAR_VOID)
{
emsg(_(e_returning_value_in_function_without_return_type));
return NULL;
}
if (legacy)
{
int save_flags = cmdmod.cmod_flags;
@@ -2231,13 +2236,6 @@ compile_return(char_u *arg, int check_return_type, int legacy, cctx_T *cctx)
}
else
{
if (cctx->ctx_ufunc->uf_ret_type->tt_type == VAR_VOID
&& stack_type->tt_type != VAR_VOID
&& stack_type->tt_type != VAR_UNKNOWN)
{
emsg(_(e_returning_value_in_function_without_return_type));
return NULL;
}
if (need_type(stack_type, cctx->ctx_ufunc->uf_ret_type, -1,
0, cctx, FALSE, FALSE) == FAIL)
return NULL;
+18 -8
View File
@@ -2200,10 +2200,12 @@ exec_instructions(ectx_T *ectx)
case ISN_LOADW:
case ISN_LOADT:
{
dictitem_T *di = NULL;
hashtab_T *ht = NULL;
char namespace;
dictitem_T *di = NULL;
hashtab_T *ht = NULL;
char namespace;
if (GA_GROW_FAILS(&ectx->ec_stack, 1))
goto theend;
switch (iptr->isn_type)
{
case ISN_LOADG:
@@ -2227,9 +2229,12 @@ exec_instructions(ectx_T *ectx)
}
di = find_var_in_ht(ht, 0, iptr->isn_arg.string, TRUE);
if (di == NULL && ht == get_globvar_ht())
if (di == NULL && ht == get_globvar_ht()
&& vim_strchr(iptr->isn_arg.string,
AUTOLOAD_CHAR) != NULL)
{
// may need to load autoload script
// Global variable has an autoload name, may still need
// to load the script.
if (script_autoload(iptr->isn_arg.string, FALSE))
di = find_var_in_ht(ht, 0,
iptr->isn_arg.string, TRUE);
@@ -2240,14 +2245,19 @@ exec_instructions(ectx_T *ectx)
if (di == NULL)
{
SOURCING_LNUM = iptr->isn_lnum;
semsg(_(e_undefined_variable_char_str),
if (vim_strchr(iptr->isn_arg.string,
AUTOLOAD_CHAR) != NULL)
// no check if the item exists in the script but
// isn't exported, it is too complicated
semsg(_(e_item_not_found_in_script_str),
iptr->isn_arg.string);
else
semsg(_(e_undefined_variable_char_str),
namespace, iptr->isn_arg.string);
goto on_error;
}
else
{
if (GA_GROW_FAILS(&ectx->ec_stack, 1))
goto theend;
copy_tv(&di->di_tv, STACK_TV_BOT(0));
++ectx->ec_stack.ga_len;
}
+26 -10
View File
@@ -21,6 +21,9 @@
# include "vim9.h"
#endif
// flag passed from compile_subscript() to compile_load_scriptvar()
static int paren_follows_after_expr = 0;
/*
* Generate code for any ppconst entries.
*/
@@ -277,7 +280,6 @@ compile_load_scriptvar(
int done = FALSE;
int res = OK;
// TODO: if this is an autoload import do something else.
// Need to lookup the member.
if (*p != '.')
{
@@ -306,7 +308,7 @@ compile_load_scriptvar(
// autoload script must be loaded later, access by the autoload
// name.
if (cc == '(')
if (cc == '(' || paren_follows_after_expr)
res = generate_PUSHFUNC(cctx, auto_name, &t_func_any);
else
res = generate_LOAD(cctx, ISN_LOADG, 0, auto_name, &t_any);
@@ -1732,21 +1734,30 @@ compile_subscript(
}
else
{
int fail;
int save_len = cctx->ctx_ufunc->uf_lines.ga_len;
*paren = NUL;
if (compile_expr8(arg, cctx, ppconst) == FAIL
|| *skipwhite(*arg) != NUL)
// instead of using LOADG for "import.Func" use PUSHFUNC
++paren_follows_after_expr;
// do not look in the next line
cctx->ctx_ufunc->uf_lines.ga_len = 1;
fail = compile_expr8(arg, cctx, ppconst) == FAIL
|| *skipwhite(*arg) != NUL;
*paren = '(';
--paren_follows_after_expr;
cctx->ctx_ufunc->uf_lines.ga_len = save_len;
if (fail)
{
*paren = '(';
semsg(_(e_invalid_expression_str), pstart);
return FAIL;
}
*paren = '(';
}
// Remember the next instruction index, where the instructions
// for arguments are being written.
expr_isn_end = cctx->ctx_instr.ga_len;
// Compile the arguments.
if (**arg != '(')
{
@@ -1756,6 +1767,11 @@ compile_subscript(
semsg(_(e_missing_parenthesis_str), *arg);
return FAIL;
}
// Remember the next instruction index, where the instructions
// for arguments are being written.
expr_isn_end = cctx->ctx_instr.ga_len;
*arg = skipwhite(*arg + 1);
if (compile_arguments(arg, cctx, &argcount, FALSE) == FAIL)
return FAIL;
+28 -23
View File
@@ -69,7 +69,6 @@ ex_vim9script(exarg_T *eap UNUSED)
int sid = current_sctx.sc_sid;
scriptitem_T *si;
int found_noclear = FALSE;
int found_autoload = FALSE;
char_u *p;
if (!getline_equal(eap->getline, eap->cookie, getsourceline))
@@ -96,20 +95,6 @@ ex_vim9script(exarg_T *eap UNUSED)
}
found_noclear = TRUE;
}
else if (STRNCMP(p, "autoload", 8) == 0 && IS_WHITE_OR_NUL(p[8]))
{
if (found_autoload)
{
semsg(_(e_duplicate_argument_str), p);
return;
}
found_autoload = TRUE;
if (script_name_after_autoload(si) == NULL)
{
emsg(_(e_using_autoload_in_script_not_under_autoload_directory));
return;
}
}
else
{
semsg(_(e_invalid_argument_str), eap->arg);
@@ -411,7 +396,7 @@ handle_import(
int ret = FAIL;
char_u *as_name = NULL;
typval_T tv;
int sid = -1;
int sid = -2;
int res;
long start_lnum = SOURCING_LNUM;
garray_T *import_gap;
@@ -468,7 +453,13 @@ handle_import(
vim_free(from_name);
}
}
else if (mch_isFullName(tv.vval.v_string))
else if (mch_isFullName(tv.vval.v_string)
#ifdef BACKSLASH_IN_FILENAME
// On MS-Windows omitting the drive is still handled like an
// absolute path, not using 'runtimepath'.
|| *tv.vval.v_string == '/' || *tv.vval.v_string == '\\'
#endif
)
{
// Absolute path: "/tmp/name.vim"
if (is_autoload)
@@ -519,7 +510,7 @@ handle_import(
if (res == FAIL || sid <= 0)
{
semsg(_(is_autoload && sid <= 0
semsg(_(is_autoload && sid == -2
? e_autoload_import_cannot_use_absolute_or_relative_path
: e_could_not_import_str), tv.vval.v_string);
goto erret;
@@ -716,22 +707,36 @@ find_exported(
sprintf((char *)funcname + 3, "%ld_%s", (long)sid, name);
}
*ufunc = find_func(funcname, FALSE);
if (funcname != buffer)
vim_free(funcname);
if (*ufunc == NULL)
{
if (verbose)
semsg(_(e_item_not_found_in_script_str), name);
return -1;
{
ufunc_T *alt_ufunc = NULL;
if (script->sn_autoload_prefix != NULL)
{
// try find the function by the script-local name
funcname[0] = K_SPECIAL;
funcname[1] = KS_EXTRA;
funcname[2] = (int)KE_SNR;
sprintf((char *)funcname + 3, "%ld_%s", (long)sid, name);
alt_ufunc = find_func(funcname, FALSE);
}
if (alt_ufunc != NULL)
semsg(_(e_item_not_exported_in_script_str), name);
else
semsg(_(e_item_not_found_in_script_str), name);
}
}
else if (((*ufunc)->uf_flags & FC_EXPORT) == 0)
{
if (verbose)
semsg(_(e_item_not_exported_in_script_str), name);
*ufunc = NULL;
return -1;
}
if (funcname != buffer)
vim_free(funcname);
}
return idx;