├── plugin └── health.vim ├── ftplugin └── checkhealth.vim ├── syntax └── checkhealth.vim ├── README.md ├── autoload ├── health │ └── vim.vim └── health.vim ├── doc └── pi_health.txt └── LICENSE /plugin/health.vim: -------------------------------------------------------------------------------- 1 | if exists('g:loaded_healthcheck') || has('nvim') 2 | finish 3 | endif 4 | let g:loaded_healthcheck = 1 5 | 6 | command -nargs=* -bar CheckHealth call health#check([]) 7 | -------------------------------------------------------------------------------- /ftplugin/checkhealth.vim: -------------------------------------------------------------------------------- 1 | " Vim filetype plugin 2 | " Language: Neovim checkhealth buffer 3 | " Last Change: 2021 Dec 15 4 | 5 | if has('nvim') || exists("b:did_ftplugin") 6 | finish 7 | endif 8 | 9 | runtime! ftplugin/markdown.vim ftplugin/markdown_*.vim ftplugin/markdown/*.vim 10 | 11 | setlocal wrap breakindent linebreak 12 | setlocal conceallevel=2 concealcursor=nc 13 | setlocal keywordprg=:help 14 | let &l:iskeyword='!-~,^*,^|,^",192-255' 15 | 16 | if exists("b:undo_ftplugin") 17 | let b:undo_ftplugin .= "|setl wrap< bri< lbr< cole< cocu< kp< isk<" 18 | else 19 | let b:undo_ftplugin = "setl wrap< bri< lbr< cole< cocu< kp< isk<" 20 | endif 21 | -------------------------------------------------------------------------------- /syntax/checkhealth.vim: -------------------------------------------------------------------------------- 1 | " Vim syntax file 2 | " Language: Neovim checkhealth buffer 3 | " Last Change: 2021 Dec 15 4 | 5 | if has('nvim') || exists("b:current_syntax") 6 | finish 7 | endif 8 | 9 | runtime! syntax/markdown.vim 10 | unlet! b:current_syntax 11 | 12 | syn case match 13 | 14 | " We do not care about markdown syntax errors 15 | if hlexists('markdownError') 16 | syn clear markdownError 17 | endif 18 | 19 | syn keyword healthError ERROR[:] containedin=markdownCodeBlock,mkdListItemLine 20 | syn keyword healthWarning WARNING[:] containedin=markdownCodeBlock,mkdListItemLine 21 | syn keyword healthSuccess OK[:] containedin=markdownCodeBlock,mkdListItemLine 22 | syn match healthHelp "|.\{-}|" containedin=markdownCodeBlock,mkdListItemLine contains=healthBar 23 | syn match healthBar "|" contained conceal 24 | 25 | hi def link healthError Error 26 | hi def link healthWarning WarningMsg 27 | hi def healthSuccess guibg=#5fff00 guifg=#080808 ctermbg=82 ctermfg=232 28 | hi def link healthHelp Identifier 29 | 30 | let b:current_syntax = "checkhealth" 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Polyfill for `:checkhealth` in Vim 2 | ================================== 3 | 4 | [vim-healthcheck][] is a polyfill plugin for Vim to use a health-check feature in [Neovim][]. Neovim's 5 | health-check feature is a minimal framework to help with troubleshooting user configuration. 6 | [vim-healthcheck][] provides the same feature for Vim. 7 | 8 | Plugin authors can write health-checks for their plugins using the APIs. And plugin users can check 9 | if the installation is healthy. By this polyfill, plugin authors can write common health-checks for 10 | both Neovim and Vim. And plugin users can check their configuration using the health-checks which 11 | was written for Neovim. It would be useful for troubleshooting or triaging issues. 12 | 13 | This plugin is just a port of Neovim's health-check implementation. 14 | 15 | ## Usage 16 | 17 | Instead of Neovim's standard `:checkhealth` command, it provides `:CheckHealth` command on Vim. 18 | If no argument is given, it runs all health-checks and show the results. 19 | 20 | ``` 21 | :CheckHealth 22 | ``` 23 | 24 | If some plugin names are specified as arguments, it runs health-checks for them. 25 | 26 | ``` 27 | :CheckHealth {plugin1} {plugin2} ... 28 | ``` 29 | 30 | For example, `:CheckHealth vim` runs health-checks for Vim itself. 31 | 32 | To know the detail of the command behavior or to know how to implement health-checks for your plugins, 33 | please read a help document. 34 | 35 | ``` 36 | :help health 37 | ``` 38 | 39 | ## Installation 40 | 41 | If you use a plugin manager, please follow the instruction. Please note that this plugin is needed 42 | only on Vim because Neovim supports health-check feature by default. 43 | 44 | ### vim-plug 45 | 46 | ```vim 47 | if !has('nvim') 48 | Plug 'rhysd/vim-healthcheck' 49 | endif 50 | ``` 51 | 52 | ### dein.vim 53 | 54 | ```vim 55 | if !has('nvim') 56 | call dein#add('rhysd/vim-healthcheck') 57 | endif 58 | ``` 59 | 60 | ### minpac 61 | 62 | ```vim 63 | if !has('nvim') 64 | call minpac#add('rhysd/vim-healthcheck') 65 | endif 66 | ``` 67 | 68 | ## License 69 | 70 | This plugin was created by porting the implementation of health-check feature for Neovim. So this 71 | plugin is distributed under the same license as Neovim. Please read [LICENSE](LICENSE) for the 72 | details. 73 | 74 | [vim-healthcheck]: https://github.com/rhysd/vim-healthcheck 75 | [Neovim]: https://github.com/neovim/neovim 76 | -------------------------------------------------------------------------------- /autoload/health/vim.vim: -------------------------------------------------------------------------------- 1 | if has('nvim') 2 | finish 3 | endif 4 | 5 | let s:path_sep = has('win32') || has('win64') ? '\' : '/' 6 | 7 | function! s:VIM_is_correct() abort 8 | " 800 -> 80, 801 -> 81, 1201 -> 121 9 | let v = v:version[:-3] . v:version[-1:] 10 | let candidates = [ 11 | \ [$VIM, 'runtime', 'doc', 'usr_01.txt'], 12 | \ [$VIM, 'vim' . v, 'doc', 'usr_01.txt'], 13 | \ ] 14 | for entries in candidates 15 | if filereadable(join(entries, s:path_sep)) 16 | return v:true 17 | endif 18 | endfor 19 | return v:false 20 | endfunction 21 | 22 | function! s:check_config() abort 23 | let ok = v:true 24 | call health#report_start('Configuration') 25 | 26 | if !s:VIM_is_correct() 27 | let ok = v:false 28 | call health#report_error('$VIM is invalid: ' . $VIM, [ 29 | \ 'Read `:help $VIM` and set $VIM properly.', 30 | \ 'Remove config to set $VIM manually.', 31 | \]) 32 | endif 33 | 34 | if &paste 35 | let ok = v:false 36 | call health#report_error("'paste' is enabled. This option is only for pasting text.\nIt should not be set in your config.", [ 37 | \ 'Remove `set paste` from your vimrc, if applicable.', 38 | \ 'Check `:verbose set paste?` to see if a plugin or script set the option.', 39 | \]) 40 | endif 41 | 42 | if ok 43 | call health#report_ok('no issues found') 44 | endif 45 | endfunction 46 | 47 | " Port of s:check_tmux() in health/nvim.vim 48 | let s:suggest_faq = 'https://github.com/neovim/neovim/wiki/FAQ' 49 | function! s:get_tmux_option(option) abort 50 | let cmd = 'tmux show-option -qvg '.a:option " try global scope 51 | let out = system(cmd) 52 | let val = substitute(out, '\v(\s|\r|\n)', '', 'g') 53 | if v:shell_error 54 | call health#report_error('command failed: '.cmd."\n".out) 55 | return 'error' 56 | elseif empty(val) 57 | let cmd = 'tmux show-option -qvgs '.a:option " try session scope 58 | let out = system(cmd) 59 | let val = substitute(out, '\v(\s|\r|\n)', '', 'g') 60 | if v:shell_error 61 | call health#report_error('command failed: '.cmd."\n".out) 62 | return 'error' 63 | endif 64 | endif 65 | return val 66 | endfunction 67 | function! s:check_tmux() abort 68 | if empty($TMUX) || !executable('tmux') 69 | return 70 | endif 71 | call health#report_start('tmux') 72 | 73 | " check escape-time 74 | let suggestions = ["set escape-time in ~/.tmux.conf:\nset-option -sg escape-time 10", 75 | \ s:suggest_faq] 76 | let tmux_esc_time = s:get_tmux_option('escape-time') 77 | if tmux_esc_time !=# 'error' 78 | if empty(tmux_esc_time) 79 | call health#report_error('`escape-time` is not set', suggestions) 80 | elseif tmux_esc_time > 300 81 | call health#report_error( 82 | \ '`escape-time` ('.tmux_esc_time.') is higher than 300ms', suggestions) 83 | else 84 | call health#report_ok('escape-time: '.tmux_esc_time) 85 | endif 86 | endif 87 | 88 | " check focus-events 89 | let suggestions = ["(tmux 1.9+ only) Set `focus-events` in ~/.tmux.conf:\nset-option -g focus-events on"] 90 | let tmux_focus_events = s:get_tmux_option('focus-events') 91 | call health#report_info('Checking stuff') 92 | if tmux_focus_events !=# 'error' 93 | if empty(tmux_focus_events) || tmux_focus_events !=# 'on' 94 | call health#report_warn( 95 | \ "`focus-events` is not enabled. |'autoread'| may not work.", suggestions) 96 | else 97 | call health#report_ok('focus-events: '.tmux_focus_events) 98 | endif 99 | endif 100 | 101 | " check default-terminal and $TERM 102 | call health#report_info('$TERM: '.$TERM) 103 | let cmd = 'tmux show-option -qvg default-terminal' 104 | let out = system(cmd) 105 | let tmux_default_term = substitute(out, '\v(\s|\r|\n)', '', 'g') 106 | if empty(tmux_default_term) 107 | let cmd = 'tmux show-option -qvgs default-terminal' 108 | let out = system(cmd) 109 | let tmux_default_term = substitute(out, '\v(\s|\r|\n)', '', 'g') 110 | endif 111 | 112 | if v:shell_error 113 | call health#report_error('command failed: '.cmd."\n".out) 114 | elseif tmux_default_term !=# $TERM 115 | call health#report_info('default-terminal: '.tmux_default_term) 116 | call health#report_error( 117 | \ '$TERM differs from the tmux `default-terminal` setting. Colors might look wrong.', 118 | \ ['$TERM may have been set by some rc (.bashrc, .zshrc, ...).']) 119 | elseif $TERM !~# '\v(tmux-256color|screen-256color)' 120 | call health#report_error( 121 | \ '$TERM should be "screen-256color" or "tmux-256color" in tmux. Colors might look wrong.', 122 | \ ["Set default-terminal in ~/.tmux.conf:\nset-option -g default-terminal \"screen-256color\"", 123 | \ s:suggest_faq]) 124 | endif 125 | 126 | " check for RGB capabilities 127 | let info = system('tmux server-info') 128 | let has_tc = stridx(info, " Tc: (flag) true") != -1 129 | let has_rgb = stridx(info, " RGB: (flag) true") != -1 130 | if !has_tc && !has_rgb 131 | call health#report_warn( 132 | \ "Neither Tc nor RGB capability set. True colors are disabled. |'termguicolors'| won't work properly.", 133 | \ ["Put this in your ~/.tmux.conf and replace XXX by your $TERM outside of tmux:\nset-option -sa terminal-overrides ',XXX:RGB'", 134 | \ "For older tmux versions use this instead:\nset-option -ga terminal-overrides ',XXX:Tc'"]) 135 | endif 136 | endfunction 137 | 138 | " Port of s:check_peformance() in health/nvim.vim 139 | function! s:check_performance() abort 140 | call health#report_start('Performance') 141 | 142 | " check for slow shell invocation 143 | let slow_cmd_time = 1.5 144 | let start_time = reltime() 145 | call system('echo') 146 | let elapsed_time = reltimefloat(reltime(start_time)) 147 | if elapsed_time > slow_cmd_time 148 | call health#report_warn( 149 | \ 'Slow shell invocation (took '.printf('%.2f', elapsed_time).' seconds).') 150 | else 151 | call health#report_ok('`echo` command took '.printf('%.2f', elapsed_time).' seconds.') 152 | endif 153 | endfunction 154 | 155 | function! health#vim#check() abort 156 | call s:check_config() 157 | call s:check_tmux() 158 | call s:check_performance() 159 | endfunction 160 | -------------------------------------------------------------------------------- /autoload/health.vim: -------------------------------------------------------------------------------- 1 | " Same as `execute 'tab sbuffer' health#polyfill#nvim_create_buff(v:true, v:true)` 2 | function! s:create_scratch_buf() abort 3 | tabnew 4 | set buflisted nomodified nomodeline buftype=nofile bufhidden=hide noswapfile 5 | endfunction 6 | 7 | function! s:nvim_get_runtime_file(pat) abort 8 | return globpath(&rtp, a:pat, v:true, v:true) 9 | endfunction 10 | 11 | " Runs the specified healthchecks. 12 | " Runs all discovered healthchecks if a:plugin_names is empty. 13 | function! health#check(plugin_names) abort 14 | let healthchecks = empty(a:plugin_names) 15 | \ ? s:discover_healthchecks() 16 | \ : s:get_healthcheck(a:plugin_names) 17 | 18 | " create scratch-buffer 19 | call s:create_scratch_buf() 20 | setfiletype checkhealth 21 | 22 | if empty(healthchecks) 23 | call setline(1, 'ERROR: No healthchecks found.') 24 | else 25 | redraw|echo 'Running healthchecks...' 26 | for name in sort(keys(healthchecks)) 27 | let [func, type] = healthchecks[name] 28 | let s:output = [] 29 | try 30 | if func == '' 31 | throw 'healthcheck_not_found' 32 | endif 33 | eval type == 'v' ? call(func, []) : luaeval(func) 34 | " in the event the healthcheck doesn't return anything 35 | " (the plugin author should avoid this possibility) 36 | if len(s:output) == 0 37 | throw 'healthcheck_no_return_value' 38 | endif 39 | catch 40 | let s:output = [] " Clear the output 41 | if v:exception =~# 'healthcheck_not_found' 42 | call health#report_error('No healthcheck found for "'.name.'" plugin.') 43 | elseif v:exception =~# 'healthcheck_no_return_value' 44 | call health#report_error('The healthcheck report for "'.name.'" plugin is empty.') 45 | else 46 | call health#report_error(printf( 47 | \ "Failed to run healthcheck for \"%s\" plugin. Exception:\n%s\n%s", 48 | \ name, v:throwpoint, v:exception)) 49 | endif 50 | endtry 51 | let header = [name. ': ' . func, repeat('=', 72)] 52 | " remove empty line after header from report_start 53 | let s:output = s:output[0] == '' ? s:output[1:] : s:output 54 | let s:output = header + s:output + [''] 55 | call append('$', s:output) 56 | redraw 57 | endfor 58 | endif 59 | 60 | " needed for plasticboy/vim-markdown, because it uses fdm=expr 61 | normal! zR 62 | redraw|echo '' 63 | endfunction 64 | 65 | function! s:collect_output(output) 66 | let s:output += split(a:output, "\n", 1) 67 | endfunction 68 | 69 | " Starts a new report. 70 | function! health#report_start(name) abort 71 | call s:collect_output("\n## " . a:name) 72 | endfunction 73 | 74 | " Indents lines *except* line 1 of a string if it contains newlines. 75 | function! s:indent_after_line1(s, columns) abort 76 | let lines = split(a:s, "\n", 0) 77 | if len(lines) < 2 " We do not indent line 1, so nothing to do. 78 | return a:s 79 | endif 80 | for i in range(1, len(lines)-1) " Indent lines after the first. 81 | let lines[i] = substitute(lines[i], '^\s*', repeat(' ', a:columns), 'g') 82 | endfor 83 | return join(lines, "\n") 84 | endfunction 85 | 86 | " Changes ':h clipboard' to ':help |clipboard|'. 87 | function! s:help_to_link(s) abort 88 | return substitute(a:s, '\v:h%[elp] ([^|][^"\r\n ]+)', ':help |\1|', 'g') 89 | endfunction 90 | 91 | " Format a message for a specific report item. 92 | " a:1: Optional advice (string or list) 93 | function! s:format_report_message(status, msg, ...) abort " {{{ 94 | let output = ' - ' . a:status . ': ' . s:indent_after_line1(a:msg, 4) 95 | 96 | " Optional parameters 97 | if a:0 > 0 98 | let advice = type(a:1) == type('') ? [a:1] : a:1 99 | if type(advice) != type([]) 100 | throw 'a:1: expected String or List' 101 | endif 102 | 103 | " Report each suggestion 104 | if !empty(advice) 105 | let output .= "\n - ADVICE:" 106 | for suggestion in advice 107 | let output .= "\n - " . s:indent_after_line1(suggestion, 10) 108 | endfor 109 | endif 110 | endif 111 | 112 | return s:help_to_link(output) 113 | endfunction " }}} 114 | 115 | " Use {msg} to report information in the current section 116 | function! health#report_info(msg) abort " {{{ 117 | call s:collect_output(s:format_report_message('INFO', a:msg)) 118 | endfunction " }}} 119 | 120 | " Reports a successful healthcheck. 121 | function! health#report_ok(msg) abort " {{{ 122 | call s:collect_output(s:format_report_message('OK', a:msg)) 123 | endfunction " }}} 124 | 125 | " Reports a health warning. 126 | " a:1: Optional advice (string or list) 127 | function! health#report_warn(msg, ...) abort " {{{ 128 | if a:0 > 0 129 | call s:collect_output(s:format_report_message('WARNING', a:msg, a:1)) 130 | else 131 | call s:collect_output(s:format_report_message('WARNING', a:msg)) 132 | endif 133 | endfunction " }}} 134 | 135 | " Reports a failed healthcheck. 136 | " a:1: Optional advice (string or list) 137 | function! health#report_error(msg, ...) abort " {{{ 138 | if a:0 > 0 139 | call s:collect_output(s:format_report_message('ERROR', a:msg, a:1)) 140 | else 141 | call s:collect_output(s:format_report_message('ERROR', a:msg)) 142 | endif 143 | endfunction " }}} 144 | 145 | " From a path return a list [{name}, {func}, {type}] representing a healthcheck 146 | function! s:filepath_to_healthcheck(path) abort 147 | if a:path =~# 'vim$' 148 | let name = matchstr(a:path, '\zs[^\/]*\ze\.vim$') 149 | let func = 'health#'.name.'#check' 150 | let type = 'v' 151 | else 152 | let base_path = substitute(a:path, 153 | \ '.*lua[\/]\(.\{-}\)[\/]health\([\/]init\)\?\.lua$', 154 | \ '\1', '') 155 | let name = substitute(base_path, '[\/]', '.', 'g') 156 | let func = 'require("'.name.'.health").check()' 157 | let type = 'l' 158 | endif 159 | return [name, func, type] 160 | endfunction 161 | 162 | function! s:discover_healthchecks() abort 163 | return s:get_healthcheck('*') 164 | endfunction 165 | 166 | " Returns Dictionary {name: [func, type], ..} representing healthchecks 167 | function! s:get_healthcheck(plugin_names) abort 168 | let health_list = s:get_healthcheck_list(a:plugin_names) 169 | let healthchecks = {} 170 | for c in health_list 171 | let normalized_name = substitute(c[0], '-', '_', 'g') 172 | let existent = get(healthchecks, normalized_name, []) 173 | " Prefer Lua over vim entries 174 | if existent != [] && existent[2] == 'l' 175 | continue 176 | else 177 | let healthchecks[normalized_name] = c 178 | endif 179 | endfor 180 | let output = {} 181 | for v in values(healthchecks) 182 | let output[v[0]] = v[1:] 183 | endfor 184 | return output 185 | endfunction 186 | 187 | " Returns list of lists [ [{name}, {func}, {type}] ] representing healthchecks 188 | function! s:get_healthcheck_list(plugin_names) abort 189 | let healthchecks = [] 190 | let plugin_names = type('') == type(a:plugin_names) 191 | \ ? split(a:plugin_names, ' ', v:false) 192 | \ : a:plugin_names 193 | for p in plugin_names 194 | " support vim/lsp/health{/init/}.lua as :checkhealth vim.lsp 195 | let p = substitute(p, '\.', '/', 'g') 196 | let p = substitute(p, '*$', '**', 'g') " find all submodule e.g vim* 197 | let paths = s:nvim_get_runtime_file('autoload/health/'.p.'.vim') 198 | \ + s:nvim_get_runtime_file('lua/**/'.p.'/health/init.lua') 199 | \ + s:nvim_get_runtime_file('lua/**/'.p.'/health.lua') 200 | if len(paths) == 0 201 | let healthchecks += [[p, '', '']] " healthcheck not found 202 | else 203 | let healthchecks += map(uniq(sort(paths)), 204 | \'filepath_to_healthcheck(v:val)') 205 | end 206 | endfor 207 | return healthchecks 208 | endfunction 209 | -------------------------------------------------------------------------------- /doc/pi_health.txt: -------------------------------------------------------------------------------- 1 | *pi_health.txt* Healthcheck framework 2 | 3 | Author: TJ DeVries 4 | 5 | Type |gO| to see the table of contents. 6 | 7 | ============================================================================== 8 | Introduction *health* 9 | 10 | health.vim is a minimal framework to help with troubleshooting user 11 | configuration. Nvim ships with healthchecks for configuration, performance, 12 | python support, ruby support, clipboard support, and more. 13 | 14 | To run the healthchecks, use this command: > 15 | 16 | :checkhealth 17 | < 18 | Plugin authors are encouraged to write new healthchecks. |health-dev| 19 | 20 | ============================================================================== 21 | Commands *health-commands* 22 | 23 | *:checkhealth* *:CheckHealth* 24 | :checkhealth Run all healthchecks. 25 | *E5009* 26 | Nvim depends on |$VIMRUNTIME|, 'runtimepath' and 'packpath' to 27 | find the standard "runtime files" for syntax highlighting, 28 | filetype-specific behavior, and standard plugins (including 29 | :checkhealth). If the runtime files cannot be found then 30 | those features will not work. 31 | 32 | :checkhealth {plugins} 33 | Run healthcheck(s) for one or more plugins. E.g. to run only 34 | the standard Nvim healthcheck: > 35 | :checkhealth nvim 36 | < 37 | To run the healthchecks for the "foo" and "bar" plugins 38 | (assuming these plugins are on 'runtimepath' or 'packpath' and 39 | they have implemented the Lua or Vimscript interface 40 | require("foo.health").check() and health#bar#check(), 41 | respectively): > 42 | :checkhealth foo bar 43 | < 44 | To run healthchecks for lua submodules, use dot notation or 45 | "*" to refer to all submodules. For example nvim provides 46 | `vim.lsp` and `vim.treesitter` > 47 | :checkhealth vim.lsp vim.treesitter 48 | :checkhealth vim* 49 | < 50 | ============================================================================== 51 | Lua Functions *health-functions-lua* *health-lua* *vim.health* 52 | 53 | The Lua "health" module can be used to create new healthchecks (see also 54 | |health-functions-vim|). To get started, simply use: 55 | 56 | vim.health.report_start({name}) *vim.health.report_start()* 57 | Starts a new report. Most plugins should call this only once, but if 58 | you want different sections to appear in your report, call this once 59 | per section. 60 | 61 | vim.health.report_info({msg}) *vim.health.report_info()* 62 | Reports an informational message. 63 | 64 | vim.health.report_ok({msg}) *vim.health.report_ok()* 65 | Reports a "success" message. 66 | 67 | vim.health.report_warn({msg} [, {advice}]) *vim.health.report_warn()* 68 | Reports a warning. {advice} is an optional List of suggestions. 69 | 70 | vim.health.report_error({msg} [, {advice}]) *vim.health.report_error()* 71 | Reports an error. {advice} is an optional List of suggestions. 72 | 73 | ============================================================================== 74 | Create a Lua healthcheck *health-dev-lua* 75 | 76 | Healthchecks are functions that check the user environment, configuration, 77 | etc. Nvim has built-in healthchecks in $VIMRUNTIME/autoload/health/. 78 | 79 | To add a new healthcheck for your own plugin, simply define a Lua module in 80 | your plugin that returns a table with a "check()" function. |:checkhealth| 81 | will automatically find and invoke this function. 82 | 83 | If your plugin is named "foo", then its healthcheck module should be a file in 84 | one of these locations on 'runtimepath' or 'packpath': 85 | - lua/foo/health/init.lua 86 | - lua/foo/health.lua 87 | 88 | If your plugin provides a submodule named "bar" for which you want a separate 89 | healthcheck, define the healthcheck at one of these locations on 'runtimepath' 90 | or 'packpath': 91 | - lua/foo/bar/health/init.lua 92 | - lua/foo/bar/health.lua 93 | 94 | All submodules should return a Lua table containing the method `check()`. 95 | 96 | Copy this sample code into `lua/foo/health/init.lua` or `lua/foo/health.lua`, 97 | replacing "foo" in the path with your plugin name: > 98 | 99 | local M = {} 100 | 101 | M.check = function() 102 | vim.health.report_start("my_plugin report") 103 | -- make sure setup function parameters are ok 104 | if check_setup() then 105 | vim.health.report_ok("Setup function is correct") 106 | else 107 | vim.health.report_error("Setup function is incorrect") 108 | end 109 | -- do some more checking 110 | -- ... 111 | end 112 | 113 | return M 114 | 115 | ============================================================================== 116 | Vimscript Functions *health-functions-vimscript* *health-vimscript* 117 | 118 | health.vim functions are for creating new healthchecks. (See also 119 | |health-functions-lua|) 120 | 121 | health#report_start({name}) *health#report_start* 122 | Starts a new report. Most plugins should call this only once, but if 123 | you want different sections to appear in your report, call this once 124 | per section. 125 | 126 | health#report_info({msg}) *health#report_info* 127 | Reports an informational message. 128 | 129 | health#report_ok({msg}) *health#report_ok* 130 | Reports a "success" message. 131 | 132 | health#report_warn({msg} [, {advice}]) *health#report_warn* 133 | Reports a warning. {advice} is an optional List of suggestions. 134 | 135 | health#report_error({msg} [, {advice}]) *health#report_error* 136 | Reports an error. {advice} is an optional List of suggestions. 137 | 138 | health#{plugin}#check() *health.user_checker* 139 | Healthcheck function for {plugin}. Called by |:checkhealth| 140 | automatically. Example: > 141 | 142 | function! health#my_plug#check() abort 143 | silent call s:check_environment_vars() 144 | silent call s:check_python_configuration() 145 | endfunction 146 | < 147 | ============================================================================== 148 | Create a healthcheck *health-dev-vim* 149 | 150 | Healthchecks are functions that check the user environment, configuration, 151 | etc. Nvim has built-in healthchecks in $VIMRUNTIME/autoload/health/. 152 | 153 | To add a new healthcheck for your own plugin, simply define a 154 | health#{plugin}#check() function in autoload/health/{plugin}.vim. 155 | |:checkhealth| automatically finds and invokes such functions. 156 | 157 | If your plugin is named "foo", then its healthcheck function must be > 158 | health#foo#check() 159 | 160 | defined in this file on 'runtimepath' or 'packpath': 161 | - autoload/health/foo.vim 162 | 163 | Copy this sample code into autoload/health/foo.vim and replace "foo" with your 164 | plugin name: > 165 | function! health#foo#check() abort 166 | call health#report_start('sanity checks') 167 | " perform arbitrary checks 168 | " ... 169 | 170 | if looks_good 171 | call health#report_ok('found required dependencies') 172 | else 173 | call health#report_error('cannot find foo', 174 | \ ['npm install --save foo']) 175 | endif 176 | endfunction 177 | 178 | vim:et:tw=78:ts=8:ft=help:fdm=marker 179 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright Neovim contributors. All rights reserved. 2 | 3 | Neovim is licensed under the terms of the Apache 2.0 license, except for 4 | parts of Neovim that were contributed under the Vim license (see below). 5 | 6 | Neovim's license follows: 7 | 8 | ==== 9 | Apache License 10 | Version 2.0, January 2004 11 | http://www.apache.org/licenses/ 12 | 13 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 14 | 15 | 1. Definitions. 16 | 17 | "License" shall mean the terms and conditions for use, reproduction, 18 | and distribution as defined by Sections 1 through 9 of this document. 19 | 20 | "Licensor" shall mean the copyright owner or entity authorized by 21 | the copyright owner that is granting the License. 22 | 23 | "Legal Entity" shall mean the union of the acting entity and all 24 | other entities that control, are controlled by, or are under common 25 | control with that entity. For the purposes of this definition, 26 | "control" means (i) the power, direct or indirect, to cause the 27 | direction or management of such entity, whether by contract or 28 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 29 | outstanding shares, or (iii) beneficial ownership of such entity. 30 | 31 | "You" (or "Your") shall mean an individual or Legal Entity 32 | exercising permissions granted by this License. 33 | 34 | "Source" form shall mean the preferred form for making modifications, 35 | including but not limited to software source code, documentation 36 | source, and configuration files. 37 | 38 | "Object" form shall mean any form resulting from mechanical 39 | transformation or translation of a Source form, including but 40 | not limited to compiled object code, generated documentation, 41 | and conversions to other media types. 42 | 43 | "Work" shall mean the work of authorship, whether in Source or 44 | Object form, made available under the License, as indicated by a 45 | copyright notice that is included in or attached to the work 46 | (an example is provided in the Appendix below). 47 | 48 | "Derivative Works" shall mean any work, whether in Source or Object 49 | form, that is based on (or derived from) the Work and for which the 50 | editorial revisions, annotations, elaborations, or other modifications 51 | represent, as a whole, an original work of authorship. For the purposes 52 | of this License, Derivative Works shall not include works that remain 53 | separable from, or merely link (or bind by name) to the interfaces of, 54 | the Work and Derivative Works thereof. 55 | 56 | "Contribution" shall mean any work of authorship, including 57 | the original version of the Work and any modifications or additions 58 | to that Work or Derivative Works thereof, that is intentionally 59 | submitted to Licensor for inclusion in the Work by the copyright owner 60 | or by an individual or Legal Entity authorized to submit on behalf of 61 | the copyright owner. For the purposes of this definition, "submitted" 62 | means any form of electronic, verbal, or written communication sent 63 | to the Licensor or its representatives, including but not limited to 64 | communication on electronic mailing lists, source code control systems, 65 | and issue tracking systems that are managed by, or on behalf of, the 66 | Licensor for the purpose of discussing and improving the Work, but 67 | excluding communication that is conspicuously marked or otherwise 68 | designated in writing by the copyright owner as "Not a Contribution." 69 | 70 | "Contributor" shall mean Licensor and any individual or Legal Entity 71 | on behalf of whom a Contribution has been received by Licensor and 72 | subsequently incorporated within the Work. 73 | 74 | 2. Grant of Copyright License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | copyright license to reproduce, prepare Derivative Works of, 78 | publicly display, publicly perform, sublicense, and distribute the 79 | Work and such Derivative Works in Source or Object form. 80 | 81 | 3. Grant of Patent License. Subject to the terms and conditions of 82 | this License, each Contributor hereby grants to You a perpetual, 83 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 84 | (except as stated in this section) patent license to make, have made, 85 | use, offer to sell, sell, import, and otherwise transfer the Work, 86 | where such license applies only to those patent claims licensable 87 | by such Contributor that are necessarily infringed by their 88 | Contribution(s) alone or by combination of their Contribution(s) 89 | with the Work to which such Contribution(s) was submitted. If You 90 | institute patent litigation against any entity (including a 91 | cross-claim or counterclaim in a lawsuit) alleging that the Work 92 | or a Contribution incorporated within the Work constitutes direct 93 | or contributory patent infringement, then any patent licenses 94 | granted to You under this License for that Work shall terminate 95 | as of the date such litigation is filed. 96 | 97 | 4. Redistribution. You may reproduce and distribute copies of the 98 | Work or Derivative Works thereof in any medium, with or without 99 | modifications, and in Source or Object form, provided that You 100 | meet the following conditions: 101 | 102 | (a) You must give any other recipients of the Work or 103 | Derivative Works a copy of this License; and 104 | 105 | (b) You must cause any modified files to carry prominent notices 106 | stating that You changed the files; and 107 | 108 | (c) You must retain, in the Source form of any Derivative Works 109 | that You distribute, all copyright, patent, trademark, and 110 | attribution notices from the Source form of the Work, 111 | excluding those notices that do not pertain to any part of 112 | the Derivative Works; and 113 | 114 | (d) If the Work includes a "NOTICE" text file as part of its 115 | distribution, then any Derivative Works that You distribute must 116 | include a readable copy of the attribution notices contained 117 | within such NOTICE file, excluding those notices that do not 118 | pertain to any part of the Derivative Works, in at least one 119 | of the following places: within a NOTICE text file distributed 120 | as part of the Derivative Works; within the Source form or 121 | documentation, if provided along with the Derivative Works; or, 122 | within a display generated by the Derivative Works, if and 123 | wherever such third-party notices normally appear. The contents 124 | of the NOTICE file are for informational purposes only and 125 | do not modify the License. You may add Your own attribution 126 | notices within Derivative Works that You distribute, alongside 127 | or as an addendum to the NOTICE text from the Work, provided 128 | that such additional attribution notices cannot be construed 129 | as modifying the License. 130 | 131 | You may add Your own copyright statement to Your modifications and 132 | may provide additional or different license terms and conditions 133 | for use, reproduction, or distribution of Your modifications, or 134 | for any such Derivative Works as a whole, provided Your use, 135 | reproduction, and distribution of the Work otherwise complies with 136 | the conditions stated in this License. 137 | 138 | 5. Submission of Contributions. Unless You explicitly state otherwise, 139 | any Contribution intentionally submitted for inclusion in the Work 140 | by You to the Licensor shall be under the terms and conditions of 141 | this License, without any additional terms or conditions. 142 | Notwithstanding the above, nothing herein shall supersede or modify 143 | the terms of any separate license agreement you may have executed 144 | with Licensor regarding such Contributions. 145 | 146 | 6. Trademarks. This License does not grant permission to use the trade 147 | names, trademarks, service marks, or product names of the Licensor, 148 | except as required for reasonable and customary use in describing the 149 | origin of the Work and reproducing the content of the NOTICE file. 150 | 151 | 7. Disclaimer of Warranty. Unless required by applicable law or 152 | agreed to in writing, Licensor provides the Work (and each 153 | Contributor provides its Contributions) on an "AS IS" BASIS, 154 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 155 | implied, including, without limitation, any warranties or conditions 156 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 157 | PARTICULAR PURPOSE. You are solely responsible for determining the 158 | appropriateness of using or redistributing the Work and assume any 159 | risks associated with Your exercise of permissions under this License. 160 | 161 | 8. Limitation of Liability. In no event and under no legal theory, 162 | whether in tort (including negligence), contract, or otherwise, 163 | unless required by applicable law (such as deliberate and grossly 164 | negligent acts) or agreed to in writing, shall any Contributor be 165 | liable to You for damages, including any direct, indirect, special, 166 | incidental, or consequential damages of any character arising as a 167 | result of this License or out of the use or inability to use the 168 | Work (including but not limited to damages for loss of goodwill, 169 | work stoppage, computer failure or malfunction, or any and all 170 | other commercial damages or losses), even if such Contributor 171 | has been advised of the possibility of such damages. 172 | 173 | 9. Accepting Warranty or Additional Liability. While redistributing 174 | the Work or Derivative Works thereof, You may choose to offer, 175 | and charge a fee for, acceptance of support, warranty, indemnity, 176 | or other liability obligations and/or rights consistent with this 177 | License. However, in accepting such obligations, You may act only 178 | on Your own behalf and on Your sole responsibility, not on behalf 179 | of any other Contributor, and only if You agree to indemnify, 180 | defend, and hold each Contributor harmless for any liability 181 | incurred by, or claims asserted against, such Contributor by reason 182 | of your accepting any such warranty or additional liability. 183 | 184 | ==== 185 | 186 | The above license applies to all parts of Neovim except (1) parts that were 187 | contributed under the Vim license and (2) externally maintained libraries. 188 | 189 | The externally maintained libraries used by Neovim are: 190 | 191 | - Klib: a Generic Library in C. MIT/X11 license. 192 | - libuv. Copyright Joyent, Inc. and other Node contributors. Node.js license. 193 | - LuaJIT: a Just-In-Time Compiler for Lua. Copyright Mike Pall. MIT license. 194 | 195 | ==== 196 | 197 | Any parts of Neovim that were contributed under the Vim license are licensed 198 | under the Vim license unless the copyright holder gave permission to license 199 | those contributions under the Apache 2.0 license. 200 | 201 | The Vim license follows: 202 | 203 | VIM LICENSE 204 | 205 | I) There are no restrictions on distributing unmodified copies of Vim except 206 | that they must include this license text. You can also distribute 207 | unmodified parts of Vim, likewise unrestricted except that they must 208 | include this license text. You are also allowed to include executables 209 | that you made from the unmodified Vim sources, plus your own usage 210 | examples and Vim scripts. 211 | 212 | II) It is allowed to distribute a modified (or extended) version of Vim, 213 | including executables and/or source code, when the following four 214 | conditions are met: 215 | 1) This license text must be included unmodified. 216 | 2) The modified Vim must be distributed in one of the following five ways: 217 | a) If you make changes to Vim yourself, you must clearly describe in 218 | the distribution how to contact you. When the maintainer asks you 219 | (in any way) for a copy of the modified Vim you distributed, you 220 | must make your changes, including source code, available to the 221 | maintainer without fee. The maintainer reserves the right to 222 | include your changes in the official version of Vim. What the 223 | maintainer will do with your changes and under what license they 224 | will be distributed is negotiable. If there has been no negotiation 225 | then this license, or a later version, also applies to your changes. 226 | The current maintainer is Bram Moolenaar . If this 227 | changes it will be announced in appropriate places (most likely 228 | vim.sf.net, www.vim.org and/or comp.editors). When it is completely 229 | impossible to contact the maintainer, the obligation to send him 230 | your changes ceases. Once the maintainer has confirmed that he has 231 | received your changes they will not have to be sent again. 232 | b) If you have received a modified Vim that was distributed as 233 | mentioned under a) you are allowed to further distribute it 234 | unmodified, as mentioned at I). If you make additional changes the 235 | text under a) applies to those changes. 236 | c) Provide all the changes, including source code, with every copy of 237 | the modified Vim you distribute. This may be done in the form of a 238 | context diff. You can choose what license to use for new code you 239 | add. The changes and their license must not restrict others from 240 | making their own changes to the official version of Vim. 241 | d) When you have a modified Vim which includes changes as mentioned 242 | under c), you can distribute it without the source code for the 243 | changes if the following three conditions are met: 244 | - The license that applies to the changes permits you to distribute 245 | the changes to the Vim maintainer without fee or restriction, and 246 | permits the Vim maintainer to include the changes in the official 247 | version of Vim without fee or restriction. 248 | - You keep the changes for at least three years after last 249 | distributing the corresponding modified Vim. When the maintainer 250 | or someone who you distributed the modified Vim to asks you (in 251 | any way) for the changes within this period, you must make them 252 | available to him. 253 | - You clearly describe in the distribution how to contact you. This 254 | contact information must remain valid for at least three years 255 | after last distributing the corresponding modified Vim, or as long 256 | as possible. 257 | e) When the GNU General Public License (GPL) applies to the changes, 258 | you can distribute the modified Vim under the GNU GPL version 2 or 259 | any later version. 260 | 3) A message must be added, at least in the output of the ":version" 261 | command and in the intro screen, such that the user of the modified Vim 262 | is able to see that it was modified. When distributing as mentioned 263 | under 2)e) adding the message is only required for as far as this does 264 | not conflict with the license used for the changes. 265 | 4) The contact information as required under 2)a) and 2)d) must not be 266 | removed or changed, except that the person himself can make 267 | corrections. 268 | 269 | III) If you distribute a modified version of Vim, you are encouraged to use 270 | the Vim license for your changes and make them available to the 271 | maintainer, including the source code. The preferred way to do this is 272 | by e-mail or by uploading the files to a server and e-mailing the URL. 273 | If the number of changes is small (e.g., a modified Makefile) e-mailing a 274 | context diff will do. The e-mail address to be used is 275 | 276 | 277 | IV) It is not allowed to remove this license from the distribution of the Vim 278 | sources, parts of it or from a modified version. You may use this 279 | license for previous Vim releases instead of the license that they came 280 | with, at your option. 281 | --------------------------------------------------------------------------------