diff --git a/runtime/doc/help.txt b/runtime/doc/help.txt index 7545d2c621..f2deac3cd8 100644 --- a/runtime/doc/help.txt +++ b/runtime/doc/help.txt @@ -175,7 +175,6 @@ DEVELOPING NVIM Standard plugins ~ *standard-plugin-list* |pi_gzip.txt| Reading and writing compressed files -|pi_health.txt| Healthcheck framework |pi_msgpack.txt| msgpack utilities |pi_netrw.txt| Reading and writing files over a network |pi_paren.txt| Highlight matching parens diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt index fccda177d2..76a6bc0801 100644 --- a/runtime/doc/lua.txt +++ b/runtime/doc/lua.txt @@ -4430,4 +4430,129 @@ tohtml.tohtml({winid}, {opt}) *tohtml.tohtml.tohtml()* (`string[]`) +============================================================================== +Lua module: vim.health *vim.health* + + +health.vim is a minimal framework to help users troubleshoot configuration and +any other environment conditions that a plugin might care about. Nvim ships +with healthchecks for configuration, performance, python support, ruby +support, clipboard support, and more. + +To run all healthchecks, use: >vim + + :checkhealth +< +Plugin authors are encouraged to write new healthchecks. |health-dev| + +Commands *health-commands* + + *:che* *:checkhealth* +:che[ckhealth] Run all healthchecks. + *E5009* + 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. + +:che[ckhealth] {plugins} + Run healthcheck(s) for one or more plugins. E.g. to run only + the standard Nvim healthcheck: >vim + :checkhealth vim.health +< + To run the healthchecks for the "foo" and "bar" plugins + (assuming they are on 'runtimepath' and they have implemented + the Lua `require("foo.health").check()` interface): >vim + :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`: >vim + :checkhealth vim.lsp vim.treesitter + :checkhealth vim* +< + +Create a healthcheck *health-dev* + +Healthchecks are functions that check the user environment, configuration, or +any other prerequisites that a plugin cares about. Nvim ships with +healthchecks in: + - $VIMRUNTIME/autoload/health/ + - $VIMRUNTIME/lua/vim/lsp/health.lua + - $VIMRUNTIME/lua/vim/treesitter/health.lua + - and more... + +To add a new healthcheck for your own plugin, simply create a "health.lua" +module on 'runtimepath' that returns a table with a "check()" function. Then +|:checkhealth| will automatically find and invoke the function. + +For example if your plugin is named "foo", define your healthcheck module at +one of these locations (on 'runtimepath'): + - lua/foo/health/init.lua + - lua/foo/health.lua + +If your plugin also provides a submodule named "bar" for which you want +a separate healthcheck, define the healthcheck at one of these locations: + - lua/foo/bar/health/init.lua + - lua/foo/bar/health.lua + +All such health modules must return a Lua table containing a `check()` +function. + +Copy this sample code into `lua/foo/health.lua`, replacing "foo" in the path +with your plugin name: >lua + + local M = {} + + M.check = function() + vim.health.start("foo report") + -- make sure setup function parameters are ok + if check_setup() then + vim.health.ok("Setup is correct") + else + vim.health.error("Setup is incorrect") + end + -- do some more checking + -- ... + end + + return M + + +vim.health.error({msg}, {...}) *vim.health.error()* + Reports an error. + + Parameters: ~ + • {msg} (`string`) + • {...} (`string|string[]`) Optional advice + +vim.health.info({msg}) *vim.health.info()* + Reports an informational message. + + Parameters: ~ + • {msg} (`string`) + +vim.health.ok({msg}) *vim.health.ok()* + Reports a "success" message. + + Parameters: ~ + • {msg} (`string`) + +vim.health.start({name}) *vim.health.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. + + Parameters: ~ + • {name} (`string`) + +vim.health.warn({msg}, {...}) *vim.health.warn()* + Reports a warning. + + Parameters: ~ + • {msg} (`string`) + • {...} (`string|string[]`) Optional advice + + vim:tw=78:ts=8:sw=4:sts=4:et:ft=help:norl: diff --git a/runtime/doc/pi_health.txt b/runtime/doc/pi_health.txt deleted file mode 100644 index bcc933d8b2..0000000000 --- a/runtime/doc/pi_health.txt +++ /dev/null @@ -1,122 +0,0 @@ -*pi_health.txt* Healthcheck framework - -Author: TJ DeVries - - Type |gO| to see the table of contents. - -============================================================================== -Introduction *health* - -health.vim is a minimal framework to help users troubleshoot configuration and -any other environment conditions that a plugin might care about. Nvim ships -with healthchecks for configuration, performance, python support, ruby -support, clipboard support, and more. - -To run all healthchecks, use: >vim - - :checkhealth -< -Plugin authors are encouraged to write new healthchecks. |health-dev| - -============================================================================== -Commands *health-commands* - - *:che* *:checkhealth* -:che[ckhealth] Run all healthchecks. - *E5009* - 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. - -:che[ckhealth] {plugins} - Run healthcheck(s) for one or more plugins. E.g. to run only - the standard Nvim healthcheck: >vim - :checkhealth nvim -< - To run the healthchecks for the "foo" and "bar" plugins - (assuming they are on 'runtimepath' and they have implemented - the Lua `require("foo.health").check()` interface): >vim - :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`: >vim - :checkhealth vim.lsp vim.treesitter - :checkhealth vim* -< -============================================================================== -Functions *health-functions* *vim.health* - -The Lua "health" module can be used to create new healthchecks. To get started -see |health-dev|. - -vim.health.start({name}) *vim.health.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. - -vim.health.info({msg}) *vim.health.info()* - Reports an informational message. - -vim.health.ok({msg}) *vim.health.ok()* - Reports a "success" message. - -vim.health.warn({msg} [, {advice}]) *vim.health.warn()* - Reports a warning. {advice} is an optional list of suggestions to - present to the user. - -vim.health.error({msg} [, {advice}]) *vim.health.error()* - Reports an error. {advice} is an optional list of suggestions to - present to the user. - -============================================================================== -Create a healthcheck *health-dev* - -Healthchecks are functions that check the user environment, configuration, or -any other prerequisites that a plugin cares about. Nvim ships with -healthchecks in: - - $VIMRUNTIME/autoload/health/ - - $VIMRUNTIME/lua/vim/lsp/health.lua - - $VIMRUNTIME/lua/vim/treesitter/health.lua - - and more... - -To add a new healthcheck for your own plugin, simply create a "health.lua" -module on 'runtimepath' that returns a table with a "check()" function. Then -|:checkhealth| will automatically find and invoke the function. - -For example if your plugin is named "foo", define your healthcheck module at -one of these locations (on 'runtimepath'): - - lua/foo/health/init.lua - - lua/foo/health.lua - -If your plugin also provides a submodule named "bar" for which you want -a separate healthcheck, define the healthcheck at one of these locations: - - lua/foo/bar/health/init.lua - - lua/foo/bar/health.lua - -All such health modules must return a Lua table containing a `check()` -function. - -Copy this sample code into `lua/foo/health.lua`, replacing "foo" in the path -with your plugin name: >lua - - local M = {} - - M.check = function() - vim.health.start("foo report") - -- make sure setup function parameters are ok - if check_setup() then - vim.health.ok("Setup is correct") - else - vim.health.error("Setup is incorrect") - end - -- do some more checking - -- ... - end - - return M - - -vim:et:tw=78:ts=8:ft=help:fdm=marker diff --git a/runtime/lua/vim/health.lua b/runtime/lua/vim/health.lua index 69a53485a4..263a6ec85f 100644 --- a/runtime/lua/vim/health.lua +++ b/runtime/lua/vim/health.lua @@ -1,3 +1,91 @@ +--- @brief +---
help
+--- health.vim is a minimal framework to help users troubleshoot configuration and
+--- any other environment conditions that a plugin might care about. Nvim ships
+--- with healthchecks for configuration, performance, python support, ruby
+--- support, clipboard support, and more.
+---
+--- To run all healthchecks, use: >vim
+---
+---         :checkhealth
+--- <
+--- Plugin authors are encouraged to write new healthchecks. |health-dev|
+---
+--- Commands                                *health-commands*
+---
+---                                                              *:che* *:checkhealth*
+--- :che[ckhealth]  Run all healthchecks.
+---                                         *E5009*
+---                 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.
+---
+--- :che[ckhealth] {plugins}
+---                 Run healthcheck(s) for one or more plugins. E.g. to run only
+---                 the standard Nvim healthcheck: >vim
+---                         :checkhealth vim.health
+--- <
+---                 To run the healthchecks for the "foo" and "bar" plugins
+---                 (assuming they are on 'runtimepath' and they have implemented
+---                 the Lua `require("foo.health").check()` interface): >vim
+---                         :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`:  >vim
+---                         :checkhealth vim.lsp vim.treesitter
+---                         :checkhealth vim*
+--- <
+---
+--- Create a healthcheck                                    *health-dev*
+---
+--- Healthchecks are functions that check the user environment, configuration, or
+--- any other prerequisites that a plugin cares about. Nvim ships with
+--- healthchecks in:
+---         - $VIMRUNTIME/autoload/health/
+---         - $VIMRUNTIME/lua/vim/lsp/health.lua
+---         - $VIMRUNTIME/lua/vim/treesitter/health.lua
+---         - and more...
+---
+--- To add a new healthcheck for your own plugin, simply create a "health.lua"
+--- module on 'runtimepath' that returns a table with a "check()" function. Then
+--- |:checkhealth| will automatically find and invoke the function.
+---
+--- For example if your plugin is named "foo", define your healthcheck module at
+--- one of these locations (on 'runtimepath'):
+---         - lua/foo/health/init.lua
+---         - lua/foo/health.lua
+---
+--- If your plugin also provides a submodule named "bar" for which you want
+--- a separate healthcheck, define the healthcheck at one of these locations:
+---         - lua/foo/bar/health/init.lua
+---         - lua/foo/bar/health.lua
+---
+--- All such health modules must return a Lua table containing a `check()`
+--- function.
+---
+--- Copy this sample code into `lua/foo/health.lua`, replacing "foo" in the path
+--- with your plugin name: >lua
+---
+---         local M = {}
+---
+---         M.check = function()
+---           vim.health.start("foo report")
+---           -- make sure setup function parameters are ok
+---           if check_setup() then
+---             vim.health.ok("Setup is correct")
+---           else
+---             vim.health.error("Setup is incorrect")
+---           end
+---           -- do some more checking
+---           -- ...
+---         end
+---
+---         return M
+---
+ local M = {} local s_output = {} ---@type string[] @@ -143,7 +231,9 @@ local function collect_output(output) vim.list_extend(s_output, vim.split(output, '\n')) end ---- Starts a new report. +--- 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. --- --- @param name string function M.start(name) @@ -151,7 +241,7 @@ function M.start(name) collect_output(input) end ---- Reports a message in the current section. +--- Reports an informational message. --- --- @param msg string function M.info(msg) @@ -159,7 +249,7 @@ function M.info(msg) collect_output(input) end ---- Reports a successful healthcheck. +--- Reports a "success" message. --- --- @param msg string function M.ok(msg) @@ -167,7 +257,7 @@ function M.ok(msg) collect_output(input) end ---- Reports a health warning. +--- Reports a warning. --- --- @param msg string --- @param ... string|string[] Optional advice @@ -176,7 +266,7 @@ function M.warn(msg, ...) collect_output(input) end ---- Reports a failed healthcheck. +--- Reports an error. --- --- @param msg string --- @param ... string|string[] Optional advice @@ -185,7 +275,7 @@ function M.error(msg, ...) collect_output(input) end -function M.provider_disabled(provider) +function M._provider_disabled(provider) local loaded_var = 'loaded_' .. provider .. '_provider' local v = vim.g[loaded_var] if v == 0 then @@ -225,7 +315,7 @@ local function shellify(cmd) return table.concat(escaped, ' ') end -function M.cmd_ok(cmd) +function M._cmd_ok(cmd) local out = vim.fn.system(cmd) return vim.v.shell_error == 0, out end @@ -238,7 +328,7 @@ end --- - stderr (boolean): Append stderr to stdout --- - ignore_error (boolean): If true, ignore error output --- - timeout (number): Number of seconds to wait before timing out (default 30) -function M.system(cmd, args) +function M._system(cmd, args) args = args or {} local stdin = args.stdin or '' local stderr = vim.F.if_nil(args.stderr, false) diff --git a/runtime/lua/vim/provider/clipboard/health.lua b/runtime/lua/vim/provider/clipboard/health.lua index e44f7d32cc..0af6a44330 100644 --- a/runtime/lua/vim/provider/clipboard/health.lua +++ b/runtime/lua/vim/provider/clipboard/health.lua @@ -9,7 +9,7 @@ function M.check() os.getenv('TMUX') and vim.fn.executable('tmux') == 1 and vim.fn.executable('pbpaste') == 1 - and not health.cmd_ok('pbpaste') + and not health._cmd_ok('pbpaste') then local tmux_version = string.match(vim.fn.system('tmux -V'), '%d+%.%d+') local advice = { diff --git a/runtime/lua/vim/provider/node/health.lua b/runtime/lua/vim/provider/node/health.lua index 471c625388..b24a9e0061 100644 --- a/runtime/lua/vim/provider/node/health.lua +++ b/runtime/lua/vim/provider/node/health.lua @@ -6,7 +6,7 @@ local M = {} function M.check() health.start('Node.js provider (optional)') - if health.provider_disabled('node') then + if health._provider_disabled('node') then return end @@ -26,7 +26,7 @@ function M.check() end -- local node_v = vim.fn.split(system({'node', '-v'}), "\n")[1] or '' - local ok, node_v = health.cmd_ok({ 'node', '-v' }) + local ok, node_v = health._cmd_ok({ 'node', '-v' }) health.info('Node.js: ' .. node_v) if not ok or vim.version.lt(node_v, '6.0.0') then health.warn('Nvim node.js host does not support Node ' .. node_v) @@ -63,7 +63,7 @@ function M.check() iswin and 'cmd /c ' .. manager .. ' info neovim --json' or manager .. ' info neovim --json' ) local latest_npm - ok, latest_npm = health.cmd_ok(vim.split(latest_npm_cmd, ' ')) + ok, latest_npm = health._cmd_ok(vim.split(latest_npm_cmd, ' ')) if not ok or latest_npm:find('^%s$') then health.error( 'Failed to run: ' .. latest_npm_cmd, @@ -81,7 +81,7 @@ function M.check() local current_npm_cmd = { 'node', host, '--version' } local current_npm - ok, current_npm = health.cmd_ok(current_npm_cmd) + ok, current_npm = health._cmd_ok(current_npm_cmd) if not ok then health.error( 'Failed to run: ' .. table.concat(current_npm_cmd, ' '), diff --git a/runtime/lua/vim/provider/perl/health.lua b/runtime/lua/vim/provider/perl/health.lua index 535093d793..ffc0419b94 100644 --- a/runtime/lua/vim/provider/perl/health.lua +++ b/runtime/lua/vim/provider/perl/health.lua @@ -5,7 +5,7 @@ local M = {} function M.check() health.start('Perl provider (optional)') - if health.provider_disabled('perl') then + if health._provider_disabled('perl') then return end @@ -24,7 +24,7 @@ function M.check() -- we cannot use cpanm that is on the path, as it may not be for the perl -- set with g:perl_host_prog - local ok = health.cmd_ok({ perl_exec, '-W', '-MApp::cpanminus', '-e', '' }) + local ok = health._cmd_ok({ perl_exec, '-W', '-MApp::cpanminus', '-e', '' }) if not ok then return { perl_exec, '"App::cpanminus" module is not installed' } end @@ -36,7 +36,7 @@ function M.check() 'my $app = App::cpanminus::script->new; $app->parse_options ("--info", "-q", "Neovim::Ext"); exit $app->doit', } local latest_cpan - ok, latest_cpan = health.cmd_ok(latest_cpan_cmd) + ok, latest_cpan = health._cmd_ok(latest_cpan_cmd) if not ok or latest_cpan:find('^%s*$') then health.error( 'Failed to run: ' .. table.concat(latest_cpan_cmd, ' '), @@ -67,7 +67,7 @@ function M.check() local current_cpan_cmd = { perl_exec, '-W', '-MNeovim::Ext', '-e', 'print $Neovim::Ext::VERSION' } local current_cpan - ok, current_cpan = health.cmd_ok(current_cpan_cmd) + ok, current_cpan = health._cmd_ok(current_cpan_cmd) if not ok then health.error( 'Failed to run: ' .. table.concat(current_cpan_cmd, ' '), diff --git a/runtime/lua/vim/provider/python/health.lua b/runtime/lua/vim/provider/python/health.lua index a5bd738063..37ccb42da3 100644 --- a/runtime/lua/vim/provider/python/health.lua +++ b/runtime/lua/vim/provider/python/health.lua @@ -70,7 +70,7 @@ end local function download(url) local has_curl = vim.fn.executable('curl') == 1 if has_curl and vim.fn.system({ 'curl', '-V' }):find('Protocols:.*https') then - local out, rc = health.system({ 'curl', '-sL', url }, { stderr = true, ignore_error = true }) + local out, rc = health._system({ 'curl', '-sL', url }, { stderr = true, ignore_error = true }) if rc ~= 0 then return 'curl error with ' .. url .. ': ' .. rc else @@ -83,7 +83,7 @@ local function download(url) from urllib2 import urlopen\n\ response = urlopen('" .. url .. "')\n\ print(response.read().decode('utf8'))\n" - local out, rc = health.system({ 'python', '-c', script }) + local out, rc = health._system({ 'python', '-c', script }) if out == '' and rc ~= 0 then return 'python urllib.request error: ' .. rc else @@ -140,7 +140,7 @@ end local function version_info(python) local pypi_version = latest_pypi_version() - local python_version, rc = health.system({ + local python_version, rc = health._system({ python, '-c', 'import sys; print(".".join(str(x) for x in sys.version_info[:3]))', @@ -151,7 +151,7 @@ local function version_info(python) end local nvim_path - nvim_path, rc = health.system({ + nvim_path, rc = health._system({ python, '-c', 'import sys; sys.path = [p for p in sys.path if p != ""]; import neovim; print(neovim.__file__)', @@ -176,7 +176,7 @@ local function version_info(python) -- Try to get neovim.VERSION (added in 0.1.11dev). local nvim_version - nvim_version, rc = health.system({ + nvim_version, rc = health._system({ python, '-c', 'from neovim import VERSION as v; print("{}.{}.{}{}".format(v.major, v.minor, v.patch, v.prerelease))', @@ -223,7 +223,7 @@ function M.check() local host_prog_var = pyname .. '_host_prog' local python_multiple = {} - if health.provider_disabled(pyname) then + if health._provider_disabled(pyname) then return end @@ -265,7 +265,7 @@ function M.check() end if pyenv ~= '' then - python_exe = health.system({ pyenv, 'which', pyname }, { stderr = true }) + python_exe = health._system({ pyenv, 'which', pyname }, { stderr = true }) if python_exe == '' then health.warn('pyenv could not find ' .. pyname .. '.') end @@ -488,7 +488,7 @@ function M.check() health.info(msg) health.info( 'Python version: ' - .. health.system( + .. health._system( 'python -c "import platform, sys; sys.stdout.write(platform.python_version())"' ) ) diff --git a/runtime/lua/vim/provider/ruby/health.lua b/runtime/lua/vim/provider/ruby/health.lua index 31c2fe3201..80932e1bb0 100644 --- a/runtime/lua/vim/provider/ruby/health.lua +++ b/runtime/lua/vim/provider/ruby/health.lua @@ -6,7 +6,7 @@ local M = {} function M.check() health.start('Ruby provider (optional)') - if health.provider_disabled('ruby') then + if health._provider_disabled('ruby') then return end @@ -17,7 +17,7 @@ function M.check() ) return end - health.info('Ruby: ' .. health.system({ 'ruby', '-v' })) + health.info('Ruby: ' .. health._system({ 'ruby', '-v' })) local host, _ = vim.provider.ruby.detect() if (not host) or host:find('^%s*$') then @@ -33,7 +33,7 @@ function M.check() health.info('Host: ' .. host) local latest_gem_cmd = (iswin and 'cmd /c gem list -ra "^^neovim$"' or 'gem list -ra ^neovim$') - local ok, latest_gem = health.cmd_ok(vim.split(latest_gem_cmd, ' ')) + local ok, latest_gem = health._cmd_ok(vim.split(latest_gem_cmd, ' ')) if not ok or latest_gem:find('^%s*$') then health.error( 'Failed to run: ' .. latest_gem_cmd, @@ -46,7 +46,7 @@ function M.check() local current_gem_cmd = { host, '--version' } local current_gem - ok, current_gem = health.cmd_ok(current_gem_cmd) + ok, current_gem = health._cmd_ok(current_gem_cmd) if not ok then health.error( 'Failed to run: ' .. table.concat(current_gem_cmd, ' '), diff --git a/scripts/gen_help_html.lua b/scripts/gen_help_html.lua index b712cf1475..2a8f8308ac 100644 --- a/scripts/gen_help_html.lua +++ b/scripts/gen_help_html.lua @@ -75,7 +75,6 @@ local new_layout = { ['news-0.9.txt'] = true, ['news-0.10.txt'] = true, ['nvim.txt'] = true, - ['pi_health.txt'] = true, ['provider.txt'] = true, ['ui.txt'] = true, ['vim_diff.txt'] = true, @@ -1440,9 +1439,9 @@ function M.test_gen(help_dir) help_dir, tmpdir, -- Because gen() is slow (~30s), this test is limited to a few files. - { 'pi_health.txt', 'help.txt', 'index.txt', 'nvim.txt' } + { 'help.txt', 'index.txt', 'nvim.txt' } ) - eq(4, #rv.helpfiles) + eq(3, #rv.helpfiles) eq(0, rv.err_count, 'parse errors in :help docs') eq({}, rv.invalid_links, 'invalid tags in :help docs') end diff --git a/scripts/gen_vimdoc.lua b/scripts/gen_vimdoc.lua index 6d0fc46145..eea5688621 100755 --- a/scripts/gen_vimdoc.lua +++ b/scripts/gen_vimdoc.lua @@ -162,6 +162,7 @@ local config = { 'snippet.lua', 'text.lua', 'tohtml.lua', + 'health.lua', }, files = { 'runtime/lua/vim/iter.lua', @@ -181,6 +182,7 @@ local config = { 'runtime/lua/vim/snippet.lua', 'runtime/lua/vim/text.lua', 'runtime/lua/vim/glob.lua', + 'runtime/lua/vim/health.lua', 'runtime/lua/vim/_meta/builtin.lua', 'runtime/lua/vim/_meta/diff.lua', 'runtime/lua/vim/_meta/mpack.lua',