feat(:source, nvim_exec): support script-local variables

Based on #13143 (and #11507) with changes:

 - Omit script_type_E. Use sn_name == NULL to determine anon items.
 - Keep SID_STR. Used by anon :source for .lua files (no item).
 - Show SID in get_scriptname output (:verbose set).
 - Factor item creation into new_script_item.
 - Leave sc_seq = 0 (anon scripts don't re-use the same item when re-sourced).
 - Add tests for anon :source.

Co-authored-by: Vikram Pal <vikrampal659@gmail.com>
Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
This commit is contained in:
Sean Dewar
2021-10-09 22:13:11 +01:00
parent 6b9cb665fa
commit d4ed51eb44
4 changed files with 75 additions and 24 deletions

View File

@@ -1939,6 +1939,29 @@ static char_u *get_str_line(int c, void *cookie, int indent, bool do_concat)
return ga.ga_data;
}
/// Create a new script item and allocate script-local vars. @see new_script_vars
///
/// @param name File name of the script. NULL for anonymous :source.
/// @param[out] sid_out SID of the new item.
/// @return pointer to the created script item.
static scriptitem_T *new_script_item(char_u *const name, scid_T *const sid_out)
{
static scid_T last_current_SID = 0;
const scid_T sid = ++last_current_SID;
if (sid_out != NULL) {
*sid_out = sid;
}
ga_grow(&script_items, (int)(sid - script_items.ga_len));
while (script_items.ga_len < sid) {
script_items.ga_len++;
SCRIPT_ITEM(script_items.ga_len).sn_name = NULL;
SCRIPT_ITEM(script_items.ga_len).sn_prof_on = false;
}
SCRIPT_ITEM(sid).sn_name = name;
new_script_vars(sid); // Allocate the local script variables to use for this script.
return &SCRIPT_ITEM(sid);
}
static int source_using_linegetter(void *cookie, LineGetter fgetline, const char *traceback_name)
{
char_u *save_sourcing_name = sourcing_name;
@@ -1955,7 +1978,7 @@ static int source_using_linegetter(void *cookie, LineGetter fgetline, const char
sourcing_lnum = 0;
const sctx_T save_current_sctx = current_sctx;
current_sctx.sc_sid = SID_STR;
new_script_item(NULL, &current_sctx.sc_sid);
current_sctx.sc_seq = 0;
current_sctx.sc_lnum = save_sourcing_lnum;
funccal_entry_T entry;
@@ -2036,7 +2059,6 @@ int do_source(char_u *fname, int check_other, int is_vimrc)
char_u *fname_exp;
char_u *firstline = NULL;
int retval = FAIL;
static scid_T last_current_SID = 0;
static int last_current_SID_seq = 0;
int save_debug_break_level = debug_break_level;
scriptitem_T *si = NULL;
@@ -2183,15 +2205,7 @@ int do_source(char_u *fname, int check_other, int is_vimrc)
}
}
if (current_sctx.sc_sid == 0) {
current_sctx.sc_sid = ++last_current_SID;
ga_grow(&script_items, (int)(current_sctx.sc_sid - script_items.ga_len));
while (script_items.ga_len < current_sctx.sc_sid) {
script_items.ga_len++;
SCRIPT_ITEM(script_items.ga_len).sn_name = NULL;
SCRIPT_ITEM(script_items.ga_len).sn_prof_on = false;
}
si = &SCRIPT_ITEM(current_sctx.sc_sid);
si->sn_name = fname_exp;
si = new_script_item(fname_exp, &current_sctx.sc_sid);
fname_exp = vim_strsave(si->sn_name); // used for autocmd
if (file_id_ok) {
si->file_id_valid = true;
@@ -2199,9 +2213,6 @@ int do_source(char_u *fname, int check_other, int is_vimrc)
} else {
si->file_id_valid = false;
}
// Allocate the local script variables to use for this script.
new_script_vars(current_sctx.sc_sid);
}
if (l_do_profiling == PROF_YES) {
@@ -2375,16 +2386,21 @@ char_u *get_scriptname(LastSet last_set, bool *should_free)
case SID_LUA:
return (char_u *)_("Lua");
case SID_API_CLIENT:
vim_snprintf((char *)IObuff, IOSIZE,
_("API client (channel id %" PRIu64 ")"),
last_set.channel_id);
snprintf((char *)IObuff, IOSIZE, _("API client (channel id %" PRIu64 ")"), last_set.channel_id);
return IObuff;
case SID_STR:
return (char_u *)_("anonymous :source");
default:
default: {
char_u *const sname = SCRIPT_ITEM(last_set.script_ctx.sc_sid).sn_name;
if (sname == NULL) {
snprintf((char *)IObuff, IOSIZE, _("anonymous :source (script id %d)"),
last_set.script_ctx.sc_sid);
return IObuff;
}
*should_free = true;
return home_replace_save(NULL,
SCRIPT_ITEM(last_set.script_ctx.sc_sid).sn_name);
return home_replace_save(NULL, sname);
}
}
}