diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 213948a028..06ac44e5e4 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -8782,7 +8782,7 @@ void script_host_eval(char *name, typval_T *argvars, typval_T *rettv) /// an empty typval_T. typval_T eval_call_provider(char *provider, char *method, list_T *arguments, bool discard) { - if (!eval_has_provider(provider)) { + if (!eval_has_provider(provider, false)) { semsg("E319: No \"%s\" provider found. Run \":checkhealth provider\"", provider); return (typval_T){ @@ -8840,7 +8840,7 @@ typval_T eval_call_provider(char *provider, char *method, list_T *arguments, boo } /// Checks if provider for feature `feat` is enabled. -bool eval_has_provider(const char *feat) +bool eval_has_provider(const char *feat, bool throw_if_fast) { if (!strequal(feat, "clipboard") && !strequal(feat, "python3") @@ -8853,6 +8853,11 @@ bool eval_has_provider(const char *feat) return false; } + if (throw_if_fast && !nlua_is_deferred_safe()) { + semsg(e_luv_api_disabled, "Vimscript function"); + return false; + } + char name[32]; // Normalized: "python3_compiled" => "python3". snprintf(name, sizeof(name), "%s", feat); strchrsub(name, '_', '\0'); // Chop any "_xx" suffix. diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index dcc8cf3c8c..ae42b330a9 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -4905,6 +4905,7 @@ M.funcs = { endif < ]=], + fast = true, name = 'has', params = { { 'feature', 'any' } }, returns = '0|1', diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 8e62e3b96f..8528168be1 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -3435,19 +3435,19 @@ static void f_has(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } else if (STRICMP(name, "syntax_items") == 0) { n = syntax_present(curwin); } else if (STRICMP(name, "clipboard_working") == 0) { - n = eval_has_provider("clipboard"); + n = eval_has_provider("clipboard", true); } else if (STRICMP(name, "pythonx") == 0) { - n = eval_has_provider("python3"); + n = eval_has_provider("python3", true); } else if (STRICMP(name, "wsl") == 0) { n = has_wsl(); #ifdef UNIX } else if (STRICMP(name, "unnamedplus") == 0) { - n = eval_has_provider("clipboard"); + n = eval_has_provider("clipboard", true); #endif } } - if (!n && eval_has_provider(name)) { + if (!n && eval_has_provider(name, true)) { n = true; } diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 1b103b8aaf..a97c12568d 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -1968,7 +1968,7 @@ static int command_line_handle_key(CommandLineState *s) return command_line_not_changed(s); // Ignore mouse case K_MIDDLEMOUSE: - cmdline_paste(eval_has_provider("clipboard") ? '*' : 0, true, true); + cmdline_paste(eval_has_provider("clipboard", false) ? '*' : 0, true, true); redrawcmd(); return command_line_changed(s); diff --git a/src/nvim/main.c b/src/nvim/main.c index 50d1a5a735..608684bd36 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -641,7 +641,7 @@ int main(int argc, char **argv) // WORKAROUND(mhi): #3023 if (cb_flags & CB_UNNAMEDMASK) { - eval_has_provider("clipboard"); + eval_has_provider("clipboard", false); } if (params.luaf != NULL) { diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c index 1e70462700..9d30d7d5ab 100644 --- a/src/nvim/mouse.c +++ b/src/nvim/mouse.c @@ -467,7 +467,7 @@ bool do_mouse(oparg_T *oap, int c, int dir, int count, bool fixindent) if (regname == '.') { insert_reg(regname, true); } else { - if (regname == 0 && eval_has_provider("clipboard")) { + if (regname == 0 && eval_has_provider("clipboard", false)) { regname = '*'; } if ((State & REPLACE_FLAG) && !yank_register_mline(regname)) { @@ -819,7 +819,7 @@ popupexit: // Middle mouse click: Put text before cursor. if (which_button == MOUSE_MIDDLE) { int c2; - if (regname == 0 && eval_has_provider("clipboard")) { + if (regname == 0 && eval_has_provider("clipboard", false)) { regname = '*'; } if (yank_register_mline(regname)) { diff --git a/src/nvim/ops.c b/src/nvim/ops.c index eba3e98357..b658584410 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -6395,7 +6395,7 @@ static yankreg_T *adjust_clipboard_name(int *name, bool quiet, bool writing) goto end; } - if (!eval_has_provider("clipboard")) { + if (!eval_has_provider("clipboard", false)) { if (batch_change_count <= 1 && !quiet && (!clipboard_didwarn || (explicit_cb_reg && !redirecting()))) { clipboard_didwarn = true; diff --git a/test/functional/lua/loop_spec.lua b/test/functional/lua/loop_spec.lua index d5c5cd3cd0..566a171a84 100644 --- a/test/functional/lua/loop_spec.lua +++ b/test/functional/lua/loop_spec.lua @@ -133,6 +133,20 @@ describe('vim.uv', function() {5:-- INSERT --} | ]]) eq({ blocking = false, mode = 'n' }, exec_lua('return _G.mode')) + + exec_lua([[ + local timer = vim.uv.new_timer() + timer:start(20, 0, function () + _G.is_fast = vim.in_fast_event() + timer:close() + _G.value = vim.fn.has("nvim-0.5") + _G.unvalue = vim.fn.has("python3") + end) + ]]) + + screen:expect({ any = [[{3:Vim:E5560: Vimscript function must not be called i}]] }) + feed('') + eq({ 1, nil }, exec_lua('return {_G.value, _G.unvalue}')) end) it("is equal to require('luv')", function()