ruby-lsp icon indicating copy to clipboard operation
ruby-lsp copied to clipboard

VS Code: Add customBinaryPath option

Open palkan opened this issue 10 months ago • 11 comments

Motivation

This option allows to provide any compatible binary to be used as ruby-lsp exec. This is especially useful for containerized development with VS Code running on the host machine (i.e., not using Dev Containers or Remote Containers). A typical use case is the applications using dip (and ruby-on-whales) (see #2919). However, the ability to customize the binary path has many more potential applications.

Motivation continues...

I've been using a similar approach with Zed for a while (it already provides this option). The trick is to use a thin Bash wrapper to run ruby-lsp anywhere. Mine looks as follows:

#!/bin/bash

cd $(dirname $0)/..

dip ruby-lsp $@

That's it.

With this change, we can configure rubyLsp.customBinaryPath to point to a custom executable (say, ".dockerdev/ruby-lsp"), and benefit from LSP features even without having Ruby LSP (and even Ruby) installed locally (let me omit some Docker-specific tricks used to make it work, not relevant to the proposal).

Implementation

  • Added new configuration option to package.json: customBinaryPath
  • Updated client.ts to use the new option if present to generate commands configuration.

Automated Tests

None. Couldn't find any tests for similar functionality (commands configuration). Would love to have some guidance here.

Manual Tests

Packaged and installed the forked version locally and verified that LSP works.

palkan avatar Apr 10 '25 00:04 palkan

How to use the Graphite Merge Queue

Add the label graphite-merge to this PR to add it to the merge queue.

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

graphite-app[bot] avatar Apr 10 '25 00:04 graphite-app[bot]

I have signed the CLA!

palkan avatar Apr 10 '25 00:04 palkan

This should resolve https://github.com/Shopify/ruby-lsp/issues/2223 with the same motivation and ideas here

willtcarey avatar May 02 '25 13:05 willtcarey

Hey @vinistock,

Sorry for pushing, but it would be nice to at least know if there is something the team considers to be a good addition (and, thus, we can expect it soon) or not at all. Thanks.

palkan avatar May 03 '25 03:05 palkan

Thanks for the PR. Would supporting running the language server through sockets solve this use case?

Connecting to the LSP via sockets is standardized in the spec. If that solves the use cases, I would rather we implemented that rather than allowing customizing the executable.

The launching of the LSP ends up being the most critical part of our integration because we need to fully replicate the user's environment with the contributions of their version manager + bundler. I'm still not satisfied with the level of robustness of our launching and I'm afraid that allowing people to configure whatever executable they want could potentially build us into a corner where we cannot change the main ruby-lsp executable without a major breaking change.

Before committing to a decision, I'd also like to understand how other language servers solve this problem. What does Rust Analyzer do (or any other LSP)? As far as I know, there's no way to change its executable.

vinistock avatar May 15 '25 13:05 vinistock

Would supporting running the language server through https://github.com/Shopify/ruby-lsp/issues/1782 solve this use case?

Don't think so. The problem is not with accessing the language server but launching it.

The launching of the LSP ends up being the most critical part of our integration because we need to fully replicate the user's environment with the contributions of their version manager + bundler.

...Or let the user take care of the replication. For smaller projects, having ruby-lsp automatically set up itself and just work is great, I love it. But as soon as development environment becomes more complicated (like in our case with Docker), the magic no longer works.

I'm afraid that allowing people to configure whatever executable they want could potentially build us into a corner where we cannot change the main ruby-lsp executable without a major breaking change.

This is definitely an advanced option and must be used with caution. And it's the responsibility of the end user to comply with the ruby-lsp interface, not vice versa.

...how other language servers solve this problem

That seems more about editor plugins then LSPs.

Zed, for example, allows customizing the binary path for both Ruby LSP and Rust Analyzer (and, I think, others as well). Solargaph's VS Code extension has the commandPath setting. And Rust VS Code has the rust-analyzer.server.path.

palkan avatar May 15 '25 15:05 palkan

Hey @vinistock,

Have you had a chance to look at my previous comment?

palkan avatar Jun 11 '25 14:06 palkan

...how other language servers solve this problem

That seems more about editor plugins then LSPs.

The VSCode extension for rubocop also allows you to set a custom command, adding the to the following configuration works well:

{
  "rubocop.commandPath": "docker-compose exec my-app-name bundle exec rubocop"
}

dsager avatar Jun 12 '25 14:06 dsager

This pull request is being marked as stale because there was no activity in the last 2 months

github-actions[bot] avatar Aug 12 '25 12:08 github-actions[bot]

Container related discussions were happening in a few different places, so I created https://github.com/Shopify/ruby-lsp/discussions/3738 to try to centralize and move the discussion forward.

vinistock avatar Sep 05 '25 20:09 vinistock

This pull request is being marked as stale because there was no activity in the last 2 months

github-actions[bot] avatar Nov 05 '25 12:11 github-actions[bot]