Merge #7399 ':checkhealth (built-in)'

This commit is contained in:
Justin M. Keyes 2017-10-17 22:43:46 +02:00 committed by GitHub
commit 0cba3da26e
14 changed files with 154 additions and 111 deletions

View File

@ -18,7 +18,7 @@ function! s:enhance_syntax() abort
syntax match healthBar "|" contained conceal
highlight link healthHelp Identifier
" We do not care about markdown syntax errors in :CheckHealth output.
" We do not care about markdown syntax errors in :checkhealth output.
highlight! link markdownError Normal
endfunction
@ -159,7 +159,10 @@ endfunction
" Translates a list of plugin names to healthcheck function names.
function! s:to_fn_names(plugin_names) abort
let healthchecks = []
for p in a:plugin_names
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')
endfor
return healthchecks

View File

@ -4,12 +4,19 @@ function! s:check_config() abort
let ok = v:true
call health#report_start('Configuration')
" If $VIM is empty we don't care. Else make sure it is valid.
if !empty($VIM) && !filereadable($VIM.'/runtime/doc/nvim.txt')
let ok = v:false
call health#report_error("$VIM is invalid: ".$VIM)
endif
if exists('$NVIM_TUI_ENABLE_CURSOR_SHAPE')
let ok = v:false
call health#report_warn("$NVIM_TUI_ENABLE_CURSOR_SHAPE is ignored in Nvim 0.2+",
\ [ "Use the 'guicursor' option to configure cursor shape. :help 'guicursor'",
\ 'https://github.com/neovim/neovim/wiki/Following-HEAD#20170402' ])
endif
if &paste
let ok = v:false
call health#report_error("'paste' is enabled. This option is only for pasting text.\nIt should not be set in your config.",

View File

@ -75,7 +75,7 @@ let s:prog = provider#ruby#Detect()
let s:plugin_path = expand('<sfile>:p:h') . '/script_host.rb'
if empty(s:prog)
let s:err = 'Cannot find the neovim RubyGem. Try :CheckHealth'
let s:err = 'Cannot find the neovim RubyGem. Try :checkhealth'
endif
call remote#host#RegisterClone('legacy-ruby-provider', 'ruby')

View File

@ -5,50 +5,42 @@ Author: TJ DeVries <devries.timothyj@gmail.com>
Type <M-]> to see the table of contents.
==============================================================================
Introduction *healthcheck* *health.vim-intro*
Introduction *health*
Troubleshooting user configuration problems is a time-consuming task that
developers want to minimize. health.vim provides a simple framework for plugin
authors to hook into, and for users to invoke, to check and report the user's
configuration and environment. Type this command to try it: >
health.vim is a minimal framework to help with troubleshooting user
configuration. Nvim ships with healthchecks for configuration, performance,
python support, ruby support, clipboard support, and more.
:CheckHealth
To run the healthchecks, use this command: >
:checkhealth
<
For example, some users have broken or unusual Python setups, which breaks the
|:python| command. |:CheckHealth| detects several common Python configuration
problems and reports them. If the Neovim Python module is not installed, it
shows a warning: >
You have not installed the Neovim Python module
You might want to try `pip install Neovim`
<
Plugin authors are encouraged to add healthchecks, see |health.vim-dev|.
Plugin authors are encouraged to write new healthchecks. |health-dev|
==============================================================================
Commands and functions *health.vim-manual*
Commands *health-commands*
Commands
------------------------------------------------------------------------------
*:CheckHealth*
:CheckHealth Run all healthchecks and show the output in a new
tabpage. These healthchecks are included by default:
- python2
- python3
- ruby
- remote plugin
*:checkhealth* *:CheckHealth*
:checkhealth Run all healthchecks.
*E5009*
Nvim depends on the |$VIMRUNTIME| environment variable
to find the standard "runtime files" for syntax
highlighting, filetype-specific behavior, and standard
plugins such as :checkhealth. If $VIMRUNTIME is invalid
then those features will not work.
:CheckHealth {plugins}
Run healthchecks for one or more plugins. E.g. to run
:checkhealth {plugins}
Run healthcheck(s) for one or more plugins. E.g. to run
only the standard Nvim healthcheck: >
:CheckHealth nvim
: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
:checkhealth foo bar
<
Functions
------------------------------------------------------------------------------
==============================================================================
Functions *health-functions*
health.vim functions are for creating new healthchecks. They mostly just do
some layout and formatting, to give users a consistent presentation.
@ -59,51 +51,49 @@ health#report_start({name}) *health#report_start*
per section.
health#report_info({msg}) *health#report_info*
Displays an informational message.
Reports an informational message.
health#report_ok({msg}) *health#report_ok*
Displays a "success" message.
Reports a "success" message.
health#report_warn({msg}, [{advice}]) *health#report_warn*
Displays a warning. {advice} is an optional List of suggestions.
Reports a warning. {advice} is an optional List of suggestions.
health#report_error({msg}, [{advice}]) *health#report_error*
Displays an error. {advice} is an optional List of suggestions.
Reports an error. {advice} is an optional List of suggestions.
health#{plugin}#check() *health.user_checker*
This is the form of a healthcheck definition. Call the above functions
from this function, then |:CheckHealth| does the rest. 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
<
The function will be found and called automatically when the user
invokes |:CheckHealth|.
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.vim-dev*
Create a healthcheck *health-dev*
Healthchecks are functions that check the health of the system. Neovim has
built-in checkers, found in $VIMRUNTIME/autoload/health/.
Healthchecks are functions that check the user environment, configuration,
etc. Nvim has built-in healthchecks in $VIMRUNTIME/autoload/health/.
To add a new checker for your own plugin, simply define a
To add a new healthcheck for your own plugin, simply define a
health#{plugin}#check() function in autoload/health/{plugin}.vim.
|:CheckHealth| automatically finds and invokes such functions.
|:checkhealth| automatically finds and invokes such functions.
If your plugin is named "jslint", then its healthcheck function must be >
health#jslint#check()
If your plugin is named "foo", then its healthcheck function must be >
health#foo#check()
defined in this file on 'runtimepath': >
autoload/health/jslint.vim
autoload/health/foo.vim
Here's a sample to get started: >
function! health#jslint#check() abort
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
" ...
@ -111,8 +101,8 @@ Here's a sample to get started: >
if looks_good
call health#report_ok('found required dependencies')
else
call health#report_error('cannot find jslint',
\ ['npm install --save jslint'])
call health#report_error('cannot find foo',
\ ['npm install --save foo'])
endif
endfunction

