/* vi:set ts=8 sts=4 sw=4 noet:
*
* VIM - Vi IMproved by Bram Moolenaar
*
* Do ":help uganda" in Vim to read copying and usage conditions.
* Do ":help credits" in Vim to see a list of people who contributed.
* See README.txt for an overview of the Vim source code.
*/
/*
* vim9script.c: :vim9script, :import, :export and friends
*/
#include "vim.h"
// When not generating protos this is included in proto.h
#ifdef PROTO
# include "vim9.h"
#endif
/*
* Return TRUE when currently using Vim9 script syntax.
* Does not go up the stack, a ":function" inside vim9script uses legacy
* syntax.
*/
int
in_vim9script(void)
{
// "sc_version" is also set when compiling a ":def" function in legacy
// script.
return (current_sctx.sc_version == SCRIPT_VERSION_VIM9
|| (cmdmod.cmod_flags & CMOD_VIM9CMD))
&& !(cmdmod.cmod_flags & CMOD_LEGACY);
}
#if defined(FEAT_EVAL) || defined(PROTO)
/*
* Return TRUE when currently in a script with script version smaller than
* "max_version" or command modifiers forced it.
*/
int
in_old_script(int max_version)
{
return (current_sctx.sc_version < max_version
&& !(cmdmod.cmod_flags & CMOD_VIM9CMD))
|| (cmdmod.cmod_flags & CMOD_LEGACY);
}
/*
* Return TRUE if the current script is Vim9 script.
* This also returns TRUE in a legacy function in a Vim9 script.
*/
int
current_script_is_vim9(void)
{
return SCRIPT_ID_VALID(current_sctx.sc_sid)
&& SCRIPT_ITEM(current_sctx.sc_sid)->sn_version
== SCRIPT_VERSION_VIM9;
}
#endif
#ifdef FEAT_EVAL
/*
* Clear Vim9 script-local variables and functions.
*/
void
clear_vim9_scriptlocal_vars(int sid)
{
hashtab_T *ht = &SCRIPT_VARS(sid);
hashtab_free_contents(ht);
hash_init(ht);
delete_script_functions(sid);
// old imports and script variables are no longer valid
free_imports_and_script_vars(sid);
}
#endif
/*
* ":vim9script".
*/
void
ex_vim9script(exarg_T *eap UNUSED)
{
#ifdef FEAT_EVAL
int sid = current_sctx.sc_sid;
scriptitem_T *si;
int found_noclear = FALSE;
char_u *p;
if (!sourcing_a_script(eap))
{
emsg(_(e_vim9script_can_only_be_used_in_script));
return;
}
si = SCRIPT_ITEM(sid);
if (si->sn_state == SN_STATE_HAD_COMMAND)
{
emsg(_(e_vim9script_must_be_first_command_in_script));
return;
}
for (p = eap->arg; !IS_WHITE_OR_NUL(*p); p = skipwhite(skiptowhite(p)))
{
if (STRNCMP(p, "noclear", 7) == 0 && IS_WHITE_OR_NUL(p[7]))
{
if (found_noclear)
{
semsg(_(e_duplicate_argument_str), p);
return;
}
found_noclear = TRUE;
}
else
{
semsg(_(e_invalid_argument_str), eap->arg);
return;
}
}
if (si->sn_state == SN_STATE_RELOAD && !found_noclear)
// Reloading a script without the "noclear" argument: clear
// script-local variables and functions.
clear_vim9_scriptlocal_vars(sid);
si->sn_state = SN_STATE_HAD_COMMAND;
// Store the prefix with the script, it is used to find exported functions.
if (si->sn_autoload_prefix == NULL)
si->sn_autoload_prefix = get_autoload_prefix(si);
current_sctx.sc_version = SCRIPT_VERSION_VIM9;
si->sn_version = SCRIPT_VERSION_VIM9;
if (STRCMP(p_cpo, CPO_VIM) != 0)
{
si->sn_save_cpo = vim_strsave(p_cpo);
set_option_value((char_u *)"cpo", 0L, (char_u *)CPO_VIM, OPT_NO_REDRAW);
}
#else
// No check for this being the first command, it doesn't matter.
current_sctx.sc_version = SCRIPT_VERSION_VIM9;
#endif
}
#if defined(FEAT_EVAL) || defined(PROTO)
/*
* When in Vim9 script give an error and return FAIL.
*/
int
not_in_vim9(exarg_T *eap)
{
if (in_vim9script())
switch (eap->cmdidx)
{
case CMD_k:
if (eap->addr_count > 0)
{
emsg(_(e_no_range_allowed));
return FAIL;
}
// FALLTHROUGH
case CMD_append: