From 8c418dc7992c470bb4e181d10255f060b8543223 Mon Sep 17 00:00:00 2001 From: Dominik Jain Date: Thu, 2 Jul 2026 16:11:59 +0200 Subject: [PATCH] Support ls_base_cmd in LanguageServerDependencyProviderBaseCommand ls_base_cmd allows the user to override the base command with a multi-element command (e.g. ["npx", "-y", "/my/local/package"]), generalising ls_path, which it takes precedence over. --- CHANGELOG.md | 2 +- docs/02-usage/050_configuration.md | 16 ++++++++-------- src/solidlsp/ls.py | 17 ++++++++++++----- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c616bbea..02c78676 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,7 +59,7 @@ Status of the `main` branch. Changes prior to the next official version change w - Improve quoting of arguments in shell executions - Add **LaTeX** support (experimental) via [texlab](https://github.com/latex-lsp/texlab). - PHP: add support for PHPantom as alternative to the already supported PHP LS #1554. - - Add new launch command customization options: `ls_args`, `ls_extra_args` + - Add new launch command customization options: `ls_args`, `ls_extra_args` and `ls_base_cmd` * JetBrains: - Add configuration option `jetbrains_launch_command`, allowing Serena to spawn IDE instances automatically diff --git a/docs/02-usage/050_configuration.md b/docs/02-usage/050_configuration.md index ee00ea57..c69faaaf 100644 --- a/docs/02-usage/050_configuration.md +++ b/docs/02-usage/050_configuration.md @@ -222,15 +222,15 @@ Most of Serena's language servers construct the command that launches the langua a *base command* or a *core dependency*. For these language servers, the following settings can be used to customize the launch command: -| Setting | Description | -|------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `ls_path` (string) | overrides the path of the language server's core dependency (e.g. its executable or a JAR file). Use this if you have installed the language server yourself and want Serena to use your installation instead of its managed installation. | -| `ls_args` (list) | overrides the internal command construction completely and simply adds `ls_args` to the base command | -| `ls_extra_args` (list) | a list of additional arguments to append to the launch command | +| Setting | Description | +|--------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `ls_path` (string) or `ls_base_cmd` (list) | overrides the path of the language server's core dependency (`ls_path`), e.g. its executable or a JAR file, or a base command for its execution (`ls_base_cmd`), e.g. `["npx", "-y", "/my/local/package"]`. Use this if you have installed the language server yourself and want Serena to use your installation instead of its managed installation. | +| `ls_args` (list) | overrides the internal command construction completely and simply adds `ls_args` to the base command | +| `ls_extra_args` (list) | a list of additional arguments to append to the launch command | * If you set `ls_args`, the internal command construction (which may do more than to append arguments to a base command) is bypassed. - You can define the full launch command by providing both `ls_path` and `ls_args`. -* If `ls_args` is not set, the internal command construction (which sets default arguments) is applied, and you can use `ls_path` to override the path of the core dependency. + You can define the full launch command by providing both `ls_path`/`ls_base_cmd` and `ls_args`. +* If `ls_args` is not set, the internal command construction (which sets default arguments) is applied, and you can use `ls_path` or `ls_base_cmd` to override the path of the core dependency/the base command. * `ls_extra_args` is always appended to the end of the launch command. Example: @@ -243,7 +243,7 @@ ls_specific_settings: ``` These settings are supported by all language servers whose dependency provider derives from -`LanguageServerDependencyProviderBaseCommand`, and `ls_path` is additionally exposed by some wrappers explicitly. +`LanguageServerDependencyProviderBaseCommand`, and `ls_path` is additionally exposed by some implementations explicitly. Common examples include: `ansible`, `bash`, `bsl`, `clojure`, `cpp`, `cpp_ccls`, `hlsl`, `html`, `kotlin`, `lean4`, `luau`, `markdown`, `php`, `php_phpactor`, `python`, `rust`, `scss`, `solidity`, `systemverilog`, `toml`, `typescript`, and `yaml`. diff --git a/src/solidlsp/ls.py b/src/solidlsp/ls.py index 7b116419..a769a3b3 100644 --- a/src/solidlsp/ls.py +++ b/src/solidlsp/ls.py @@ -305,6 +305,7 @@ class LanguageServerDependencyProviderBaseCommand(LanguageServerDependencyProvid The user can configure aspects of the launch command in LS-specific settings: + * ``ls_base_cmd`: overrides the base command * ``ls_path``: overrides the path of the language server's core dependency (e.g. its executable or a JAR file), from which the base command is formed, bypassing Serena's managed installation * ``ls_args``: overrides the arguments that are added to the base command in order to form the launch command @@ -333,11 +334,17 @@ class LanguageServerDependencyProviderBaseCommand(LanguageServerDependencyProvid def create_launch_command(self) -> list[str]: # obtain base command - ls_path = self._custom_settings.get("ls_path", None) - if ls_path is not None: - base_command = [ls_path] - else: - base_command = self._create_default_base_command() + base_command = self._custom_settings.get("ls_base_cmd", None) + if base_command is not None and not isinstance(base_command, list): + log.warning("The 'ls_base_cmd' setting should be a list of strings. Ignoring the provided value: %s", base_command) + base_command = None + if base_command is None: + ls_path = self._custom_settings.get("ls_path", None) + if ls_path is not None: + base_command = [ls_path] + else: + # default case: base command is constructed by the provider implementation + base_command = self._create_default_base_command() # create launch command from base command ls_args = self._custom_settings.get("ls_args")