Is there a way to start the client without executing a new process?

What?

I’m trying to figure out if neovim’s builtin LSP client offers any other way to start the client without requiring a command to be run where neovim talks to the spawned LSP server over stdin & stdout.

  • If I already had an LSP running, could I attach to it?
  • If I had some alternative means to talk to the LSP server, could I provide a means for the neovim client to send requests to it and receive responses that isn’t stdin/stdout?

Why?

I’m working on a plugin that enables editing files, running programs, and using neovim’s LSP client against a remote machine. Similar to Facebook’s old nuclide offering or Microsoft’s remote code development.

The plugin is currently functional and works just fine including the LSP client, but it requires me spawning additional processes - one per LSP client - to mirror the remote LSP’s stdout/stderr as well as supporting the client sending requests via stdin.

I’d like to simplify this by forwarding the LSP client’s requests to my already-running process and passing back results to the client. Ideally, this would happen by letting me package up the client’s stdin to send to my proxy and then unpackage the response, which would be in JSON.

There’s not an easy way to do this, no. This is more a general unix question than something specific to LSP/our client.

Language servers can communicate via stdin/stdout or TCP. Most commonly stdin/stdout is used, only some server support TCP. With TCP, it’s a bit easier since you could hypothetically just point the client at a running server. I think this answers your second question.

In regards to your first question, with stdin/stdout, you’ll need to look into the documentation of libuv’s uv_spawn. We use the luv lua api binding to uv_spawn in order to launch language servers and communicate via stdin/stdout/stderr. We pass handles to stdin/stdout/stderr when launching the servers. I suppose you could use pipe’s/redirection, but this would require PRs to neovim’s client, th RPC loops is not currently overridable.

Thanks for the reply! :slight_smile:

I was torn between where this would belong. Because it’s centered around how to engage with the neovim LSP client specifically, I figured it would be best suited here.

One of my goals is to support any remote LSP server, including ones that only support stdin/stdout, which is why the TCP route wasn’t a good choice. That and the need to support end-to-end encryption over the network, of course the remote machine chatting with the LSP server running on itself wouldn’t be encrypted.

I was fairly sure that there wasn’t a way to do this at the moment, but wanted to check with others before skipping over it. For the time being, I can keep the solution I’ve got as it works perfectly fine, but may look into PRs to the client in the future to support this feature.

Nw! Please let me know if you have more questions, as distant looks very exciting. We can also modify the built-in client once you have a wishlist :slight_smile: If there’s a specific minimal example you need as well (like connecting to a pipe of a running language server, let me know!

Thanks! I’ll reach out if I need something. Been standing up e2e tests for the plugin and the Rust binary that accompanies it to facilitate the networking. There’s one additional snag I found out that I’ll need to handle, but nothing related to the neovim client.

Once this has stabilized, I’ll document gaps that neovim could help improve.

I’ve also submitted a talk request regarding the plugin and architecture to the upcoming vimconf.live, so we’ll see if that gets accepted.