diff options
| -rw-r--r-- | src/nvim/ex_getln.c | 82 | ||||
| -rw-r--r-- | test/functional/plugin/health_spec.lua | 1 | 
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)  | 