View File

@ -20,7 +20,7 @@ Note: Only the Vim 7.3 API is supported; bindeval (Vim 7.4) is not.
PYTHON QUICKSTART ~
If you used a package manager to install Nvim, you might already have the
required `neovim` Python package. Run |:CheckHealth| to see if your system is
required `neovim` Python package. Run |:checkhealth| to see if your system is
up-to-date.
Following are steps to install the package with Python's `pip` tool.
@ -88,7 +88,7 @@ Ruby integration *provider-ruby*
Nvim supports the Vim legacy |ruby-vim| interface via external Ruby
interpreters connected via |RPC|.
Run |:CheckHealth| to see if your system is up-to-date.
Run |:checkhealth| to see if your system is up-to-date.
RUBY QUICKSTART ~

View File

@ -633,54 +633,40 @@ though.
==============================================================================
3. $VIM and $VIMRUNTIME
*$VIM*
The environment variable "$VIM" is used to locate various user files for Vim,
The environment variable "$VIM" is used to locate various user files for Nvim,
such as the user startup script |init.vim|. This depends on the system, see
|startup|.
To avoid the need for every user to set the $VIM environment variable, Vim
will try to get the value for $VIM in this order:
1. The value defined by the $VIM environment variable. You can use this to
make Vim look in a specific directory for its support files. Example: >
setenv VIM /home/paul/vim
2. The path from 'helpfile' is used, unless it contains some environment
variable too (the default is "$VIMRUNTIME/doc/help.txt": chicken-egg
problem). The file name ("help.txt" or any other) is removed. Then
trailing directory names are removed, in this order: "doc", "runtime" and
"vim{version}" (e.g., "vim54").
3. For MSDOS and Win32 Vim tries to use the directory name of the
executable. If it ends in "/src", this is removed. This is useful if you
unpacked the .zip file in some directory, and adjusted the search path to
find the vim executable. Trailing directory names are removed, in this
order: "runtime" and "vim{version}" (e.g., "vim54").
4. For Unix the compile-time defined installation directory is used (see the
output of ":version").
Nvim will try to get the value for $VIM in this order:
1. Environment variable $VIM, if it is set.
2. Path derived from the 'helpfile' option, unless it contains some
environment variable too (default is "$VIMRUNTIME/doc/help.txt"). File
name ("help.txt", etc.) is removed. Trailing directory names are removed,
in this order: "doc", "runtime".
3. Path derived from the location of the `nvim` executable.
4. Compile-time defined installation directory (see output of ":version").
After doing this once, Nvim sets the $VIM environment variable.
Once Vim has done this once, it will set the $VIM environment variable. To
change it later, use a ":let" command like this: >
:let $VIM = "/home/paul/vim/"
<
*$VIMRUNTIME*
The environment variable "$VIMRUNTIME" is used to locate various support
files, such as the on-line documentation and files used for syntax
highlighting. For example, the main help file is normally
"$VIMRUNTIME/doc/help.txt".
You don't normally set $VIMRUNTIME yourself, but let Vim figure it out. This
is the order used to find the value of $VIMRUNTIME:
1. If the environment variable $VIMRUNTIME is set, it is used. You can use
this when the runtime files are in an unusual location.
2. If "$VIM/vim{version}" exists, it is used. {version} is the version
number of Vim, without any '-' or '.'. For example: "$VIM/vim54". This is
the normal value for $VIMRUNTIME.
3. If "$VIM/runtime" exists, it is used.
4. The value of $VIM is used. This is for backwards compatibility with older
versions.
5. If "../share/nvim/runtime" exists relative to |v:progpath|, it is used.
6. When the 'helpfile' option is set and doesn't contain a '$', its value is
used, with "doc/help.txt" removed from the end.
files, such as the documentation and syntax-highlighting files. For example,
the main help file is normally "$VIMRUNTIME/doc/help.txt".
Once Vim has done this once, it will set the $VIMRUNTIME environment variable.
To change it later, use a ":let" command like this: >
:let $VIMRUNTIME = "/home/piet/vim/vim54"
Nvim will try to get the value for $VIMRUNTIME in this order:
1. Environment variable $VIMRUNTIME, if it is set.
2. Directory path "$VIM/vim{version}", if it exists, where {version} is the
Vim version number without '-' or '.'. For example: "$VIM/vim54".
3. Directory path "$VIM/runtime", if it exists.
4. Value of $VIM environment variable. This is for backwards compatibility
with older Vim versions.
5. If "../share/nvim/runtime" exists relative to |v:progpath|, it is used.
6. Path derived from the 'helpfile' option (if it doesn't contain '$') with
"doc/help.txt" removed from the end.
After doing this once, Nvim sets the $VIMRUNTIME environment variable.
In case you need the value of $VIMRUNTIME in a shell (e.g., for a script that
greps in the help files) you might be able to use this: >

View File

@ -127,7 +127,7 @@ Variables:
|v:windowid| is always available (for use by external UIs)
Commands:
|:CheckHealth|
|:checkhealth|
|:drop| is available on all platforms
|:Man| is available by default, with many improvements such as completion

View File

@ -22850,3 +22850,32 @@ void eval_format_source_name_line(char *buf, size_t bufsize)
(sourcing_name ? sourcing_name : (char_u *)"?"),
(sourcing_name ? sourcing_lnum : 0));
}
/// ":checkhealth [plugins]"
void ex_checkhealth(exarg_T *eap)
{
bool found = !!find_func((char_u *)"health#check");
if (!found
&& script_autoload("health#check", sizeof("health#check") - 1, false)) {
found = !!find_func((char_u *)"health#check");
}
if (!found) {
const char *vimruntime_env = os_getenv("VIMRUNTIME");
if (vimruntime_env == NULL) {
EMSG(_("E5009: $VIMRUNTIME is empty or unset"));
return;
} else {
EMSG2(_("E5009: Invalid $VIMRUNTIME: %s"), os_getenv("VIMRUNTIME"));
return;
}
}
size_t bufsize = STRLEN(eap->arg) + sizeof("call health#check('')");
char *buf = xmalloc(bufsize);
snprintf(buf, bufsize, "call health#check('%s')", eap->arg);
do_cmdline_cmd(buf);
xfree(buf);
}

