mirror of
https://github.com/neovim/neovim.git
synced 2025-09-23 19:48:32 +00:00
fix(lua): don't override script ID from :source (#32626)
Problem: When setting an option, mapping etc. from Lua without -V1, the script ID is set to SID_LUA even if there already is a script ID assigned by :source. Solution: Don't set script ID to SID_LUA if it is already a Lua script. Also add _editor.lua to ignorelist to make script context more useful when using vim.cmd().
This commit is contained in:
@@ -30,6 +30,7 @@
|
||||
#include "nvim/message.h"
|
||||
#include "nvim/msgpack_rpc/unpacker.h"
|
||||
#include "nvim/pos_defs.h"
|
||||
#include "nvim/runtime.h"
|
||||
#include "nvim/types_defs.h"
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
@@ -1057,10 +1058,18 @@ const char *get_default_stl_hl(win_T *wp, bool use_winbar, int stc_hl_id)
|
||||
sctx_T api_set_sctx(uint64_t channel_id)
|
||||
{
|
||||
sctx_T old_current_sctx = current_sctx;
|
||||
// The script context is already properly set when calling an API from Vimscript.
|
||||
if (channel_id != VIML_INTERNAL_CALL) {
|
||||
current_sctx.sc_sid = channel_id == LUA_INTERNAL_CALL ? SID_LUA : SID_API_CLIENT;
|
||||
current_sctx.sc_lnum = 0;
|
||||
current_sctx.sc_chan = channel_id;
|
||||
if (channel_id == LUA_INTERNAL_CALL) {
|
||||
// When the current script is a Lua script, don't override sc_sid.
|
||||
if (!script_is_lua(current_sctx.sc_sid)) {
|
||||
current_sctx.sc_sid = SID_LUA;
|
||||
}
|
||||
} else {
|
||||
current_sctx.sc_sid = SID_API_CLIENT;
|
||||
current_sctx.sc_chan = channel_id;
|
||||
}
|
||||
}
|
||||
return old_current_sctx;
|
||||
}
|
||||
|
@@ -7646,22 +7646,8 @@ hashtab_T *find_var_ht_dict(const char *name, const size_t name_len, const char
|
||||
|| current_sctx.sc_sid == SID_LUA)
|
||||
&& current_sctx.sc_sid <= script_items.ga_len) {
|
||||
// For anonymous scripts without a script item, create one now so script vars can be used
|
||||
if (current_sctx.sc_sid == SID_LUA) {
|
||||
// try to resolve lua filename & line no so it can be shown in lastset messages.
|
||||
nlua_set_sctx(¤t_sctx);
|
||||
if (current_sctx.sc_sid != SID_LUA) {
|
||||
// Great we have valid location. Now here this out we'll create a new
|
||||
// script context with the name and lineno of this one. why ?
|
||||
// for behavioral consistency. With this different anonymous exec from
|
||||
// same file can't access each others script local stuff. We need to do
|
||||
// this all other cases except this will act like that otherwise.
|
||||
bool should_free;
|
||||
// should_free is ignored as script_ctx will be resolved to a fname
|
||||
// and new_script_item() will consume it.
|
||||
char *sc_name = get_scriptname(current_sctx, &should_free);
|
||||
new_script_item(sc_name, ¤t_sctx.sc_sid);
|
||||
}
|
||||
}
|
||||
// Try to resolve lua filename & linenr so it can be shown in last-set messages.
|
||||
nlua_set_sctx(¤t_sctx);
|
||||
if (current_sctx.sc_sid == SID_STR || current_sctx.sc_sid == SID_LUA) {
|
||||
// Create SID if s: scope is accessed from Lua or anon Vimscript. #15994
|
||||
new_script_item(NULL, ¤t_sctx.sc_sid);
|
||||
|
@@ -2110,7 +2110,8 @@ bool nlua_execute_on_key(int c, char *typed_buf)
|
||||
// @param[out] current
|
||||
void nlua_set_sctx(sctx_T *current)
|
||||
{
|
||||
if (p_verbose <= 0 || current->sc_sid != SID_LUA) {
|
||||
if (p_verbose <= 0 || (current->sc_sid > 0 && current->sc_lnum > 0)
|
||||
|| !script_is_lua(current->sc_sid)) {
|
||||
return;
|
||||
}
|
||||
lua_State *const lstate = global_lstate;
|
||||
@@ -2119,6 +2120,7 @@ void nlua_set_sctx(sctx_T *current)
|
||||
// Files where internal wrappers are defined so we can ignore them
|
||||
// like vim.o/opt etc are defined in _options.lua
|
||||
char *ignorelist[] = {
|
||||
"vim/_editor.lua",
|
||||
"vim/_options.lua",
|
||||
"vim/keymap.lua",
|
||||
};
|
||||
@@ -2153,7 +2155,8 @@ void nlua_set_sctx(sctx_T *current)
|
||||
if (sid > 0) {
|
||||
xfree(source_path);
|
||||
} else {
|
||||
new_script_item(source_path, &sid);
|
||||
scriptitem_T *si = new_script_item(source_path, &sid);
|
||||
si->sn_lua = true;
|
||||
}
|
||||
current->sc_sid = sid;
|
||||
current->sc_seq = -1;
|
||||
|
@@ -2023,7 +2023,7 @@ static int source_using_linegetter(void *cookie, LineGetter fgetline, const char
|
||||
estack_push(ETYPE_SCRIPT, sname, 0);
|
||||
|
||||
const sctx_T save_current_sctx = current_sctx;
|
||||
if (current_sctx.sc_sid != SID_LUA) {
|
||||
if (!script_is_lua(current_sctx.sc_sid)) {
|
||||
current_sctx.sc_sid = SID_STR;
|
||||
}
|
||||
current_sctx.sc_seq = 0;
|
||||
@@ -2241,6 +2241,7 @@ int do_source(char *fname, int check_other, int is_vimrc, int *ret_sid)
|
||||
} else {
|
||||
// It's new, generate a new SID.
|
||||
si = new_script_item(fname_exp, &sid);
|
||||
si->sn_lua = path_with_extension(fname_exp, "lua");
|
||||
fname_exp = xstrdup(si->sn_name); // used for autocmd
|
||||
if (ret_sid != NULL) {
|
||||
*ret_sid = sid;
|
||||
@@ -2268,9 +2269,8 @@ int do_source(char *fname, int check_other, int is_vimrc, int *ret_sid)
|
||||
|
||||
cookie.conv.vc_type = CONV_NONE; // no conversion
|
||||
|
||||
if (path_with_extension(fname_exp, "lua")) {
|
||||
if (si->sn_lua) {
|
||||
const sctx_T current_sctx_backup = current_sctx;
|
||||
current_sctx.sc_sid = SID_LUA;
|
||||
current_sctx.sc_lnum = 0;
|
||||
// Source the file as lua
|
||||
nlua_exec_file(fname_exp);
|
||||
@@ -2356,6 +2356,18 @@ theend:
|
||||
return retval;
|
||||
}
|
||||
|
||||
/// Checks if the script with the given script ID is a Lua script.
|
||||
bool script_is_lua(scid_T sid)
|
||||
{
|
||||
if (sid == SID_LUA) {
|
||||
return true;
|
||||
}
|
||||
if (!SCRIPT_ID_VALID(sid)) {
|
||||
return false;
|
||||
}
|
||||
return SCRIPT_ITEM(sid)->sn_lua;
|
||||
}
|
||||
|
||||
/// Find an already loaded script "name".
|
||||
/// If found returns its script ID. If not found returns -1.
|
||||
int find_script_by_name(char *name)
|
||||
@@ -2447,7 +2459,8 @@ char *get_scriptname(sctx_T script_ctx, bool *should_free)
|
||||
case SID_STR:
|
||||
return _("anonymous :source");
|
||||
default: {
|
||||
char *const sname = SCRIPT_ITEM(script_ctx.sc_sid)->sn_name;
|
||||
scriptitem_T *const si = SCRIPT_ITEM(script_ctx.sc_sid);
|
||||
char *sname = si->sn_name;
|
||||
if (sname == NULL) {
|
||||
snprintf(IObuff, IOSIZE, _("anonymous :source (script id %d)"),
|
||||
script_ctx.sc_sid);
|
||||
@@ -2455,7 +2468,13 @@ char *get_scriptname(sctx_T script_ctx, bool *should_free)
|
||||
}
|
||||
|
||||
*should_free = true;
|
||||
return home_replace_save(NULL, sname);
|
||||
sname = home_replace_save(NULL, sname);
|
||||
if (si->sn_lua && script_ctx.sc_lnum == 0) {
|
||||
char *const ret = concat_str(sname, _(" (run Nvim with -V1 for more details)"));
|
||||
xfree(sname);
|
||||
return ret;
|
||||
}
|
||||
return sname;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -49,6 +49,7 @@ typedef struct {
|
||||
scriptvar_T *sn_vars; ///< stores s: variables for this script
|
||||
|
||||
char *sn_name;
|
||||
bool sn_lua; ///< true for a lua script
|
||||
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
|
||||
|
Reference in New Issue
Block a user