Skip to content

Format on save for all filetypes with a language server #956

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
dlukes opened this issue Jan 20, 2020 · 3 comments
Closed

Format on save for all filetypes with a language server #956

dlukes opened this issue Jan 20, 2020 · 3 comments

Comments

@dlukes
Copy link

dlukes commented Jan 20, 2020

I'm trying to figure out the best way to set up format on save for all filetypes which have a language server. At first, I thought I could just do this, and at worst, I'd maybe have to silence warnings/errors if no language server is running:

autocmd BufWritePre * call LanguageClient#textDocument_formatting_sync()

As it turns out, this does work for filetypes which have a language server, but hangs indefinitely on save for filetypes which don't, waiting forever in this loop in LanguageClient_runSync (presumably because the Rust bridge isn't there to respond?):

while len(l:LanguageClient_runSync_outputs) == 0
sleep 100m
endwhile

So I searched the issue tracker and found out about LanguageClient#isAlive, which I thought I could use at runtime to determine whether LanguageClient#textDocument_formatting_sync is safe to run (presumably, if LanguageClient#isAlive, then the call won't hang). However, as per the suggestion in the linked comment, I would need to use LanguageClient_runSync to run LanguageClient#isAlive synchronously, which means we get stuck in the aforementioned while loop once again.

So I ended up devising with the following solution, which seems to be working so far:

execute 'autocmd FileType '
  \ . join(keys(g:LanguageClient_serverCommands), ',')
  \ . ' autocmd BufWritePre <buffer> call LanguageClient#textDocument_formatting_sync()'

In other words: install a FileType autocommand, which sets up a per-buffer autocommand to run LSP formatting for each buffer belonging to one of the supported filetypes. To make matters worse, the whole thing has to be wrapped in an execute, because we need determine the list of supported filetypes based on the keys of g:LanguageClient_serverCommands.

This feels somewhat baroque and complicated, so I was wondering whether I've missed a more obvious, cleaner way, that someone better acquainted with the internals of the project might recommend over this? :)

@martskins
Copy link
Collaborator

Have you considered setting up a function for it and calling that in the autocmd instead?

function! MaybeFormat() abort
    if !has_key(g:LanguageClient_serverCommands, &filetype)
        return
    endif

    call LanguageClient#textDocument_formatting_sync()
endfunction

autocmd BufWritePre * call MaybeFormat()

This still has the problem that if the language server does not have formatting capabilities you will probably face an error (or maybe even end up in the loop again, not sure).

@dlukes
Copy link
Author

dlukes commented Jul 3, 2020

Thanks very much for the alternative suggestion! I'm currently using/evaluating the builtin LSP in Neovim nightly, so I don't have a pressing need for this anymore, but it's definitely useful to have it here :)

@EvanCarroll
Copy link

#1212

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants