Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions docs/src/languages/ruby.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,20 @@ Solargraph has formatting and diagnostics disabled by default. We can tell Zed t
}
```

To use Solargraph in the context of the bundle, you can use [folder-specific settings](../configuring-zed#settings-files) and specify the absolute path to the [`binstub`](https://bundler.io/v2.5/man/bundle-binstubs.1.html) of Solargraph:

```json
{
"lsp": {
"solargraph": {
"binary": {
"path": "<path_to_your_project>/bin/solargraph"
}
}
}
}
```

### Configuration

Solargraph reads its configuration from a file called `.solargraph.yml` in the root of your project. For more information about this file, see the [Solargraph configuration documentation](https://solargraph.org/guides/configuration).
Expand Down Expand Up @@ -120,6 +134,20 @@ Rubocop has unsafe autocorrection disabled by default. We can tell Zed to enable
}
```

To use Rubocop in the context of the bundle, you can use [folder-specific settings](../configuring-zed#settings-files) and specify the absolute path to the [`binstub`](https://bundler.io/v2.5/man/bundle-binstubs.1.html) of Rubocop:

```json
{
"lsp": {
"rubocop": {
"binary": {
"path": "<path_to_your_project>/bin/rubocop"
}
}
}
}
```

## Using the Tailwind CSS Language Server with Ruby

It's possible to use the [Tailwind CSS Language Server](https://github.com/tailwindlabs/tailwindcss-intellisense/tree/HEAD/packages/tailwindcss-language-server#readme) in Ruby and ERB files.
Expand Down
52 changes: 46 additions & 6 deletions extensions/ruby/src/language_servers/rubocop.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
use zed_extension_api::{self as zed, Result};
use zed_extension_api::{self as zed, settings::LspSettings, LanguageServerId, Result};

pub struct RubocopBinary {
pub path: String,
pub args: Option<Vec<String>>,
}

pub struct Rubocop {}

Expand All @@ -9,11 +14,46 @@ impl Rubocop {
Self {}
}

pub fn server_script_path(&mut self, worktree: &zed::Worktree) -> Result<String> {
let path = worktree.which("rubocop").ok_or_else(|| {
"rubocop must be installed manually. Install it with `gem install rubocop` or specify the 'binary' path to it via local settings.".to_string()
})?;
pub fn language_server_command(
&mut self,
language_server_id: &LanguageServerId,
worktree: &zed::Worktree,
) -> Result<zed::Command> {
let binary = self.language_server_binary(language_server_id, worktree)?;

Ok(zed::Command {
command: binary.path,
args: binary.args.unwrap_or_else(|| vec!["--lsp".to_string()]),
env: worktree.shell_env(),
})
}

fn language_server_binary(
&self,
_language_server_id: &LanguageServerId,
worktree: &zed::Worktree,
) -> Result<RubocopBinary> {
let binary_settings = LspSettings::for_worktree("rubocop", worktree)
.ok()
.and_then(|lsp_settings| lsp_settings.binary);
let binary_args = binary_settings
.as_ref()
.and_then(|binary_settings| binary_settings.arguments.clone());

if let Some(path) = binary_settings.and_then(|binary_settings| binary_settings.path) {
return Ok(RubocopBinary {
path,
args: binary_args,
});
}

if let Some(path) = worktree.which("rubocop") {
return Ok(RubocopBinary {
path,
args: binary_args,
});
}

Ok(path)
Err("rubocop must be installed manually. Install it with `gem install rubocop` or specify the 'binary' path to it via local settings.".to_string())
}
}
61 changes: 52 additions & 9 deletions extensions/ruby/src/language_servers/ruby_lsp.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
use zed::{
use zed_extension_api::{
self as zed,
lsp::{Completion, CompletionKind, Symbol, SymbolKind},
CodeLabel, CodeLabelSpan,
settings::LspSettings,
CodeLabel, CodeLabelSpan, LanguageServerId, Result,
};
use zed_extension_api::{self as zed, Result};

pub struct RubyLspBinary {
pub path: String,
pub args: Option<Vec<String>>,
}

pub struct RubyLsp {}

Expand All @@ -13,13 +19,50 @@ impl RubyLsp {
Self {}
}

pub fn server_script_path(&mut self, worktree: &zed::Worktree) -> Result<String> {
let path = worktree.which("ruby-lsp").ok_or_else(|| {
"ruby-lsp must be installed manually. Install it with `gem install ruby-lsp`."
.to_string()
})?;
pub fn language_server_command(
&mut self,
language_server_id: &LanguageServerId,
worktree: &zed::Worktree,
) -> Result<zed::Command> {
let binary = self.language_server_binary(language_server_id, worktree)?;

Ok(zed::Command {
command: binary.path,
args: binary.args.unwrap_or_default(),
env: worktree.shell_env(),
})
}

fn language_server_binary(
&self,
_language_server_id: &LanguageServerId,
worktree: &zed::Worktree,
) -> Result<RubyLspBinary> {
let binary_settings = LspSettings::for_worktree("ruby-lsp", worktree)
.ok()
.and_then(|lsp_settings| lsp_settings.binary);
let binary_args = binary_settings
.as_ref()
.and_then(|binary_settings| binary_settings.arguments.clone());

if let Some(path) = binary_settings.and_then(|binary_settings| binary_settings.path) {
return Ok(RubyLspBinary {
path,
args: binary_args,
});
}

Ok(path)
if let Some(path) = worktree.which("ruby-lsp") {
return Ok(RubyLspBinary {
path,
args: binary_args,
});
}

Err(
"ruby-lsp must be installed manually. Install it with `gem install ruby-lsp`."
.to_string(),
)
}

pub fn label_for_completion(&self, completion: Completion) -> Option<CodeLabel> {
Expand Down
53 changes: 47 additions & 6 deletions extensions/ruby/src/language_servers/solargraph.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
use zed::lsp::{Completion, CompletionKind, Symbol, SymbolKind};
use zed::{CodeLabel, CodeLabelSpan};
use zed_extension_api::{self as zed, Result};
use zed_extension_api::settings::LspSettings;
use zed_extension_api::{self as zed, LanguageServerId, Result};

pub struct SolargraphBinary {
pub path: String,
pub args: Option<Vec<String>>,
}

pub struct Solargraph {}

Expand All @@ -11,12 +17,47 @@ impl Solargraph {
Self {}
}

pub fn server_script_path(&mut self, worktree: &zed::Worktree) -> Result<String> {
let path = worktree
.which("solargraph")
.ok_or_else(|| "solargraph must be installed manually".to_string())?;
pub fn language_server_command(
&mut self,
language_server_id: &LanguageServerId,
worktree: &zed::Worktree,
) -> Result<zed::Command> {
let binary = self.language_server_binary(language_server_id, worktree)?;

Ok(zed::Command {
command: binary.path,
args: binary.args.unwrap_or_else(|| vec!["stdio".to_string()]),
env: worktree.shell_env(),
})
}

Ok(path)
fn language_server_binary(
&self,
_language_server_id: &LanguageServerId,
worktree: &zed::Worktree,
) -> Result<SolargraphBinary> {
let binary_settings = LspSettings::for_worktree("solargraph", worktree)
.ok()
.and_then(|lsp_settings| lsp_settings.binary);
let binary_args = binary_settings
.as_ref()
.and_then(|binary_settings| binary_settings.arguments.clone());

if let Some(path) = binary_settings.and_then(|binary_settings| binary_settings.path) {
return Ok(SolargraphBinary {
path,
args: binary_args,
});
}

if let Some(path) = worktree.which("solargraph") {
return Ok(SolargraphBinary {
path,
args: binary_args,
});
}

Err("solargraph must be installed manually".to_string())
}

pub fn label_for_completion(&self, completion: Completion) -> Option<CodeLabel> {
Expand Down
21 changes: 3 additions & 18 deletions extensions/ruby/src/ruby.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,30 +30,15 @@ impl zed::Extension for RubyExtension {
match language_server_id.as_ref() {
Solargraph::LANGUAGE_SERVER_ID => {
let solargraph = self.solargraph.get_or_insert_with(|| Solargraph::new());

Ok(zed::Command {
command: solargraph.server_script_path(worktree)?,
args: vec!["stdio".into()],
env: worktree.shell_env(),
})
solargraph.language_server_command(language_server_id, worktree)
}
RubyLsp::LANGUAGE_SERVER_ID => {
let ruby_lsp = self.ruby_lsp.get_or_insert_with(|| RubyLsp::new());

Ok(zed::Command {
command: ruby_lsp.server_script_path(worktree)?,
args: vec![],
env: worktree.shell_env(),
})
ruby_lsp.language_server_command(language_server_id, worktree)
}
Rubocop::LANGUAGE_SERVER_ID => {
let rubocop = self.rubocop.get_or_insert_with(|| Rubocop::new());

Ok(zed::Command {
command: rubocop.server_script_path(worktree)?,
args: vec!["--lsp".into()],
env: worktree.shell_env(),
})
rubocop.language_server_command(language_server_id, worktree)
}
language_server_id => Err(format!("unknown language server: {language_server_id}")),
}
Expand Down