diff options
-rw-r--r-- | src/nvim/api/vim.c | 18 | ||||
-rw-r--r-- | src/nvim/option.c | 6 | ||||
-rw-r--r-- | src/nvim/option_defs.h | 2 | ||||
-rw-r--r-- | src/nvim/os/provider.c | 166 |
4 files changed, 66 insertions, 126 deletions
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index b1d5a067b4..e14c427dc1 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -502,22 +502,28 @@ void vim_unsubscribe(uint64_t channel_id, String event) channel_unsubscribe(channel_id, e); } -/// Registers the channel as the provider for `method`. This fails if -/// a provider for `method` is already registered. +/// Registers the channel as the provider for `feature`. This fails if +/// a provider for `feature` is already provided by another channel. /// /// @param channel_id The channel id -/// @param method The method name +/// @param feature The feature name /// @param[out] err Details of an error that may have occurred -void vim_register_provider(uint64_t channel_id, String method, Error *err) +void vim_register_provider(uint64_t channel_id, String feature, Error *err) { char buf[METHOD_MAXLEN]; - xstrlcpy(buf, method.data, sizeof(buf)); + xstrlcpy(buf, feature.data, sizeof(buf)); if (!provider_register(buf, channel_id)) { - set_api_error("Provider already registered", err); + set_api_error("Feature doesn't exist", err); } } +/// Returns a feature->method list dictionary for all pluggable features +Dictionary vim_discover_features(void) +{ + return provider_get_all(); +} + /// Writes a message to vim output or error buffer. The string is split /// and flushed after each newline. Incomplete lines are kept for writing /// later. diff --git a/src/nvim/option.c b/src/nvim/option.c index b9becebbf4..b26b6ed4cc 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -974,12 +974,6 @@ static struct vimoption {"infercase", "inf", P_BOOL|P_VI_DEF, (char_u *)&p_inf, PV_INF, {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, - {"initclipboard","icpb",P_STRING|P_VI_DEF|P_SECURE, - (char_u *)&p_icpb, PV_NONE, - {(char_u *)"", (char_u *)0L} SCRIPTID_INIT}, - {"initpython","ipy",P_STRING|P_VI_DEF|P_SECURE, - (char_u *)&p_ipy, PV_NONE, - {(char_u *)"", (char_u *)0L} SCRIPTID_INIT}, {"insertmode", "im", P_BOOL|P_VI_DEF|P_VIM, (char_u *)&p_im, PV_NONE, {(char_u *)FALSE, (char_u *)0L} SCRIPTID_INIT}, diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h index 555e9166d6..cd61b6427c 100644 --- a/src/nvim/option_defs.h +++ b/src/nvim/option_defs.h @@ -631,8 +631,6 @@ EXTERN int p_write; /* 'write' */ EXTERN int p_wa; /* 'writeany' */ EXTERN int p_wb; /* 'writebackup' */ EXTERN long p_wd; /* 'writedelay' */ -EXTERN char *p_ipy; // 'initpython' -EXTERN char *p_icpb; // 'initclipboard' /* * "indir" values for buffer-local opions. diff --git a/src/nvim/os/provider.c b/src/nvim/os/provider.c index 57c2e57a3c..e56e33aa1a 100644 --- a/src/nvim/os/provider.c +++ b/src/nvim/os/provider.c @@ -17,33 +17,31 @@ #define FEATURE_COUNT (sizeof(features) / sizeof(features[0])) -#define FEATURE(feature_name, provider_bootstrap_command, ...) { \ +#define FEATURE(feature_name, ...) { \ .name = feature_name, \ - .bootstrap_command = provider_bootstrap_command, \ - .argv = NULL, \ .channel_id = 0, \ .methods = (char *[]){__VA_ARGS__, NULL} \ } -static struct feature { - char *name, **bootstrap_command, **argv, **methods; +typedef struct { + char *name, **methods; size_t name_length; uint64_t channel_id; -} features[] = { +} Feature; + +static Feature features[] = { FEATURE("python", - &p_ipy, "python_execute", "python_execute_file", "python_do_range", "python_eval"), FEATURE("clipboard", - &p_icpb, "clipboard_get", "clipboard_set") }; -static Map(cstr_t, uint64_t) *registered_providers = NULL; +static PMap(cstr_t) *registered_providers = NULL; #ifdef INCLUDE_GENERATED_DECLARATIONS # include "os/provider.c.generated.h" @@ -52,60 +50,57 @@ static Map(cstr_t, uint64_t) *registered_providers = NULL; void provider_init(void) { - registered_providers = map_new(cstr_t, uint64_t)(); + registered_providers = pmap_new(cstr_t)(); } bool provider_has_feature(char *name) { - for (size_t i = 0; i < FEATURE_COUNT; i++) { - struct feature *f = &features[i]; - if (!STRICMP(name, f->name)) { - return f->channel_id || can_execute(f); - } - } - - return false; + Feature *f = find_feature(name); + return f != NULL && channel_exists(f->channel_id); } -bool provider_available(char *method) +bool provider_register(char *name, uint64_t channel_id) { - return map_has(cstr_t, uint64_t)(registered_providers, method); -} + Feature *f = find_feature(name); -bool provider_register(char *method, uint64_t channel_id) -{ - if (map_has(cstr_t, uint64_t)(registered_providers, method)) { + if (!f) { return false; } - // First check if this method is part of a feature, and if so, update - // the feature structure with the channel id - struct feature *f = get_feature_for(method); - if (f) { - DLOG("Registering provider for \"%s\" " - "which is part of the \"%s\" feature", - method, - f->name); - f->channel_id = channel_id; + if (f->channel_id && channel_exists(f->channel_id)) { + ILOG("Feature \"%s\" is already provided by another channel" + "(will be replaced)", name); + } + + DLOG("Registering provider for \"%s\"", name); + f->channel_id = channel_id; + + // Associate all method names with the feature struct + size_t i; + char *method; + for (method = f->methods[i = 0]; method; method = f->methods[++i]) { + pmap_put(cstr_t)(registered_providers, method, f); + DLOG("Channel \"%" PRIu64 "\" will be sent requests for \"%s\"", + channel_id, + method); } - map_put(cstr_t, uint64_t)(registered_providers, xstrdup(method), channel_id); - ILOG("Registered channel %" PRIu64 " as the provider for \"%s\"", + ILOG("Registered channel %" PRIu64 " as the provider for the \"%s\" feature", channel_id, - method); + name); return true; } Object provider_call(char *method, Array args) { - uint64_t channel_id = get_provider_for(method); + Feature *f = pmap_get(cstr_t)(registered_providers, method); - if (!channel_id) { + if (!f || !channel_exists(f->channel_id)) { char buf[256]; snprintf(buf, sizeof(buf), - "Provider for \"%s\" is not available", + "Provider for method \"%s\" is not available", method); report_error(buf); api_free_array(args); @@ -114,7 +109,7 @@ Object provider_call(char *method, Array args) bool error = false; Object result = NIL; - channel_send_call(channel_id, method, args, &result, &error); + channel_send_call(f->channel_id, method, args, &result, &error); if (error) { report_error(result.data.string.data); @@ -125,62 +120,36 @@ Object provider_call(char *method, Array args) return result; } -static uint64_t get_provider_for(char *method) +Dictionary provider_get_all(void) { - uint64_t channel_id = map_get(cstr_t, uint64_t)(registered_providers, method); - - if (channel_id) { - return channel_id; - } - - // Try to bootstrap if the method is part of a feature - struct feature *f = get_feature_for(method); - - if (!f || !can_execute(f)) { - ELOG("Cannot bootstrap provider for \"%s\"", method); - goto err; - } + Dictionary rv = ARRAY_DICT_INIT; - if (f->channel_id) { - ELOG("Already bootstrapped provider for \"%s\"", f->name); - goto err; - } + for (size_t i = 0; i < FEATURE_COUNT; i++) { + Array methods = ARRAY_DICT_INIT; + Feature *f = &features[i]; - f->channel_id = channel_from_job(f->argv); + size_t j; + char *method; + for (method = f->methods[j = 0]; method; method = f->methods[++j]) { + ADD(methods, STRING_OBJ(cstr_to_string(method))); + } - if (!f->channel_id) { - ELOG("The provider for \"%s\" failed to bootstrap", f->name); - goto err; + PUT(rv, f->name, ARRAY_OBJ(methods)); } - return f->channel_id; - -err: - // Ensure we won't try to restart the provider - if (f) { - f->bootstrap_command = NULL; - f->channel_id = 0; - } - return 0; + return rv; } -static bool can_execute(struct feature *f) +static Feature * find_feature(char *name) { - if (!f->bootstrap_command) { - return false; - } - - char *cmd = *f->bootstrap_command; - - if (!cmd || !strlen(cmd)) { - return false; - } - - if (!f->argv) { - f->argv = shell_build_argv((uint8_t *)cmd, NULL); + for (size_t i = 0; i < FEATURE_COUNT; i++) { + Feature *f = &features[i]; + if (!STRICMP(name, f->name)) { + return f; + } } - return os_can_exe((uint8_t *)f->argv[0]); + return NULL; } static void report_error(char *str) @@ -188,30 +157,3 @@ static void report_error(char *str) vim_err_write((String) {.data = str, .size = strlen(str)}); vim_err_write((String) {.data = "\n", .size = 1}); } - -static bool feature_has_method(struct feature *f, char *method) -{ - size_t i; - char *m; - - for (m = f->methods[i = 0]; m; m = f->methods[++i]) { - if (!STRCMP(method, m)) { - return true; - } - } - - return false; -} - - -static struct feature *get_feature_for(char *method) -{ - for (size_t i = 0; i < FEATURE_COUNT; i++) { - struct feature *f = &features[i]; - if (feature_has_method(f, method)) { - return f; - } - } - - return NULL; -} |