Shopify / ruby-lsp

An opinionated language server for Ruby
https://shopify.github.io/ruby-lsp/
MIT License
1.36k stars 125 forks source link

windows compatibility #1567

Closed NoahELE closed 1 year ago

NoahELE commented 1 year ago

I tried install the extension on vscode on windows, but cannot get it to work.

Is it because the extension does not support windows? If so, is there any plan for windows compatibility?

vinistock commented 1 year ago

Why did it not work? Can you provide more information regarding what happened? There's nothing platform specific as far as I know, so it should work on windows.

NoahELE commented 1 year ago

I use ruby installer for windows, and after I open a ruby file with vscode. It shows error image

vinistock commented 1 year ago

Is Ruby installer a version manager? If it is, we unfortunately do not support it yet. Here's the list of supported managers https://github.com/Shopify/vscode-ruby-lsp#ruby-version-managers.

NoahELE commented 1 year ago

I think the problem is that all the ruby version managers are not available on Windows.

I notice that there is a none version manager option. But I can’t get it to work on Windows too.

vinistock commented 1 year ago

How is Ruby inserted into the PATH on Windows? We need to understand what is done to load Ruby into the PATH so that we can do the same on the extension.

NoahELE commented 1 year ago

It just add ruby's bin path which looks like this,

d----            2023/4/2     3:42                etc
d----            2023/4/2     3:42                ruby_builtin_dlls
-a---            2023/4/2     3:42            707 bundle
-a---            2023/4/2     3:42             41 bundle.bat
-a---            2023/4/2     3:42            709 bundler
-a---            2023/4/2     3:42             41 bundler.bat
-a---            2023/4/2     3:42            668 erb
-a---            2023/4/2     3:42             41 erb.bat
-a---            2023/4/2     3:42            222 gem
-a---            2023/4/2     3:42            365 gem.cmd
-a---            2023/4/2     3:42            703 irb
-a---            2023/4/2     3:42             41 irb.bat
-a---            2023/4/2     3:42            674 racc
-a---            2023/4/2     3:42             41 racc.bat
-a---            2023/4/2     3:42            674 rake
-a---            2023/4/2     3:42             41 rake.bat
-a---            2023/4/2     3:42            668 rbs
-a---            2023/4/2     3:42             41 rbs.bat
-a---            2023/4/2     3:42            674 rdoc
-a---            2023/4/2     3:42             41 rdoc.bat
-a---            2023/4/2     3:42            670 ri
-a---            2023/4/2     3:42             41 ri.bat
-a---            2023/4/2     3:42            694 ridk.cmd
-a---            2023/4/2     3:42            876 ridk.ps1
-a---            2023/4/2     3:42          35840 ruby.exe
-a---            2023/4/2     3:42          35840 rubyw.exe
-a---            2023/4/2     3:42            312 setrbvars.cmd
-a---            2023/4/2     3:42            698 typeprof
-a---            2023/4/2     3:42             41 typeprof.bat
-a---            2023/4/2     3:42        4104704 x64-ucrt-ruby320.dll

and gem's bin path which looks like this,