View File

@ -450,6 +450,12 @@ return {
addr_type=ADDR_LINES,
func='ex_changes',
},
{
command='checkhealth',
flags=bit.bor(EXTRA, TRLBAR),
addr_type=ADDR_LINES,
func='ex_checkhealth',
},
{
command='checkpath',
flags=bit.bor(TRLBAR, BANG, CMDWIN),

View File

@ -5535,7 +5535,7 @@ int get_default_register_name(void)
static yankreg_T *adjust_clipboard_name(int *name, bool quiet, bool writing)
{
#define MSG_NO_CLIP "clipboard: No provider. " \
"Try \":CheckHealth\" or \":h clipboard\"."
"Try \":checkhealth\" or \":h clipboard\"."
yankreg_T *target = NULL;
bool explicit_cb_reg = (*name == '*' || *name == '+');

View File

@ -1365,7 +1365,7 @@ void intro_message(int colon)
N_("https://neovim.io/community"),
"",
N_("type :help nvim<Enter> if you are new! "),
N_("type :CheckHealth<Enter> to optimize Nvim"),
N_("type :checkhealth<Enter> to optimize Nvim"),
N_("type :q<Enter> to exit "),
N_("type :help<Enter> for help "),
"",

View File

@ -100,7 +100,7 @@ describe('clipboard', function()
^ |
~ |
~ |
clipboard: No provider. Try ":CheckHealth" or ":h clipboard". |
clipboard: No provider. Try ":checkhealth" or ":h clipboard". |
]], nil, {{bold = true, foreground = Screen.colors.Blue}})
end)
@ -112,7 +112,7 @@ describe('clipboard', function()
feed_command('redir @+> | bogus_cmd | redir END')
screen:expect([[
~ |
clipboard: No provider. Try ":CheckHealth" or ":h clipboard". |
clipboard: No provider. Try ":checkhealth" or ":h clipboard". |
E492: Not an editor command: bogus_cmd | redir END |
Press ENTER or type command to continue^ |
]], nil, {{bold = true, foreground = Screen.colors.Blue}})
@ -132,7 +132,7 @@ describe('clipboard', function()
^ |
~ |
~ |
clipboard: No provider. Try ":CheckHealth" or ":h clipboard". |
clipboard: No provider. Try ":checkhealth" or ":h clipboard". |
]], nil, {{bold = true, foreground = Screen.colors.Blue}})
end)

