Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pop open the terminal and run UCM if we dont find it #7

Merged
merged 9 commits into from
Nov 7, 2022
14 changes: 13 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"displayName": "Unison Language",
"publisher": "unison-lang",
"description": "Official extension for unison language support",
"version": "0.0.7",
"version": "0.0.8",
"icon": "images/unison.png",
"main": "./out/main.js",
"engines": {
Expand Down Expand Up @@ -67,6 +67,18 @@
],
"default": "off",
"description": "Traces the communication between VSCode and the language server."
},
"unison.automaticallyOpenUCM": {
"scope": "window",
"type": "boolean",
"default": true,
"description": "Automatically open an embedded terminal and start UCM if no existing UCM session is detected."
},
"unison.ucmCommand": {
"scope": "window",
"type": "string",
"default": "ucm",
"description": "Which command to run when automatically opening ucm in a terminal."
}
}
}
Expand Down
35 changes: 29 additions & 6 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ import { connect } from "node:net";

const outputChannel: OutputChannel = window.createOutputChannel("Unison");
const clients: Map<string, LanguageClient> = new Map();
// This is global mutable state so that when the extension host gets restarted after
// the terminal is closed, we don't immediately open another one.
let shouldOpenTerminal = true;

function log(msg: string) {
outputChannel.appendLine(msg)
outputChannel.appendLine(msg);
}

exports.activate = function () {
Expand All @@ -31,7 +34,7 @@ async function addWorkspaceFolder(workspaceFolder: WorkspaceFolder) {
documentSelector: [{ language: "unison" }],
});

log(`Activating unison language server at ${folderPath}`)
log(`Activating unison language server at ${folderPath}`);
clients.set(folderPath, client);
await client.start();
}
Expand All @@ -40,7 +43,7 @@ async function removeWorkspaceFolder(workspaceFolder: WorkspaceFolder) {
let folderPath = workspaceFolder.uri.fsPath;
let client = clients.get(folderPath);
if (client) {
log(`Deactivating unison language server at ${folderPath}`)
log(`Deactivating unison language server at ${folderPath}`);
clients.delete(folderPath);
await client.stop();
}
Expand All @@ -52,15 +55,19 @@ async function sleep(ms: number): Promise<void> {

async function connectToServer() {
let haveShownError = false;

while (true) {
try {
const host = "127.0.0.1";
const port = workspace.getConfiguration("unison").lspPort;

log(`Trying to connect to ucm lsp server at ${host}:${port}`);
let socket = connect({ port, host: "127.0.0.1" });
await new Promise((resolve, reject) =>
socket.once("connect", resolve).once("error", reject)
);

shouldOpenTerminal = false;
// Show a success message, but only if we were in an error state
const okMsg = `Unison: Connected to Language Server at ${host}:${port}.`;
log(okMsg);
Expand All @@ -70,10 +77,26 @@ async function connectToServer() {
return { reader: socket, writer: socket };
} catch (e) {
const errMsg = "Language server failed to connect";
log(`${errMsg}, cause: ${e}`)
if (!haveShownError) {
log(`${errMsg}, cause: ${e}`);

// Only ever try to open the terminal once, so we don't get stuck in weird loops
// or in a strange state if the user tries to quit UCM or close the terminal.
if (
shouldOpenTerminal &&
workspace.getConfiguration("unison").automaticallyOpenUCM
) {
let ucmCommand = workspace.getConfiguration("unison").ucmCommand;
shouldOpenTerminal = false;
log("Opening ucm terminal");
// Start up a new terminal in the IDE, tell it to run UCM, and then show it.
const terminal = window.createTerminal();
terminal.sendText(ucmCommand);
terminal.show();
} else if (!haveShownError) {
haveShownError = true;
window.showErrorMessage(`Unison: ${errMsg}, is there a UCM running? (version M4a or later)`);
window.showErrorMessage(
`Unison: ${errMsg}, is there a UCM running? (version M4a or later)`
);
}
await sleep(2000);
continue;
Expand Down