[vim/vim] Bring neovim's CheckHealth plugin to vim by default (Issue #9838)

577 views
Skip to first unread message

Prabir Shrestha

unread,
Feb 23, 2022, 8:38:13 PM2/23/22
to vim/vim, Subscribed

Instructions: Replace the template text and remove irrelevant text (including this line)

Is your feature request about something that is currently impossible or hard to do? Please describe the problem.
Neovim bundles :CheckHealth command that easily allows to run custom healtchecks provides by plugins to make sure the plugins are configured correctly. This helps easily debug potential plugins issues or misconfiguration. You can see a quick demo at http://vimcasts.org/episodes/neovim-checkhealth/.

image

Describe the solution you'd like
Bundle neovim's builtin CheckHealth plugin by default in vim.

Describe alternatives you've considered
Vim users need to manually install https://github.com/rhysd/vim-healthcheck plugin.

Additional context
Add any other context or screenshots about the feature request here.


Reply to this email directly, view it on GitHub.
Triage notifications on the go with GitHub Mobile for iOS or Android.
You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/9838@github.com>

Christian Brabandt

unread,
Feb 24, 2022, 2:54:38 AM2/24/22
to vim/vim, Subscribed

I think it would be nice, if vim doesn't need a health-check and everything is fine from the beginning :)

So let's ask differently: What would you expect to be part of the health-check? I don't see anything on your screenshot, that is relevant to Vim currently (perhaps Configuration, but it doesn't tell us what exactly it checks).

If you need it for your own plugin, you can already create a custom-healthcheck just for your plugin, right?


Reply to this email directly, view it on GitHub.
Triage notifications on the go with GitHub Mobile for iOS or Android.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/9838/1049584251@github.com>

David Briscoe

unread,
Oct 29, 2022, 1:11:37 AM10/29/22
to vim/vim, Subscribed

I think the value in healthcheck is not running it for vim, but providing a standard API that plugins can rely on and users can expect. ale has three :ALEInfo commands, vim-lsp has :LspStatus, omnisharp has :OmniSharpStatus. Some of these commands only print results, some create a buffer, some write to a file.

As a user, if I can run :CheckHealth to see issues with my plugins (e.g., binaries they depend on are missing or failing to run, dump configuration info, etc), then it's easier for me to know how to start debugging my problems.

As a plugin author, if vim has a built-in framework for triggering and displaying diagnostic information then I'm more likely to implement those diagnostics. The alternative of writing my own mini version of checkhealth is usually more work than I want to bother and getting users to :redir @+ | call myplugin#dump_state() | :redir END is unreliable and undiscoverable.


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/9838/1295737828@github.com>

Bram Moolenaar

unread,
Oct 29, 2022, 6:05:17 PM10/29/22
to vim...@googlegroups.com, David Briscoe

> I think the value in healthcheck is not running it for vim, but
> providing a standard API that **plugins** can rely on and users can
> expect. ale has three `:ALEInfo` commands, vim-lsp has `:LspStatus`,
> omnisharp has `:OmniSharpStatus`. Some of these commands only print
> results, some create a buffer, some write to a file.
>
> As a user, if I can run `:CheckHealth` to see issues with my plugins
> (e.g., binaries they depend on are missing or failing to run, dump
> configuration info, etc), then it's easier for me to know how to start
> debugging my problems.
>
> As a plugin author, if vim has a built-in framework for triggering and
> displaying diagnostic information then I'm more likely to implement
> those diagnostics. The alternative of writing my own mini version of
> checkhealth is usually more work than I want to bother and getting
> users to `:redir @+ | call myplugin#dump_state() | :redir END` is
> unreliable and undiscoverable.

I agree, it would be nice to have an independent way to do this, no
matter what plugin framework you use. Big question is how plugins would
hook into this. Where is the documentation for this CheckHealth plugin?
Demo is just advertising, I want to see the technical side of it.
Perhaps just a global dictionary where each plugin can add an entry
under its name? There must be an API for reporting back the results.

--
ALL: A witch! A witch!
WITCH: It's a fair cop.
ALL: Burn her! Burn her! Let's make her into a ladder.
"Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD

/// Bram Moolenaar -- Br...@Moolenaar.net -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///

Prabir Shrestha

unread,
Nov 1, 2022, 11:03:33 PM11/1/22
to vim/vim, Subscribed

(not sure if there is something wrong with the sync but Bram's reply from google groups doesn't seem to be synced here in github).

Here is the doc for the :CheckHealth feature which pollyfills vim8 https://github.com/rhysd/vim-healthcheck/blob/master/doc/pi_health.txt. It is pretty detailed with info. Pasting some useful snippets and text from doc here:

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.

To try it out include the following plugin if you are running in vim.

if !has('nvim')
    Plug 'rhysd/vim-healthcheck'
endif

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
  " ...

  if looks_good
    call health#report_ok('found required dependencies')
  else
    call health#report_error('cannot find foo', 
      \ ['npm install --save foo'])
  endif
