2

I come from the following problem:

  • I'm using Neovim (0.8.3) with AstroNvim as plugin/everything-manager.
  • I've successfully set up multiple LSP servers from within that, which use the right servers, interpreters, settings etc via the user configuration file. So, I'd like to not circumvent loading the configuration.
  • I want to use that to format files from my shell command line non-interactively.

What I've thought should work is:

nvim -c ':e qa_throttle.py'  -c ':lua vim.lsp.buf.format()' -c ':wq'

(as running :lua vim.lsp.buf.format() manually after opening the file using nvim qa_throttle.py just works.)

It doesn't; omitting the q to see the errors, I get told that for the buffer there's no LSP set up; "[LSP] Format request failed; no matching language server".

My first guess was that LSP server bring up and connection takes a moment, so I added a -c :sleep before the -c ':lua… option - didn't help at all.

So, my second guess was that the -c-specified commands just happen to run on some invisible or command buffer or something, and not on the actual file-containing buffer. OK, so, maybe I can script the selection of that buffer? nvim -c ':argdo lua vim.lsp.buf.format()' -c ':wq' qa_throttle.py has the same problem.

Let's prove that if I run the command on all buffers, at least one commands "hits" the right buffer and formats it: replacing :lua with :luado should run on all buffers: nvim -c ':e qa_throttle.py' -c ':luado vim.lsp.buf.format()' -c ':wq'
This time, execution took way longer, I got not a single but a whole battery of the aforementioned failure messages. But the buffer I want to format remains unchanged.

So, I'm a bit blocked here.

How do I execute (esp. lua) commands in Neovim on the right document buffer from a command line to achieve document formatting?

1
  • Is vim.lsp.buf.format() synchronous? If it is async, you need to wait for it to finish; otherwise, there's a good chance :wq triggers before any changes are made.
    – D. Ben Knoble
    Apr 18 at 18:21

2 Answers 2

1
+50

Would you like to try this? I think it is better than the previous solution:

nvim -c ':e qa_throttle.py' \
     -c ':lua vim.api.nvim_create_autocmd("LspAttach", {
      callback = function(args)
        vim.lsp.buf.format({timeout_ms=5000})
        vim.cmd("wq")
      end,
    })'

It will trigger the lsp formatting when Lsp is attached. And the timeout_ms is vitally important to wait the lsp formatting to be done as the lsp server could be not ready when attached.
I have tested this with JDTLs.

4
  • Will do as soon as I'm back on my PC! Apr 23 at 9:21
  • that works nicely! Stupid question though: shouldn't one first define the callback on LspAttach, and then open the file? Apr 23 at 9:42
  • The order does not matter. As autocmd defining is much quicker than the Lsp loading. Anyway you can define the autocmd before opening the file.
    – sanigo
    Apr 23 at 9:58
  • Thanks! Yeah, as someone who does code reviews: one order has the potential for a race condition, the other won't – but that's really of little practical relevance here. Apr 23 at 11:26
1

I believe you can achieve it like this:

nvim -c ':e qa_throttle.py' \
     -c ':lua vim.defer_fn(
            function()
              vim.lsp.buf.format()
              vim.cmd("wq")
            end, 5000)'

The "5000" means that we should wait 5 seconds to call lsp formatter.

1
  • OK, I could verify this works, but it's kind of a sad solution to defer execution by some "safe" amount (which needs to be safe enough for even the largest projects for pylsp to initialize) instead of triggering after the LSP integration has signalled readiness. But: It solves the problem, and it gives me a starting point to research further. So, thanks, and please accept my bounty :) Apr 22 at 9:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.