-a---            2023/4/2    17:05            686 htmldiff
-a---            2023/4/2    17:05             34 htmldiff.bat
-a---            2023/4/3    14:42            653 irb
-a---            2023/4/3    14:42             34 irb.bat
-a---            2023/4/2    17:04            683 kramdown
-a---            2023/4/2    17:04             34 kramdown.bat
-a---            2023/4/2    17:05            680 ldiff
-a---            2023/4/2    17:05             34 ldiff.bat
-a---            2023/4/2    17:04            683 nokogiri
-a---            2023/4/2    17:04             34 nokogiri.bat
-a---            2023/4/2    17:00            659 rake
-a---            2023/4/2    17:00             34 rake.bat
-a---            2023/4/2    17:04            731 reverse_markdown
-a---            2023/4/2    17:04             34 reverse_markdown.bat
-a---            2023/4/2    17:04            677 rubocop
-a---            2023/4/2    17:04             34 rubocop.bat
-a---            2023/4/2    17:04            679 ruby-parse
-a---            2023/4/2    17:04             34 ruby-parse.bat
-a---            2023/4/2    17:04            683 ruby-rewrite
-a---            2023/4/2    17:04             34 ruby-rewrite.bat
-a---            2023/4/2    17:05            695 solargraph
-a---            2023/4/2    17:05             34 solargraph.bat
-a---            2023/4/3    14:43            719 syntax_suggest
-a---            2023/4/3    14:43             34 syntax_suggest.bat
-a---            2023/4/2    17:04            659 thor
-a---            2023/4/2    17:04             34 thor.bat
-a---            2023/4/2    17:04            659 tilt
-a---            2023/4/2    17:04             34 tilt.bat
-a---            2023/4/2    17:04            659 yard
-a---            2023/4/2    17:04             34 yard.bat
-a---            2023/4/2    17:04            663 yardoc
-a---            2023/4/2    17:04             34 yardoc.bat
-a---            2023/4/2    17:04            657 yri
-a---            2023/4/2    17:04             34 yri.bat
vinistock commented 1 year ago

Right, but how does it do it? Sorry, I have very little Windows experience so my terminology here might be too Unix focused. Are any files sourced automatically by your shell to add Ruby's bin folder to the PATH?

For example, on macos or linux, it would be common to have something in somebody's ~/.bashrc or ~/.zshrc that inserts the correct paths for finding Ruby.

That's the key piece we need to understand to add support for this.

NoahELE commented 1 year ago

I think windows PATH are added system wide instead of a shell. It can be accessed through a dialog like this

image

NoahELE commented 1 year ago

The output I get when opening a ruby file is

>> Running `bundle install`...
>> `bundle install` exited with code -4058
aharpervc commented 1 year ago

I think windows PATH are added system wide instead of a shell. It can be accessed through a dialog like this

If so, that'd have been done by the installer you used rather than being something inherent to Windows itself. Plus, there's no absolute requirement to use an installer vs downloading a zip file or compiling ruby yourself.

In terms of path management, there's also tools like uru, rbenv-for-windows, or rbenv-win

NoahELE commented 1 year ago

I think the problem might be here, https://github.com/Shopify/vscode-ruby-lsp/blob/b2ae0784bac651f3efc4486e6df5cf2753168fbc/src/client.ts#L483

Since bundle on windows is actually a bat file, it needs to be spawned fully like bundle.bat.

But I'm not an expert in vscode extension dev, so it's just a guess.

vinistock commented 1 year ago

As long as Ruby stuff is loaded into the path, you should be able to execute bundle (at least I think). I think we need to provide a way to point to the Ruby installation without a version manager.

NoahELE commented 1 year ago

image

image

Some test on my machine,it seems that child_process does not recognise bundle, I need to spawn bundle.bat to access bundle correctly

vinistock commented 1 year ago

The reason it doesn't recognize bundle is because it's not in the NodeJS environment's PATH. The bundle executable does exist as you showed in your screenshot (as well as a bundle.bat).

I believe Shopify/ruby-lsp#1571 will fix this by allowing you to add the right paths manually.

NoahELE commented 1 year ago

I don't think that bundle file is callable on windows. Windows allows you to omit exe, bat and cmd file extensions when calling something from commandline, but windows does not allow you run any file.

As far as I understand, unix allows running any script file as executable via shebang, but windows does not support it.

I think the problem is node's child_process can automatically append exe to command but cannot append bat to them, thus to spawn bat file we need to append bat extension ourselves.

image

image

Some test on my machine,it seems that child_process does not recognise bundle, I need to spawn bundle.bat to access bundle correctly

Like this example, node can spawn bundle.bat but not bundle. I haven't done anything to my PATH for this example, so I think the path to bundle can be correctly found by node.