endfunction


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/9838/1299499578@github.com>

Bram Moolenaar

unread,
Nov 5, 2022, 6:27:03 PM11/5/22
to vim/vim, Subscribed


Thanks.

Adding a ":checkhealth" command, which would then source a script to do
the work, makes sense. Similar to a command like ":syntax on" which
also loads a script. This makes it easier to maintain. For most people
writing Vim9 script is probably simpler than writing C code.

I'm ignoring the Lua part of this, since we went with Vim9 script we
stopped adding more stuff for interpreters. There can be some support
to reach the Vim9 health functionality from Lua/Python/Perl/etc.
through some interface perhaps. Just to make it simpler.

I would think that a plugin that supports health checks registers
itself. That is better than adding another script file somewhere else,
because it makes updating simpler and keeps all the pieces of the plugin
in one place, instead of spreading it out over multiple directories.
And makes removing a plugin simpler.

Perhaps something like:

vim9script
# This is MyPlugin.vim
...

import autoload 'healthreport.vim'
def Check()
healthreport.start('MyPlugin')
healthreport.info('active')
if there-is-some-problem
healthreport.warn('that does not work')
else
healthreport.ok('fully functional')
endif
enddef

import 'dist/healthregister.vim'
healthregister.register('MyPlugin', Check)


Note that healthregister.vim should be really minimal, since it's always
loaded. It just keeps a list of all the plugins that called register().

The healthreport.vim script can be big, it's only used when actually
checking health.

Should the Check() function have some argument and return value?
Perhaps a "silent" flag to only report problems and nothing else?
Well, then healthreport functions could take care of it, the Check()
function doesn't need to know what ends up getting displayed.


--
For a moment, nothing happened.
Then, after a second or so, nothing continued to happen.
-- Douglas Adams, "The Hitchhiker's Guide to the Galaxy"

/// Bram Moolenaar -- ***@***.*** -- http://www.Moolenaar.net \\\

/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/9838/1304652896@github.com>

Prabir Shrestha

unread,
Nov 5, 2022, 11:16:12 PM11/5/22
to vim/vim, Subscribed

I'm fine with only support vim9 as long as it is easy to call a vim8 function so most of my code can be in vim8 script so it is compatible with neovim. Same can be said for lua/python/ruby so doesn't make sense to add specific compatibility support for those languages.

I don't think plugin needs any arguments but the vim command should include args so we can explicitly tell which plugin to run it for :checkhealth plugin1 plugin2 *lsp*.

silent could be implemented by passing healthreport that does noop.

def Check(healthreport)
   healthreport.warn(..)
enddef


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/9838/1304704845@github.com>

Bram Moolenaar

unread,
Nov 6, 2022, 7:11:10 AM11/6/22
to vim/vim, Subscribed


> I'm fine with only support vim9 as long as it is easy to call a vim8
> function so most of my code can be in vim8 script so it is compatible
> with neovim. Same can be said for lua/python/ruby so doesn't make
> sense to add specific compatibility support for those languages.

You can import Vim9 script into a legacy script and call the functions,
that should just work. It's still a bit new, so try it out to find any
issues. If there are we can most likely fix them (import/export is not
a simple mechanism, requires support in many places of the code).


> I don't think plugin needs any arguments but the vim command should
> include args so we can explicitly tell which plugin to run it for
> `:checkhealth plugin1 plugin2 *lsp*`.

