diff options
author | Matthieu Coudron <teto@users.noreply.github.com> | 2021-10-05 11:27:07 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-05 11:27:07 +0200 |
commit | 93a7571faba529f7b3e527336e933731eb91bbec (patch) | |
tree | 804a61b2ff65eaef7c06a7390768ece5e890142f | |
parent | 655e489e90712cc3c2f06d84a5030c66e5c51d91 (diff) | |
parent | 8b43b07333bc8ae9ca347daffb09f2bdf50af3ed (diff) | |
download | rneovim-93a7571faba529f7b3e527336e933731eb91bbec.tar.gz rneovim-93a7571faba529f7b3e527336e933731eb91bbec.tar.bz2 rneovim-93a7571faba529f7b3e527336e933731eb91bbec.zip |
Merge pull request #15259 from muniter/muniter/checkhealth-from-lua
feat(checkhealth): support Lua healthchecks
-rw-r--r-- | runtime/autoload/health.vim | 103 | ||||
-rw-r--r-- | runtime/doc/pi_health.txt | 175 | ||||
-rw-r--r-- | runtime/lua/health.lua | 23 | ||||
-rw-r--r-- | src/nvim/ex_getln.c | 82 | ||||
-rw-r--r-- | test/functional/fixtures/autoload/health/full_render.vim | 8 | ||||
-rw-r--r-- | test/functional/fixtures/lua/test_plug/health/init.lua | 11 | ||||
-rw-r--r-- | test/functional/fixtures/lua/test_plug/submodule/health.lua | 11 | ||||
-rw-r--r-- | test/functional/fixtures/lua/test_plug/submodule_failed/health.lua | 12 | ||||
-rw-r--r-- | test/functional/plugin/health_spec.lua | 151 |
9 files changed, 443 insertions, 133 deletions
diff --git a/runtime/autoload/health.vim b/runtime/autoload/health.vim index 0f7983f175..17047707fb 100644 --- a/runtime/autoload/health.vim +++ b/runtime/autoload/health.vim @@ -26,8 +26,8 @@ endfunction " Runs all discovered healthchecks if a:plugin_names is empty. function! health#check(plugin_names) abort let healthchecks = empty(a:plugin_names) - \ ? s:discover_health_checks() - \ : s:to_fn_names(a:plugin_names) + \ ? s:discover_healthchecks() + \ : s:get_healthcheck(a:plugin_names) tabnew setlocal wrap breakindent linebreak @@ -42,24 +42,28 @@ function! health#check(plugin_names) abort else redraw|echo 'Running healthchecks...' for c in healthchecks - let output = '' - call append('$', split(printf("\n%s\n%s", c, repeat('=',72)), "\n")) + let [name, func, type] = c + let s:output = [] try - let output = "\n\n".execute('call '.c.'()') + if func == '' + throw 'healthcheck_not_found' + endif + eval type == 'v' ? call(func, []) : luaeval(func) catch - if v:exception =~# '^Vim\%((\a\+)\)\=:E117.*\V'.c - let output = execute( - \ 'call health#report_error(''No healthcheck found for "' - \ .s:to_plugin_name(c) - \ .'" plugin.'')') + let s:output = [] " Clear the output + if v:exception =~# 'healthcheck_not_found' + call health#report_error('No healthcheck found for "'.name.'" plugin.') else - let output = execute( - \ 'call health#report_error(''Failed to run healthcheck for "' - \ .s:to_plugin_name(c) - \ .'" plugin. Exception:''."\n".v:throwpoint."\n".v:exception)') + call health#report_error(printf( + \ "Failed to run healthcheck for \"%s\" plugin. Exception:\n%s\n%s", + \ name, v:throwpoint, v:exception)) endif endtry - call append('$', split(output, "\n") + ['']) + let header = [name. ': ' . func, repeat('=', 72)] + " remove empty line after header from report_start + let s:output = s:output[0] == '' ? s:output[1:] : s:output + let s:output = header + s:output + [''] + call append('$', s:output) redraw endfor endif @@ -71,9 +75,13 @@ function! health#check(plugin_names) abort redraw|echo '' endfunction +function! s:collect_output(output) + let s:output += split(a:output, "\n", 1) +endfunction + " Starts a new report. function! health#report_start(name) abort - echo "\n## " . a:name + call s:collect_output("\n## " . a:name) endfunction " Indents lines *except* line 1 of a string if it contains newlines. @@ -119,21 +127,21 @@ endfunction " }}} " Use {msg} to report information in the current section function! health#report_info(msg) abort " {{{ - echo s:format_report_message('INFO', a:msg) + call s:collect_output(s:format_report_message('INFO', a:msg)) endfunction " }}} " Reports a successful healthcheck. function! health#report_ok(msg) abort " {{{ - echo s:format_report_message('OK', a:msg) + call s:collect_output(s:format_report_message('OK', a:msg)) endfunction " }}} " Reports a health warning. " a:1: Optional advice (string or list) function! health#report_warn(msg, ...) abort " {{{ if a:0 > 0 - echo s:format_report_message('WARNING', a:msg, a:1) + call s:collect_output(s:format_report_message('WARNING', a:msg, a:1)) else - echo s:format_report_message('WARNING', a:msg) + call s:collect_output(s:format_report_message('WARNING', a:msg)) endif endfunction " }}} @@ -141,37 +149,52 @@ endfunction " }}} " a:1: Optional advice (string or list) function! health#report_error(msg, ...) abort " {{{ if a:0 > 0 - echo s:format_report_message('ERROR', a:msg, a:1) + call s:collect_output(s:format_report_message('ERROR', a:msg, a:1)) else - echo s:format_report_message('ERROR', a:msg) + call s:collect_output(s:format_report_message('ERROR', a:msg)) endif endfunction " }}} -function! s:filepath_to_function(name) abort - return substitute(substitute(substitute(a:name, '.*autoload[\/]', '', ''), - \ '\.vim', '#check', ''), '[\/]', '#', 'g') +" From a path return a list [{name}, {func}, {type}] representing a healthcheck +function! s:filepath_to_healthcheck(path) abort + if a:path =~# 'vim$' + let name = matchstr(a:path, '\zs[^\/]*\ze\.vim$') + let func = 'health#'.name.'#check' + let type = 'v' + else + let base_path = substitute(a:path, + \ '.*lua[\/]\(.\{-}\)[\/]health\([\/]init\)\?\.lua$', + \ '\1', '') + let name = substitute(base_path, '[\/]', '.', 'g') + let func = 'require("'.name.'.health").check()' + let type = 'l' + endif + return [name, func, type] endfunction -function! s:discover_health_checks() abort - let healthchecks = globpath(&runtimepath, 'autoload/health/*.vim', 1, 1) - let healthchecks = map(healthchecks, '<SID>filepath_to_function(v:val)') - return healthchecks +function! s:discover_healthchecks() abort + return s:get_healthcheck('*') endfunction -" Translates a list of plugin names to healthcheck function names. -function! s:to_fn_names(plugin_names) abort +" Returns list of lists [ [{name}, {func}, {type}] ] representing healthchecks +function! s:get_healthcheck(plugin_names) abort let healthchecks = [] - let plugin_names = type('') ==# type(a:plugin_names) - \ ? split(a:plugin_names, '', v:false) + let plugin_names = type('') == type(a:plugin_names) + \ ? split(a:plugin_names, ' ', v:false) \ : a:plugin_names for p in plugin_names - call add(healthchecks, 'health#'.p.'#check') + " support vim/lsp/health{/init/}.lua as :checkhealth vim.lsp + let p = substitute(p, '\.', '/', 'g') + let p = substitute(p, '*$', '**', 'g') " find all submodule e.g vim* + let paths = nvim_get_runtime_file('autoload/health/'.p.'.vim', v:true) + \ + nvim_get_runtime_file('lua/**/'.p.'/health/init.lua', v:true) + \ + nvim_get_runtime_file('lua/**/'.p.'/health.lua', v:true) + if len(paths) == 0 + let healthchecks += [[p, '', '']] " healthchek not found + else + let healthchecks += map(uniq(sort(paths)), + \'<SID>filepath_to_healthcheck(v:val)') + end endfor return healthchecks endfunction - -" Extracts 'foo' from 'health#foo#check'. -function! s:to_plugin_name(fn_name) abort - return substitute(a:fn_name, - \ '\v.*health\#(.+)\#check.*', '\1', '') -endfunction diff --git a/runtime/doc/pi_health.txt b/runtime/doc/pi_health.txt index bb688770fc..69655ba902 100644 --- a/runtime/doc/pi_health.txt +++ b/runtime/doc/pi_health.txt @@ -13,7 +13,7 @@ python support, ruby support, clipboard support, and more. To run the healthchecks, use this command: > - :checkhealth + :checkhealth < Plugin authors are encouraged to write new healthchecks. |health-dev| @@ -23,32 +23,107 @@ Commands *health-commands* *:checkhealth* *:CheckHealth* :checkhealth Run all healthchecks. *E5009* - Nvim depends on |$VIMRUNTIME| and 'runtimepath' to find - the standard "runtime files" for syntax highlighting, - filetype-specific behavior, and standard plugins - (including :checkhealth). If the runtime files cannot - be found then those features will not work. + Nvim depends on |$VIMRUNTIME|, 'runtimepath' and 'packpath' to + find the standard "runtime files" for syntax highlighting, + filetype-specific behavior, and standard plugins (including + :checkhealth). If the runtime files cannot be found then + those features will not work. :checkhealth {plugins} - Run healthcheck(s) for one or more plugins. E.g. to run - only the standard Nvim healthcheck: > - :checkhealth nvim -< To run the healthchecks for the "foo" and "bar" plugins - (assuming these plugins are on your 'runtimepath' and - they have implemented health#foo#check() and - health#bar#check(), respectively): > - :checkhealth foo bar + Run healthcheck(s) for one or more plugins. E.g. to run only + the standard Nvim healthcheck: > + :checkhealth nvim < + To run the healthchecks for the "foo" and "bar" plugins + (assuming these plugins are on 'runtimepath' or 'packpath' and + they have implemented the Lua or Vimscript interface + require("foo.health").check() and health#bar#check(), + respectively): > + :checkhealth foo bar +< + To run healthchecks for lua submodules, use dot notation or + "*" to refer to all submodules. For example nvim provides + `vim.lsp` and `vim.treesitter` > + :checkhealth vim.lsp vim.treesitter + :checkhealth vim* +< +============================================================================== +Lua Functions *health-functions-lua* *health-lua* + +The Lua "health" module can be used to create new healthchecks (see also +|health-functions-vim|). To get started, simply use: > + local health = require('health') +< +health.report_start({name}) *health.report_start()* + Starts a new report. Most plugins should call this only once, but if + you want different sections to appear in your report, call this once + per section. + +health.report_info({msg}) *health.report_info()* + Reports an informational message. + +health.report_ok({msg}) *health.report_ok()* + Reports a "success" message. + +health.report_warn({msg} [, {advice}]) *health.report_warn()* + Reports a warning. {advice} is an optional List of suggestions. + +health.report_error({msg} [, {advice}]) *health.report_error()* + Reports an error. {advice} is an optional List of suggestions. + +============================================================================== +Create a Lua healthcheck *health-dev-lua* + +Healthchecks are functions that check the user environment, configuration, +etc. Nvim has built-in healthchecks in $VIMRUNTIME/autoload/health/. + +To add a new healthcheck for your own plugin, simply define a Lua module in +your plugin that returns a table with a "check()" function. |:checkhealth| +will automatically find and invoke this function. + +If your plugin is named "foo", then its healthcheck module should be a file in +one of these locations on 'runtimepath' or 'packpath': + - `lua/foo/health/init.lua` + - `lua/foo/health.lua` + +If your plugin provides a submodule named "bar" for which you want a separate +healthcheck, define the healthcheck at one of these locations on 'runtimepath' +or 'packpath': + - `lua/foo/bar/health/init.lua` + - `lua/foo/bar/health.lua` + +All submodules should return a Lua table containing the method `check()`. + +Copy this sample code into `lua/foo/health/init.lua` or `lua/foo/health.lua`, +replacing "foo" in the path with your plugin name: > + + local M = {} + local health = require("health") + + M.check = function() + health.report_start("my_plugin report") + -- make sure setup function parameters are ok + if check_setup() then + health.report_ok("Setup function is correct") + else + health.report_error("Setup function is incorrect") + end + -- do some more checking + -- ... + end + + return M + ============================================================================== -Functions *health-functions* +Vimscript Functions *health-functions-vimscript* *health-vimscript* -health.vim functions are for creating new healthchecks. They mostly just do -some layout and formatting, to give users a consistent presentation. +health.vim functions are for creating new healthchecks. (See also +|health-functions-lua|) health#report_start({name}) *health#report_start* Starts a new report. Most plugins should call this only once, but if - you want different sections to appear in your report, call this once - per section. + you want different sections to appear in your report, call this once + per section. health#report_info({msg}) *health#report_info* Reports an informational message. @@ -56,27 +131,23 @@ health#report_info({msg}) *health#report_info* health#report_ok({msg}) *health#report_ok* Reports a "success" message. -health#report_warn({msg}, [{advice}]) *health#report_warn* - Reports a warning. {advice} is an optional List of suggestions. +health#report_warn({msg} [, {advice}]) *health#report_warn* + Reports a warning. {advice} is an optional List of suggestions. -health#report_error({msg}, [{advice}]) *health#report_error* - Reports an error. {advice} is an optional List of suggestions. +health#report_error({msg} [, {advice}]) *health#report_error* + Reports an error. {advice} is an optional List of suggestions. health#{plugin}#check() *health.user_checker* - Healthcheck function for {plugin}. Called by |:checkhealth| - automatically. Example: > + Healthcheck function for {plugin}. Called by |:checkhealth| + automatically. Example: > - function! health#my_plug#check() abort - silent call s:check_environment_vars() - silent call s:check_python_configuration() - endfunction + function! health#my_plug#check() abort + silent call s:check_environment_vars() + silent call s:check_python_configuration() + endfunction < - All output will be captured from the healthcheck. Use the - health#report_* functions so that your healthcheck has a format - consistent with the standard healthchecks. - ============================================================================== -Create a healthcheck *health-dev* +Create a healthcheck *health-dev-vim* Healthchecks are functions that check the user environment, configuration, etc. Nvim has built-in healthchecks in $VIMRUNTIME/autoload/health/. @@ -86,26 +157,24 @@ health#{plugin}#check() function in autoload/health/{plugin}.vim. |:checkhealth| automatically finds and invokes such functions. If your plugin is named "foo", then its healthcheck function must be > - health#foo#check() + health#foo#check() -defined in this file on 'runtimepath': > - autoload/health/foo.vim +defined in this file on 'runtimepath' or 'packpath': > + autoload/health/foo.vim Copy this sample code into autoload/health/foo.vim and replace "foo" with your plugin name: > - function! health#foo#check() abort - call health#report_start('sanity checks') - " perform arbitrary checks - " ... - - if looks_good - call health#report_ok('found required dependencies') - else - call health#report_error('cannot find foo', - \ ['npm install --save foo']) - endif - endfunction - -============================================================================== - -vim:tw=78:ts=8:ft=help:fdm=marker + function! health#foo#check() abort + call health#report_start('sanity checks') + " perform arbitrary checks + " ... + + if looks_good + call health#report_ok('found required dependencies') + else + call health#report_error('cannot find foo', + \ ['npm install --save foo']) + endif + endfunction + +vim:noet tw=78:ts=8:ft=help:fdm=marker diff --git a/runtime/lua/health.lua b/runtime/lua/health.lua new file mode 100644 index 0000000000..142a353bf2 --- /dev/null +++ b/runtime/lua/health.lua @@ -0,0 +1,23 @@ +local M = {} + +function M.report_start(msg) + vim.fn['health#report_start'](msg) +end + +function M.report_info(msg) + vim.fn['health#report_info'](msg) +end + +function M.report_ok(msg) + vim.fn['health#report_ok'](msg) +end + +function M.report_warn(msg, ...) + vim.fn['health#report_warn'](msg, ...) +end + +function M.report_error(msg, ...) + vim.fn['health#report_error'](msg, ...) +end + +return M 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/fixtures/autoload/health/full_render.vim b/test/functional/fixtures/autoload/health/full_render.vim new file mode 100644 index 0000000000..2064b8606e --- /dev/null +++ b/test/functional/fixtures/autoload/health/full_render.vim @@ -0,0 +1,8 @@ +function! health#full_render#check() + call health#report_start("report 1") + call health#report_ok("life is fine") + call health#report_warn("no what installed", ["pip what", "make what"]) + call health#report_start("report 2") + call health#report_info("stuff is stable") + call health#report_error("why no hardcopy", [":h :hardcopy", ":h :TOhtml"]) +endfunction diff --git a/test/functional/fixtures/lua/test_plug/health/init.lua b/test/functional/fixtures/lua/test_plug/health/init.lua new file mode 100644 index 0000000000..d07632cff4 --- /dev/null +++ b/test/functional/fixtures/lua/test_plug/health/init.lua @@ -0,0 +1,11 @@ +local M = {} +local health = require("health") + +M.check = function() + health.report_start("report 1") + health.report_ok("everything is fine") + health.report_start("report 2") + health.report_ok("nothing to see here") +end + +return M diff --git a/test/functional/fixtures/lua/test_plug/submodule/health.lua b/test/functional/fixtures/lua/test_plug/submodule/health.lua new file mode 100644 index 0000000000..d07632cff4 --- /dev/null +++ b/test/functional/fixtures/lua/test_plug/submodule/health.lua @@ -0,0 +1,11 @@ +local M = {} +local health = require("health") + +M.check = function() + health.report_start("report 1") + health.report_ok("everything is fine") + health.report_start("report 2") + health.report_ok("nothing to see here") +end + +return M diff --git a/test/functional/fixtures/lua/test_plug/submodule_failed/health.lua b/test/functional/fixtures/lua/test_plug/submodule_failed/health.lua new file mode 100644 index 0000000000..3a8af6ebb2 --- /dev/null +++ b/test/functional/fixtures/lua/test_plug/submodule_failed/health.lua @@ -0,0 +1,12 @@ +local M = {} +local health = require("health") + +M.check = function() + health.report_start("report 1") + health.report_ok("everything is fine") + health.report_warn("About to add a number to nil") + local a = nil + 2 + return a +end + +return M diff --git a/test/functional/plugin/health_spec.lua b/test/functional/plugin/health_spec.lua index 85c67be8f9..2a86391e76 100644 --- a/test/functional/plugin/health_spec.lua +++ b/test/functional/plugin/health_spec.lua @@ -1,4 +1,5 @@ local helpers = require('test.functional.helpers')(after_each) +local global_helpers = require('test.helpers') local Screen = require('test.functional.ui.screen') local clear = helpers.clear @@ -35,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) @@ -48,42 +50,34 @@ describe('health.vim', function() command("set runtimepath+=test/functional/fixtures") end) - it("health#report_*()", function() - helpers.source([[ - let g:health_report = execute([ - \ "call health#report_start('Check Bar')", - \ "call health#report_ok('Bar status')", - \ "call health#report_ok('Other Bar status')", - \ "call health#report_warn('Zub')", - \ "call health#report_start('Baz')", - \ "call health#report_warn('Zim', ['suggestion 1', 'suggestion 2'])" - \ ]) - ]]) - local result = helpers.eval("g:health_report") - - helpers.eq(helpers.dedent([[ - - - ## Check Bar - - OK: Bar status - - OK: Other Bar status - - WARNING: Zub - - ## Baz - - WARNING: Zim + describe(":checkhealth", function() + it("functions health#report_*() render correctly", function() + command("checkhealth full_render") + helpers.expect([[ + + full_render: health#full_render#check + ======================================================================== + ## report 1 + - OK: life is fine + - WARNING: no what installed - ADVICE: - - suggestion 1 - - suggestion 2]]), - result) - end) + - pip what + - make what + ## report 2 + - INFO: stuff is stable + - ERROR: why no hardcopy + - ADVICE: + - :help |:hardcopy| + - :help |:TOhtml| + ]]) + end) - describe(":checkhealth", function() it("concatenates multiple reports", function() - command("checkhealth success1 success2") + command("checkhealth success1 success2 test_plug") helpers.expect([[ - health#success1#check + success1: health#success1#check ======================================================================== ## report 1 - OK: everything is fine @@ -91,25 +85,109 @@ describe('health.vim', function() ## report 2 - OK: nothing to see here - health#success2#check + success2: health#success2#check ======================================================================== ## another 1 - OK: ok + + test_plug: require("test_plug.health").check() + ======================================================================== + ## report 1 + - OK: everything is fine + + ## report 2 + - OK: nothing to see here + ]]) + end) + + it("lua plugins", function() + command("checkhealth test_plug") + helpers.expect([[ + + test_plug: require("test_plug.health").check() + ======================================================================== + ## report 1 + - OK: everything is fine + + ## report 2 + - OK: nothing to see here ]]) end) + it("lua plugins submodules", function() + command("checkhealth test_plug.submodule") + helpers.expect([[ + + test_plug.submodule: require("test_plug.submodule.health").check() + ======================================================================== + ## report 1 + - OK: everything is fine + + ## report 2 + - OK: nothing to see here + ]]) + end) + + it("lua plugins submodules with expression '*'", function() + command("checkhealth test_plug*") + local buf_lines = helpers.curbuf('get_lines', 0, -1, true) + -- avoid dealing with path separators + local received = table.concat(buf_lines, '\n', 1, #buf_lines - 2) + local expected = helpers.dedent([[ + + test_plug: require("test_plug.health").check() + ======================================================================== + ## report 1 + - OK: everything is fine + + ## report 2 + - OK: nothing to see here + + test_plug.submodule: require("test_plug.submodule.health").check() + ======================================================================== + ## report 1 + - OK: everything is fine + + ## report 2 + - OK: nothing to see here + + test_plug.submodule_failed: require("test_plug.submodule_failed.health").check() + ======================================================================== + - ERROR: Failed to run healthcheck for "test_plug.submodule_failed" plugin. Exception: + function health#check, line 24]]) + eq(expected, received) + end) + it("gracefully handles broken healthcheck", function() command("checkhealth broken") helpers.expect([[ - health#broken#check + broken: health#broken#check ======================================================================== - ERROR: Failed to run healthcheck for "broken" plugin. Exception: - function health#check[21]..health#broken#check, line 1 + function health#check[24]..health#broken#check, line 1 caused an error ]]) end) + it("gracefully handles broken lua healthcheck", function() + command("checkhealth test_plug.submodule_failed") + local buf_lines = helpers.curbuf('get_lines', 0, -1, true) + local received = table.concat(buf_lines, '\n', 1, #buf_lines - 2) + -- avoid dealing with path separators + local lua_err = "attempt to perform arithmetic on a nil value" + local last_line = buf_lines[#buf_lines - 1] + assert(string.find(last_line, lua_err) ~= nil, "Lua error not present") + + local expected = global_helpers.dedent([[ + + test_plug.submodule_failed: require("test_plug.submodule_failed.health").check() + ======================================================================== + - ERROR: Failed to run healthcheck for "test_plug.submodule_failed" plugin. Exception: + function health#check, line 24]]) + eq(expected, received) + end) + it("highlights OK, ERROR", function() local screen = Screen.new(72, 10) screen:attach() @@ -126,11 +204,11 @@ describe('health.vim', function() command("set laststatus=0") screen:expect{grid=[[ ^ | - {Heading:health#foo#check} | + {Heading:foo: } | {Bar:========================================================================}| {Bullet: -} {Error:ERROR:} No healthcheck found for "foo" plugin. | | - {Heading:health#success1#check} | + {Heading:success1: health#success1#check} | {Bar:========================================================================}| {Heading2:##}{Heading: report 1} | {Bullet: -} {Ok:OK:} everything is fine | @@ -140,9 +218,10 @@ describe('health.vim', function() it("gracefully handles invalid healthcheck", function() command("checkhealth non_existent_healthcheck") + -- luacheck: ignore 613 helpers.expect([[ - health#non_existent_healthcheck#check + non_existent_healthcheck: ======================================================================== - ERROR: No healthcheck found for "non_existent_healthcheck" plugin. ]]) |