diff --git a/book/src/languages.md b/book/src/languages.md index ea18e9c39..c69926583 100644 --- a/book/src/languages.md +++ b/book/src/languages.md @@ -142,6 +142,7 @@ These are the available options for a language server. | `config` | Language server initialization options | | `timeout` | The maximum time a request to the language server may take, in seconds. Defaults to `20` | | `environment` | Any environment variables that will be used when starting the language server `{ "KEY1" = "Value1", "KEY2" = "Value2" }` | +| `roots` | A set of marker files to look for when trying to find the workspace root. These apply befory `language.roots` | | `required-root-patterns` | A list of `glob` patterns to look for in the working directory. The language server is started if at least one of them is found. | A `format` sub-table within `config` can be used to pass extra formatting options to diff --git a/helix-core/src/syntax/config.rs b/helix-core/src/syntax/config.rs index 432611bb0..11d071c53 100644 --- a/helix-core/src/syntax/config.rs +++ b/helix-core/src/syntax/config.rs @@ -394,8 +394,7 @@ where #[serde(rename_all = "kebab-case")] pub struct LanguageServerConfiguration { pub command: String, - #[serde(default)] - #[serde(skip_serializing_if = "Vec::is_empty")] + #[serde(default, skip_serializing_if = "Vec::is_empty")] pub args: Vec, #[serde(default, skip_serializing_if = "HashMap::is_empty")] pub environment: HashMap, @@ -403,6 +402,8 @@ pub struct LanguageServerConfiguration { pub config: Option, #[serde(default = "default_timeout")] pub timeout: u64, + #[serde(default, skip_serializing_if = "Vec::is_empty")] + pub roots: Vec, #[serde( default, skip_serializing, diff --git a/helix-lsp/src/lib.rs b/helix-lsp/src/lib.rs index 567e8a702..cfae83d91 100644 --- a/helix-lsp/src/lib.rs +++ b/helix-lsp/src/lib.rs @@ -873,11 +873,17 @@ fn start_client( ) -> Result { let (workspace, workspace_is_cwd) = helix_loader::find_workspace(); let workspace = path::normalize(workspace); + let mut roots = config.roots.clone(); + if !ls_config.roots.is_empty() { + let mut ls_roots = ls_config.roots.clone(); + ls_roots.append(&mut roots); + roots = ls_roots; + }; let root = find_lsp_workspace( doc_path .and_then(|x| x.parent().and_then(|x| x.to_str())) .unwrap_or("."), - &config.roots, + &roots, config.workspace_lsp_roots.as_deref().unwrap_or(root_dirs), &workspace, workspace_is_cwd, diff --git a/languages.toml b/languages.toml index 50f02e191..481fe2538 100644 --- a/languages.toml +++ b/languages.toml @@ -93,7 +93,7 @@ prisma-language-server = { command = "prisma-language-server", args = ["--stdio" purescript-language-server = { command = "purescript-language-server", args = ["--stdio"] } pylsp = { command = "pylsp" } pyrefly = { command = "pyrefly", args = ["lsp"] } -pyright = { command = "pyright-langserver", args = ["--stdio"], config = {} } +pyright = { command = "pyright-langserver", args = ["--stdio"], config = {}, roots = ["pyrightconfig.json"] } protols = { command = "protols", args = [] } basedpyright = { command = "basedpyright-langserver", args = ["--stdio"], config = {} } pylyzer = { command = "pylyzer", args = ["--server"] } @@ -945,7 +945,7 @@ scope = "source.python" injection-regex = "py(thon)?" file-types = ["py", "pyi", "py3", "pyw", "ptl", "rpy", "cpy", "ipy", "pyt", { glob = ".python_history" }, { glob = ".pythonstartup" }, { glob = ".pythonrc" }, { glob = "*SConstruct" }, { glob = "*SConscript" }, { glob = "*sconstruct" }] shebangs = ["python", "uv"] -roots = ["pyproject.toml", "setup.py", "poetry.lock", "pyrightconfig.json"] +roots = ["pyproject.toml", "setup.py", "poetry.lock"] comment-token = "#" language-servers = ["ty", "ruff", "jedi", "pylsp"] # TODO: pyls needs utf-8 offsets