Yeah, it needs some logic to map the argument to the actual plugin.
Might also depend on what plugin manager is being used and where plugins
are found in 'runtimepath' or 'packpath'. Not sure how many times we
would run into having more than one plugin fall under a name. Did you
have ideas about different versions of a plugin? It might not be that
important, the user would just see more info than what was asked for.

> `silent` could be implemented by passing healthreport that does noop.
>
> ```
> def Check(healthreport)
> healthreport.warn(..)
> enddef
> ```

Hmm, that looks a bit like passing an object, that hasn't been
implemented yet. A Dict can be used for now, but it's a bit clumsy.
You would need to define the type as dict<any>, not much can be done at
compile time.

--
How To Keep A Healthy Level Of Insanity:
5. Put decaf in the coffee maker for 3 weeks. Once everyone has gotten
over their caffeine addictions, switch to espresso.


/// Bram Moolenaar -- ***@***.*** -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/9838/1304786901@github.com>

David Briscoe

unread,
Nov 14, 2022, 7:41:26 PM11/14/22
to vim/vim, Subscribed

You can import Vim9 script into a legacy script and call the functions,
that should just work. It's still a bit new, so try it out to find any
issues. If there are we can most likely fix them (import/export is not
a simple mechanism, requires support in many places of the code).

I think the important part for compatibility is to avoid requiring plugins from implementing vim9-specific functionality. It would be great for a plugin's implementation to work with vim9's builtin support, vim8 + checkhealth plugin, and nvim's builtin support. Having each plugin write a vim9 shim isn't the worst and is better than nothing, but isn't ideal.

Here's an example of adding checkhealth support to a plugin. The addition of autoload/health/lsp.vim is all that's necessary from the plugin side because checkhealth uses globpath to discover support. Example: :echo globpath(&rtp, 'autoload/health/*', v:true, v:true)


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/9838/1314599438@github.com>

David Briscoe

unread,
Nov 14, 2022, 8:27:08 PM11/14/22
to vim/vim, Subscribed

Fiddled around trying to figure out a vim9 implementation. I don't think the existing checkhealth API can be implemented with vim9script because it uses lower case function names: I don't think you can do something like export def report_start() -- it'd have to be written in legacy vimscript.

Here's a barebones implementation that doesn't handle 'packpath' nor passing arguments to CheckHealth.

" In autoload/health.vim
let s:report = []

function! health#report_start(msg)
    call add(s:report, '## '.. a:msg)
endf

function! health#report_error(msg, suggestion)
    call add(s:report, "- ERROR: ".. a:msg)
    if !empty(a:suggestion)
        call add(s:report, "  * Suggestion:")
    endif
    for line in a:suggestion
        call add(s:report, "    ".. line)
    endfor
endf

function! health#report_info(msg)
    call add(s:report, a:msg)
endf

function! health#report_ok(msg)
    call add(s:report, "- SUCCESS: ".. a:msg)
endf

function! health#report_warn(msg)
    call add(s:report, "- WARNING: ".. a:msg)
endf


function! health#check()
    let pat = 'autoload/health/*.vim'
    let plugs = globpath(&runtimepath, pat, v:true, v:true)
    let plugs = plugs->map({ i, fpath -> fnamemodify(fpath, ':t:r') })

    let s:report = []
    for plugin in plugs
        let func_name = printf("health#%s#check", plugin)
        call add(s:report, func_name)
        call add(s:report, '==============================')
        let Fn = function(func_name)
        call Fn()
        call add(s:report, "")
    endfor
    split
    silent exec 'edit' tempname()
    silent 0file
    setlocal buftype=nofile bufhidden=hide noswapfile buflisted
    setfiletype markdown
    call append(1, s:report)
endf

" In plugin/health.vim:
command! -nargs=* -bar CheckHealth call health#check()

