第106章 Ruby 语言支持
通过Ruby 扩展可获得对 Ruby 的支持。
- Tree-sitters:
- Language Servers:
- Debug Adapter:
rdbg
Ruby 扩展还支持 ERB 文件。
Language Servers
目前有多种可供 Ruby 使用的 language server。Zed 支持以下两种:
两者都具备自动补全、诊断、代码操作等重叠功能集,由您决定使用哪一个。请注意,不能同时使用两者。
除了这两个 language server,Zed 还支持:
- rubocop:Ruby 的静态代码分析器和 linter。在底层,Zed 也将其用作 language server,但其功能与 solargraph 和 ruby-lsp 互补。
- sorbet:Ruby 的静态类型检查器,拥有自定义的渐进式类型系统。
- steep:使用 Ruby Signature (RBS) 的 Ruby 静态类型检查器。
- Herb:用于 ERB 文件的 language server。
- kanayago:将 Ruby 解析器以 gem 形式提供的 Ruby language server。
配置语言服务器时,建议用 "dev: Open Language Server Logs" 命令打开 LSP 日志窗口,然后选择对应的语言实例查看日志信息。
配置语言服务器
Ruby 扩展同时支持 solargraph 和 ruby-lsp 两种语言服务器。
语言服务器激活
对于所有受支持的 Ruby 语言服务器(solargraph、ruby-lsp、rubocop、sorbet 和 steep),Ruby 扩展都按以下顺序激活:
- 如果语言服务器在项目的
Gemfile中,则通过bundle exec使用它。 - 如果
Gemfile中没有,则在系统PATH中查找可执行文件。 - 如果两者都没有找到,Ruby 扩展会自动将其安装为全局 gem(注意:不会安装到当前的 Ruby gemset 中)。
可以在设置中把 use_bundler 设为 false 来跳过第 1 步,强制使用系统中的可执行文件:
{
"lsp": {
"<SERVER_NAME>": {
"settings": {
"use_bundler": false
}
}
}
}
使用 solargraph
Ruby 扩展默认启用 solargraph。
使用 ruby-lsp
在 Settings({#kb zed::OpenSettings})的 Languages > Ruby 下配置语言服务器,或直接添加到设置文件中:
第106章:Ruby ```json { "languages": { "Ruby": { "language_servers": ["ruby-lsp", "!solargraph", "!rubocop", "..."] }, // 为 *.html.erb 文件启用 herb 和 ruby-lsp "HTML+ERB": { "language_servers": ["herb", "ruby-lsp", "..."] }, // 为 *.js.erb 文件启用 ruby-lsp "JS+ERB": { "language_servers": ["ruby-lsp", "..."] }, // 为 *.yaml.erb 文件启用 ruby-lsp "YAML+ERB": { "language_servers": ["ruby-lsp", "..."] } } } ``` 这段配置禁用了solargraph 和 rubocop,转而使用 ruby-lsp。
### 使用 rubocop
Ruby 扩展还提供了对 rubocop 语言服务器(language server)的支持,用于错误检测和自动修正。
你可以在设置({#kb zed::OpenSettings})的 Languages > Ruby 部分配置语言服务器,或者在配置文件中添加以下内容:
```json
{
"languages": {
"Ruby": {
"language_servers": ["ruby-lsp", "rubocop", "!solargraph", "..."]
}
}
}
```
相反,你也可以禁用 ruby-lsp,并启用 solargraph 和 rubocop:
```json
{
"languages": {
"Ruby": {
"language_servers": ["solargraph", "rubocop", "!ruby-lsp", "..."]
}
}
}
```
### 配置 solargraph
Solargraph 默认禁用了格式化和诊断功能。你可以通过在 settings.json 中添加以下内容来让 Zed 启用这些功能:
```json
{
"lsp": {
"solargraph": {
"initialization_options": {
"diagnostics": true,
"formatting": true
}
}
}
}
```
#### 配置说明
Solargraph 会从项目根目录下的 .solargraph.yml 文件读取配置。有关该文件的更多信息,请参阅 Solargraph 配置文档。
### 配置 ruby-lsp
你可以将 Ruby LSP 配置传入 initialization_options,例如:
{
"languages": {
"Ruby": {
"language_servers": ["ruby-lsp", "!solargraph", "..."]
}
},
"lsp": {
"ruby-lsp": {
"initialization_options": {
"enabledFeatures": {
// "someFeature": false
}
}
}
}
}
完整的配置选项请参考 Ruby LSP 网站。
LSP 的 settings 和 initialization_options 也可以针对特定项目设置。例如,若要在某个特定项目中将 standardrb/standard 用作格式化器和代码检查器,请在项目仓库中的 .zed/settings.json 里添加以下内容:
{
"lsp": {
"ruby-lsp": {
"initialization_options": {
"formatter": "standard",
"linters": ["standard"]
}
}
}
}
配置 rubocop LSP
Rubocop 默认禁用了不安全的自动修复功能。我们可以通过在 settings.json 中添加以下内容,让 Zed 启用该功能:
{
"languages": {
"Ruby": {
// 使用 ruby-lsp 作为主要语言服务器,rubocop 作为次要。
"language_servers": ["ruby-lsp", "rubocop", "!solargraph", "..."]
}
},
"lsp": {
"rubocop": {
"initialization_options": {
"safeAutocorrect": false
}
},
"ruby-lsp": {
"initialization_options": {
"enabledFeatures": {
"diagnostics": false
}
}
}
}
}
配置 Sorbet
Sorbet 是 Ruby 中一款流行的静态类型检查器,并附带语言服务器。
要启用 Sorbet,在 Ruby 的 language_servers 列表中添加 \"sorbet\"。如果 Sorbet 是你的主力 LSP,或者你打算将它与另一个 LSP 搭配使用(比如只用后者做类型检查等特定功能),可能需要禁用其他语言服务器。
在设置({#kb zed::OpenSettings})中的 Languages > Ruby 下配置语言服务器,或在设置文件中添加:
{
"languages": {
"Ruby": {
"language_servers": [
"ruby-lsp",
"sorbet",
"!rubocop",
"!solargraph",
"..."
]
}
}
}
关于 Sorbet 的安装、项目配置以及行为设置等所有内容,请参阅 Sorbet 官方文档。
配置 Steep
Steep 是 Ruby 的静态类型检查器,通过 RBS 文件定义类型。
要启用 Steep,在 Ruby 的 language_servers 列表中添加 \"steep\"。根据你的实际需求,可能需要调整顺序或禁用其他 LSP。
在设置({#kb zed::OpenSettings})中的 Languages > Ruby 下配置语言服务器,或在设置文件中添加:
{
"languages": {
"Ruby": {
"language_servers": [
"ruby-lsp",
"steep",
"!solargraph",
"!rubocop",
"..."
]
}
}
}
配置 Herb
对于 HTML+ERB 语言,Herb 默认已启用。
在 Ruby 中使用 Tailwind CSS 语言服务器
要想在 Ruby/ERB 文件中获得 Tailwind CSS 语言服务器的全部功能(自动补全、lint 检查等),需要配置该语言服务器,让它知道去哪里查找 CSS 类名。在 settings.json 中添加以下内容:
{
"lsp": {
"tailwindcss-language-server": {
"settings": {
"experimental": {
"classRegex": ["\\bclass:\\s*['\"]([^'\"]*)['\"]"]
}
}
}
}
}
配置这些选项后,你可以在 ERB 文件的 HTML 属性中,以及紧跟在 class: 键之后的 Ruby/ERB 字符串中,获得 Tailwind CSS 类的自动补全。示例:
# Ruby 文件:
def method
div(class: "pl-2 <此处补全>") do
p(class: "mt-2 <此处补全>") { "Hello World" }
end
end
# ERB 文件:
<%= link_to "Hello", "/hello", class: "pl-2 <此处补全>" %>
<a href="/hello" class="pl-2 <此处补全>">Hello</a>
运行测试
要在 Ruby 项目中运行测试,你可以在本地的 .zed/tasks.json 配置文件中设置自定义任务。这些任务可以针对不同的测试框架进行定义,例如 Minitest、RSpec、quickdraw 和 tldr。以下是一些示例,展示了如何设置这些任务以便在编辑器内运行测试。
Rails 环境下的 Minitest
[
{
"label": "test $ZED_RELATIVE_FILE -n /$ZED_CUSTOM_RUBY_TEST_NAME/",
"command": "bin/rails",
"args": [
"test",
"$ZED_RELATIVE_FILE",
"-n",
"\"$ZED_CUSTOM_RUBY_TEST_NAME\""
],
"cwd": "$ZED_WORKTREE_ROOT",
"tags": ["ruby-test"]
}
]
Minitest
纯 Minitest 不支持按行号运行测试,只能按名称运行,因此我们需要使用 $ZED_CUSTOM_RUBY_TEST_NAME:
[
{
"label": "-Itest $ZED_RELATIVE_FILE -n /$ZED_CUSTOM_RUBY_TEST_NAME/",
"command": "bundle",
"args": [
"exec",
"ruby",
"-Itest",
"$ZED_RELATIVE_FILE",
"-n",
"\"$ZED_CUSTOM_RUBY_TEST_NAME\""
],
"cwd": "$ZED_WORKTREE_ROOT",
"tags": ["ruby-test"]
}
]
RSpec
[
{
"label": "test $ZED_RELATIVE_FILE:$ZED_ROW",
"command": "bundle",
"args": ["exec", "rspec", "\"$ZED_RELATIVE_FILE:$ZED_ROW\""],
"cwd": "$ZED_WORKTREE_ROOT",
"tags": ["ruby-test"]
}
]
相同的任务语法也适用于其他测试框架,例如 quickdraw 或 tldr。
调试
Ruby 扩展提供调试适配器,用于调试 Ruby 代码。该适配器在 Zed 中的名称(在 UI 和 debug.json 中)为 rdbg,底层使用了 debug gem。该扩展使用的激活逻辑与语言服务器相同。
示例
调试 Ruby 脚本
[
{
"label": "Debug current file",
"adapter": "rdbg",
"request": "launch",
"script": "$ZED_FILE",
"cwd": "$ZED_WORKTREE_ROOT"
}
]
调试 Rails 服务器
[
{
"label": "Debug Rails server",
"adapter": "rdbg",
"request": "launch",
"command": "./bin/rails",
"args": ["server"],
"cwd": "$ZED_WORKTREE_ROOT",
"env": {
"RUBY_DEBUG_OPEN": "true"
}
}
]
格式化器
erb-formatter
要格式化 ERB 模板,可以使用 erb-formatter 格式化器。该格式化器使用 erb-formatter gem 来格式化 ERB 模板。
在设置中({#kb zed::OpenSettings})的 Languages > HTML+ERB 下配置格式化,或在设置文件中添加:
{
"languages": {
"HTML+ERB": {
"formatter": {
"external": {
"command": "erb-formatter",
"arguments": ["--stdin-filename", "{buffer_path}"]
}
}
}
}
}