diff options
Diffstat (limited to 'src/nvim/eval.c')
-rw-r--r-- | src/nvim/eval.c | 144 |
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; +} |