
## Summary [Internal design document](https://www.notion.so/astral-sh/In-editor-settings-19e48797e1ca807fa8c2c91b689d9070?pvs=4) This PR expands `ruff.configuration` to allow inline configuration directly in the editor. For example: ```json { "ruff.configuration": { "line-length": 100, "lint": { "unfixable": ["F401"], "flake8-tidy-imports": { "banned-api": { "typing.TypedDict": { "msg": "Use `typing_extensions.TypedDict` instead" } } } }, "format": { "quote-style": "single" } } } ``` This means that now `ruff.configuration` accepts either a path to configuration file or the raw config itself. It's _mostly_ similar to `--config` with one difference that's highlighted in the following section. So, it can be said that the format of `ruff.configuration` when provided the config map is same as the one on the [playground] [^1]. ## Limitations <details><summary><b>Casing (<code>kebab-case</code> v/s/ <code>camelCase</code>)</b></summary> <p> The config keys needs to be in `kebab-case` instead of `camelCase` which is being used for other settings in the editor. This could be a bit confusing. For example, the `line-length` option can be set directly via an editor setting or can be configured via `ruff.configuration`: ```json { "ruff.configuration": { "line-length": 100 }, "ruff.lineLength": 120 } ``` #### Possible solution We could use feature flag with [conditional compilation](https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute) to indicate that when used in `ruff_server`, we need the `Options` fields to be renamed as `camelCase` while for other crates it needs to be renamed as `kebab-case`. But, this might not work very easily because it will require wrapping the `Options` struct and create two structs in which we'll have to add `#[cfg_attr(...)]` because otherwise `serde` will complain: ``` error: duplicate serde attribute `rename_all` --> crates/ruff_workspace/src/options.rs:43:38 | 43 | #[cfg_attr(feature = "editor", serde(rename_all = "camelCase"))] | ^^^^^^^^^^ ``` </p> </details> <details><summary><b>Nesting (flat v/s nested keys)</b></summary> <p> This is the major difference between `--config` flag on the command-line v/s `ruff.configuration` and it makes it such that `ruff.configuration` has same value format as [playground] [^1]. The config keys needs to be split up into keys which can result in nested structure instead of flat structure: So, the following **won't work**: ```json { "ruff.configuration": { "format.quote-style": "single", "lint.flake8-tidy-imports.banned-api.\"typing.TypedDict\".msg": "Use `typing_extensions.TypedDict` instead" } } ``` But, instead it would need to be split up like the following: ```json { "ruff.configuration": { "format": { "quote-style": "single" }, "lint": { "flake8-tidy-imports": { "banned-api": { "typing.TypedDict": { "msg": "Use `typing_extensions.TypedDict` instead" } } } } } } ``` #### Possible solution (1) The way we could solve this and make it same as `--config` would be to add a manual logic of converting the JSON map into an equivalent TOML string which would be then parsed into `Options`. So, the following JSON map: ```json { "lint.flake8-tidy-imports": { "banned-api": {"\"typing.TypedDict\".msg": "Use typing_extensions.TypedDict instead"}}} ``` would need to be converted into the following TOML string: ```toml lint.flake8-tidy-imports = { banned-api = { "typing.TypedDict".msg = "Use typing_extensions.TypedDict instead" } } ``` by recursively convering `"key": value` into `key = value` which is to remove the quotes from key and replacing `:` with `=`. #### Possible solution (2) Another would be to just accept `Map<String, String>` strictly and convert it into `key = value` and then parse it as a TOML string. This would also match `--config` but quotes might become a nuisance because JSON only allows double quotes and so it'll require escaping any inner quotes or use single quotes. </p> </details> ## Test Plan ### VS Code **Requires https://github.com/astral-sh/ruff-vscode/pull/702** **`settings.json`**: ```json { "ruff.lint.extendSelect": ["TID"], "ruff.configuration": { "line-length": 50, "format": { "quote-style": "single" }, "lint": { "unfixable": ["F401"], "flake8-tidy-imports": { "banned-api": { "typing.TypedDict": { "msg": "Use `typing_extensions.TypedDict` instead" } } } } } } ``` Following video showcases me doing the following: 1. Check diagnostics that it includes `TID` 2. Run `Ruff: Fix all auto-fixable problems` to test `unfixable` 3. Run `Format: Document` to test `line-length` and `quote-style` https://github.com/user-attachments/assets/0a38176f-3fb0-4960-a213-73b2ea5b1180 ### Neovim **`init.lua`**: ```lua require('lspconfig').ruff.setup { init_options = { settings = { lint = { extendSelect = { 'TID' }, }, configuration = { ['line-length'] = 50, format = { ['quote-style'] = 'single', }, lint = { unfixable = { 'F401' }, ['flake8-tidy-imports'] = { ['banned-api'] = { ['typing.TypedDict'] = { msg = 'Use typing_extensions.TypedDict instead', }, }, }, }, }, }, }, } ``` Same steps as in the VS Code test: https://github.com/user-attachments/assets/cfe49a9b-9a89-43d7-94f2-7f565d6e3c9d ## Documentation Preview https://github.com/user-attachments/assets/e0062f58-6ec8-4e01-889d-fac76fd8b3c7 [playground]: https://play.ruff.rs [^1]: This has one advantage that the value can be copy-pasted directly into the playground
22 KiB
Settings
The Ruff Language Server provides a set of configuration options to customize its behavior
along with the ability to use an existing pyproject.toml
or ruff.toml
file to configure the
linter and formatter. This is done by providing these settings while initializing the server.
VS Code provides a UI to configure these settings, while other editors may require manual
configuration. The setup section provides instructions on where to place these settings
as per the editor.
Top-level
configuration
The configuration
setting allows you to configure editor-specific Ruff behavior. This can be done
in one of the following ways:
- Configuration file path: Specify the path to a
ruff.toml
orpyproject.toml
file that contains the configuration. User home directory and environment variables will be expanded. - Inline JSON configuration: Directly provide the configuration as a JSON object.
!!! note "Added in Ruff 0.9.8
"
The **Inline JSON configuration** option was introduced in Ruff `0.9.8`.
The default behavior, if configuration
is unset, is to load the settings from the project's
configuration (a ruff.toml
or pyproject.toml
in the project's directory), consistent with when
running Ruff on the command-line.
The configurationPreference
setting controls the precedence if both an
editor-provided configuration (configuration
) and a project level configuration file are present.
Resolution order {: #configuration_resolution_order }
In an editor, Ruff supports three sources of configuration, prioritized as follows (from highest to lowest):
- Specific settings: Individual settings like
lineLength
orlint.select
defined in the editor ruff.configuration
: Settings provided via theconfiguration
field (either a path to a configuration file or an inline configuration object)- Configuration file: Settings defined in a
ruff.toml
orpyproject.toml
file in the project's directory (if present)
For example, if the line length is specified in all three sources, Ruff will use the value from the
lineLength
setting.
Default value: null
Type: string
Example usage:
Using configuration file path:
=== "VS Code"
```json
{
"ruff.configuration": "~/path/to/ruff.toml"
}
```
=== "Neovim"
```lua
require('lspconfig').ruff.setup {
init_options = {
configuration = "~/path/to/ruff.toml"
}
}
```
=== "Zed"
```json
{
"lsp": {
"ruff": {
"initialization_options": {
"settings": {
"configuration": "~/path/to/ruff.toml"
}
}
}
}
}
```
Using inline configuration:
=== "VS Code"
```json
{
"ruff.configuration": {
"lint": {
"unfixable": ["F401"],
"extend-select": ["TID251"],
"flake8-tidy-imports": {
"banned-api": {
"typing.TypedDict": {
"msg": "Use `typing_extensions.TypedDict` instead",
}
}
}
},
"format": {
"quote-style": "single"
}
}
}
```
=== "Neovim"
```lua
require('lspconfig').ruff.setup {
init_options = {
configuration = {
lint = {
unfixable = {"F401"},
["extend-select"] = {"TID251"},
["flake8-tidy-imports"] = {
["banned-api"] = {
["typing.TypedDict"] = {
msg = "Use `typing_extensions.TypedDict` instead"
}
}
}
},
format = {
["quote-style"] = "single"
}
}
}
}
```
=== "Zed"
```json
{
"lsp": {
"ruff": {
"initialization_options": {
"settings": {
"configuration": {
"lint": {
"unfixable": ["F401"],
"extend-select": ["TID251"],
"flake8-tidy-imports": {
"banned-api": {
"typing.TypedDict": {
"msg": "Use `typing_extensions.TypedDict` instead"
}
}
}
},
"format": {
"quote-style": "single"
}
}
}
}
}
}
}
```
configurationPreference
The strategy to use when resolving settings across VS Code and the filesystem. By default, editor
configuration is prioritized over ruff.toml
and pyproject.toml
files.
"editorFirst"
: Editor settings take priority over configuration files present in the workspace."filesystemFirst"
: Configuration files present in the workspace takes priority over editor settings."editorOnly"
: Ignore configuration files entirely i.e., only use editor settings.
Default value: "editorFirst"
Type: "editorFirst" | "filesystemFirst" | "editorOnly"
Example usage:
=== "VS Code"
```json
{
"ruff.configurationPreference": "filesystemFirst"
}
```
=== "Neovim"
```lua
require('lspconfig').ruff.setup {
init_options = {
settings = {
configurationPreference = "filesystemFirst"
}
}
}
```
=== "Zed"
```json
{
"lsp": {
"ruff": {
"initialization_options": {
"settings": {
"configurationPreference": "filesystemFirst"
}
}
}
}
}
```
exclude
A list of file patterns to exclude from linting and formatting. See the documentation for more details.
Default value: null
Type: string[]
Example usage:
=== "VS Code"
```json
{
"ruff.exclude": ["**/tests/**"]
}
```
=== "Neovim"
```lua
require('lspconfig').ruff.setup {
init_options = {
settings = {
exclude = ["**/tests/**"]
}
}
}
```
=== "Zed"
```json
{
"lsp": {
"ruff": {
"initialization_options": {
"settings": {
"exclude": ["**/tests/**"]
}
}
}
}
}
```
lineLength
The line length to use for the linter and formatter.
Default value: null
Type: int
Example usage:
=== "VS Code"
```json
{
"ruff.lineLength": 100
}
```
=== "Neovim"
```lua
require('lspconfig').ruff.setup {
init_options = {
settings = {
lineLength = 100
}
}
}
```
=== "Zed"
```json
{
"lsp": {
"ruff": {
"initialization_options": {
"settings": {
"lineLength": 100
}
}
}
}
}
```
fixAll
Whether to register the server as capable of handling source.fixAll
code actions.
Default value: true
Type: bool
Example usage:
=== "VS Code"
```json
{
"ruff.fixAll": false
}
```
=== "Neovim"
```lua
require('lspconfig').ruff.setup {
init_options = {
settings = {
fixAll = false
}
}
}
```
=== "Zed"
```json
{
"lsp": {
"ruff": {
"initialization_options": {
"settings": {
"fixAll": false
}
}
}
}
}
```
organizeImports
Whether to register the server as capable of handling source.organizeImports
code actions.
Default value: true
Type: bool
Example usage:
=== "VS Code"
```json
{
"ruff.organizeImports": false
}
```
=== "Neovim"
```lua
require('lspconfig').ruff.setup {
init_options = {
settings = {
organizeImports = false
}
}
}
```
=== "Zed"
```json
{
"lsp": {
"ruff": {
"initialization_options": {
"settings": {
"organizeImports": false
}
}
}
}
}
```
showSyntaxErrors
New in Ruff v0.5.0
Whether to show syntax error diagnostics.
Default value: true
Type: bool
Example usage:
=== "VS Code"
```json
{
"ruff.showSyntaxErrors": false
}
```
=== "Neovim"
```lua
require('lspconfig').ruff.setup {
init_options = {
settings = {
showSyntaxErrors = false
}
}
}
```
=== "Zed"
```json
{
"lsp": {
"ruff": {
"initialization_options": {
"settings": {
"showSyntaxErrors": false
}
}
}
}
}
```
logLevel
The log level to use for the server.
Default value: "info"
Type: "trace" | "debug" | "info" | "warn" | "error"
Example usage:
=== "VS Code"
```json
{
"ruff.logLevel": "debug"
}
```
=== "Neovim"
```lua
require('lspconfig').ruff.setup {
init_options = {
settings = {
logLevel = "debug"
}
}
}
```
=== "Zed"
```json
{
"lsp": {
"ruff": {
"initialization_options": {
"settings": {
"logLevel": "debug"
}
}
}
}
}
```
logFile
Path to the log file to use for the server.
If not set, logs will be written to stderr.
Default value: null
Type: string
Example usage:
=== "VS Code"
```json
{
"ruff.logFile": "~/path/to/ruff.log"
}
```
=== "Neovim"
```lua
require('lspconfig').ruff.setup {
init_options = {
settings = {
logFile = "~/path/to/ruff.log"
}
}
}
```
=== "Zed"
```json
{
"lsp": {
"ruff": {
"initialization_options": {
"settings": {
"logFile": "~/path/to/ruff.log"
}
}
}
}
}
```
codeAction
Enable or disable code actions provided by the server.
disableRuleComment.enable
Whether to display Quick Fix actions to disable rules via noqa
suppression comments.
Default value: true
Type: bool
Example usage:
=== "VS Code"
```json
{
"ruff.codeAction.disableRuleComment.enable": false
}
```
=== "Neovim"
```lua
require('lspconfig').ruff.setup {
init_options = {
settings = {
codeAction = {
disableRuleComment = {
enable = false
}
}
}
}
}
```
=== "Zed"
```json
{
"lsp": {
"ruff": {
"initialization_options": {
"settings": {
"codeAction": {
"disableRuleComment": {
"enable": false
}
}
}
}
}
}
}
```
fixViolation.enable
Whether to display Quick Fix actions to autofix violations.
Default value: true
Type: bool
Example usage:
=== "VS Code"
```json
{
"ruff.codeAction.fixViolation.enable": false
}
```
=== "Neovim"
```lua
require('lspconfig').ruff.setup {
init_options = {
settings = {
codeAction = {
fixViolation = {
enable = false
}
}
}
}
}
```
=== "Zed"
```json
{
"lsp": {
"ruff": {
"initialization_options": {
"settings": {
"codeAction": {
"fixViolation": = {
"enable": false
}
}
}
}
}
}
}
```
lint
Settings specific to the Ruff linter.
enable
{: #lint_enable }
Whether to enable linting. Set to false
to use Ruff exclusively as a formatter.
Default value: true
Type: bool
Example usage:
=== "VS Code"
```json
{
"ruff.lint.enable": false
}
```
=== "Neovim"
```lua
require('lspconfig').ruff.setup {
init_options = {
settings = {
lint = {
enable = false
}
}
}
}
```
=== "Zed"
```json
{
"lsp": {
"ruff": {
"initialization_options": {
"settings": {
"lint": {
"enable": false
}
}
}
}
}
}
```
preview
{: #lint_preview }
Whether to enable Ruff's preview mode when linting.
Default value: null
Type: bool
Example usage:
=== "VS Code"
```json
{
"ruff.lint.preview": true
}
```
=== "Neovim"
```lua
require('lspconfig').ruff.setup {
init_options = {
settings = {
lint = {
preview = true
}
}
}
}
```
=== "Zed"
```json
{
"lsp": {
"ruff": {
"initialization_options": {
"settings": {
"lint": {
"preview": true
}
}
}
}
}
}
```
select
Rules to enable by default. See the documentation.
Default value: null
Type: string[]
Example usage:
=== "VS Code"
```json
{
"ruff.lint.select": ["E", "F"]
}
```
=== "Neovim"
```lua
require('lspconfig').ruff.setup {
init_options = {
settings = {
lint = {
select = {"E", "F"}
}
}
}
}
```
=== "Zed"
```json
{
"lsp": {
"ruff": {
"initialization_options": {
"settings": {
"lint": {
"select": ["E", "F"]
}
}
}
}
}
}
```
extendSelect
Rules to enable in addition to those in lint.select
.
Default value: null
Type: string[]
Example usage:
=== "VS Code"
```json
{
"ruff.lint.extendSelect": ["W"]
}
```
=== "Neovim"
```lua
require('lspconfig').ruff.setup {
init_options = {
settings = {
lint = {
extendSelect = {"W"}
}
}
}
}
```
=== "Zed"
```json
{
"lsp": {
"ruff": {
"initialization_options": {
"settings": {
"lint": {
"extendSelect": ["W"]
}
}
}
}
}
}
```
ignore
Rules to disable by default. See the documentation.
Default value: null
Type: string[]
Example usage:
=== "VS Code"
```json
{
"ruff.lint.ignore": ["E4", "E7"]
}
```
=== "Neovim"
```lua
require('lspconfig').ruff.setup {
init_options = {
settings = {
lint = {
ignore = {"E4", "E7"}
}
}
}
}
```
=== "Zed"
```json
{
"lsp": {
"ruff": {
"initialization_options": {
"settings": {
"lint": {
"ignore": ["E4", "E7"]
}
}
}
}
}
}
```
format
Settings specific to the Ruff formatter.
preview
{: #format_preview }
Whether to enable Ruff's preview mode when formatting.
Default value: null
Type: bool
Example usage:
=== "VS Code"
```json
{
"ruff.format.preview": true
}
```
=== "Neovim"
```lua
require('lspconfig').ruff.setup {
init_options = {
settings = {
format = {
preview = true
}
}
}
}
```
=== "Zed"
```json
{
"lsp": {
"ruff": {
"initialization_options": {
"settings": {
"format": {
"preview": true
}
}
}
}
}
}
```
VS Code specific
Additionally, the Ruff extension provides the following settings specific to VS Code. These settings are not used by the language server and are only relevant to the extension.
enable
Whether to enable the Ruff extension. Modifying this setting requires restarting VS Code to take effect.
Default value: true
Type: bool
Example usage:
{
"ruff.enable": false
}
format.args
!!! warning "Deprecated"
This setting is only used by [`ruff-lsp`](https://github.com/astral-sh/ruff-lsp) which is
deprecated in favor of the native language server. Refer to the [migration
guide](migration.md) for more information.
This setting is not used by the native language server.
Additional arguments to pass to the Ruff formatter.
Default value: []
Type: string[]
Example usage:
{
"ruff.format.args": ["--line-length", "100"]
}
ignoreStandardLibrary
!!! warning "Deprecated"
This setting is only used by [`ruff-lsp`](https://github.com/astral-sh/ruff-lsp) which is
deprecated in favor of the native language server. Refer to the [migration
guide](migration.md) for more information.
This setting is not used by the native language server.
Whether to ignore files that are inferred to be part of the Python standard library.
Default value: true
Type: bool
Example usage:
{
"ruff.ignoreStandardLibrary": false
}
importStrategy
Strategy for loading the ruff
executable.
fromEnvironment
finds Ruff in the environment, falling back to the bundled versionuseBundled
uses the version bundled with the extension
Default value: "fromEnvironment"
Type: "fromEnvironment" | "useBundled"
Example usage:
{
"ruff.importStrategy": "useBundled"
}
interpreter
A list of paths to Python interpreters. Even though this is a list, only the first interpreter is used.
This setting depends on the ruff.nativeServer
setting:
- If using the native server, the interpreter is used to find the
ruff
executable whenruff.importStrategy
is set tofromEnvironment
. - Otherwise, the interpreter is used to run the
ruff-lsp
server.
Default value: []
Type: string[]
Example usage:
{
"ruff.interpreter": ["/home/user/.local/bin/python"]
}
lint.args
!!! warning "Deprecated"
This setting is only used by [`ruff-lsp`](https://github.com/astral-sh/ruff-lsp) which is
deprecated in favor of the native language server. Refer to the [migration
guide](migration.md) for more information.
This setting is not used by the native language server.
Additional arguments to pass to the Ruff linter.
Default value: []
Type: string[]
Example usage:
{
"ruff.lint.args": ["--config", "/path/to/pyproject.toml"]
}
lint.run
!!! warning "Deprecated"
This setting is only used by [`ruff-lsp`](https://github.com/astral-sh/ruff-lsp) which is
deprecated in favor of the native language server. Refer to the [migration
guide](migration.md) for more information.
This setting is not used by the native language server.
Run Ruff on every keystroke (onType
) or on save (onSave
).
Default value: "onType"
Type: "onType" | "onSave"
Example usage:
{
"ruff.lint.run": "onSave"
}
nativeServer
Whether to use the native language server, ruff-lsp
or
automatically decide between the two based on the Ruff version and extension settings.
"on"
: Use the native language server. A warning will be displayed if deprecated settings are detected."off"
: Useruff-lsp
. A warning will be displayed if settings specific to the native server are detected."auto"
: Automatically select between the native language server andruff-lsp
based on the following conditions:true
: Same ason
false
: Same asoff
Default value: "auto"
Type: "on" | "off" | "auto" | true | false
Example usage:
{
"ruff.nativeServer": "on"
}
path
A list of path to ruff
executables.
The first executable in the list which is exists is used. This setting takes precedence over the
ruff.importStrategy
setting.
Default value: []
Type: string[]
Example usage:
{
"ruff.path": ["/home/user/.local/bin/ruff"]
}
showNotifications
!!! warning "Deprecated"
This setting is only used by [`ruff-lsp`](https://github.com/astral-sh/ruff-lsp) which is
deprecated in favor of the native language server. Refer to the [migration
guide](migration.md) for more information.
Setting to control when a notification is shown.
Default value: "off"
Type: "off" | "onError" | "onWarning" | "always"
Example usage:
{
"ruff.showNotifications": "onWarning"
}
trace.server
The trace level for the language server. Refer to the LSP specification for more information.
Default value: "off"
Type: "off" | "messages" | "verbose"
Example usage:
{
"ruff.trace.server": "messages"
}