diff options
Diffstat (limited to 'runtime/autoload/health.vim')
-rw-r--r-- | runtime/autoload/health.vim | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/runtime/autoload/health.vim b/runtime/autoload/health.vim new file mode 100644 index 0000000000..93ca4dfc54 --- /dev/null +++ b/runtime/autoload/health.vim @@ -0,0 +1,178 @@ +function! s:enhance_syntax() abort + syntax case match + + syntax keyword healthError ERROR + \ containedin=markdownCodeBlock,mkdListItemLine + highlight link healthError Error + + syntax keyword healthWarning WARNING + \ containedin=markdownCodeBlock,mkdListItemLine + highlight link healthWarning WarningMsg + + syntax keyword healthInfo INFO + \ containedin=markdownCodeBlock,mkdListItemLine + highlight link healthInfo ModeMsg + + syntax keyword healthSuccess SUCCESS + \ containedin=markdownCodeBlock,mkdListItemLine + highlight link healthSuccess ModeMsg + + syntax keyword healthSuggestion SUGGESTIONS + \ containedin=markdownCodeBlock,mkdListItemLine + highlight link healthSuggestion String + + syntax match healthHelp "|.\{-}|" contains=healthBar + \ containedin=markdownCodeBlock,mkdListItemLine + syntax match healthBar "|" contained conceal + highlight link healthHelp Identifier + + " We do not care about markdown syntax errors in :CheckHealth output. + highlight! link markdownError Normal +endfunction + +" Runs the specified healthchecks. +" Runs all discovered healthchecks if a:plugin_names is empty. +function! health#check(plugin_names) abort + let healthchecks = empty(a:plugin_names) + \ ? s:discover_health_checks() + \ : s:to_fn_names(a:plugin_names) + + tabnew + setlocal wrap breakindent + setlocal filetype=markdown + setlocal conceallevel=2 concealcursor=nc + setlocal keywordprg=:help + call s:enhance_syntax() + + if empty(healthchecks) + call setline(1, 'ERROR: No healthchecks found.') + else + redraw|echo 'Running healthchecks...' + for c in healthchecks + let output = '' + call append('$', split(printf("\n%s\n%s", c, repeat('=',72)), "\n")) + try + let output = "\n\n".execute('call '.c.'()') + catch + if v:exception =~# '^Vim\%((\a\+)\)\=:E117.*\V'.c + let output = execute( + \ 'call health#report_error(''No healthcheck found for "' + \ .s:to_plugin_name(c) + \ .'" plugin.'')') + else + let output = execute( + \ 'call health#report_error(''Failed to run healthcheck for "' + \ .s:to_plugin_name(c) + \ .'" plugin. Exception:''."\n".v:throwpoint."\n".v:exception)') + endif + endtry + call append('$', split(output, "\n") + ['']) + redraw + endfor + endif + + " needed for plasticboy/vim-markdown, because it uses fdm=expr + normal! zR + setlocal nomodified + redraw|echo '' +endfunction + +" Starts a new report. +function! health#report_start(name) abort + echo "\n## " . a:name +endfunction + +" Indents lines *except* line 1 of a string if it contains newlines. +function! s:indent_after_line1(s, columns) abort + let lines = split(a:s, "\n", 0) + if len(lines) < 2 " We do not indent line 1, so nothing to do. + return a:s + endif + for i in range(1, len(lines)-1) " Indent lines after the first. + let lines[i] = substitute(lines[i], '^\s*', repeat(' ', a:columns), 'g') + endfor + return join(lines, "\n") +endfunction + +" Changes ':h clipboard' to ':help |clipboard|'. +function! s:help_to_link(s) abort + return substitute(a:s, '\v[''"]?:h%[elp] ([^''"]+)[''"]?', '":help |\1|"', 'g') +endfunction + +" Format a message for a specific report item +function! s:format_report_message(status, msg, ...) abort " {{{ + let output = ' - ' . a:status . ': ' . s:indent_after_line1(a:msg, 4) + let suggestions = [] + + " Optional parameters + if a:0 > 0 + let suggestions = type(a:1) == type("") ? [a:1] : a:1 + if type(suggestions) != type([]) + echoerr "Expected String or List" + endif + endif + + " Report each suggestion + if len(suggestions) > 0 + let output .= "\n - SUGGESTIONS:" + endif + for suggestion in suggestions + let output .= "\n - " . s:indent_after_line1(suggestion, 10) + endfor + + return s:help_to_link(output) +endfunction " }}} + +" Use {msg} to report information in the current section +function! health#report_info(msg) abort " {{{ + echo s:format_report_message('INFO', a:msg) +endfunction " }}} + +" Reports a successful healthcheck. +function! health#report_ok(msg) abort " {{{ + echo s:format_report_message('SUCCESS', a:msg) +endfunction " }}} + +" Reports a health warning. +function! health#report_warn(msg, ...) abort " {{{ + if a:0 > 0 + echo s:format_report_message('WARNING', a:msg, a:1) + else + echo s:format_report_message('WARNING', a:msg) + endif +endfunction " }}} + +" Reports a failed healthcheck. +function! health#report_error(msg, ...) abort " {{{ + if a:0 > 0 + echo s:format_report_message('ERROR', a:msg, a:1) + else + echo s:format_report_message('ERROR', a:msg) + endif +endfunction " }}} + +function! s:filepath_to_function(name) abort + return substitute(substitute(substitute(a:name, '.*autoload[\/]', '', ''), + \ '\.vim', '#check', ''), '[\/]', '#', 'g') +endfunction + +function! s:discover_health_checks() abort + let healthchecks = globpath(&runtimepath, 'autoload/health/*.vim', 1, 1) + let healthchecks = map(healthchecks, '<SID>filepath_to_function(v:val)') + return healthchecks +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 + call add(healthchecks, 'health#'.p.'#check') + endfor + return healthchecks +endfunction + +" Extracts 'foo' from 'health#foo#check'. +function! s:to_plugin_name(fn_name) abort + return substitute(a:fn_name, + \ '\v.*health\#(.+)\#check.*', '\1', '') +endfunction |