(For a robust and flexible vim8 implementation, it'd be better to take rhysd/vim-healthcheck.)

@brammool: would you be open to exposing this API so plugins using it will automatically be able to check health in vim?


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/9838/1314631069@github.com>

Bram Moolenaar

unread,
Nov 15, 2022, 12:26:35 PM11/15/22
to vim/vim, Subscribed


> Fiddled around trying to figure out a vim9 implementation. I don't
> think the existing checkhealth API can be implemented with vim9script
> because it uses lower case function names: I don't think you can do
> something like `export def report_start()` -- it'd have to be written
> in legacy vimscript.

User function names should always start with an upper case letter. In
legacy script the lower case was allowed after the "#" for autoloaded
scripts, just because it wouldn't collide with a builtin function name,
but it's a bit inconsistent, thus not recommended.

Of course you can decide to use legacy script, but keep in mind that
Vim9 script is much easier to use for most people and it provides much
better type and error checking. A little investment right now will pay
back in the long term.


> Here's a barebones implementation that doesn't handle 'packpath' nor
> passing arguments to CheckHealth.

[...]


> (For a robust and flexible vim8 implementation, it'd be better to take
> rhysd/vim-healthcheck.)
>
> @brammool: would you be open to exposing this API so plugins using it
> will automatically be able to check health in vim?

Yes, it appears to be useful. But let's spend some time discussing on
how we want to do this, since this is something that (hopefully) many
plugin authors are going to use. We should at least get the basic setup
right, so that we won't regret choices later. And think of what we'll
want to add later.

One thing I was thinking of: A :CheckHealth command is OK
interactively, but it would be good to also have some kind of API, so
that information can be gathered and used in a different way than just
displaying it. Maybe even an interactive way to spot a problem and let
the user choose one of several ways to fix it.

--
Proof techniques #2: Proof by Oddity.
SAMPLE: To prove that horses have an infinite number of legs.
(1) Horses have an even number of legs.
(2) They have two legs in back and fore legs in front.
(3) This makes a total of six legs, which certainly is an odd number of
legs for a horse.
(4) But the only number that is both odd and even is infinity.
(5) Therefore, horses must have an infinite number of legs.


/// Bram Moolenaar -- ***@***.*** -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/9838/1315642097@github.com>

David Briscoe

unread,
Nov 15, 2022, 1:44:38 PM11/15/22
to vim/vim, Subscribed

Of course you can decide to use legacy script, but keep in mind that
Vim9 script is much easier to use for most people and it provides much
better type and error checking. A little investment right now will pay
back in the long term.

I mean in vim. If plugins currently have an implementation that uses an API that requires legacy script, then I think vim should include a legacy script API.

Exposing a more flexible api is fine with me! A minimal entrypoint shim is also fine (so plugins could write everything in vim9): Requiring plugin authors expose health#plugin#CheckHealth (vim9-compatible) and health#plugin#check (vim8 and nvim compatible) also seems okay so long as they're both able to call the same lowercase health#report_info functions.

Requiring plugins to write shims that map their existing health#report_info() calls to a new health#ReportInfo() or healthreport.warn() is what I'm asking to avoid since it means a compatibility shim that each plugin must provide.


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/9838/1315722495@github.com>

Phạm Bình An

unread,
Nov 5, 2024, 9:46:51 AM11/5/24
to vim/vim, Subscribed

Is there any progress on this?


Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/9838/2457368832@github.com>

David Briscoe

unread,
Nov 6, 2024, 11:09:21 AM11/6/24
to vim/vim, Subscribed

No progress I know of.

I think the ideal solution is to provide a default vim implementation that aligns with the neovim one to take advantage of plugins that already have healthchecks implemented. Possibly start with rhysd/vim-healthcheck -- it supports healthchecks in vimscript and lua (but is apache licensed). I think Bram was leaning towards a vim-specific solution without trying to be compatible with neovim? Not sure what way active maintainers would prefer.

I think the main blockers are:

  • Can it support both vim9-style health#plugin#CheckHealth and vim8-style health#plugin#check (maybe with FuncUndefined or :try)?
  • Does it need more design aside from neovim's "spec"? And possibly become incompatible? (Active maintainer needs to weigh in.)


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/9838/2460189287@github.com>

Phạm Bình An

unread,
Nov 6, 2024, 11:17:47 AM11/6/24
to vim/vim, Subscribed

I don't think it needs to be Neovim-compatible, since the Vimscript functions for checkhealth in Neovim have been deprecated, leaving only its Lua counterpart. Though I guess if Vim adds this feature, Neovim may re-add the Vim functions to make it compatible with Vim?


Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/9838/2460212598@github.com>

Reply all
Reply to author
Forward
0 new messages