aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/ex_getln.c82
-rw-r--r--test/functional/plugin/health_spec.lua1
2 files changed, 79 insertions, 4 deletions
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index e0ff9bab3a..f4f07e0680 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -230,7 +230,22 @@ static int compl_match_arraysize;
static int compl_startcol;
static int compl_selected;
+/// |:checkhealth| completion items
+///
+/// Regenerates on every new command line prompt, to accomodate changes on the
+/// runtime files.
+typedef struct {
+ garray_T names; // healthcheck names
+ unsigned last_gen; // last_prompt_id where names were generated
+} CheckhealthComp;
+
+/// Cookie used when converting filepath to name
+struct healthchecks_cookie {
+ garray_T *names; // global healthchecks
+ bool is_lua; // true if the current entry is a Lua healthcheck
+};
+static CheckhealthComp healthchecks = { GA_INIT(sizeof(char_u *), 10), 0 };
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "ex_getln.c.generated.h"
@@ -273,6 +288,68 @@ static void init_incsearch_state(incsearch_state_T *s)
save_viewstate(&s->old_viewstate);
}
+/// Completion for |:checkhealth| command.
+///
+/// Given to ExpandGeneric() to obtain all available heathcheck names.
+/// @param[in] idx Index of the healthcheck item.
+/// @param[in] xp Not used.
+static char_u *get_healthcheck_names(expand_T *xp, int idx)
+{
+ // Generate the first time or on new prompt.
+ if (healthchecks.last_gen == 0 || healthchecks.last_gen != last_prompt_id) {
+ ga_clear_strings(&healthchecks.names);
+ char *patterns[3] = { "autoload/health/**.vim", "lua/**/**/health/init.lua", // NOLINT
+ "lua/**/**/health.lua" }; // NOLINT
+ for (int i = 0; i < 3; i++) {
+ struct healthchecks_cookie hcookie = { .names = &healthchecks.names, .is_lua = i != 0 };
+ do_in_runtimepath((char_u *)patterns[i], DIP_ALL, get_healthcheck_cb, &hcookie);
+
+ if (healthchecks.names.ga_len > 0) {
+ ga_remove_duplicate_strings(&healthchecks.names);
+ }
+ }
+ // Tracked to regenerate items on next prompt.
+ healthchecks.last_gen = last_prompt_id;
+ }
+ return idx <
+ (int)healthchecks.names.ga_len ? ((char_u **)(healthchecks.names.ga_data))[idx] : NULL;
+}
+
+/// Transform healthcheck file path into it's name.
+///
+/// Used as a callback for do_in_runtimepath
+/// @param[in] path Expanded path to a possible healthcheck.
+/// @param[out] cookie Array where names will be inserted.
+static void get_healthcheck_cb(char_u *path, void *cookie)
+{
+ if (path != NULL) {
+ struct healthchecks_cookie *hcookie = (struct healthchecks_cookie *)cookie;
+ char *pattern;
+ char *sub = "\\1";
+ char_u *res;
+
+ if (hcookie->is_lua) {
+ // Lua: transform "../lua/vim/lsp/health.lua" into "vim.lsp"
+ pattern = ".*lua[\\/]\\(.\\{-}\\)[\\/]health\\([\\/]init\\)\\?\\.lua$";
+ } else {
+ // Vim: transform "../autoload/health/provider.vim" into "provider"
+ pattern = ".*[\\/]\\([^\\/]*\\)\\.vim$";
+ }
+
+ res = do_string_sub(path, (char_u *)pattern, (char_u *)sub, NULL, (char_u *)"g");
+ if (hcookie->is_lua && res != NULL) {
+ // Replace slashes with dots as represented by the healthcheck plugin.
+ char_u *ares = do_string_sub(res, (char_u *)"[\\/]", (char_u *)".", NULL, (char_u *)"g");
+ xfree(res);
+ res = ares;
+ }
+
+ if (res != NULL) {
+ GA_APPEND(char_u *, hcookie->names, res);
+ }
+ }
+}
+
// Return true when 'incsearch' highlighting is to be done.
// Sets search_first_line and search_last_line to the address range.
static bool do_incsearch_highlighting(int firstc, int *search_delim, incsearch_state_T *s,
@@ -4902,10 +4979,6 @@ static int ExpandFromContext(expand_T *xp, char_u *pat, int *num_file, char_u **
char *directories[] = { "syntax", "indent", "ftplugin", NULL };
return ExpandRTDir(pat, DIP_LUA, num_file, file, directories);
}
- if (xp->xp_context == EXPAND_CHECKHEALTH) {
- char *directories[] = { "autoload/health", NULL };
- return ExpandRTDir(pat, 0, num_file, file, directories);
- }
if (xp->xp_context == EXPAND_USER_LIST) {
return ExpandUserList(xp, num_file, file);
}
@@ -4982,6 +5055,7 @@ static int ExpandFromContext(expand_T *xp, char_u *pat, int *num_file, char_u **
{ EXPAND_ENV_VARS, get_env_name, true, true },
{ EXPAND_USER, get_users, true, false },
{ EXPAND_ARGLIST, get_arglist_name, true, false },
+ { EXPAND_CHECKHEALTH, get_healthcheck_names, true, false },
};
int i;
diff --git a/test/functional/plugin/health_spec.lua b/test/functional/plugin/health_spec.lua
index c5b8df488b..2a86391e76 100644
--- a/test/functional/plugin/health_spec.lua
+++ b/test/functional/plugin/health_spec.lua
@@ -36,6 +36,7 @@ describe(':checkhealth', function()
clear()
eq('nvim', getcompletion('nvim', 'checkhealth')[1])
eq('provider', getcompletion('prov', 'checkhealth')[1])
+ eq('vim.lsp', getcompletion('vim.ls', 'checkhealth')[1])
end)
end)