mirror of
https://github.com/astral-sh/ruff.git
synced 2025-07-15 17:15:10 +00:00

## Summary
Refer to the VS Code PR
(https://github.com/astral-sh/ruff-vscode/pull/659) for details on the
change.
This PR changes the following:
1. Add tracing span for both request (request id and method name) and
notification (method name) handler
2. Remove the `RUFF_TRACE` environment variable. This was being used to
turn on / off logging for the server
3. Similarly, remove reading the `trace` value from the initialization
options
4. Remove handling the `$/setTrace` notification
5. Remove the specialized `TraceLogWriter` used for Zed and VS Code
(https://github.com/astral-sh/ruff/pull/12564)
Regarding the (5) for the Zed editor, the reason that was implemented
was because there was no way of looking at the stderr messages in the
editor which has been changed. Now, it captures the stderr as part of
the "Server Logs".
(82492d74a8/crates/language_tools/src/lsp_log.rs (L548-L552)
)
### Question
Regarding (1), I think having just a simple trace level message should
be good for now as the spans are not hierarchical. This could be tackled
with #12744. The difference between the two:
<details><summary>Using <code>tracing::trace</code></summary>
<p>
```
0.019243416s DEBUG ThreadId(08) ruff_server::session::index::ruff_settings: Ignored path via `exclude`: /Users/dhruv/playground/ruff/.vscode
0.026398750s INFO main ruff_server::session::index: Registering workspace: /Users/dhruv/playground/ruff
0.026802125s TRACE ruff:main ruff_server::server::api: Received notification "textDocument/didOpen"
0.026930666s TRACE ruff:main ruff_server::server::api: Received notification "textDocument/didOpen"
0.026962333s TRACE ruff:main ruff_server::server::api: Received request "textDocument/diagnostic" (1)
0.027042875s TRACE ruff:main ruff_server::server::api: Received request "textDocument/diagnostic" (2)
0.027097500s TRACE ruff:main ruff_server::server::api: Received request "textDocument/codeAction" (3)
0.027107458s DEBUG ruff:worker:0 ruff_server::resolve: Included path via `include`: /Users/dhruv/playground/ruff/lsp/play.py
0.027123541s DEBUG ruff:worker:3 ruff_server::resolve: Included path via `include`: /Users/dhruv/playground/ruff/lsp/organize_imports.py
0.027514875s INFO ruff:main ruff_server::server: Configuration file watcher successfully registered
0.285689833s TRACE ruff:main ruff_server::server::api: Received request "textDocument/codeAction" (4)
45.741101666s TRACE ruff:main ruff_server::server::api: Received notification "textDocument/didClose"
47.108745500s TRACE ruff:main ruff_server::server::api: Received notification "textDocument/didOpen"
47.109802041s TRACE ruff:main ruff_server::server::api: Received request "textDocument/diagnostic" (5)
47.109926958s TRACE ruff:main ruff_server::server::api: Received request "textDocument/codeAction" (6)
47.110027791s DEBUG ruff:worker:6 ruff_server::resolve: Included path via `include`: /Users/dhruv/playground/ruff/lsp/play.py
51.863679125s TRACE ruff:main ruff_server::server::api: Received request "textDocument/hover" (7)
```
</p>
</details>
<details><summary>Using <code>tracing::trace_span</code></summary>
<p>
Only logging the enter event:
```
0.018638750s DEBUG ThreadId(11) ruff_server::session::index::ruff_settings: Ignored path via `exclude`: /Users/dhruv/playground/ruff/.vscode
0.025895791s INFO main ruff_server::session::index: Registering workspace: /Users/dhruv/playground/ruff
0.026378791s TRACE ruff:main notification{method="textDocument/didOpen"}: ruff_server::server::api: enter
0.026531208s TRACE ruff:main notification{method="textDocument/didOpen"}: ruff_server::server::api: enter
0.026567583s TRACE ruff:main request{id=1 method="textDocument/diagnostic"}: ruff_server::server::api: enter
0.026652541s TRACE ruff:main request{id=2 method="textDocument/diagnostic"}: ruff_server::server::api: enter
0.026711041s DEBUG ruff:worker:2 ruff_server::resolve: Included path via `include`: /Users/dhruv/playground/ruff/lsp/organize_imports.py
0.026729166s DEBUG ruff:worker:1 ruff_server::resolve: Included path via `include`: /Users/dhruv/playground/ruff/lsp/play.py
0.027023083s INFO ruff:main ruff_server::server: Configuration file watcher successfully registered
5.197554750s TRACE ruff:main notification{method="textDocument/didClose"}: ruff_server::server::api: enter
6.534458000s TRACE ruff:main notification{method="textDocument/didOpen"}: ruff_server::server::api: enter
6.535027958s TRACE ruff:main request{id=3 method="textDocument/diagnostic"}: ruff_server::server::api: enter
6.535271166s DEBUG ruff:worker:3 ruff_server::resolve: Included path via `include`: /Users/dhruv/playground/ruff/lsp/organize_imports.py
6.544240583s TRACE ruff:main request{id=4 method="textDocument/codeAction"}: ruff_server::server::api: enter
7.049692458s TRACE ruff:main request{id=5 method="textDocument/codeAction"}: ruff_server::server::api: enter
7.508142541s TRACE ruff:main request{id=6 method="textDocument/hover"}: ruff_server::server::api: enter
7.872421958s TRACE ruff:main request{id=7 method="textDocument/hover"}: ruff_server::server::api: enter
8.024498583s TRACE ruff:main request{id=8 method="textDocument/codeAction"}: ruff_server::server::api: enter
13.895063666s TRACE ruff:main request{id=9 method="textDocument/codeAction"}: ruff_server::server::api: enter
14.774706083s TRACE ruff:main request{id=10 method="textDocument/hover"}: ruff_server::server::api: enter
16.058918958s TRACE ruff:main notification{method="textDocument/didChange"}: ruff_server::server::api: enter
16.060562208s TRACE ruff:main request{id=11 method="textDocument/diagnostic"}: ruff_server::server::api: enter
16.061109083s DEBUG ruff:worker:8 ruff_server::resolve: Included path via `include`: /Users/dhruv/playground/ruff/lsp/play.py
21.561742875s TRACE ruff:main notification{method="textDocument/didChange"}: ruff_server::server::api: enter
21.563573791s TRACE ruff:main request{id=12 method="textDocument/diagnostic"}: ruff_server::server::api: enter
21.564206750s DEBUG ruff:worker:4 ruff_server::resolve: Included path via `include`: /Users/dhruv/playground/ruff/lsp/play.py
21.826691375s TRACE ruff:main request{id=13 method="textDocument/codeAction"}: ruff_server::server::api: enter
22.091080125s TRACE ruff:main request{id=14 method="textDocument/codeAction"}: ruff_server::server::api: enter
```
</p>
</details>
**Todo**
- [x] Update documentation (I'll be adding a troubleshooting section
under "Editors" as a follow-up which is for all editors)
- [x] Check for backwards compatibility. I don't think this should break
backwards compatibility as it's mainly targeted towards improving the
debugging experience.
~**Before I go on to updating the documentation, I'd appreciate initial
review on the chosen approach.**~
resolves: #14959
## Test Plan
Refer to the test plan in
https://github.com/astral-sh/ruff-vscode/pull/659.
Example logs at `debug` level:
```
0.010770083s DEBUG ThreadId(15) ruff_server::session::index::ruff_settings: Ignored path via `exclude`: /Users/dhruv/playground/ruff/.vscode
0.018101916s INFO main ruff_server::session::index: Registering workspace: /Users/dhruv/playground/ruff
0.018559916s DEBUG ruff:worker:4 ruff_server::resolve: Included path via `include`: /Users/dhruv/playground/ruff/lsp/play.py
0.018992375s INFO ruff:main ruff_server::server: Configuration file watcher successfully registered
23.408802375s DEBUG ruff:worker:11 ruff_server::resolve: Included path via `include`: /Users/dhruv/playground/ruff/lsp/play.py
24.329127416s DEBUG ruff:worker:6 ruff_server::resolve: Included path via `include`: /Users/dhruv/playground/ruff/lsp/play.py
```
Example logs at `trace` level:
```
0.010296375s DEBUG ThreadId(13) ruff_server::session::index::ruff_settings: Ignored path via `exclude`: /Users/dhruv/playground/ruff/.vscode
0.017422583s INFO main ruff_server::session::index: Registering workspace: /Users/dhruv/playground/ruff
0.018034458s TRACE ruff:main notification{method="textDocument/didOpen"}: ruff_server::server::api: enter
0.018199708s TRACE ruff:worker:0 request{id=1 method="textDocument/diagnostic"}: ruff_server::server::api: enter
0.018251167s DEBUG ruff:worker:0 request{id=1 method="textDocument/diagnostic"}: ruff_server::resolve: Included path via `include`: /Users/dhruv/playground/ruff/lsp/play.py
0.018528708s INFO ruff:main ruff_server::server: Configuration file watcher successfully registered
1.611798417s TRACE ruff:worker:1 request{id=2 method="textDocument/codeAction"}: ruff_server::server::api: enter
1.861757542s TRACE ruff:worker:4 request{id=3 method="textDocument/codeAction"}: ruff_server::server::api: enter
7.027361792s TRACE ruff:worker:2 request{id=4 method="textDocument/codeAction"}: ruff_server::server::api: enter
7.851361500s TRACE ruff:worker:5 request{id=5 method="textDocument/codeAction"}: ruff_server::server::api: enter
7.901690875s TRACE ruff:main notification{method="textDocument/didChange"}: ruff_server::server::api: enter
7.903063167s TRACE ruff:worker:10 request{id=6 method="textDocument/diagnostic"}: ruff_server::server::api: enter
7.903183500s DEBUG ruff:worker:10 request{id=6 method="textDocument/diagnostic"}: ruff_server::resolve: Included path via `include`: /Users/dhruv/playground/ruff/lsp/play.py
8.702385292s TRACE ruff:main notification{method="textDocument/didChange"}: ruff_server::server::api: enter
8.704106625s TRACE ruff:worker:3 request{id=7 method="textDocument/diagnostic"}: ruff_server::server::api: enter
8.704304875s DEBUG ruff:worker:3 request{id=7 method="textDocument/diagnostic"}: ruff_server::resolve: Included path via `include`: /Users/dhruv/playground/ruff/lsp/play.py
8.966853458s TRACE ruff:worker:9 request{id=8 method="textDocument/codeAction"}: ruff_server::server::api: enter
9.229622792s TRACE ruff:worker:6 request{id=9 method="textDocument/codeAction"}: ruff_server::server::api: enter
10.513111583s TRACE ruff:worker:7 request{id=10 method="textDocument/codeAction"}: ruff_server::server::api: enter
```
530 lines
16 KiB
Markdown
530 lines
16 KiB
Markdown
# Setup
|
|
|
|
We have specific setup instructions depending on your editor of choice. If you don't see your editor on this
|
|
list and would like a setup guide, please open an issue.
|
|
|
|
If you're transferring your configuration from [`ruff-lsp`](https://github.com/astral-sh/ruff-lsp),
|
|
regardless of editor, there are several settings which have changed or are no longer available. See
|
|
the [migration guide](./migration.md) for more.
|
|
|
|
!!! note
|
|
|
|
The setup instructions provided below are on a best-effort basis. If you encounter any issues
|
|
while setting up the Ruff in an editor, please [open an issue](https://github.com/astral-sh/ruff/issues/new)
|
|
for assistance and help in improving this documentation.
|
|
|
|
!!! tip
|
|
|
|
Regardless of the editor, it is recommended to disable the older language server
|
|
([`ruff-lsp`](https://github.com/astral-sh/ruff-lsp)) to prevent any conflicts.
|
|
|
|
## VS Code
|
|
|
|
Install the Ruff extension from the [VS Code
|
|
Marketplace](https://marketplace.visualstudio.com/items?itemName=charliermarsh.ruff). It is
|
|
recommended to have the Ruff extension version `2024.32.0` or later to get the best experience with
|
|
the Ruff Language Server.
|
|
|
|
For more documentation on the Ruff extension, refer to the
|
|
[README](https://github.com/astral-sh/ruff-vscode/blob/main/README.md) of the extension repository.
|
|
|
|
## Neovim
|
|
|
|
The [`nvim-lspconfig`](https://github.com/neovim/nvim-lspconfig) plugin can be used to configure the
|
|
Ruff Language Server in Neovim. To set it up, install
|
|
[`nvim-lspconfig`](https://github.com/neovim/nvim-lspconfig) plugin, set it up as per the
|
|
[configuration](https://github.com/neovim/nvim-lspconfig#configuration) documentation, and add the
|
|
following to your `init.lua`:
|
|
|
|
```lua
|
|
require('lspconfig').ruff.setup({
|
|
init_options = {
|
|
settings = {
|
|
-- Ruff language server settings go here
|
|
}
|
|
}
|
|
})
|
|
```
|
|
|
|
!!! note
|
|
|
|
If the installed version of `nvim-lspconfig` includes the changes from
|
|
[neovim/nvim-lspconfig@`70d1c2c`](https://github.com/neovim/nvim-lspconfig/commit/70d1c2c31a88af4b36019dc1551be16bffb8f9db),
|
|
you will need to use Ruff version `0.5.3` or later.
|
|
|
|
If you're using Ruff alongside another language server (like Pyright), you may want to defer to that
|
|
language server for certain capabilities, like [`textDocument/hover`](./features.md#hover):
|
|
|
|
```lua
|
|
vim.api.nvim_create_autocmd("LspAttach", {
|
|
group = vim.api.nvim_create_augroup('lsp_attach_disable_ruff_hover', { clear = true }),
|
|
callback = function(args)
|
|
local client = vim.lsp.get_client_by_id(args.data.client_id)
|
|
if client == nil then
|
|
return
|
|
end
|
|
if client.name == 'ruff' then
|
|
-- Disable hover in favor of Pyright
|
|
client.server_capabilities.hoverProvider = false
|
|
end
|
|
end,
|
|
desc = 'LSP: Disable hover capability from Ruff',
|
|
})
|
|
```
|
|
|
|
If you'd like to use Ruff exclusively for linting, formatting, and organizing imports, you can disable those
|
|
capabilities for Pyright:
|
|
|
|
```lua
|
|
require('lspconfig').pyright.setup {
|
|
settings = {
|
|
pyright = {
|
|
-- Using Ruff's import organizer
|
|
disableOrganizeImports = true,
|
|
},
|
|
python = {
|
|
analysis = {
|
|
-- Ignore all files for analysis to exclusively use Ruff for linting
|
|
ignore = { '*' },
|
|
},
|
|
},
|
|
},
|
|
}
|
|
```
|
|
|
|
By default, the log level for Ruff is set to `info`. To change the log level, you can set the
|
|
[`logLevel`](./settings.md#loglevel) setting:
|
|
|
|
```lua
|
|
require('lspconfig').ruff.setup {
|
|
init_options = {
|
|
settings = {
|
|
logLevel = 'debug',
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
By default, Ruff will write logs to stderr which will be available in Neovim's LSP client log file
|
|
(`:lua vim.print(vim.lsp.get_log_path())`). It's also possible to divert these logs to a separate
|
|
file with the [`logFile`](./settings.md#logfile) setting.
|
|
|
|
To view the trace logs between Neovim and Ruff, set the log level for Neovim's LSP client to `debug`:
|
|
|
|
```lua
|
|
vim.lsp.set_log_level('debug')
|
|
```
|
|
|
|
## Vim
|
|
|
|
The [`vim-lsp`](https://github.com/prabirshrestha/vim-lsp) plugin can be used to configure the Ruff Language Server in Vim.
|
|
To set it up, install [`vim-lsp`](https://github.com/prabirshrestha/vim-lsp) plugin and register the server using the following
|
|
in your `.vimrc`:
|
|
|
|
```vim
|
|
if executable('ruff')
|
|
au User lsp_setup call lsp#register_server({
|
|
\ 'name': 'ruff',
|
|
\ 'cmd': {server_info->['ruff', 'server']},
|
|
\ 'allowlist': ['python'],
|
|
\ 'workspace_config': {},
|
|
\ })
|
|
endif
|
|
```
|
|
|
|
See the `vim-lsp`
|
|
[documentation](https://github.com/prabirshrestha/vim-lsp/blob/master/doc/vim-lsp.txt) for more
|
|
details on how to configure the language server.
|
|
|
|
If you're using Ruff alongside another LSP (like Pyright), you may want to defer to that LSP for certain capabilities,
|
|
like [`textDocument/hover`](./features.md#hover) by adding the following to the function `s:on_lsp_buffer_enabled()`:
|
|
|
|
```vim
|
|
function! s:on_lsp_buffer_enabled() abort
|
|
" add your keybindings here (see https://github.com/prabirshrestha/vim-lsp?tab=readme-ov-file#registering-servers)
|
|
|
|
let l:capabilities = lsp#get_server_capabilities('ruff')
|
|
if !empty(l:capabilities)
|
|
let l:capabilities.hoverProvider = v:false
|
|
endif
|
|
endfunction
|
|
```
|
|
|
|
Ruff is also available as part of the [coc-pyright](https://github.com/fannheyward/coc-pyright)
|
|
extension for [coc.nvim](https://github.com/neoclide/coc.nvim).
|
|
|
|
<details>
|
|
<summary>With the <a href="https://github.com/dense-analysis/ale">ALE</a> plugin for Vim or Neovim.</summary>
|
|
|
|
```vim
|
|
" Linters
|
|
let g:ale_linters = { "python": ["ruff"] }
|
|
" Fixers
|
|
let g:ale_fixers = { "python": ["ruff", "ruff_format"] }
|
|
```
|
|
|
|
For the fixers, `ruff` will run `ruff check --fix` (to fix all auto-fixable problems) whereas
|
|
`ruff_format` will run `ruff format`.
|
|
|
|
</details>
|
|
|
|
<details>
|
|
<summary>Ruff can also be integrated via <a href="https://github.com/mattn/efm-langserver">efm language server</a> in just a few lines.</summary>
|
|
<br>
|
|
|
|
Following is an example config for efm to use Ruff for linting and formatting Python files:
|
|
|
|
```yaml
|
|
tools:
|
|
python-ruff:
|
|
lint-command: "ruff check --stdin-filename ${INPUT} --output-format concise --quiet -"
|
|
lint-stdin: true
|
|
lint-formats:
|
|
- "%f:%l:%c: %m"
|
|
format-command: "ruff format --stdin-filename ${INPUT} --quiet -"
|
|
format-stdin: true
|
|
```
|
|
|
|
</details>
|
|
|
|
<details>
|
|
<summary>With the <a href="https://github.com/stevearc/conform.nvim"><code>conform.nvim</code></a> plugin for Neovim.</summary>
|
|
<br>
|
|
|
|
```lua
|
|
require("conform").setup({
|
|
formatters_by_ft = {
|
|
python = {
|
|
-- To fix auto-fixable lint errors.
|
|
"ruff_fix",
|
|
-- To run the Ruff formatter.
|
|
"ruff_format",
|
|
-- To organize the imports.
|
|
"ruff_organize_imports",
|
|
},
|
|
},
|
|
})
|
|
```
|
|
|
|
</details>
|
|
|
|
<details>
|
|
<summary>With the <a href="https://github.com/mfussenegger/nvim-lint"><code>nvim-lint</code></a> plugin for Neovim.</summary>
|
|
|
|
```lua
|
|
require("lint").linters_by_ft = {
|
|
python = { "ruff" },
|
|
}
|
|
```
|
|
|
|
</details>
|
|
|
|
## Helix
|
|
|
|
Open the [language configuration file](https://docs.helix-editor.com/languages.html#languagestoml-files) for
|
|
Helix and add the language server as follows:
|
|
|
|
```toml
|
|
[language-server.ruff]
|
|
command = "ruff"
|
|
args = ["server"]
|
|
```
|
|
|
|
Then, you'll register the language server as the one to use with Python. If you don't already have a
|
|
language server registered to use with Python, add this to `languages.toml`:
|
|
|
|
```toml
|
|
[[language]]
|
|
name = "python"
|
|
language-servers = ["ruff"]
|
|
```
|
|
|
|
Otherwise, if you already have `language-servers` defined, you can simply add `"ruff"` to the list. For example,
|
|
if you already have `pylsp` as a language server, you can modify the language entry as follows:
|
|
|
|
```toml
|
|
[[language]]
|
|
name = "python"
|
|
language-servers = ["ruff", "pylsp"]
|
|
```
|
|
|
|
!!! note
|
|
|
|
Support for multiple language servers for a language is only available in Helix version
|
|
[`23.10`](https://github.com/helix-editor/helix/blob/master/CHANGELOG.md#2310-2023-10-24) and later.
|
|
|
|
If you want to, as an example, turn on auto-formatting, add `auto-format = true`:
|
|
|
|
```toml
|
|
[[language]]
|
|
name = "python"
|
|
language-servers = ["ruff", "pylsp"]
|
|
auto-format = true
|
|
```
|
|
|
|
See the [Helix documentation](https://docs.helix-editor.com/languages.html) for more settings you can use here.
|
|
|
|
You can pass settings into `ruff server` using `[language-server.ruff.config.settings]`. For example:
|
|
|
|
```toml
|
|
[language-server.ruff.config.settings]
|
|
lineLength = 80
|
|
|
|
[language-server.ruff.config.settings.lint]
|
|
select = ["E4", "E7"]
|
|
preview = false
|
|
|
|
[language-server.ruff.config.settings.format]
|
|
preview = true
|
|
```
|
|
|
|
By default, the log level for Ruff is set to `info`. To change the log level, you can set the
|
|
[`logLevel`](./settings.md#loglevel) setting:
|
|
|
|
```toml
|
|
[language-server.ruff]
|
|
command = "ruff"
|
|
args = ["server"]
|
|
|
|
[language-server.ruff.config.settings]
|
|
logLevel = "debug"
|
|
```
|
|
|
|
You can also divert Ruff's logs to a separate file with the [`logFile`](./settings.md#logfile) setting.
|
|
|
|
To view the trace logs between Helix and Ruff, pass in the `-v` (verbose) flag when starting Helix:
|
|
|
|
```sh
|
|
hx -v path/to/file.py
|
|
```
|
|
|
|
## Kate
|
|
|
|
1. Activate the [LSP Client plugin](https://docs.kde.org/stable5/en/kate/kate/plugins.html#kate-application-plugins).
|
|
1. Setup LSP Client [as desired](https://docs.kde.org/stable5/en/kate/kate/kate-application-plugin-lspclient.html).
|
|
1. Finally, add this to `Settings` -> `Configure Kate` -> `LSP Client` -> `User Server Settings`:
|
|
|
|
```json
|
|
{
|
|
"servers": {
|
|
"python": {
|
|
"command": ["ruff", "server"],
|
|
"url": "https://github.com/astral-sh/ruff",
|
|
"highlightingModeRegex": "^Python$",
|
|
"settings": {}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
See [LSP Client documentation](https://docs.kde.org/stable5/en/kate/kate/kate-application-plugin-lspclient.html) for more details
|
|
on how to configure the server from there.
|
|
|
|
!!! important
|
|
|
|
Kate's LSP Client plugin does not support multiple servers for the same language. As a
|
|
workaround, you can use the [`python-lsp-server`](https://github.com/python-lsp/python-lsp-server)
|
|
along with the [`python-lsp-ruff`](https://github.com/python-lsp/python-lsp-ruff) plugin to
|
|
use Ruff alongside another language server. Note that this setup won't use the [server settings](settings.md)
|
|
because the [`python-lsp-ruff`](https://github.com/python-lsp/python-lsp-ruff) plugin uses the
|
|
`ruff` executable and not the language server.
|
|
|
|
## Sublime Text
|
|
|
|
To use Ruff with Sublime Text, install Sublime Text's [LSP](https://github.com/sublimelsp/LSP)
|
|
and [LSP-ruff](https://github.com/sublimelsp/LSP-ruff) package.
|
|
|
|
## PyCharm
|
|
|
|
### Via External Tool
|
|
|
|
Ruff can be installed as an [External Tool](https://www.jetbrains.com/help/pycharm/configuring-third-party-tools.html)
|
|
in PyCharm. Open the Preferences pane, then navigate to "Tools", then "External Tools". From there,
|
|
add a new tool with the following configuration:
|
|
|
|

|
|
|
|
Ruff should then appear as a runnable action:
|
|
|
|

|
|
|
|
### Via third-party plugin
|
|
|
|
Ruff is also available as the [Ruff](https://plugins.jetbrains.com/plugin/20574-ruff) plugin on the
|
|
IntelliJ Marketplace (maintained by [@koxudaxi](https://github.com/koxudaxi)).
|
|
|
|
## Emacs
|
|
|
|
Ruff can be utilized as a language server via [`Eglot`](https://github.com/joaotavora/eglot), which is in Emacs's core.
|
|
To enable Ruff with automatic formatting on save, use the following configuration:
|
|
|
|
```elisp
|
|
(add-hook 'python-mode-hook 'eglot-ensure)
|
|
(with-eval-after-load 'eglot
|
|
(add-to-list 'eglot-server-programs
|
|
'(python-mode . ("ruff" "server")))
|
|
(add-hook 'after-save-hook 'eglot-format))
|
|
```
|
|
|
|
Ruff is available as [`flymake-ruff`](https://melpa.org/#/flymake-ruff) on MELPA:
|
|
|
|
```elisp
|
|
(require 'flymake-ruff)
|
|
(add-hook 'python-mode-hook #'flymake-ruff-load)
|
|
```
|
|
|
|
Ruff is also available as [`emacs-ruff-format`](https://github.com/scop/emacs-ruff-format):
|
|
|
|
```elisp
|
|
(require 'ruff-format)
|
|
(add-hook 'python-mode-hook 'ruff-format-on-save-mode)
|
|
```
|
|
|
|
Alternatively, it can be used via the [Apheleia](https://github.com/radian-software/apheleia) formatter library, by setting this configuration:
|
|
|
|
```emacs-lisp
|
|
;; Replace default (black) to use ruff for sorting import and formatting.
|
|
(setf (alist-get 'python-mode apheleia-mode-alist)
|
|
'(ruff-isort ruff))
|
|
(setf (alist-get 'python-ts-mode apheleia-mode-alist)
|
|
'(ruff-isort ruff))
|
|
```
|
|
|
|
## TextMate
|
|
|
|
Ruff is also available via the [`textmate2-ruff-linter`](https://github.com/vigo/textmate2-ruff-linter)
|
|
bundle for TextMate.
|
|
|
|
## Zed
|
|
|
|
Ruff is available as an extension for the Zed editor. To install it:
|
|
|
|
1. Open the command palette with `Cmd+Shift+P`
|
|
1. Search for "zed: extensions"
|
|
1. Search for "ruff" in the extensions list and click "Install"
|
|
|
|
To configure Zed to use the Ruff language server for Python files, add the following
|
|
to your `settings.json` file:
|
|
|
|
```json
|
|
{
|
|
"languages": {
|
|
"Python": {
|
|
"language_servers": ["ruff"]
|
|
// Or, if there are other language servers you want to use with Python
|
|
// "language_servers": ["pyright", "ruff"]
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
To configure the language server, you can provide the [server settings](settings.md)
|
|
under the [`lsp.ruff.initialization_options.settings`](https://zed.dev/docs/configuring-zed#lsp) key:
|
|
|
|
```json
|
|
{
|
|
"lsp": {
|
|
"ruff": {
|
|
"initialization_options": {
|
|
"settings": {
|
|
// Ruff server settings goes here
|
|
"lineLength": 80,
|
|
"lint": {
|
|
"extendSelect": ["I"],
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
!!! note
|
|
|
|
Support for multiple formatters for a given language is only available in Zed version
|
|
`0.146.0` and later.
|
|
|
|
You can configure Ruff to format Python code on-save by registering the Ruff formatter
|
|
and enabling the [`format_on_save`](https://zed.dev/docs/configuring-zed#format-on-save) setting:
|
|
|
|
=== "Zed 0.146.0+"
|
|
|
|
```json
|
|
{
|
|
"languages": {
|
|
"Python": {
|
|
"language_servers": ["ruff"],
|
|
"format_on_save": "on",
|
|
"formatter": [
|
|
{
|
|
"language_server": {
|
|
"name": "ruff"
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
You can configure Ruff to fix lint violations and/or organize imports on-save by enabling the
|
|
`source.fixAll.ruff` and `source.organizeImports.ruff` code actions respectively:
|
|
|
|
=== "Zed 0.146.0+"
|
|
|
|
```json
|
|
{
|
|
"languages": {
|
|
"Python": {
|
|
"language_servers": ["ruff"],
|
|
"format_on_save": "on",
|
|
"formatter": [
|
|
{
|
|
"code_actions": {
|
|
// Fix all auto-fixable lint violations
|
|
"source.fixAll.ruff": true,
|
|
// Organize imports
|
|
"source.organizeImports.ruff": true
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
Taken together, you can configure Ruff to format, fix, and organize imports on-save via the
|
|
following `settings.json`:
|
|
|
|
!!! note
|
|
|
|
For this configuration, it is important to use the correct order of the code action and
|
|
formatter language server settings. The code actions should be defined before the formatter to
|
|
ensure that the formatter takes care of any remaining style issues after the code actions have
|
|
been applied.
|
|
|
|
=== "Zed 0.146.0+"
|
|
|
|
```json
|
|
{
|
|
"languages": {
|
|
"Python": {
|
|
"language_servers": ["ruff"],
|
|
"format_on_save": "on",
|
|
"formatter": [
|
|
{
|
|
"code_actions": {
|
|
"source.organizeImports.ruff": true,
|
|
"source.fixAll.ruff": true
|
|
}
|
|
},
|
|
{
|
|
"language_server": {
|
|
"name": "ruff"
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
```
|