Skip to content

Commit fb94808

Browse files
Merge pull request intersystems-community#1156 from gjsjohnmurray/fix-WSTlaunchCommand
Make WebSocket Terminal launchable from Command Palette and Server Manager tree
2 parents d835d3e + 20c2135 commit fb94808

File tree

3 files changed

+87
-33
lines changed

3 files changed

+87
-33
lines changed

package.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@
9090
"onCommand:vscode-objectscript.modifyWsFolder",
9191
"onCommand:vscode-objectscript.openErrorLocation",
9292
"onCommand:vscode-objectscript.launchWebSocketTerminal",
93+
"onCommand:vscode-objectscript.intersystems-servermanager.webterminal",
9394
"onTerminalProfile:vscode-objectscript.webSocketTerminal",
9495
"onLanguage:objectscript",
9596
"onLanguage:objectscript-int",
@@ -98,6 +99,7 @@
9899
"onLanguage:xml",
99100
"onView:ObjectScriptExplorer",
100101
"onView:ObjectScriptProjectsExplorer",
102+
"onView:intersystems-community_servermanager",
101103
"onFileSystem:isfs",
102104
"onFileSystem:isfs-readonly",
103105
"onFileSystem:objectscript",
@@ -349,6 +351,10 @@
349351
{
350352
"command": "vscode-objectscript.launchWebSocketTerminal",
351353
"when": "vscode-objectscript.connectActive"
354+
},
355+
{
356+
"command": "vscode-objectscript.intersystems-servermanager.webterminal",
357+
"when": "false"
352358
}
353359
],
354360
"view/title": [
@@ -473,6 +479,11 @@
473479
"command": "vscode-objectscript.explorer.project.closeOtherServerNs",
474480
"when": "view == ObjectScriptProjectsExplorer && viewItem == projectsServerNsNode:extra",
475481
"group": "inline@10"
482+
},
483+
{
484+
"command": "vscode-objectscript.intersystems-servermanager.webterminal",
485+
"when": "view == intersystems-community_servermanager && viewItem =~ /namespace$/",
486+
"group": "inline@1"
476487
}
477488
],
478489
"editor/context": [
@@ -1130,6 +1141,11 @@
11301141
"category": "ObjectScript",
11311142
"command": "vscode-objectscript.launchWebSocketTerminal",
11321143
"title": "Launch WebSocket Terminal"
1144+
},
1145+
{
1146+
"command": "vscode-objectscript.intersystems-servermanager.webterminal",
1147+
"title": "Launch WebSocket Terminal",
1148+
"icon": "$(terminal)"
11331149
}
11341150
],
11351151
"keybindings": [

src/commands/webSocketTerminal.ts

Lines changed: 61 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ import * as vscode from "vscode";
22
import WebSocket = require("ws");
33

44
import { AtelierAPI } from "../api";
5-
import { currentFile, outputChannel } from "../utils";
5+
import { connectionTarget, currentFile, outputChannel } from "../utils";
6+
import { config, resolveConnectionSpec } from "../extension";
67

78
const keys = {
89
enter: "\r",
@@ -593,45 +594,87 @@ class WebSocketTerminal implements vscode.Pseudoterminal {
593594
}
594595
}
595596

597+
function reportError(msg: string, throwErrors = false) {
598+
if (throwErrors) {
599+
throw new Error(msg);
600+
} else {
601+
vscode.window.showErrorMessage(msg, "Dismiss");
602+
}
603+
}
604+
596605
function terminalConfigForUri(
597606
api: AtelierAPI,
598607
extensionUri: vscode.Uri,
608+
targetUri: vscode.Uri,
599609
throwErrors = false
600610
): vscode.ExtensionTerminalOptions | undefined {
601-
const reportError = (msg: string) => {
602-
if (throwErrors) {
603-
throw new Error(msg);
604-
} else {
605-
vscode.window.showErrorMessage(msg, "Dismiss");
606-
}
607-
};
608-
609611
// Make sure the server connection is active
610612
if (!api.active || api.ns == "") {
611-
reportError("WebSocket Terminal requires an active server connection.");
613+
reportError("WebSocket Terminal requires an active server connection.", throwErrors);
612614
return;
613615
}
614616
// Make sure the server has the terminal endpoint
615617
if (api.config.apiVersion < 7) {
616-
reportError("WebSocket Terminal requires InterSystems IRIS version 2023.2 or above.");
618+
reportError("WebSocket Terminal requires InterSystems IRIS version 2023.2 or above.", throwErrors);
617619
return;
618620
}
619621

620622
return {
621623
name: api.config.serverName && api.config.serverName != "" ? api.config.serverName : "iris",
622-
location: vscode.TerminalLocation.Panel,
624+
location:
625+
// Mimic what a built-in profile does. When it is the default and the Terminal tab is selected while empty,
626+
// a terminal is always created in the Panel.
627+
vscode.workspace.getConfiguration("terminal.integrated", targetUri).get("defaultLocation") === "editor" &&
628+
vscode.window.terminals.length > 0
629+
? vscode.TerminalLocation.Editor
630+
: vscode.TerminalLocation.Panel,
623631
pty: new WebSocketTerminal(api),
624632
isTransient: true,
625633
iconPath: vscode.Uri.joinPath(extensionUri, "images", "fileIcon.svg"),
626634
};
627635
}
628636

629-
export async function launchWebSocketTerminal(extensionUri: vscode.Uri): Promise<void> {
637+
async function workspaceUriForTerminal(throwErrors = false) {
638+
let uri: vscode.Uri;
639+
const workspaceFolders = vscode.workspace.workspaceFolders || [];
640+
if (workspaceFolders.length == 0) {
641+
reportError("WebSocket Terminal requires an open workspace.", throwErrors);
642+
} else if (workspaceFolders.length == 1) {
643+
// Use the current connection
644+
uri = workspaceFolders[0].uri;
645+
} else {
646+
// Pick from the workspace folders
647+
uri = (
648+
await vscode.window.showWorkspaceFolderPick({
649+
ignoreFocusOut: true,
650+
placeHolder: "Pick the workspace folder to get server connection information from",
651+
})
652+
)?.uri;
653+
}
654+
return uri;
655+
}
656+
657+
export async function launchWebSocketTerminal(extensionUri: vscode.Uri, targetUri?: vscode.Uri): Promise<void> {
630658
// Determine the server to connect to
631-
const api = new AtelierAPI(currentFile()?.uri);
659+
if (targetUri) {
660+
// Uri passed as command argument might be for a server we haven't yet resolve connection details such as password,
661+
// so make sure that happens now if needed
662+
const { configName } = connectionTarget(targetUri);
663+
const serverName = targetUri.scheme === "file" ? config("conn", configName).server : configName;
664+
await resolveConnectionSpec(serverName);
665+
} else {
666+
targetUri = currentFile()?.uri;
667+
if (!targetUri) {
668+
targetUri = await workspaceUriForTerminal();
669+
}
670+
}
671+
const api = new AtelierAPI(targetUri);
672+
673+
// Guarantee we know the apiVersion of the server
674+
await api.serverInfo();
632675

633676
// Get the terminal configuration
634-
const terminalOpts = terminalConfigForUri(api, extensionUri);
677+
const terminalOpts = terminalConfigForUri(api, extensionUri, targetUri);
635678
if (terminalOpts) {
636679
// Launch the terminal
637680
const terminal = vscode.window.createTerminal(terminalOpts);
@@ -642,28 +685,13 @@ export async function launchWebSocketTerminal(extensionUri: vscode.Uri): Promise
642685
export class WebSocketTerminalProfileProvider implements vscode.TerminalProfileProvider {
643686
constructor(private readonly _extensionUri: vscode.Uri) {}
644687

645-
async provideTerminalProfile(token: vscode.CancellationToken): Promise<vscode.TerminalProfile> {
688+
async provideTerminalProfile(_token: vscode.CancellationToken): Promise<vscode.TerminalProfile> {
646689
// Determine the server connection to use
647-
let uri: vscode.Uri;
648-
const workspaceFolders = vscode.workspace.workspaceFolders || [];
649-
if (workspaceFolders.length == 0) {
650-
throw new Error("WebSocket Terminal requires an open workspace.");
651-
} else if (workspaceFolders.length == 1) {
652-
// Use the current connection
653-
uri = workspaceFolders[0].uri;
654-
} else {
655-
// Pick from the workspace folders
656-
uri = (
657-
await vscode.window.showWorkspaceFolderPick({
658-
ignoreFocusOut: true,
659-
placeHolder: "Pick the workspace folder to get server connection information from",
660-
})
661-
)?.uri;
662-
}
690+
const uri: vscode.Uri = await workspaceUriForTerminal(true);
663691

664692
if (uri) {
665693
// Get the terminal configuration. Will throw if there's an error.
666-
const terminalOpts = terminalConfigForUri(new AtelierAPI(uri), this._extensionUri, true);
694+
const terminalOpts = terminalConfigForUri(new AtelierAPI(uri), this._extensionUri, uri, true);
667695
return new vscode.TerminalProfile(terminalOpts);
668696
} else {
669697
throw new Error("WebSocket Terminal requires a selected workspace folder.");

src/extension.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1309,6 +1309,16 @@ export async function activate(context: vscode.ExtensionContext): Promise<any> {
13091309
vscode.commands.registerCommand("vscode-objectscript.launchWebSocketTerminal", () =>
13101310
launchWebSocketTerminal(context.extensionUri)
13111311
),
1312+
vscode.commands.registerCommand(
1313+
"vscode-objectscript.intersystems-servermanager.webterminal",
1314+
(namespaceTreeItem) => {
1315+
const idArray = namespaceTreeItem.id.split(":");
1316+
const serverId = idArray[1];
1317+
const namespace = idArray[3];
1318+
const targetUri = vscode.Uri.from({ scheme: "isfs", authority: `${serverId}:${namespace}` });
1319+
launchWebSocketTerminal(context.extensionUri, targetUri);
1320+
}
1321+
),
13121322
vscode.window.registerTerminalProfileProvider(
13131323
"vscode-objectscript.webSocketTerminal",
13141324
new WebSocketTerminalProfileProvider(context.extensionUri)

0 commit comments

Comments
 (0)