CheckHealth: Accept [plugin1 [, plugin2 [, ...]]] args.

To healthcheck the "foo" plugin:
    :CheckHealth foo
To healthcheck the "foo" and "bar" plugins:
    :CheckHealth foo bar
To run all auto-discovered healthchecks:
    :CheckHealth
This commit is contained in:
Justin M. Keyes 2016-08-20 19:37:18 -04:00
parent 545e7a4163
commit ed49d9d866
7 changed files with 136 additions and 84 deletions

View File

@ -20,46 +20,49 @@ function! s:enhance_syntax() abort
highlight link healthSuggestion String highlight link healthSuggestion String
endfunction endfunction
" Runs the health checkers. Manages the output and buffer-local settings. " Runs the specified healthchecks.
function! health#check(bang) abort " Runs all discovered healthchecks if a:plugin_names is empty.
let l:report = '' function! health#check(plugin_names) abort
let report = ''
if empty(g:health_checkers) let healthchecks = empty(a:plugin_names)
call health#add_checker(s:_default_checkers()) \ ? s:discover_health_checks()
endif \ : s:to_fn_names(a:plugin_names)
for l:checker in items(g:health_checkers) if empty(healthchecks)
" Disabled checkers will not run their registered check functions let report = "ERROR: No healthchecks found."
if l:checker[1]
let s:current_checker = l:checker[0]
let l:report .= printf("\n%s\n================================================================================",
\ s:current_checker)
let l:report .= execute('call ' . l:checker[0] . '()')
endif
endfor
if a:bang
new
setlocal bufhidden=wipe
set filetype=markdown
call s:enhance_syntax()
call setline(1, split(report, "\n"))
setlocal nomodified
else else
echo report for c in healthchecks
echo "\nTip: Use " let report .= printf("\n%s\n%s", c, repeat('=',80))
echohl Identifier try
echon ':CheckHealth!' let report .= execute('call '.c.'()')
echohl None catch /^Vim\%((\a\+)\)\=:E117/
echon ' to open this in a new buffer.' let report .= execute(
\ 'call health#report_error(''No healthcheck found for "'
\ .s:to_plugin_name(c)
\ .'" plugin.'')')
catch
let report .= execute(
\ 'call health#report_error(''Failed to run healthcheck for "'
\ .s:to_plugin_name(c)
\ .'" plugin. Exception:''."\n".v:exception)')
endtry
let report .= "\n"
endfor
endif endif
new
setlocal bufhidden=wipe
set filetype=markdown
call s:enhance_syntax()
call setline(1, split(report, "\n"))
setlocal nomodified
endfunction endfunction
" Starts a new report. " Starts a new report.
function! health#report_start(name) abort " {{{ function! health#report_start(name) abort
echo "\n## " . a:name echo "\n## " . a:name
endfunction " }}} endfunction
" Indents lines *except* line 1 of a string if it contains newlines. " Indents lines *except* line 1 of a string if it contains newlines.
function! s:indent_after_line1(s, columns) abort function! s:indent_after_line1(s, columns) abort
@ -102,12 +105,12 @@ function! health#report_info(msg) abort " {{{
echo s:format_report_message('INFO', a:msg) echo s:format_report_message('INFO', a:msg)
endfunction " }}} endfunction " }}}
" Use {msg} to represent the check that has passed " Reports a successful healthcheck.
function! health#report_ok(msg) abort " {{{ function! health#report_ok(msg) abort " {{{
echo s:format_report_message('SUCCESS', a:msg) echo s:format_report_message('SUCCESS', a:msg)
endfunction " }}} endfunction " }}}
" Use {msg} to represent a failed health check and optionally a list of suggestions on how to fix it. " Reports a health warning.
function! health#report_warn(msg, ...) abort " {{{ function! health#report_warn(msg, ...) abort " {{{
if a:0 > 0 if a:0 > 0
echo s:format_report_message('WARNING', a:msg, a:1) echo s:format_report_message('WARNING', a:msg, a:1)
@ -116,7 +119,7 @@ function! health#report_warn(msg, ...) abort " {{{
endif endif
endfunction " }}} endfunction " }}}
" Use {msg} to represent a critically failed health check and optionally a list of suggestions on how to fix it. " Reports a failed healthcheck.
function! health#report_error(msg, ...) abort " {{{ function! health#report_error(msg, ...) abort " {{{
if a:0 > 0 if a:0 > 0
echo s:format_report_message('ERROR', a:msg, a:1) echo s:format_report_message('ERROR', a:msg, a:1)
@ -181,19 +184,28 @@ function! health#disable_checker(checker_name) abort " {{{
endif endif
endfunction " }}} endfunction " }}}
function! s:change_file_name_to_health_checker(name) abort " {{{ function! s:filepath_to_function(name) abort
return substitute(substitute(substitute(a:name, ".*autoload/", "", ""), "\\.vim", "#check", ""), "/", "#", "g") return substitute(substitute(substitute(a:name, ".*autoload/", "", ""),
endfunction " }}} \ "\\.vim", "#check", ""), "/", "#", "g")
endfunction
function! s:_default_checkers() abort " {{{ function! s:discover_health_checks() abort
" Get all of the files that are in autoload/health/ folders with a vim let healthchecks = globpath(&runtimepath, 'autoload/health/*.vim', 1, 1)
" suffix let healthchecks = map(healthchecks, '<SID>filepath_to_function(v:val)')
let checker_files = globpath(&runtimepath, 'autoload/health/*.vim', 1, 1) return healthchecks
let temp = checker_files[0] endfunction
let checkers_to_source = [] " Translates a list of plugin names to healthcheck function names.
for file_name in checker_files function! s:to_fn_names(plugin_names) abort
call add(checkers_to_source, s:change_file_name_to_health_checker(file_name)) let healthchecks = []
for p in a:plugin_names
call add(healthchecks, 'health#'.p.'#check')
endfor endfor
return checkers_to_source return healthchecks
endfunction " }}} 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

View File

@ -107,6 +107,7 @@ Events:
|TabClosed| |TabClosed|
|TermOpen| |TermOpen|
|TermClose| |TermClose|
|TextYankPost|
Highlight groups: Highlight groups:
|hl-EndOfBuffer| |hl-EndOfBuffer|

View File

@ -1 +1 @@
command! -bang CheckHealth call health#check(<bang>0) command! -nargs=* CheckHealth call health#check([<f-args>])

View File

@ -0,0 +1,3 @@
function! health#broken#check()
throw 'caused an error'
endfunction

View File

@ -0,0 +1,6 @@
function! health#success1#check()
call health#report_start("report 1")
call health#report_ok("everything is fine")
call health#report_start("report 2")
call health#report_ok("nothing to see here")
endfunction

View File

@ -0,0 +1,4 @@
function! health#success2#check()
call health#report_start("another 1")
call health#report_ok("ok")
endfunction

View File

@ -4,52 +4,78 @@ local plugin_helpers = require('test.functional.plugin.helpers')
describe('health.vim', function() describe('health.vim', function()
before_each(function() before_each(function()
plugin_helpers.reset() plugin_helpers.reset()
-- Provides functions:
-- health#broken#check()
-- health#success1#check()
-- health#success2#check()
helpers.execute("set runtimepath+=test/functional/fixtures")
end) end)
it('reports results', function() it("reports", function()
helpers.execute("call health#report_start('Foo')") helpers.source([[
local report = helpers.redir_exec([[call health#report_start('Check Bar')]]) let g:health_report = execute([
.. helpers.redir_exec([[call health#report_ok('Bar status')]]) \ "call health#report_start('Check Bar')",
.. helpers.redir_exec([[call health#report_ok('Other Bar status')]]) \ "call health#report_ok('Bar status')",
.. helpers.redir_exec([[call health#report_warn('Zub')]]) \ "call health#report_ok('Other Bar status')",
.. helpers.redir_exec([[call health#report_start('Baz')]]) \ "call health#report_warn('Zub')",
.. helpers.redir_exec([[call health#report_warn('Zim', ['suggestion 1', 'suggestion 2'])]]) \ "call health#report_start('Baz')",
\ "call health#report_warn('Zim', ['suggestion 1', 'suggestion 2'])"
\ ])
]])
local result = helpers.eval("g:health_report")
local expected_contents = { helpers.eq(helpers.dedent([[
'Checking: Check Bar',
'SUCCESS: Bar status',
'WARNING: Zub',
'SUGGESTIONS:',
'- suggestion 1',
'- suggestion 2'
}
for _, content in ipairs(expected_contents) do
assert(string.find(report, content)) ## Check Bar
end - SUCCESS: Bar status
- SUCCESS: Other Bar status
- WARNING: Zub
## Baz
- WARNING: Zim
- SUGGESTIONS:
- suggestion 1
- suggestion 2]]),
result)
end) end)
describe(':CheckHealth', function() describe(":CheckHealth", function()
-- Run it here because it may be slow, depending on the system. it("concatenates multiple reports", function()
helpers.execute([[CheckHealth!]]) helpers.execute("CheckHealth success1 success2")
local report = helpers.curbuf_contents() helpers.expect([[
local health_checkers = helpers.redir_exec("echo g:health_checkers") health#success1#check
================================================================================
it('finds the default checker', function() ## report 1
assert(string.find(health_checkers, "'health#nvim#check': v:true")) - SUCCESS: everything is fine
## report 2
- SUCCESS: nothing to see here
health#success2#check
================================================================================
## another 1
- SUCCESS: ok]])
end) end)
it('prints a header with the name of the checker', function() it("gracefully handles broken healthcheck", function()
assert(string.find(report, 'health#nvim#check')) helpers.execute("CheckHealth broken")
helpers.expect([[
health#broken#check
================================================================================
- ERROR: Failed to run healthcheck for "broken" plugin. Exception:
caused an error]])
end) end)
end)
it('allows users to disable checkers', function() it("gracefully handles invalid healthcheck", function()
helpers.execute("call health#disable_checker('health#nvim#check')") helpers.execute("CheckHealth non_existent_healthcheck")
helpers.execute("CheckHealth!") helpers.expect([[
local health_checkers = helpers.redir_exec("echo g:health_checkers") health#non_existent_healthcheck#check
================================================================================
assert(string.find(health_checkers, "'health#nvim#check': v:false")) - ERROR: No healthcheck found for "non_existent_healthcheck" plugin.]])
end)
end) end)
end) end)