diff options
author | Justin M. Keyes <justinkz@gmail.com> | 2021-10-17 06:20:35 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-17 06:20:35 -0700 |
commit | 30af69509dc91552dc41451857b18907f018c1bd (patch) | |
tree | 7700d6d0b75e59ba40c351c328c3cf151b81e88c /src | |
parent | f19dc0608161622f7786eb3cddee27d086cc3ea3 (diff) | |
parent | da9b0abc67a936021a4ecf7634395db860edcab1 (diff) | |
download | rneovim-30af69509dc91552dc41451857b18907f018c1bd.tar.gz rneovim-30af69509dc91552dc41451857b18907f018c1bd.tar.bz2 rneovim-30af69509dc91552dc41451857b18907f018c1bd.zip |
Merge #15994 feat(:source, nvim_exec): script-local scope
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/eval.c | 6 | ||||
-rw-r--r-- | src/nvim/ex_cmds2.c | 80 | ||||
-rw-r--r-- | src/nvim/ex_cmds2.h | 25 | ||||
-rw-r--r-- | src/nvim/globals.h | 2 |
4 files changed, 66 insertions, 47 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c index b19ea36bd5..e6a3901dcf 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -9191,8 +9191,12 @@ static hashtab_T *find_var_ht_dict(const char *name, const size_t name_len, cons } else if (*name == 'l' && funccal != NULL) { // local variable *d = &funccal->l_vars; } else if (*name == 's' // script variable - && current_sctx.sc_sid > 0 + && (current_sctx.sc_sid > 0 || current_sctx.sc_sid == SID_STR) && current_sctx.sc_sid <= ga_scripts.ga_len) { + // For anonymous scripts without a script item, create one now so script vars can be used + if (current_sctx.sc_sid == SID_STR) { + new_script_item(NULL, ¤t_sctx.sc_sid); + } *d = &SCRIPT_SV(current_sctx.sc_sid)->sv_dict; } diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c index 40a2960a85..5d40d7a16a 100644 --- a/src/nvim/ex_cmds2.c +++ b/src/nvim/ex_cmds2.c @@ -52,33 +52,7 @@ #include "nvim/version.h" #include "nvim/window.h" - /// Growarray to store info about already sourced scripts. -/// Also store the dev/ino, so that we don't have to stat() each -/// script when going through the list. -typedef struct scriptitem_S { - char_u *sn_name; - bool file_id_valid; - FileID file_id; - bool sn_prof_on; ///< true when script is/was profiled - bool sn_pr_force; ///< forceit: profile functions in this script - proftime_T sn_pr_child; ///< time set when going into first child - int sn_pr_nest; ///< nesting for sn_pr_child - // profiling the script as a whole - int sn_pr_count; ///< nr of times sourced - proftime_T sn_pr_total; ///< time spent in script + children - proftime_T sn_pr_self; ///< time spent in script itself - proftime_T sn_pr_start; ///< time at script start - proftime_T sn_pr_children; ///< time in children after script start - // profiling the script per line - garray_T sn_prl_ga; ///< things stored for every line - proftime_T sn_prl_start; ///< start time for current line - proftime_T sn_prl_children; ///< time spent in children for this line - proftime_T sn_prl_wait; ///< wait start time for current line - linenr_T sn_prl_idx; ///< index of line being timed; -1 if none - int sn_prl_execed; ///< line being timed was executed -} scriptitem_T; - static garray_T script_items = { 0, 0, sizeof(scriptitem_T), 4, NULL }; #define SCRIPT_ITEM(id) (((scriptitem_T *)script_items.ga_data)[(id) - 1]) @@ -1939,6 +1913,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. +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; @@ -2036,7 +2033,6 @@ int do_source(char *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 +2179,7 @@ int do_source(char *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, ¤t_sctx.sc_sid); fname_exp = vim_strsave(si->sn_name); // used for autocmd if (file_id_ok) { si->file_id_valid = true; @@ -2199,9 +2187,6 @@ int do_source(char *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 +2360,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); + } } } diff --git a/src/nvim/ex_cmds2.h b/src/nvim/ex_cmds2.h index de4e1429b7..d426ff28f8 100644 --- a/src/nvim/ex_cmds2.h +++ b/src/nvim/ex_cmds2.h @@ -16,6 +16,31 @@ #define CCGD_ALLBUF 8 // may write all buffers #define CCGD_EXCMD 16 // may suggest using ! +/// Also store the dev/ino, so that we don't have to stat() each +/// script when going through the list. +typedef struct scriptitem_S { + char_u *sn_name; + bool file_id_valid; + FileID file_id; + bool sn_prof_on; ///< true when script is/was profiled + bool sn_pr_force; ///< forceit: profile functions in this script + proftime_T sn_pr_child; ///< time set when going into first child + int sn_pr_nest; ///< nesting for sn_pr_child + // profiling the script as a whole + int sn_pr_count; ///< nr of times sourced + proftime_T sn_pr_total; ///< time spent in script + children + proftime_T sn_pr_self; ///< time spent in script itself + proftime_T sn_pr_start; ///< time at script start + proftime_T sn_pr_children; ///< time in children after script start + // profiling the script per line + garray_T sn_prl_ga; ///< things stored for every line + proftime_T sn_prl_start; ///< start time for current line + proftime_T sn_prl_children; ///< time spent in children for this line + proftime_T sn_prl_wait; ///< wait start time for current line + linenr_T sn_prl_idx; ///< index of line being timed; -1 if none + int sn_prl_execed; ///< line being timed was executed +} scriptitem_T; + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "ex_cmds2.h.generated.h" #endif diff --git a/src/nvim/globals.h b/src/nvim/globals.h index 1d120bbe6b..8a36b3bedd 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -335,7 +335,7 @@ EXTERN int garbage_collect_at_exit INIT(= false); #define SID_WINLAYOUT -7 // changing window size #define SID_LUA -8 // for Lua scripts/chunks #define SID_API_CLIENT -9 // for API clients -#define SID_STR -10 // for sourcing a string +#define SID_STR -10 // for sourcing a string with no script item // Script CTX being sourced or was sourced to define the current function. EXTERN sctx_T current_sctx INIT(= { 0 COMMA 0 COMMA 0 }); |