From 6fef8e9c71ed5036e3bf7f781ac8f644ae3ce534 Mon Sep 17 00:00:00 2001 From: stefan toubia Date: Thu, 21 Nov 2019 20:47:34 -0800 Subject: [PATCH] Add evaluation status bar item --- CHANGELOG.md | 1 + src/animation.ts | 42 +++++++++++++++++++++++++++++++++++++++++ src/evaluate.ts | 13 +++++++++++-- src/state.ts | 13 +++++++++++-- src/statusbar.ts | 49 ++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 114 insertions(+), 4 deletions(-) create mode 100644 src/animation.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 44167dfad..1bb01d666 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ Changes to Calva. ## [Unreleased] +- Add status bar item for evaluation status. - Fix: ["Load current Namespace in REPL Window" command not working](https://github.com/BetterThanTomorrow/calva/issues/477) - Fix: [Tokenization errors with quotes, derefs, etcetera](https://github.com/BetterThanTomorrow/calva/issues/467) - Fix: [Wrong current form in the REPL window when cursor is to the right of a form](https://github.com/BetterThanTomorrow/calva/issues/472) diff --git a/src/animation.ts b/src/animation.ts new file mode 100644 index 000000000..e5bb8c5e9 --- /dev/null +++ b/src/animation.ts @@ -0,0 +1,42 @@ + +import * as vscode from 'vscode'; + +export interface TextIncrementor { + next(): string; + reset(): void; +} + +export class Incrementor { + constructor( + private start: number, + private end: number + ) { + this._val = start; + } + private _val: number; + + next() { + if(this._val > this.end) { + this._val = this.start; + } + return this._val++; + } + reset = () => this._val = this.start; +} + +export class StatusBarAnimator { + constructor( + private incrementor: TextIncrementor, + private interval: number + ) { } + timer: NodeJS.Timer; + + start(sbi: vscode.StatusBarItem) { + this.incrementor.reset(); + this.timer = setInterval( + () => sbi.text = this.incrementor.next(), + this.interval + ); + } + stop = () => clearInterval(this.timer); +} diff --git a/src/evaluate.ts b/src/evaluate.ts index 30d257fb9..8aa3c9e6f 100644 --- a/src/evaluate.ts +++ b/src/evaluate.ts @@ -1,6 +1,7 @@ import * as vscode from 'vscode'; import * as _ from 'lodash'; import * as state from './state'; +import { EvaluationStatus } from "./state"; import annotations from './providers/annotations'; import * as path from 'path'; import select from './select'; @@ -168,6 +169,11 @@ function evaluateCurrentForm(document = {}, options = {}) { .catch(e => console.warn(`Unhandled error: ${e.message}`)); } +function setEvalStatus(status: EvaluationStatus) { + state.cursor.set("evaluation", status); + statusbar.update(); +} + async function loadFile(document, callback: () => { }, pprintOptions: PrettyPrintingOptions) { let current = state.deref(), doc = util.getDocument(document), @@ -181,7 +187,7 @@ async function loadFile(document, callback: () => { }, pprintOptions: PrettyPrin if (doc && doc.languageId == "clojure" && fileType != "edn" && current.get('connected')) { state.analytics().logEvent("Evaluation", "LoadFile").send(); chan.appendLine("Evaluating file: " + fileName); - + setEvalStatus(EvaluationStatus.evaluating); let res = client.loadFile(doc.getText(), { fileName: fileName, filePath: doc.fileName, @@ -191,18 +197,21 @@ async function loadFile(document, callback: () => { }, pprintOptions: PrettyPrin }) await res.value.then((value) => { if (value) { + setEvalStatus(EvaluationStatus.success); chan.appendLine("=> " + value); } else { + setEvalStatus(EvaluationStatus.none); chan.appendLine("No results from file evaluation."); } }).catch((e) => { chan.appendLine(`Evaluation of file ${fileName} failed: ${e}`); + setEvalStatus(EvaluationStatus.error); }); } if (callback) { try { callback(); - } catch (e) { + } catch (e) { chan.appendLine(`After evaluation callback for file ${fileName} failed: ${e}`); }; } diff --git a/src/state.ts b/src/state.ts index 8d03b73aa..c6e053a1a 100644 --- a/src/state.ts +++ b/src/state.ts @@ -17,6 +17,13 @@ export function setExtensionContext(context: vscode.ExtensionContext) { } } +enum EvaluationStatus { + none, + evaluating, + success, + error +} + // include the 'file' and 'untitled' to the // document selector. All other schemes are // not known and therefore not supported. @@ -39,7 +46,8 @@ const initialData = { outputChannel: vscode.window.createOutputChannel("Calva says"), connectionLogChannel: vscode.window.createOutputChannel("Calva Connection Log"), diagnosticCollection: vscode.languages.createDiagnosticCollection('calva: Evaluation errors'), - analytics: null + analytics: null, + evaluation: EvaluationStatus.none }; reset(); @@ -240,5 +248,6 @@ export { extensionContext, outputChannel, connectionLogChannel, - analytics + analytics, + EvaluationStatus }; diff --git a/src/statusbar.ts b/src/statusbar.ts index be46f2b83..bf793f829 100644 --- a/src/statusbar.ts +++ b/src/statusbar.ts @@ -1,4 +1,9 @@ import * as vscode from 'vscode'; +import { + Incrementor, + TextIncrementor, + StatusBarAnimator +} from "./animation"; import { activeReplWindow } from './repl-window'; import * as state from './state'; import * as util from './utilities'; @@ -6,6 +11,7 @@ import * as util from './utilities'; const connectionStatus = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left); const typeStatus = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left); const cljsBuildStatus = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left); +const evalStatus = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left); const prettyPrintToggle = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right); const color = { active: "white", @@ -99,6 +105,49 @@ function update() { cljsBuildStatus.hide(); } prettyPrintToggle.show(); + + updateEvalStatus( + evalStatus, + current.get("evaluation"), + current.get('connected') + ); +} + +class EvalIncrementor implements TextIncrementor { + constructor() { + this.incrementor = new Incrementor(1, 3); + } + incrementor: Incrementor; + next = () => "🔨".repeat(this.incrementor.next()); + reset = () => this.incrementor.reset(); +} + +const evalAnimation = new StatusBarAnimator(new EvalIncrementor(), 500); + +function updateEvalStatus( + sbi: vscode.StatusBarItem, + evaluationStatus: state.EvaluationStatus, + visible: boolean + ) { + sbi.color = color.inactive; + evalAnimation.stop(); + // TODO: Toggle calva says output + sbi.command = "workbench.action.output.toggleOutput"; + switch(evaluationStatus) { + case state.EvaluationStatus.none: + sbi.text = "🔵"; + break; + case state.EvaluationStatus.evaluating: + evalAnimation.start(sbi); + break; + case state.EvaluationStatus.success: + sbi.text = "✅"; + break; + case state.EvaluationStatus.error: + sbi.text = "❌"; + break; + } + visible ? sbi.show() : sbi.hide(); } export default {