diff --git a/src/commands/newFile.ts b/src/commands/newFile.ts index 81e6adb7..c98c9bc2 100644 --- a/src/commands/newFile.ts +++ b/src/commands/newFile.ts @@ -247,7 +247,7 @@ export async function newFile(type: NewFileType): Promise { wsFolder = vscode.workspace.workspaceFolders[0]; } else { wsFolder = await vscode.window.showWorkspaceFolderPick({ - placeHolder: "Pick the workspace folder to create the file in.", + placeHolder: "Pick the workspace folder where you want to create the file", }); } if (!wsFolder) { diff --git a/src/commands/webSocketTerminal.ts b/src/commands/webSocketTerminal.ts index e0526ba0..614a1211 100644 --- a/src/commands/webSocketTerminal.ts +++ b/src/commands/webSocketTerminal.ts @@ -2,7 +2,7 @@ import * as vscode from "vscode"; import WebSocket = require("ws"); import { AtelierAPI } from "../api"; -import { connectionTarget, currentFile, handleError, notIsfs, outputChannel } from "../utils"; +import { connectionTarget, currentFile, getWsServerConnection, handleError, notIsfs, outputChannel } from "../utils"; import { config, iscIcon, resolveConnectionSpec } from "../extension"; const keys = { @@ -755,26 +755,6 @@ function terminalConfigForUri( }; } -async function workspaceUriForTerminal(throwErrors = false) { - let uri: vscode.Uri; - const workspaceFolders = vscode.workspace.workspaceFolders || []; - if (workspaceFolders.length == 0) { - reportError("Lite Terminal requires an open workspace.", throwErrors); - } else if (workspaceFolders.length == 1) { - // Use the current connection - uri = workspaceFolders[0].uri; - } else { - // Pick from the workspace folders - uri = ( - await vscode.window.showWorkspaceFolderPick({ - ignoreFocusOut: true, - placeHolder: "Pick the workspace folder to get server connection information from", - }) - )?.uri; - } - return uri; -} - export async function launchWebSocketTerminal(targetUri?: vscode.Uri): Promise { // Determine the server to connect to if (targetUri) { @@ -784,10 +764,9 @@ export async function launchWebSocketTerminal(targetUri?: vscode.Uri): Promise { // Determine the server connection to use - const uri: vscode.Uri = await workspaceUriForTerminal(true); + const uri: vscode.Uri = await getWsServerConnection("2023.2.0"); if (uri) { // Get the terminal configuration. Will throw if there's an error. const terminalOpts = terminalConfigForUri(new AtelierAPI(uri), uri, true); return new vscode.TerminalProfile(terminalOpts); - } else { - throw new Error("Lite Terminal requires a selected workspace folder."); + } else if (uri == undefined) { + throw new Error( + "Lite Terminal requires an active server connection to InterSystems IRIS version 2023.2 or above." + ); } } } diff --git a/src/extension.ts b/src/extension.ts index 8b42fa49..d226ced9 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -100,6 +100,7 @@ import { handleError, cspApps, otherDocExts, + getWsServerConnection, } from "./utils"; import { ObjectScriptDiagnosticProvider } from "./providers/ObjectScriptDiagnosticProvider"; import { DocumentLinkProvider } from "./providers/DocumentLinkProvider"; @@ -996,31 +997,14 @@ export async function activate(context: vscode.ExtensionContext): Promise { } if (!connectionUri) { // May need to ask the user - const workspaceFolders = vscode.workspace.workspaceFolders || []; - if (workspaceFolders.length == 0) { - vscode.window.showErrorMessage(`Attaching to a server process requires a workspace to be open.`, { - modal: true, - }); - return; - } - if (workspaceFolders.length == 1) { - connectionUri = workspaceFolders[0].uri; - } else { - // Pick from the workspace folders - connectionUri = ( - await vscode.window.showWorkspaceFolderPick({ - ignoreFocusOut: true, - placeHolder: "Pick the workspace folder to get server connection information from", - }) - )?.uri; - } + connectionUri = await getWsServerConnection(); } if (!connectionUri) { return; } const api = new AtelierAPI(connectionUri); if (!api.active) { - vscode.window.showErrorMessage(`No active server connection.`, { + vscode.window.showErrorMessage(`Server connection is inactive.`, { modal: true, }); return; @@ -1489,7 +1473,9 @@ export async function activate(context: vscode.ExtensionContext): Promise { wsFolder = workspaceFolders[0]; } else if (workspaceFolders.length > 1) { // Pick from the workspace folders - wsFolder = await vscode.window.showWorkspaceFolderPick(); + wsFolder = await vscode.window.showWorkspaceFolderPick({ + placeHolder: "Pick the workspace folder where you want to open a document", + }); } if (!wsFolder) return; const api = new AtelierAPI(wsFolder.uri); diff --git a/src/utils/index.ts b/src/utils/index.ts index bbe35b4c..f8c6f70c 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,6 +1,7 @@ import path = require("path"); import { exec } from "child_process"; import * as vscode from "vscode"; +import { lt } from "semver"; import { config, schemas, @@ -768,6 +769,53 @@ export function base64EncodeContent(content: Buffer): string[] { return result; } +interface ConnQPItem extends vscode.QuickPickItem { + uri: vscode.Uri; + ns: string; +} + +/** + * Prompt the user to pick an active server connection that's used in this workspace. + * Returns the uri of the workspace folder corresponding to the chosen connection. + * Returns `undefined` if there are no active server connections in this workspace, + * or if the user dismisses the QuickPick. If there is only one active server + * connection, that will be returned without prompting the user. + * + * @param minVersion Optional minimum server version to enforce, in semantic version form (20XX.Y.Z). + * @returns `undefined` if there were no suitable server connections and `null` if the + * user explicitly escaped from the QuickPick. + */ +export async function getWsServerConnection(minVersion?: string): Promise { + if (!vscode.workspace.workspaceFolders?.length) return; + const conns: ConnQPItem[] = []; + for (const wsFolder of vscode.workspace.workspaceFolders) { + const api = new AtelierAPI(wsFolder.uri); + if (!api.active) continue; + const config = api.config; + if (minVersion && lt(config.serverVersion, minVersion)) continue; + const conn = { + label: api.connInfo, + description: isUnauthenticated(config.username) ? "Unauthenticated" : config.username, + detail: `http${config.https ? "s" : ""}://${config.host}:${config.port}${config.pathPrefix}`, + uri: wsFolder.uri, + ns: api.ns, + }; + if (!conns.some((c) => c.detail == conn.detail && c.description == conn.description && c.ns == conn.ns)) + conns.push(conn); + } + if (!conns.length) return; + if (conns.length == 1) return conns[0].uri; + return vscode.window + .showQuickPick(conns, { + canPickMany: false, + ignoreFocusOut: true, + matchOnDescription: true, + matchOnDetail: true, + title: "Pick a server connection from the current workspace", + }) + .then((c) => c?.uri ?? null); +} + // --------------------------------------------------------------------- // Source: https://github.com/amsterdamharu/lib/blob/master/src/index.js