aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/eval.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/eval.c')
-rw-r--r--src/nvim/eval.c144
1 files changed, 128 insertions, 16 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index a0e6f84259..498795dc38 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -89,7 +89,6 @@
#include "nvim/api/private/helpers.h"
#include "nvim/api/vim.h"
#include "nvim/os/dl.h"
-#include "nvim/os/provider.h"
#include "nvim/os/event.h"
#define DICT_MAXNEST 100 /* maximum nesting of lists and dicts */
@@ -457,7 +456,7 @@ typedef struct {
} JobEvent;
#define JobEventFreer(x)
KMEMPOOL_INIT(JobEventPool, JobEvent, JobEventFreer)
-kmempool_t(JobEventPool) *job_event_pool = NULL;
+static kmempool_t(JobEventPool) *job_event_pool = NULL;
/*
* Initialize the global and v: variables.
@@ -5152,7 +5151,7 @@ void list_append_string(list_T *l, char_u *str, int len)
/*
* Append "n" to list "l".
*/
-static void list_append_number(list_T *l, varnumber_T n)
+void list_append_number(list_T *l, varnumber_T n)
{
listitem_T *li = listitem_alloc();
li->li_tv.v_type = VAR_NUMBER;
@@ -9987,7 +9986,7 @@ static void f_has(typval_T *argvars, typval_T *rettv)
}
}
- if (n == FALSE && provider_has_feature((char *)name)) {
+ if (n == FALSE && eval_has_provider((char *)name)) {
n = TRUE;
}
@@ -11695,7 +11694,7 @@ static void f_pumvisible(typval_T *argvars, typval_T *rettv)
*/
static void f_pyeval(typval_T *argvars, typval_T *rettv)
{
- script_host_eval("python_eval", argvars, rettv);
+ script_host_eval("python", argvars, rettv);
}
/*
@@ -12540,11 +12539,52 @@ static void f_rpcrequest(typval_T *argvars, typval_T *rettv)
ADD(args, vim_to_object(tv));
}
+ scid_T save_current_SID;
+ uint8_t *save_sourcing_name, *save_autocmd_fname, *save_autocmd_match;
+ linenr_T save_sourcing_lnum;
+ int save_autocmd_fname_full, save_autocmd_bufnr;
+ void *save_funccalp;
+
+ if (provider_call_nesting) {
+ // If this is called from a provider function, restore the scope
+ // information of the caller.
+ save_current_SID = current_SID;
+ save_sourcing_name = sourcing_name;
+ save_sourcing_lnum = sourcing_lnum;
+ save_autocmd_fname = autocmd_fname;
+ save_autocmd_match = autocmd_match;
+ save_autocmd_fname_full = autocmd_fname_full;
+ save_autocmd_bufnr = autocmd_bufnr;
+ save_funccalp = save_funccal();
+ //
+ current_SID = provider_caller_scope.SID;
+ sourcing_name = provider_caller_scope.sourcing_name;
+ sourcing_lnum = provider_caller_scope.sourcing_lnum;
+ autocmd_fname = provider_caller_scope.autocmd_fname;
+ autocmd_match = provider_caller_scope.autocmd_match;
+ autocmd_fname_full = provider_caller_scope.autocmd_fname_full;
+ autocmd_bufnr = provider_caller_scope.autocmd_bufnr;
+ restore_funccal(provider_caller_scope.funccalp);
+ }
+
+
Error err = ERROR_INIT;
Object result = channel_send_call((uint64_t)argvars[0].vval.v_number,
(char *)argvars[1].vval.v_string,
args,
&err);
+
+ if (provider_call_nesting) {
+ current_SID = save_current_SID;
+ sourcing_name = save_sourcing_name;
+ sourcing_lnum = save_sourcing_lnum;
+ autocmd_fname = save_autocmd_fname;
+ autocmd_match = save_autocmd_match;
+ autocmd_fname_full = save_autocmd_fname_full;
+ autocmd_bufnr = save_autocmd_bufnr;
+ restore_funccal(save_funccalp);
+ }
+
if (err.set) {
vim_report_error(cstr_as_string(err.msg));
goto end;
@@ -19671,22 +19711,94 @@ static void apply_job_autocmds(int id, char *name, char *type,
}
}
-static void script_host_eval(char *method, typval_T *argvars, typval_T *rettv)
+static void script_host_eval(char *name, typval_T *argvars, typval_T *rettv)
{
- Array args = ARRAY_DICT_INIT;
- ADD(args, vim_to_object(argvars));
- Object result = provider_call(method, args);
-
- if (result.type == kObjectTypeNil) {
+ if (check_restricted() || check_secure()) {
return;
}
- Error err = ERROR_INIT;
-
- if (!object_to_vim(result, rettv, &err)){
- EMSG("Error converting value back to vim");
+ if (argvars[0].v_type != VAR_STRING) {
+ EMSG(_(e_invarg));
}
- api_free_object(result);
+ list_T *args = list_alloc();
+ list_append_string(args, argvars[0].vval.v_string, -1);
+ *rettv = eval_call_provider(name, "eval", args);
}
+typval_T eval_call_provider(char *provider, char *method, list_T *arguments)
+{
+ char func[256];
+ int name_len = snprintf(func, sizeof(func), "provider#%s#Call", provider);
+
+ // Save caller scope information
+ struct caller_scope saved_provider_caller_scope = provider_caller_scope;
+ provider_caller_scope = (struct caller_scope) {
+ .SID = current_SID,
+ .sourcing_name = sourcing_name,
+ .sourcing_lnum = sourcing_lnum,
+ .autocmd_fname = autocmd_fname,
+ .autocmd_match = autocmd_match,
+ .autocmd_fname_full = autocmd_fname_full,
+ .autocmd_bufnr = autocmd_bufnr,
+ .funccalp = save_funccal()
+ };
+ provider_call_nesting++;
+
+ typval_T argvars[3] = {
+ {.v_type = VAR_STRING, .vval.v_string = (uint8_t *)method, .v_lock = 0},
+ {.v_type = VAR_LIST, .vval.v_list = arguments, .v_lock = 0},
+ {.v_type = VAR_UNKNOWN}
+ };
+ typval_T rettv = {.v_type = VAR_UNKNOWN, .v_lock = 0};
+ arguments->lv_refcount++;
+
+ int dummy;
+ (void)call_func((uint8_t *)func,
+ name_len,
+ &rettv,
+ 2,
+ argvars,
+ curwin->w_cursor.lnum,
+ curwin->w_cursor.lnum,
+ &dummy,
+ true,
+ NULL);
+
+ arguments->lv_refcount--;
+ // Restore caller scope information
+ restore_funccal(provider_caller_scope.funccalp);
+ provider_caller_scope = saved_provider_caller_scope;
+ provider_call_nesting--;
+
+ return rettv;
+}
+
+bool eval_has_provider(char *name)
+{
+#define source_provider(name) \
+ do_source((uint8_t *)"$VIMRUNTIME/autoload/provider/" name ".vim", \
+ false, \
+ false)
+
+#define check_provider(name) \
+ if (has_##name == -1) { \
+ has_##name = !!find_func((uint8_t *)"provider#" #name "#Call"); \
+ if (!has_##name) { \
+ source_provider(#name); \
+ has_##name = !!find_func((uint8_t *)"provider#" #name "#Call"); \
+ } \
+ }
+
+ static int has_clipboard = -1, has_python = -1;
+
+ if (!strcmp(name, "clipboard")) {
+ check_provider(clipboard);
+ return has_clipboard;
+ } else if (!strcmp(name, "python")) {
+ check_provider(python);
+ return has_python;
+ }
+
+ return false;
+}