diff --git a/bundled/tool/lsp_server.py b/bundled/tool/lsp_server.py index 6abc0f8..50c6da8 100644 --- a/bundled/tool/lsp_server.py +++ b/bundled/tool/lsp_server.py @@ -289,6 +289,23 @@ def on_shutdown(_params: Optional[Any] = None) -> None: jsonrpc.shutdown_json_rpc() +def get_cwd(settings: dict, document: Optional[workspace.Document]) -> str: + """Returns the working directory for running the tool. + + Resolves ``${fileDirname}`` to the directory of the current document. + If no document is available, falls back to the workspace root. + + Examples of supported patterns: ``${fileDirname}``, ``${fileDirname}/subdir``. + """ + cwd = settings.get("cwd", settings["workspaceFS"]) + if "${fileDirname}" in cwd: + if document and document.path: + cwd = cwd.replace("${fileDirname}", os.path.dirname(document.path)) + else: + cwd = settings["workspaceFS"] + return cwd + + def _get_global_defaults(): return { "path": GLOBAL_SETTINGS.get("path", []), @@ -393,7 +410,8 @@ def _run_tool_on_document( settings = copy.deepcopy(_get_settings_by_document(document)) code_workspace = settings["workspaceFS"] - cwd = settings["cwd"] + # Pass document so get_cwd can resolve ${fileDirname} to this file's directory. + cwd = get_cwd(settings, document) use_path = False use_rpc = False @@ -498,7 +516,7 @@ def _run_tool(extra_args: Sequence[str]) -> utils.RunResult: settings = copy.deepcopy(_get_settings_by_document(None)) code_workspace = settings["workspaceFS"] - cwd = settings["workspaceFS"] + cwd = get_cwd(settings, None) use_path = False use_rpc = False diff --git a/package.json b/package.json index ffd3eea..bed4ceb 100644 --- a/package.json +++ b/package.json @@ -64,6 +64,12 @@ "contributes": { "configuration": { "properties": { + ".cwd": { + "default": "${workspaceFolder}", + "description": "Sets the working directory for . Supported variables: `${workspaceFolder}` (workspace root) and `${fileDirname}` (directory of the current file).", + "scope": "resource", + "type": "string" + }, ".args": { "default": [], "description": "Arguments passed in. Each argument is a separate item in the array.", diff --git a/src/common/settings.ts b/src/common/settings.ts index 0259aff..2e59956 100644 --- a/src/common/settings.ts +++ b/src/common/settings.ts @@ -46,6 +46,11 @@ export function getInterpreterFromSetting(namespace: string, scope?: Configurati return config.get('interpreter'); } +function getCwd(config: WorkspaceConfiguration, workspace: WorkspaceFolder): string { + const cwd = config.get('cwd', '${workspaceFolder}'); + return resolveVariables([cwd], workspace)[0]; +} + export async function getWorkspaceSettings( namespace: string, workspace: WorkspaceFolder, @@ -62,7 +67,7 @@ export async function getWorkspaceSettings( } const workspaceSetting = { - cwd: workspace.uri.fsPath, + cwd: getCwd(config, workspace), workspace: workspace.uri.toString(), args: resolveVariables(config.get(`args`) ?? [], workspace), path: resolveVariables(config.get(`path`) ?? [], workspace), @@ -104,6 +109,7 @@ export async function getGlobalSettings(namespace: string, includeInterpreter?: export function checkIfConfigurationChanged(e: ConfigurationChangeEvent, namespace: string): boolean { const settings = [ `${namespace}.args`, + `${namespace}.cwd`, `${namespace}.path`, `${namespace}.interpreter`, `${namespace}.importStrategy`,