diff --git a/README.md b/README.md index f46946c..39f7c43 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,11 @@ There are several settings you can configure to customize the behavior of this e off Controls when notifications are shown by this extension. Accepted values are onError, onWarning, always and off. + + black-formatter.serverTransport + stdio + Selects the transport protocol to be used by the Black server. When set to stdio, the extension will use the standard input/output streams to communicate with the Black server. When set to pipe, the extension will use a named pipe (on Windows) or Unix Domain Socket (on Linux/Mac) to communicate with the Black server. The stdio transport protocol is the default and recommended option for most users. + diff --git a/package.json b/package.json index d96f77e..00484ce 100644 --- a/package.json +++ b/package.json @@ -155,6 +155,20 @@ ], "scope": "machine", "type": "string" + }, + "black-formatter.serverTransport": { + "default": "stdio", + "enum": [ + "stdio", + "pipe" + ], + "markdownDescription": "%settings.serverTransport.description%", + "markdownEnumDescriptions": [ + "%settings.serverTransport.stdio.description%", + "%settings.serverTransport.pipe.description%" + ], + "scope": "window", + "type": "string" } } }, diff --git a/package.nls.json b/package.nls.json index 98abc02..5a9cae6 100644 --- a/package.nls.json +++ b/package.nls.json @@ -8,6 +8,9 @@ "settings.importStrategy.useBundled.description": "Always use the bundled version of Black to format Python files.", "settings.importStrategy.fromEnvironment.description": "Use the Black binary from the selected Python environment. If the extension fails to find a valid Black binary, it will fallback to using the bundled version of Black.", "settings.interpreter.description": "Path to a Python executable or a command that will be used to launch the Black server and any subprocess. Accepts an array of a single or multiple strings. When set to `[]`, the extension will use the path to the selected Python interpreter. If passing a command, each argument should be provided as a separate string in the array.", + "settings.serverTransport.description": "Selects the transport protocol to be used by the Black server. When set to `stdio`, the extension will use the standard input/output streams to communicate with the Black server. When set to `pipe`, the extension will use a named pipe (on Windows) or Unix Domain Socket (on Linux/Mac) to communicate with the Black server. The `stdio` transport protocol is the default and recommended option for most users.", + "settings.serverTransport.stdio.description": "Use the standard input/output streams to communicate with the Black server.", + "settings.serverTransport.pipe.description": "Use a named pipe (on windows) and Unix Domain Socket (on linux/mac) to communicate with the Black server.", "settings.showNotifications.description": "Controls when notifications are shown by this extension.", "settings.showNotifications.off.description": "All notifications are turned off, any errors or warnings when formatting Python files are still available in the logs.", "settings.showNotifications.onError.description": "Notifications are shown only in the case of an error when formatting Python files.", diff --git a/src/common/server.ts b/src/common/server.ts index 6405fdd..6aaf453 100644 --- a/src/common/server.ts +++ b/src/common/server.ts @@ -14,7 +14,7 @@ import { import { DEBUG_SERVER_SCRIPT_PATH, SERVER_SCRIPT_PATH } from './constants'; import { traceError, traceInfo, traceVerbose } from './logging'; import { getDebuggerPath } from './python'; -import { getExtensionSettings, getGlobalSettings, ISettings } from './settings'; +import { getExtensionSettings, getGlobalSettings, getServerTransport, ISettings } from './settings'; import { getDocumentSelector, getLSClientTraceLevel } from './utilities'; import { updateStatus } from './status'; import { unregisterEmptyFormatter } from './nullFormatter'; @@ -29,7 +29,8 @@ async function createServer( initializationOptions: IInitOptions, ): Promise { const command = settings.interpreter[0]; - const cwd = settings.cwd === '${fileDirname}' ? Uri.parse(settings.workspace).fsPath : settings.cwd; + const workspaceUri = Uri.parse(settings.workspace); + const cwd = settings.cwd === '${fileDirname}' ? workspaceUri.fsPath : settings.cwd; // Set debugger path needed for debugging python code. const newEnv = { ...process.env }; @@ -57,7 +58,7 @@ async function createServer( command, args, options: { cwd, env: newEnv }, - transport: TransportKind.pipe, + transport: getServerTransport(serverId, workspaceUri), }; // Options to control the language client diff --git a/src/common/settings.ts b/src/common/settings.ts index e5d7580..f7e3a2c 100644 --- a/src/common/settings.ts +++ b/src/common/settings.ts @@ -1,11 +1,12 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import { ConfigurationChangeEvent, ConfigurationScope, WorkspaceConfiguration, WorkspaceFolder } from 'vscode'; +import { ConfigurationChangeEvent, ConfigurationScope, Uri, WorkspaceConfiguration, WorkspaceFolder } from 'vscode'; import { getInterpreterDetails } from './python'; import { getConfiguration, getWorkspaceFolders } from './vscodeapi'; import { traceInfo, traceLog, traceWarn } from './logging'; import { EXTENSION_ID } from './constants'; +import { TransportKind } from 'vscode-languageclient/node'; export interface ISettings { cwd: string; @@ -17,6 +18,12 @@ export interface ISettings { showNotifications: string; } +export function getServerTransport(namespace: string, uri: Uri): TransportKind { + const config = getConfiguration(namespace, uri); + const value = config.get('serverTransport', 'stdio'); + return value === 'pipe' ? TransportKind.pipe : TransportKind.stdio; +} + export function getExtensionSettings(namespace: string, includeInterpreter?: boolean): Promise { return Promise.all(getWorkspaceFolders().map((w) => getWorkspaceSettings(namespace, w, includeInterpreter))); } @@ -152,6 +159,7 @@ export function checkIfConfigurationChanged(e: ConfigurationChangeEvent, namespa `${namespace}.interpreter`, `${namespace}.importStrategy`, `${namespace}.showNotifications`, + `${namespace}.serverTransport`, ]; const changed = settings.map((s) => e.affectsConfiguration(s)); return changed.includes(true);