diff options
Diffstat (limited to 'src/nvim/runtime.c')
-rw-r--r-- | src/nvim/runtime.c | 76 |
1 files changed, 40 insertions, 36 deletions
diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c index c316b61082..c9667d58ed 100644 --- a/src/nvim/runtime.c +++ b/src/nvim/runtime.c @@ -78,6 +78,8 @@ garray_T script_items = { 0, 0, sizeof(scriptitem_T *), 20, NULL }; /// The names of packages that once were loaded are remembered. static garray_T ga_loaded = { 0, 0, sizeof(char *), 4, NULL }; +static int last_current_SID_seq = 0; + /// Initialize the execution stack. void estack_init(void) { @@ -266,7 +268,7 @@ void set_context_in_runtime_cmd(expand_T *xp, const char *arg) static void source_callback(char *fname, void *cookie) { - (void)do_source(fname, false, DOSO_NONE); + (void)do_source(fname, false, DOSO_NONE, cookie); } /// Find the file "name" in all directories in "path" and invoke @@ -855,7 +857,7 @@ static void source_all_matches(char *pat) } for (int i = 0; i < num_files; i++) { - (void)do_source(files[i], false, DOSO_NONE); + (void)do_source(files[i], false, DOSO_NONE, NULL); } FreeWild(num_files, files); } @@ -1701,7 +1703,7 @@ static void cmd_source(char *fname, exarg_T *eap) || eap->cstack->cs_idx >= 0); // ":source" read ex commands - } else if (do_source(fname, false, DOSO_NONE) == FAIL) { + } else if (do_source(fname, false, DOSO_NONE, NULL) == FAIL) { semsg(_(e_notopen), fname); } } @@ -1954,9 +1956,12 @@ int do_source_str(const char *cmd, const char *traceback_name) /// @param fname /// @param check_other check for .vimrc and _vimrc /// @param is_vimrc DOSO_ value +/// @param ret_sid if not NULL and we loaded the script before, don't load it again /// /// @return FAIL if file could not be opened, OK otherwise -int do_source(char *fname, int check_other, int is_vimrc) +/// +/// If a scriptitem_T was found or created "*ret_sid" is set to the SID. +int do_source(char *fname, int check_other, int is_vimrc, int *ret_sid) { struct source_cookie cookie; char *p; @@ -1982,6 +1987,15 @@ int do_source(char *fname, int check_other, int is_vimrc) goto theend; } + // See if we loaded this script before. + int sid = find_script_by_name(fname_exp); + if (sid > 0 && ret_sid != NULL) { + // Already loaded and no need to load again, return here. + *ret_sid = sid; + retval = OK; + goto theend; + } + // Apply SourceCmd autocommands, they should get the file and source it. if (has_autocmd(EVENT_SOURCECMD, fname_exp, NULL) && apply_autocmds(EVENT_SOURCECMD, fname_exp, fname_exp, @@ -2080,7 +2094,24 @@ int do_source(char *fname, int check_other, int is_vimrc) save_funccal(&funccalp_entry); const sctx_T save_current_sctx = current_sctx; - si = get_current_script_id(&fname_exp, ¤t_sctx); + + current_sctx.sc_lnum = 0; + + // Always use a new sequence number. + current_sctx.sc_seq = ++last_current_SID_seq; + + if (sid > 0) { + // loading the same script again + si = SCRIPT_ITEM(sid); + } else { + // It's new, generate a new SID. + si = new_script_item(fname_exp, &sid); + fname_exp = xstrdup(si->sn_name); // used for autocmd + if (ret_sid != NULL) { + *ret_sid = sid; + } + } + current_sctx.sc_sid = sid; // Keep the sourcing name/lnum, for recursive calls. estack_push(ETYPE_SCRIPT, si->sn_name, 0); @@ -2192,7 +2223,7 @@ theend: /// Find an already loaded script "name". /// If found returns its script ID. If not found returns -1. -static int find_script_by_name(char *name) +int find_script_by_name(char *name) { assert(script_items.ga_len >= 0); for (int sid = script_items.ga_len; sid > 0; sid--) { @@ -2209,35 +2240,6 @@ static int find_script_by_name(char *name) return -1; } -/// Check if fname was sourced before to finds its SID. -/// If it's new, generate a new SID. -/// -/// @param[in,out] fnamep pointer to file path of script -/// @param[out] ret_sctx sctx of this script -scriptitem_T *get_current_script_id(char **fnamep, sctx_T *ret_sctx) -{ - static int last_current_SID_seq = 0; - - scriptitem_T *si; - int sid = find_script_by_name(*fnamep); - if (sid > 0) { - si = SCRIPT_ITEM(sid); - } else { - si = new_script_item(*fnamep, &sid); - *fnamep = xstrdup(si->sn_name); - } - - sctx_T script_sctx = { .sc_seq = ++last_current_SID_seq, - .sc_lnum = 0, - .sc_sid = sid }; - - if (ret_sctx != NULL) { - *ret_sctx = script_sctx; - } - - return si; -} - /// ":scriptnames" void ex_scriptnames(exarg_T *eap) { @@ -2704,7 +2706,9 @@ bool script_autoload(const char *const name, const size_t name_len, const bool r } // Try loading the package from $VIMRUNTIME/autoload/<name>.vim - if (source_runtime(scriptname, 0) == OK) { + // Use "ret_sid" to avoid loading the same script again. + int ret_sid; + if (do_in_runtimepath(scriptname, 0, source_callback, &ret_sid) == OK) { ret = true; } } |