consolidate and cleanup statusbar items (#345)

This commit is contained in:
Tyler Wilding 2024-03-15 01:40:30 -04:00 committed by GitHub
parent 31d22058f0
commit 92d168700e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 219 additions and 251 deletions

View file

@ -55,6 +55,14 @@
"command": "opengoal.switchFile", "command": "opengoal.switchFile",
"title": "OpenGOAL - Switch File" "title": "OpenGOAL - Switch File"
}, },
{
"command": "opengoal.openLogs",
"title": "OpenGOAL - Open Logs"
},
{
"command": "opengoal.decomp.openLogs",
"title": "OpenGOAL - Open Decompiler Logs"
},
{ {
"command": "opengoal.decomp.openMostRecentIRFile", "command": "opengoal.decomp.openMostRecentIRFile",
"title": "OpenGOAL - Open Recent IR2 File" "title": "OpenGOAL - Open Recent IR2 File"
@ -159,6 +167,10 @@
"command": "opengoal.lsp.restart", "command": "opengoal.lsp.restart",
"title": "OpenGOAL - LSP - Restart" "title": "OpenGOAL - LSP - Restart"
}, },
{
"command": "opengoal.lsp.openLogs",
"title": "OpenGOAL - LSP - Open Logs"
},
{ {
"command": "opengoal.nrepl.jackin", "command": "opengoal.nrepl.jackin",
"title": "OpenGOAL - nREPL - Jack-In" "title": "OpenGOAL - nREPL - Jack-In"
@ -216,6 +228,11 @@
"id": "opengoal-decomp", "id": "opengoal-decomp",
"title": "Decompilation", "title": "Decompilation",
"properties": { "properties": {
"opengoal.autoDecompilation": {
"type": "boolean",
"default": true,
"description": "Automatically active IR2 files"
},
"opengoal.eeManPagePath": { "opengoal.eeManPagePath": {
"type": [ "type": [
"string", "string",

View file

@ -16,7 +16,6 @@ export function getConfig() {
formatDecompilationOutput: configOptions.get<boolean>( formatDecompilationOutput: configOptions.get<boolean>(
"formatDecompilationOutput", "formatDecompilationOutput",
), ),
eeManPagePath: configOptions.get<string>("eeManPagePath"), eeManPagePath: configOptions.get<string>("eeManPagePath"),
vuManPagePath: configOptions.get<string>("vuManPagePath"), vuManPagePath: configOptions.get<string>("vuManPagePath"),
decompilerPath: configOptions.get<string>("decompilerPath"), decompilerPath: configOptions.get<string>("decompilerPath"),
@ -34,6 +33,7 @@ export function getConfig() {
"decompilerJak3ConfigVersion", "decompilerJak3ConfigVersion",
"ntsc_v1", "ntsc_v1",
), ),
autoDecompilation: configOptions.get<boolean>("autoDecompilation"),
colorsGoalGlobals: configOptions.get<string>("colors.goal.entity.global"), colorsGoalGlobals: configOptions.get<string>("colors.goal.entity.global"),
colorsGoalStorageControl: configOptions.get<string>( colorsGoalStorageControl: configOptions.get<string>(
"colors.goal.storage.control", "colors.goal.storage.control",
@ -60,6 +60,15 @@ export function getConfig() {
}; };
} }
export async function updateAutoDecompilation(val: boolean) {
const userConfig = vscode.workspace.getConfiguration();
await userConfig.update(
"opengoal.autoDecompilation",
val,
vscode.ConfigurationTarget.Global,
);
}
export async function updateEeManPagePath(path: string) { export async function updateEeManPagePath(path: string) {
const userConfig = vscode.workspace.getConfiguration(); const userConfig = vscode.workspace.getConfiguration();
await userConfig.update( await userConfig.update(

View file

@ -3,19 +3,35 @@
import * as vscode from "vscode"; import * as vscode from "vscode";
import { RecentFiles } from "./RecentFiles"; import { RecentFiles } from "./RecentFiles";
import { getWorkspaceFolderByName } from "./utils/workspace"; import { getWorkspaceFolderByName } from "./utils/workspace";
import { getConfig } from "./config/config";
import { isJackedIn } from "./tools/opengoal/nrepl/opengoal-nrepl";
import { getLspStatus } from "./lsp/main";
const channel = vscode.window.createOutputChannel("OpenGOAL"); const channel = vscode.window.createOutputChannel("OpenGOAL");
let extensionContext: vscode.ExtensionContext; let extensionContext: vscode.ExtensionContext;
let recentFiles: RecentFiles; let recentFiles: RecentFiles;
let projectRoot: vscode.Uri | undefined = undefined; let projectRoot: vscode.Uri | undefined = undefined;
let extensionStatus: vscode.StatusBarItem;
export function initContext(extContext: vscode.ExtensionContext) { export function initContext(extContext: vscode.ExtensionContext) {
extensionContext = extContext; extensionContext = extContext;
extensionStatus = vscode.window.createStatusBarItem(
vscode.StatusBarAlignment.Left,
0,
);
updateStatusBar(false, false);
recentFiles = new RecentFiles(extensionContext); recentFiles = new RecentFiles(extensionContext);
if (vscode.window.activeTextEditor?.document != undefined) { if (vscode.window.activeTextEditor?.document != undefined) {
recentFiles.addFile(vscode.window.activeTextEditor?.document.fileName); recentFiles.addFile(vscode.window.activeTextEditor?.document.fileName);
} }
// Commands
extensionContext.subscriptions.push(
vscode.commands.registerCommand("opengoal.openLogs", () => {
channel.show();
}),
);
} }
export function getRecentFiles() { export function getRecentFiles() {
@ -43,3 +59,89 @@ export function getProjectRoot(): vscode.Uri {
} }
return projectRoot; return projectRoot;
} }
export function updateStatusBar(
workInProgress: boolean,
errorOccurred: boolean,
text?: string,
): void {
let statusIcon = "";
const statusItem = extensionStatus;
statusItem.show();
statusItem.tooltip = new vscode.MarkdownString("", true);
statusItem.tooltip.isTrusted = true;
if (errorOccurred) {
statusIcon = "$(testing-error-icon) ";
} else if (workInProgress) {
statusIcon = "$(loading~spin) ";
}
if (errorOccurred) {
statusItem.backgroundColor = new vscode.ThemeColor(
"statusBarItem.errorForeground",
);
} else {
statusItem.backgroundColor = undefined;
}
statusItem.command = "opengoal.openLogs";
if (text) {
statusItem.text = `${statusIcon}${text}`;
} else {
statusItem.text = `${statusIcon}OpenGOAL`;
}
// tooltip
statusItem.tooltip.appendMarkdown("**General**");
statusItem.tooltip.appendMarkdown("\n\n---\n\n");
statusItem.tooltip.appendMarkdown(
`\n\n[Open Extension Logs](command:opengoal.openLogs)`,
);
if (isJackedIn()) {
statusItem.tooltip.appendMarkdown(
`\n\n[nREPL Un-jack](command:opengoal.nrepl.unjack)`,
);
} else {
statusItem.tooltip.appendMarkdown(
`\n\n[nREPL Jack-in](command:opengoal.nrepl.jackin)`,
);
}
statusItem.tooltip.appendMarkdown(
`\n\n[Change Parinfer Mode](command:opengoal.parinfer.changeMode): ${
getConfig().opengoalParinferMode
}`,
);
statusItem.tooltip.appendMarkdown("\n\n**LSP**");
statusItem.tooltip.appendMarkdown("\n\n---\n\n");
if (getLspStatus() === "started" || getLspStatus() === "error") {
statusItem.tooltip.appendMarkdown(
`\n\n[Restart Server](command:opengoal.lsp.restart)`,
);
} else if (getLspStatus() === "stopped") {
statusItem.tooltip.appendMarkdown(
`\n\n[Start Server](command:opengoal.lsp.start)`,
);
}
if (
getLspStatus() !== "stopped" &&
getLspStatus() !== "downloading" &&
getLspStatus() !== "error"
) {
statusItem.tooltip.appendMarkdown(
`\n\n[Stop Server](command:opengoal.lsp.stop)`,
);
}
if (getConfig().opengoalLspLogPath !== undefined) {
statusItem.tooltip.appendMarkdown(
`\n\n[Open LSP Logs](command:opengoal.lsp.openLogs)`,
);
}
statusItem.tooltip.appendMarkdown("\n\n**Decompiling**");
statusItem.tooltip.appendMarkdown("\n\n---\n\n");
statusItem.tooltip.appendMarkdown(
`\n\n[Open Decompiler Logs](command:opengoal.decomp.openLogs)`,
);
statusItem.tooltip.appendMarkdown(
`\n\n[${
getConfig().autoDecompilation ? "Disable" : "Enable"
} Auto-Decompilation](command:opengoal.decomp.toggleAutoDecompilation)`,
);
}

View file

@ -6,11 +6,16 @@ import { open_in_pdf } from "./man-page";
import * as util from "util"; import * as util from "util";
import { import {
getConfig, getConfig,
updateAutoDecompilation,
updateDecompilerPath, updateDecompilerPath,
updateFormatterPath, updateFormatterPath,
} from "../config/config"; } from "../config/config";
import * as path from "path"; import * as path from "path";
import { getExtensionContext, getProjectRoot } from "../context"; import {
getExtensionContext,
getProjectRoot,
updateStatusBar,
} from "../context";
import { import {
getFileNamesFromUris, getFileNamesFromUris,
getUrisFromTabs, getUrisFromTabs,
@ -31,14 +36,9 @@ const execAsync = util.promisify(exec);
let channel: vscode.OutputChannel; let channel: vscode.OutputChannel;
let fsWatcher: vscode.FileSystemWatcher | undefined; let fsWatcher: vscode.FileSystemWatcher | undefined;
const decompStatusItem = vscode.window.createStatusBarItem(
vscode.StatusBarAlignment.Left,
0,
);
enum DecompStatus { enum DecompStatus {
Idle, Idle,
Running, Decompiling,
Errored, Errored,
Formatting, Formatting,
FormattingError, FormattingError,
@ -48,40 +48,12 @@ function updateStatus(status: DecompStatus, metadata?: any) {
let subText = ""; let subText = "";
switch (status) { switch (status) {
case DecompStatus.Errored: case DecompStatus.Errored:
decompStatusItem.tooltip = "Toggle Auto-Decomp"; updateStatusBar(false, true, "Decomp Failed");
decompStatusItem.command = "opengoal.decomp.toggleAutoDecompilation";
decompStatusItem.text = "$(testing-error-icon) Decomp Failed";
break; break;
case DecompStatus.FormattingError: case DecompStatus.FormattingError:
decompStatusItem.tooltip = "Toggle Auto-Decomp"; updateStatusBar(false, true, "Formatting Failed");
decompStatusItem.command = "opengoal.decomp.toggleAutoDecompilation";
decompStatusItem.text = "$(testing-error-icon) Formatting Failed";
break;
case DecompStatus.Idle:
decompStatusItem.tooltip = "Toggle Auto-Decomp";
decompStatusItem.command = "opengoal.decomp.toggleAutoDecompilation";
if (fsWatcher === undefined) {
decompStatusItem.text =
"$(extensions-sync-ignored) Auto-Decomp Disabled";
} else {
decompStatusItem.text =
"$(extensions-sync-enabled) Auto-Decomp Enabled";
}
break;
case DecompStatus.Running:
if (metadata.objectNames.length > 0) {
if (metadata.objectNames.length <= 5) {
subText = metadata.objectNames.join(", ");
} else {
subText = `${metadata.objectNames.slice(0, 5).join(", ")}, and ${
metadata.objectNames.length - 5
} more`;
}
}
decompStatusItem.text = `$(loading~spin) Decompiling - ${subText} - [ ${metadata.decompConfig} ]`;
decompStatusItem.tooltip = "Decompiling...";
decompStatusItem.command = undefined;
break; break;
case DecompStatus.Decompiling:
case DecompStatus.Formatting: case DecompStatus.Formatting:
if (metadata.objectNames.length > 0) { if (metadata.objectNames.length > 0) {
if (metadata.objectNames.length <= 5) { if (metadata.objectNames.length <= 5) {
@ -92,11 +64,14 @@ function updateStatus(status: DecompStatus, metadata?: any) {
} more`; } more`;
} }
} }
decompStatusItem.text = `$(loading~spin) Formatting - ${subText} - [ ${metadata.decompConfig} ]`; updateStatusBar(
decompStatusItem.tooltip = "Formatting..."; true,
decompStatusItem.command = undefined; false,
`${status == DecompStatus.Decompiling ? "Decompiling" : "Formatting"} - ${subText} - [ ${metadata.decompConfig} ]`,
);
break; break;
default: default:
updateStatusBar(false, false);
break; break;
} }
} }
@ -247,7 +222,7 @@ async function decompFiles(
} }
const allowed_objects = fileNames.map((name) => `"${name}"`).join(","); const allowed_objects = fileNames.map((name) => `"${name}"`).join(",");
updateStatus(DecompStatus.Running, { updateStatus(DecompStatus.Decompiling, {
objectNames: fileNames, objectNames: fileNames,
decompConfig: path.parse(decompConfig).name, decompConfig: path.parse(decompConfig).name,
}); });
@ -375,7 +350,7 @@ async function decompSpecificFile() {
gameName = GameName.Jak1; gameName = GameName.Jak1;
} else if (gameNameSelection == "jak2") { } else if (gameNameSelection == "jak2") {
gameName = GameName.Jak2; gameName = GameName.Jak2;
} else if (gameNameSelection == "jak3") { } else {
gameName = GameName.Jak3; gameName = GameName.Jak3;
} }
} }
@ -496,8 +471,9 @@ function openManPage() {
open_in_pdf(word); open_in_pdf(word);
} }
function toggleAutoDecompilation() { function setupAutoDecompilation() {
if (fsWatcher === undefined) { const isEnabled = getConfig().autoDecompilation;
if (isEnabled && fsWatcher === undefined) {
fsWatcher = vscode.workspace.createFileSystemWatcher( fsWatcher = vscode.workspace.createFileSystemWatcher(
"**/decompiler/config/**/*.{jsonc,json,gc}", "**/decompiler/config/**/*.{jsonc,json,gc}",
); );
@ -511,11 +487,19 @@ function toggleAutoDecompilation() {
}); });
fsWatcher.onDidCreate(() => decompAllActiveFiles()); fsWatcher.onDidCreate(() => decompAllActiveFiles());
fsWatcher.onDidDelete(() => decompAllActiveFiles()); fsWatcher.onDidDelete(() => decompAllActiveFiles());
} else { }
}
async function toggleAutoDecompilation() {
const isEnabled = getConfig().autoDecompilation;
await updateAutoDecompilation(!isEnabled);
if (!getConfig().autoDecompilation && fsWatcher !== undefined) {
fsWatcher.dispose(); fsWatcher.dispose();
fsWatcher = undefined; fsWatcher = undefined;
} else if (getConfig().autoDecompilation) {
setupAutoDecompilation();
} }
updateStatus(DecompStatus.Idle); updateStatusBar(false, false);
} }
async function updateSourceFile() { async function updateSourceFile() {
@ -737,12 +721,15 @@ export async function activateDecompTools() {
"opengoal-ir", "opengoal-ir",
); );
toggleAutoDecompilation(); setupAutoDecompilation();
updateStatus(DecompStatus.Idle); updateStatus(DecompStatus.Idle);
decompStatusItem.show();
// Commands // Commands
getExtensionContext().subscriptions.push(
vscode.commands.registerCommand("opengoal.decomp.openLogs", () => {
channel.show();
}),
);
getExtensionContext().subscriptions.push( getExtensionContext().subscriptions.push(
vscode.commands.registerCommand("opengoal.decomp.openManPage", openManPage), vscode.commands.registerCommand("opengoal.decomp.openManPage", openManPage),
); );

View file

@ -3,6 +3,7 @@ import * as vscode from "vscode";
import { integer } from "vscode-languageclient"; import { integer } from "vscode-languageclient";
import { getConfig, updateOpengoalParinferMode } from "../../config/config"; import { getConfig, updateOpengoalParinferMode } from "../../config/config";
import { getEditorRange } from "../../utils/editor-utils"; import { getEditorRange } from "../../utils/editor-utils";
import { updateStatusBar } from "../../context";
// TODO: // TODO:
// - iron out some quirks around undoing // - iron out some quirks around undoing
@ -72,45 +73,9 @@ const eventQueue: EventQueueItem[] = [];
const maxEventQueueSize = 10; const maxEventQueueSize = 10;
let currentParinferMode = ParinferMode.DISABLED; let currentParinferMode = ParinferMode.DISABLED;
const parinferStatusItem = vscode.window.createStatusBarItem(
vscode.StatusBarAlignment.Left,
0,
);
function updateStatus() {
switch (currentParinferMode) {
case ParinferMode.DISABLED:
parinferStatusItem.text = "$(json) Parinfer Disabled";
parinferStatusItem.tooltip = "Currently doing nothing! - Change Mode";
parinferStatusItem.command = "opengoal.parinfer.changeMode";
break;
case ParinferMode.SMART:
parinferStatusItem.text = "$(json) Smart Parinfer";
parinferStatusItem.tooltip =
"Automatically runs in Paren or Indent mode - Change Mode";
parinferStatusItem.command = "opengoal.parinfer.changeMode";
break;
case ParinferMode.PAREN:
parinferStatusItem.text = "$(json) Paren Parinfer";
parinferStatusItem.tooltip =
"You handle the parens while parinfer handles indentation! - Change Mode";
parinferStatusItem.command = "opengoal.parinfer.changeMode";
break;
case ParinferMode.INDENT:
parinferStatusItem.text = "$(json) Parinfer Disabled";
parinferStatusItem.tooltip =
"You handle the indentation while parinfer handles the parens! - Change Mode";
parinferStatusItem.command = "opengoal.parinfer.changeMode";
break;
default:
break;
}
}
async function changeParinferMode(mode: ParinferMode) { async function changeParinferMode(mode: ParinferMode) {
currentParinferMode = mode; currentParinferMode = mode;
await updateOpengoalParinferMode(mode); await updateOpengoalParinferMode(mode);
updateStatus();
} }
function cleanUpEventQueue() { function cleanUpEventQueue() {
@ -333,6 +298,7 @@ function showChangeModeMenu() {
.then((v) => { .then((v) => {
if (v !== undefined) { if (v !== undefined) {
changeParinferMode(v.label as ParinferMode); changeParinferMode(v.label as ParinferMode);
updateStatusBar(false, false);
} }
}); });
} }
@ -343,8 +309,6 @@ export function registerParinferCommands(
changeParinferMode( changeParinferMode(
(getConfig().opengoalParinferMode as ParinferMode) ?? ParinferMode.DISABLED, (getConfig().opengoalParinferMode as ParinferMode) ?? ParinferMode.DISABLED,
); );
updateStatus();
parinferStatusItem.hide(); // TODO - consolidate menu https://github.com/rust-lang/rust-analyzer/blob/9c03aa1ac2e67051db83a85baf3cfee902e4dd84/editors/code/src/ctx.ts#L406
context.subscriptions.push( context.subscriptions.push(
vscode.commands.registerCommand( vscode.commands.registerCommand(
"opengoal.parinfer.changeMode", "opengoal.parinfer.changeMode",

View file

@ -1,101 +1,55 @@
import * as vscode from "vscode"; import * as vscode from "vscode";
import * as path from "path"; import * as path from "path";
import { import {
BaseLanguageClient,
ClientCapabilities,
DocumentSelector,
FeatureState,
InitializeParams,
LanguageClient, LanguageClient,
LanguageClientOptions, LanguageClientOptions,
ServerCapabilities,
ServerOptions, ServerOptions,
StaticFeature,
TransportKind, TransportKind,
WorkDoneProgress,
WorkDoneProgressCreateRequest,
} from "vscode-languageclient/node"; } from "vscode-languageclient/node";
import { getConfig } from "../config/config"; import { getConfig } from "../config/config";
import { downloadLsp } from "./download"; import { downloadLsp } from "./download";
import { getLatestVersion, getLspPath, getVersionFromMetaFile } from "./util"; import { getLatestVersion, getLspPath, getVersionFromMetaFile } from "./util";
import * as fs from "fs"; import * as fs from "fs";
import { disposeAll } from "../vendor/vscode-pdfviewer/disposable"; import { updateStatusBar } from "../context";
let extensionContext: vscode.ExtensionContext; let extensionContext: vscode.ExtensionContext;
let opengoalLspPath: string | undefined; let opengoalLspPath: string | undefined;
let activeClient: LanguageClient | undefined; let activeClient: LanguageClient | undefined;
type LspStatus = export type LspStatus =
| "stopped" | "stopped"
| "starting" | "starting"
| "started" | "started"
| "downloading" | "downloading"
| "error" | "error";
| "serverProgressBegin"
| "serverProgressEnd";
// TODO - rust analyzer's context menu on hover is nice let currentStatus: LspStatus = "stopped";
class LSPStatusItem { function updateStatus(status: LspStatus, extraInfo?: string) {
private currentStatus: LspStatus = "stopped"; currentStatus = status;
switch (currentStatus) {
constructor(private readonly statusItem: vscode.StatusBarItem) {}
public updateStatus(status: LspStatus, extraInfo?: string) {
this.currentStatus = status;
switch (this.currentStatus) {
case "stopped":
this.statusItem.text = "$(circle-outline) OpenGOAL LSP Stopped";
this.statusItem.tooltip = "Launch LSP";
this.statusItem.command = "opengoal.lsp.start";
break;
case "starting": case "starting":
this.statusItem.text = "$(loading~spin) OpenGOAL LSP Starting"; updateStatusBar(true, false, "LSP Starting");
this.statusItem.tooltip = "LSP Starting";
this.statusItem.command = undefined;
break;
case "started":
this.statusItem.text = "$(circle-filled) OpenGOAL LSP Ready";
this.statusItem.tooltip = `LSP Active - ${extraInfo}`;
this.statusItem.command = "opengoal.lsp.showLspStartedMenu";
break; break;
case "downloading": case "downloading":
this.statusItem.text = `$(sync~spin) OpenGOAL LSP Downloading - ${extraInfo}`; updateStatusBar(true, false, `LSP Downloading - ${extraInfo}`);
this.statusItem.tooltip = `Downloading version - ${extraInfo}`;
this.statusItem.command = undefined;
break; break;
case "error": case "error":
this.statusItem.text = "$(error) OpenGOAL LSP Error"; updateStatusBar(false, true, "LSP Startup Error");
this.statusItem.tooltip = "LSP not running due to an error";
this.statusItem.command = undefined;
break;
case "serverProgressBegin":
this.statusItem.text = `$(loading~spin) ${extraInfo}`;
this.statusItem.tooltip = extraInfo;
this.statusItem.command = "opengoal.lsp.showLspStartedMenu";
break;
case "serverProgressEnd":
this.statusItem.text = `$(circle-filled) ${extraInfo}`;
this.statusItem.tooltip = extraInfo;
this.statusItem.command = "opengoal.lsp.showLspStartedMenu";
break; break;
default: default:
updateStatusBar(false, false);
break; break;
} }
} }
public hide() { /**
this.statusItem.hide(); * Get the current status of the LSP.
* @returns A string representing the current status of the LSP, one of "stopped", "starting", "started", "downloading", or "error".
*/
export function getLspStatus(): LspStatus {
return currentStatus;
} }
public show() {
this.statusItem.show();
}
}
const statusItem = new LSPStatusItem(
vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 0),
);
async function ensureServerDownloaded(): Promise<string | undefined> { async function ensureServerDownloaded(): Promise<string | undefined> {
const installedVersion = getVersionFromMetaFile( const installedVersion = getVersionFromMetaFile(
extensionContext.extensionPath, extensionContext.extensionPath,
@ -130,15 +84,15 @@ async function ensureServerDownloaded(): Promise<string | undefined> {
} }
// Install the LSP and update the version metadata file // Install the LSP and update the version metadata file
statusItem.updateStatus("downloading", versionToDownload); updateStatus("downloading", versionToDownload);
const newLspPath = await downloadLsp( const newLspPath = await downloadLsp(
extensionContext.extensionPath, extensionContext.extensionPath,
versionToDownload, versionToDownload,
); );
if (newLspPath === undefined) { if (newLspPath === undefined) {
statusItem.updateStatus("error"); updateStatus("error");
} else { } else {
statusItem.updateStatus("stopped"); updateStatus("stopped");
} }
return newLspPath; return newLspPath;
} }
@ -221,7 +175,7 @@ function createClient(lspPath: string): LanguageClient {
} }
async function stopClient() { async function stopClient() {
statusItem.updateStatus("stopped"); updateStatus("stopped");
if (activeClient !== undefined) { if (activeClient !== undefined) {
console.log("Stopping opengoal-lsp"); console.log("Stopping opengoal-lsp");
return await activeClient return await activeClient
@ -235,80 +189,27 @@ async function stopClient() {
} }
} }
class StatusBarFeature implements StaticFeature {
private requestHandlers: vscode.Disposable[] = [];
public fillClientCapabilities(capabilities: ClientCapabilities): void {
if (!capabilities.window) {
capabilities.window = {};
}
capabilities.window.workDoneProgress = true;
}
constructor(private readonly client: BaseLanguageClient) {}
fillInitializeParams?: ((params: InitializeParams) => void) | undefined;
preInitialize?:
| ((
capabilities: ServerCapabilities<any>,
documentSelector: DocumentSelector | undefined,
) => void)
| undefined;
clear(): void {
throw new Error("Method not implemented.");
}
public getState(): FeatureState {
return { kind: "static" };
}
public dispose(): void {
// nothing to dispose here
}
public initialize(): void {
this.requestHandlers.push(
this.client.onRequest(WorkDoneProgressCreateRequest.type, ({ token }) => {
this.client.onProgress(WorkDoneProgress.type, token, (progress) => {
if (progress.kind === "begin") {
statusItem.updateStatus("serverProgressBegin", progress.title);
}
if (progress.kind === "report") {
// do nothing right now, goalc provides no feedback on it's status
}
if (progress.kind === "end") {
statusItem.updateStatus("serverProgressEnd", progress.message);
disposeAll(this.requestHandlers);
}
});
}),
);
}
}
async function startClient(): Promise<void> { async function startClient(): Promise<void> {
if (opengoalLspPath === undefined) { if (opengoalLspPath === undefined) {
return; return;
} }
const client = createClient(opengoalLspPath); const client = createClient(opengoalLspPath);
client.registerFeature(new StatusBarFeature(client));
console.log("Starting opengoal-lsp at", opengoalLspPath); console.log("Starting opengoal-lsp at", opengoalLspPath);
// TODO - some form of startup test would be nice // TODO - some form of startup test would be nice
try { try {
statusItem.updateStatus("starting"); updateStatus("starting");
await client.start(); await client.start();
activeClient = client; activeClient = client;
statusItem.updateStatus("started", path.basename(opengoalLspPath)); updateStatus("started", path.basename(opengoalLspPath));
} catch (error) { } catch (error) {
console.error("opengoal-lsp:", error); console.error("opengoal-lsp:", error);
statusItem.updateStatus("error"); updateStatus("error");
statusItem.hide();
await stopClient(); await stopClient();
} }
} }
export async function startClientCommand() { export async function startClientCommand() {
statusItem.show();
await maybeDownloadLspServer(); await maybeDownloadLspServer();
if (opengoalLspPath !== undefined) { if (opengoalLspPath !== undefined) {
await startClient(); await startClient();
@ -359,7 +260,15 @@ function startedMenuCommand() {
showMenu(items, commands); showMenu(items, commands);
} }
function registerLifeCycleCommands(context: vscode.ExtensionContext): void { function registerCommands(context: vscode.ExtensionContext): void {
context.subscriptions.push(
vscode.commands.registerCommand("opengoal.lsp.openLogs", () => {
const logPath = getConfig().opengoalLspLogPath;
if (logPath !== undefined) {
vscode.commands.executeCommand("vscode.open", vscode.Uri.file(logPath));
}
}),
);
context.subscriptions.push( context.subscriptions.push(
vscode.commands.registerCommand("opengoal.lsp.start", startClientCommand), vscode.commands.registerCommand("opengoal.lsp.start", startClientCommand),
); );
@ -381,11 +290,7 @@ export async function activate(
context: vscode.ExtensionContext, context: vscode.ExtensionContext,
): Promise<void> { ): Promise<void> {
extensionContext = context; extensionContext = context;
registerLifeCycleCommands(context); registerCommands(context);
// TODO - add info and open log file options
// registerDiagnosticsCommands(context);
statusItem.updateStatus("stopped");
statusItem.show();
const config = getConfig(); const config = getConfig();
if (config.launchLspOnStartup) { if (config.launchLspOnStartup) {
await startClientCommand(); await startClientCommand();

View file

@ -3,34 +3,21 @@ import * as path from "path";
import PromiseSocket from "promise-socket"; import PromiseSocket from "promise-socket";
import * as vscode from "vscode"; import * as vscode from "vscode";
import { getConfig } from "../../../config/config"; import { getConfig } from "../../../config/config";
import { updateStatusBar } from "../../../context";
let jackedIn = false; let jackedIn = false;
let socket: PromiseSocket<Socket> | undefined = undefined; let socket: PromiseSocket<Socket> | undefined = undefined;
const nreplStatusItem = vscode.window.createStatusBarItem( // TODO - status bar updates for errors and such
vscode.StatusBarAlignment.Left,
0,
);
function updateStatus() { export function isJackedIn() {
// TODO - show errors return jackedIn;
if (!jackedIn) {
nreplStatusItem.text = "$(call-outgoing) nREPL";
nreplStatusItem.tooltip =
"Jack-in to a running OpenGOAL nREPL on port 8181";
nreplStatusItem.command = "opengoal.nrepl.jackin";
} else {
nreplStatusItem.text = "$(debug-disconnect) nREPL";
nreplStatusItem.tooltip =
"Un-jack from a running OpenGOAL nREPL on port 8181";
nreplStatusItem.command = "opengoal.nrepl.unjack";
}
} }
export async function jackIn() { export async function jackIn() {
if (socket !== undefined) { if (socket !== undefined) {
jackedIn = true; jackedIn = true;
updateStatus(); updateStatusBar(false, false);
return; return;
} }
try { try {
@ -46,13 +33,13 @@ export async function jackIn() {
console.error(e); console.error(e);
socket = undefined; socket = undefined;
} }
updateStatus(); updateStatusBar(false, false);
} }
export async function unJack() { export async function unJack() {
if (socket === undefined) { if (socket === undefined) {
jackedIn = false; jackedIn = false;
updateStatus(); updateStatusBar(false, false);
return; return;
} }
try { try {
@ -62,7 +49,7 @@ export async function unJack() {
} }
socket = undefined; socket = undefined;
jackedIn = false; jackedIn = false;
updateStatus(); updateStatusBar(false, false);
} }
export async function reloadFile(fileName: string) { export async function reloadFile(fileName: string) {
@ -100,8 +87,6 @@ export function registerNReplCommands(context: vscode.ExtensionContext): void {
vscode.commands.registerCommand("opengoal.nrepl.jackin", jackIn), vscode.commands.registerCommand("opengoal.nrepl.jackin", jackIn),
vscode.commands.registerCommand("opengoal.nrepl.unjack", unJack), vscode.commands.registerCommand("opengoal.nrepl.unjack", unJack),
); );
updateStatus();
nreplStatusItem.show();
} }
export function nreplOnFileSaveHandler(e: vscode.TextDocument) { export function nreplOnFileSaveHandler(e: vscode.TextDocument) {
@ -110,6 +95,5 @@ export function nreplOnFileSaveHandler(e: vscode.TextDocument) {
} }
// Get the name // Get the name
const fileName = path.basename(e.fileName).replace(".gc", ""); const fileName = path.basename(e.fileName).replace(".gc", "");
console.log(fileName);
reloadFile(fileName); reloadFile(fileName);
} }