View File

@ -2,7 +2,29 @@ local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local plugin_helpers = require('test.functional.plugin.helpers')
local clear = helpers.clear
local curbuf_contents = helpers.curbuf_contents
local command = helpers.command
local eq = helpers.eq
describe(':checkhealth', function()
it("detects invalid $VIMRUNTIME", function()
clear({
env={ VIMRUNTIME='bogus', },
})
local status, err = pcall(command, 'checkhealth')
eq(false, status)
eq('Invalid $VIMRUNTIME: bogus', string.match(err, 'Invalid.*'))
end)
it("detects invalid $VIM", function()
clear()
-- Do this after startup, otherwise it just breaks $VIMRUNTIME.
command("let $VIM='zub'")
command("checkhealth nvim")
eq("ERROR: $VIM is invalid: zub",
string.match(curbuf_contents(), "ERROR: $VIM .* zub"))
end)
end)
describe('health.vim', function()
before_each(function()
@ -14,7 +36,7 @@ describe('health.vim', function()
command("set runtimepath+=test/functional/fixtures")
end)
it("reports", function()
it("health#report_*()", function()
helpers.source([[
let g:health_report = execute([
\ "call health#report_start('Check Bar')",
@ -44,9 +66,9 @@ describe('health.vim', function()
end)
describe(":CheckHealth", function()
describe(":checkhealth", function()
it("concatenates multiple reports", function()
command("CheckHealth success1 success2")
command("checkhealth success1 success2")
helpers.expect([[
health#success1#check
@ -65,7 +87,7 @@ describe('health.vim', function()
end)
it("gracefully handles broken healthcheck", function()
command("CheckHealth broken")
command("checkhealth broken")
helpers.expect([[
health#broken#check
@ -89,7 +111,7 @@ describe('health.vim', function()
Bar = { foreground=Screen.colors.Purple },
Bullet = { bold=true, foreground=Screen.colors.Brown },
})
command("CheckHealth foo success1")
command("checkhealth foo success1")
command("1tabclose")
command("set laststatus=0")
screen:expect([[
@ -107,7 +129,7 @@ describe('health.vim', function()
end)
it("gracefully handles invalid healthcheck", function()
command("CheckHealth non_existent_healthcheck")
command("checkhealth non_existent_healthcheck")
helpers.expect([[
health#non_existent_healthcheck#check

View File

@ -16,7 +16,7 @@ do
clear()
if missing_provider('ruby') then
pending(
"Cannot find the neovim RubyGem. Try :CheckHealth",
"Cannot find the neovim RubyGem. Try :checkhealth",
function() end)
return
end