vinistock commented 1 year ago

So, when you're working on the shell and want to install gems, do you run bundle.bat install? You can't do bundle install?

Inversion-des commented 1 year ago

I had the same problems on Windows: Failed to setup the bundle: spawn bundle ENOENT and 'bundle install' exited with code -4058. @NoahELE is correcnt. According to his investigation, I manually changed C:\Users\Des\.vscode\extensions\shopify.ruby-lsp-0.2.3\out\extension.js (replaced all "bundle" with "bundle.bat") — and it started to work: image

Inversion-des commented 1 year ago

And after that, I got this error: Error running diagnostics: undefined method '+' for nil:NilClass end_char: char + size, ^ Is it related to compatibility? There is no new output in the Ruby LSP console… it still says Ruby LSP is ready as the last line. image Update. Later I found in the console this:

[Error - 8:32:10 AM] Request textDocument/completion failed.
  Message: #<NoMethodError: undefined method `+' for nil:NilClass

        end_char: char + size,
                       ^>
  Code: -32603 
janbiedermann commented 1 year ago

Problem solved, see https://github.com/Shopify/vscode-ruby-lsp/pull/546

Instructions:

  1. clone ruby-lsp from https://github.com/Shopify/ruby-lsp/pull/620

  2. build the gem

  3. install the gem locally

  4. clone vscode-ruby-lsp from https://github.com/Shopify/vscode-ruby-lsp/pull/546

  5. build the extension

  6. install the extension locally from the resulting *.vsx

See it work

janbiedermann commented 1 year ago

Regarding "bundle" vs "bundle.bat":

When calling node ChildProcess.exec the command is executed within a shell, cmd.exe, so if "bundle.bat" is in the path, calling it as "bundle" will work, as cmd.exe will look for "bundle.bat"

When calling node ChildProcess.spawn the command is executed directly, thus "bundle" cannot be found, as it is installed as "bundle.bat" on Windows, so it must be called as "bundle.bat"

janbiedermann commented 1 year ago

To be more precise: The MingW-based Windows RubyInstaller installs both "bundle" and a "bundle.bat". The "bundle" however is only callable from within the bash shell of the MingW environment. Node from within VSCode executes outside if this environment in the normal Windows Environment so CP.spawn must use "bundle.bat" to be useful.

Inversion-des commented 1 year ago

Now it fails to start with a different error: image Looks like the shell var is undefined: ${this.shell} -ic …

Inversion-des commented 1 year ago

But this error started from updating to v0.2.4, so not related to your instruction. I just expected that your instruction will fix all the errors) I used master when cloned both repos.

janbiedermann commented 1 year ago

But this error started from updating to v0.2.4, so not related to your instruction. I just expected that your instruction will fix all the errors) I used master when cloned both repos.

That shouldn't happen. You need to use the branches from the PRs: https://github.com/janbiedermann/ruby-lsp/tree/use_os_tmpdir https://github.com/janbiedermann/vscode-ruby-lsp/tree/windows_support

lsegal commented 1 year ago

That shouldn't happen. You need to use the branches from the PRs: https://github.com/janbiedermann/ruby-lsp/tree/use_os_tmpdir https://github.com/janbiedermann/vscode-ruby-lsp/tree/windows_support

You should not need to use .bat suffixes if you're executing commands using the proper shell-- and, in fact, it is improper from a cross-platform POV to do so. The executable may not be packaged in .bat form, it may be any executable format, including .exe or even .cmd, and this would fail if, for instance, you had a gem.cmd (which is actually provided in the bin dir).

vinistock commented 1 year ago

I just released v0.2.5 with some fixes that are relevant for Windows support, if someone wants to give it a try and report back their findings.

LePichu commented 1 year ago

I just released v0.2.5 with some fixes that are relevant for Windows support, if someone wants to give it a try and report back their findings.

Just tried this, still does not work on WIndows. :/

vinistock commented 1 year ago

