Skip to content
This repository has been archived by the owner on Aug 31, 2023. It is now read-only.

Commit

Permalink
feat(vscode): add a status bar item for the language server (#3139)
Browse files Browse the repository at this point in the history
* feat(vscode): add a status bar item for the language server

* address PR review
  • Loading branch information
leops authored and ematipico committed Sep 5, 2022
1 parent cd95ab0 commit 5e35939
Show file tree
Hide file tree
Showing 3 changed files with 176 additions and 8 deletions.
5 changes: 4 additions & 1 deletion editors/vscode/src/commands/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
// list of commands available in the VS Code extension
export enum Commands { SyntaxTree = "rome.syntaxTree" }
export enum Commands {
SyntaxTree = "rome.syntaxTree",
ServerStatus = "rome.serverStatus",
}
55 changes: 48 additions & 7 deletions editors/vscode/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
import { spawn } from "child_process";
import { connect } from "net";
import { ExtensionContext, Uri, window, workspace } from "vscode";
import {
ExtensionContext,
languages,
TextEditor,
Uri,
window,
workspace,
} from "vscode";
import {
DocumentFilter,
LanguageClient,
LanguageClientOptions,
ServerOptions,
Expand All @@ -11,6 +19,7 @@ import { setContextValue } from "./utils";
import { Session } from "./session";
import { syntaxTree } from "./commands/syntaxTree";
import { Commands } from "./commands";
import { StatusBar } from "./statusBar";

let client: LanguageClient;

Expand All @@ -19,6 +28,7 @@ const IN_ROME_PROJECT = "inRomeProject";
export async function activate(context: ExtensionContext) {
const command =
process.env.DEBUG_SERVER_PATH || (await getServerPath(context));

if (!command) {
await window.showErrorMessage(
"The Rome extensions doesn't ship with prebuilt binaries for your platform yet. " +
Expand All @@ -28,31 +38,62 @@ export async function activate(context: ExtensionContext) {
return;
}

const statusBar = new StatusBar();

const serverOptions: ServerOptions = createMessageTransports.bind(
undefined,
command,
);

const traceOutputChannel = window.createOutputChannel("Rome Trace");

const documentSelector: DocumentFilter[] = [
{ scheme: "file", language: "javascript" },
{ scheme: "file", language: "typescript" },
{ scheme: "file", language: "javascriptreact" },
{ scheme: "file", language: "typescriptreact" },
];

const clientOptions: LanguageClientOptions = {
documentSelector: [
{ scheme: "file", language: "javascript" },
{ scheme: "file", language: "typescript" },
{ scheme: "file", language: "javascriptreact" },
{ scheme: "file", language: "typescriptreact" },
],
documentSelector,
traceOutputChannel,
};

client = new LanguageClient("rome_lsp", "Rome", serverOptions, clientOptions);

const session = new Session(context, client);

const codeDocumentSelector =
client.protocol2CodeConverter.asDocumentSelector(documentSelector);

// we are now in a rome project
setContextValue(IN_ROME_PROJECT, true);

session.registerCommand(Commands.SyntaxTree, syntaxTree(session));
session.registerCommand(Commands.ServerStatus, () => {
traceOutputChannel.show();
});

context.subscriptions.push(
client.onDidChangeState((evt) => {
statusBar.setServerState(evt.newState);
}),
);

const handleActiveTextEditorChanged = (textEditor?: TextEditor) => {
if (!textEditor) {
statusBar.setActive(false);
}

const { document } = textEditor;
statusBar.setActive(languages.match(codeDocumentSelector, document) > 0);
};

context.subscriptions.push(
window.onDidChangeActiveTextEditor(handleActiveTextEditorChanged),
);

handleActiveTextEditorChanged(window.activeTextEditor);

client.start();
}
Expand Down
124 changes: 124 additions & 0 deletions editors/vscode/src/statusBar.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import { StatusBarAlignment, StatusBarItem, ThemeColor, window } from "vscode";
import { State } from "vscode-languageclient";
import { Commands } from "./commands";

/**
* Enumeration of all the status the extension can display
*
* The string value of the enum is the ThemeIcon ID to be displayer in the status
* bar item when this status is active
*
* See https://code.visualstudio.com/api/references/icons-in-labels#icon-listing
* for a list of available icons
*/
enum Status {
Pending = "refresh",
Ready = "check",
Inactive = "eye-closed",
Warning = "warning",
Error = "error",
}

export class StatusBar {
private statusBarItem: StatusBarItem;

private serverState: State = State.Starting;
private isActive: boolean = false;

constructor() {
this.statusBarItem = window.createStatusBarItem(
"rome.status",
StatusBarAlignment.Right,
-1,
);

this.statusBarItem.name = "Rome";
this.statusBarItem.command = Commands.ServerStatus;
this.update();
}

public setServerState(state: State) {
this.serverState = state;
this.update();
}

public setActive(isActive: boolean) {
this.isActive = isActive;
this.update();
}

private update() {
let status: Status;
if (this.serverState === State.Running) {
if (this.isActive) {
status = Status.Ready;
} else {
status = Status.Inactive;
}
} else if (this.serverState === State.Starting) {
status = Status.Pending;
} else {
status = Status.Error;
}

this.statusBarItem.text = `$(${status}) Rome`;

switch (status) {
case Status.Pending: {
this.statusBarItem.tooltip = "Rome is initializing ...";
break;
}
case Status.Ready: {
this.statusBarItem.tooltip = "Rome is active";
break;
}
case Status.Inactive: {
this.statusBarItem.tooltip =
"The current file is not supported or ignored by Rome";
break;
}
// @ts-expect-error Reserved for future use
case Status.Warning: {
this.statusBarItem.tooltip = undefined;
break;
}
case Status.Error: {
this.statusBarItem.tooltip = "Rome encountered a fatal error";
break;
}
}

switch (status) {
case Status.Error: {
this.statusBarItem.color = new ThemeColor(
"statusBarItem.errorForeground",
);
this.statusBarItem.backgroundColor = new ThemeColor(
"statusBarItem.errorBackground",
);
break;
}
// @ts-expect-error Reserved for future use
case Status.Warning: {
this.statusBarItem.color = new ThemeColor(
"statusBarItem.warningForeground",
);
this.statusBarItem.backgroundColor = new ThemeColor(
"statusBarItem.warningBackground",
);
break;
}
default: {
this.statusBarItem.color = undefined;
this.statusBarItem.backgroundColor = undefined;
break;
}
}

this.statusBarItem.show();
}

public hide() {
this.statusBarItem.hide();
}
}

0 comments on commit 5e35939

Please sign in to comment.