Can you share what's happening? What are the errors? Is there anything in the output tab?

LePichu commented 1 year ago

Can you share what's happening? What are the errors? Is there anything in the output tab?

Nothing in the output tab but it can't find Ruby, I'd suggest a temporary workaround to allow us to point to a Ruby executable ourselves as an option in extension settings like how Crystal VSCode has an option for pointing to a LSP Binary.

vinistock commented 1 year ago

Yes, that's described in Shopify/ruby-lsp#1571. Weird that stuff present in the PATH on Windows doesn't show up for the NodeJS process in VS Code though.

LePichu commented 1 year ago

Yes, that's described in Shopify/ruby-lsp#1571. Weird that stuff present in the PATH on Windows doesn't show up for the NodeJS process in VS Code though.

Might be a VSCode bug?

vinistock commented 1 year ago

I put up https://github.com/Shopify/vscode-ruby-lsp/pull/583 to add the custom activation. It would be very helpful if someone gave that branch a try so that we can iron out issues to make sure the extension works on Windows on the next release.

lsegal commented 1 year ago

@vinstock are these branches being tested on your end before sharing? Just trying to understand what we're being asked to test.

vinistock commented 1 year ago

I tested the general logic of putting an arbitrary Ruby in the PATH on my machine, but I don't have a Windows machine I can test on. I want to understand if supporting this custom activation is enough to make the extension work on Windows or if there are any other missing steps.

lsegal commented 1 year ago

Hey Shopify what do we gotta do to get @vinistock a Windows laptop or VM to test on? This doesn't seem like a great way to maintain this extension in the long term. 😎

janbiedermann commented 1 year ago

Well, there is VirtualBox from virtualbox.org for free, and there are Windows Evaluation Images https://developer.microsoft.com/en-us/windows/downloads/virtual-machines/ , for free too. Not much else needed. Ruby for Windows is available here: https://rubyinstaller.org/downloads/ (use the version including the DevKit, and also install the DevKit, its required for c extensions to work)

LePichu commented 1 year ago

I put up Shopify/vscode-ruby-lsp#583 to add the custom activation. It would be very helpful if someone gave that branch a try so that we can iron out issues to make sure the extension works on Windows on the next release.

I could try that today, would be happy to return feedback after that.

LePichu commented 1 year ago

Ok so, I just got free and now I can test Shopify/vscode-ruby-lsp#583 out, @vinistock how do I use/build it locally?

andyw8 commented 1 year ago
andyw8 commented 1 year ago

Also you will need to:

vinistock commented 1 year ago

Version v0.3.0 includes the new custom activation. Please try the instructions and report back if any problems persist.

rokit commented 1 year ago

@vinistock Hello, Windows user here and I'm confused. It looks like the purpose of customRubyCommand is to simply add Ruby to the path, but Ruby is already on my path (Ruby Installer adds it automatically). And I only have one version of Ruby on my system, so there's no specific version to activate.

This is the error I'm seeing with "rubyLsp.rubyVersionManager": "none":

Failed to activate none environment: Command failed: 'ruby --disable-gems -rjson -e "printf(%{RUBY_ENV_ACTIVATE%sRUBY_ENV_ACTIVATE}, JSON.dump(ENV.to_h))"' ''ruby' is not recognized as an internal or external command, operable program or batch file.

This is despite the fact that I can run Ruby commands such as ruby --version just fine in cmd and PowerShell.

vinistock commented 1 year ago

Hello! The NodeJS process in VS Code does not seem to inherit manually configured PATHs in Windows.

You will need to use the custom command to push it into the path.

{
  "rubyLsp.rubyVersionManager": "custom",
  "rubyLsp.customRubyCommand": "PATH=something;$PATH" // not sure if this the right syntax for Windows, but you get the gist
}
janbiedermann commented 1 year ago

Hello! The NodeJS process in VS Code does not seem to inherit manually configured PATHs in Windows.

You will need to use the custom command to push it into the path.

{
  "rubyLsp.rubyVersionManager": "custom",
  "rubyLsp.customRubyCommand": "PATH=something;$PATH" // not sure if this the right syntax for Windows, but you get the gist
}

So the initial patch, that launched powershell/cmd.exe to get the path, maybe was not such a bad idea after all

rokit commented 1 year ago

@vinistock Unfortunately, I couldn't get it to work.

With "rubyLsp.rubyVersionManager": "custom":

PowerShell syntax: "rubyLsp.customRubyCommand": "$env:PATH += ';C:\\Ruby31-x64\\bin'", PowerShell error: Failed to activate custom environment: Command failed: '$env:PATH += ';C:\Ruby31-x64\bin' && ruby --disable-gems -rjson -e "printf(%{RUBY_ENV_ACTIVATE%sRUBY_ENV_ACTIVATE}, JSON.dump(ENV.to_h))"' The filename, directory name, or volume label syntax is incorrect.

cmd syntax: "rubyLsp.customRubyCommand": "set PATH=%PATH%;C:\\Ruby31-x64\\bin" error: Failed to activate custom environment: Command failed: 'set PATH=%PATH%;C:\Ruby31-x64\bin && ruby --disable-gems -rjson -e "printf(%{RUBY_ENV_ACTIVATE%sRUBY_ENV_ACTIVATE}, JSON.dump(ENV.to_h))"' ''set' is not recognized as an internal or external command, operable program or batch file.

arielbada commented 12 months ago

Hello @vinistock! I confirm I have the exact same issue than @rokit.

I'm using same cmd syntax. I tested the full command of the error in plain console and proven to be working ok: set PATH=%PATH%;C:\Ruby32-x64\bin && ruby --disable-gems -rjson -e "printf(%{RUBY_ENV_ACTIVATE%sRUBY_ENV_ACTIVATE}, JSON.dump(ENV.to_h))"

Also tested this in console without the set PATH=%PATH%;C:\Ruby32-x64\bin string, and it's working ok too, as expected: ruby --disable-gems -rjson -e "printf(%{RUBY_ENV_ACTIVATE%sRUBY_ENV_ACTIVATE}, JSON.dump(ENV.to_h))"

With this, I suspect this is not related to the PATH problem.

I don't know if it's of any help, but the error message on VScode for me is half in English (VScode enviroment) and half in Spanish (my OS language): Failed to activate custom environment: Command failed: '"set PATH=%PATH%;C:\\Ruby32-x64\\bin" && ruby --disable-gems -rjson -e "printf(%{RUBY_ENV_ACTIVATE%sRUBY_ENV_ACTIVATE}, JSON.dump(ENV.to_h))"' El sistema no puede encontrar la ruta especificada.

(Saying that the specified path cannot be found)

vinistock commented 11 months ago

I apologize, but I have no experience developing on or for Windows. I don't know the differences between cmd and powershell or why you'd use one or the other. If someone knows what the idiomatic solution is, please put up a PR and I can help verify that it works on Linux and Macos.

Inversion-des commented 11 months ago

✔ It works for me again after some patching:

In the C:\Users\Des\.vscode\extensions\shopify.ruby-lsp-0.3.3\out\extension.js: Remove single quotes in the part:

t += `'${e} --disable-gems -rjson -e "printf(%{RUBY_ENV_ACTIVATE%sRUBY_ENV_ACTIVATE}, JSON.dump([ENV.to](http://env.to/)_h))"'`;

so it should be:

t += `${e} --disable-gems -rjson -e "printf(%{RUBY_ENV_ACTIVATE%sRUBY_ENV_ACTIVATE}, JSON.dump([ENV.to](http://env.to/)_h))"`;

and replace all command:"bundle" with command:"bundle.bat" That's it.

It works with "rubyLsp.rubyVersionManager": "none" (uses the default installed Ruby), but with these fixes customized path should also work.