diff --git a/package.json b/package.json index df93d80..85dcb66 100644 --- a/package.json +++ b/package.json @@ -31,19 +31,19 @@ "viewsContainers": { "panel": [ { - "id": "myCustomPanel", - "title": "My Custom Panel", - "icon": "$(file-code)" + "id": "speedCodeResultPanel", + "title": "Speed Code", + "icon": "./timer.svg" } ] }, "views": { - "myCustomPanel": [ + "speedCodeResultPanel": [ { "type": "tree", - "id": "myCustomTab", - "name": "My Tab", - "icon": "$(file-code)" + "id": "speedCodeResultTab", + "name": "Speed Code", + "icon": "./timer.svg" } ] } diff --git a/src/extension.ts b/src/extension.ts index 58583c4..0e18a5a 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -28,6 +28,12 @@ function isPalindrome(s) { } `; +const treeDataProvider = new MyTreeDataProvider(); + +const treeView = vscode.window.createTreeView("speedCodeResultTab", { + treeDataProvider, +}); + export function activate(context: vscode.ExtensionContext) { const statusBarItem = vscode.window.createStatusBarItem( vscode.StatusBarAlignment.Left, @@ -45,10 +51,6 @@ export function activate(context: vscode.ExtensionContext) { timer: NodeJS.Timeout; }; - const treeDataProvider = new MyTreeDataProvider(); - - vscode.window.registerTreeDataProvider("myCustomTab", treeDataProvider); - resetTimer = () => { if (run) { clearInterval(run.timer); @@ -58,6 +60,7 @@ export function activate(context: vscode.ExtensionContext) { }; resetTimer(); + updateTreeMessage(); context.subscriptions.push( vscode.commands.registerCommand("speed-code.submitSpeedRun", () => { @@ -84,6 +87,7 @@ export function activate(context: vscode.ExtensionContext) { } treeDataProvider.refresh(); + updateTreeMessage(); } catch (e) { treeDataProvider.blunders.push([run.elapsed, String(e)]); } @@ -96,6 +100,7 @@ export function activate(context: vscode.ExtensionContext) { treeDataProvider.testSummary = undefined; treeDataProvider.testResults = []; treeDataProvider.blunders = []; + updateTreeMessage(); const runFilePath = path.join(speedCodePath, "isPalindrome.js"); fs.writeFileSync(runFilePath, ""); openAndFocusFile(runFilePath); @@ -119,7 +124,13 @@ export function activate(context: vscode.ExtensionContext) { ); context.subscriptions.push( - vscode.commands.registerCommand("speed-code.cancelSpeedRun", resetTimer), + vscode.commands.registerCommand("speed-code.cancelSpeedRun", () => { + resetTimer(); + treeDataProvider.testSummary = undefined; + treeDataProvider.testResults = []; + treeDataProvider.blunders = []; + treeDataProvider.refresh(); + }), statusBarItem ); } @@ -127,3 +138,15 @@ export function activate(context: vscode.ExtensionContext) { export function deactivate() { resetTimer(); } + +function updateTreeMessage() { + if ( + !treeDataProvider.testResults.length && + !treeDataProvider.blunders.length && + !treeDataProvider.testSummary + ) { + treeView.message = "No results yet. Start a speedrun!"; + } else { + treeView.message = ""; + } +} diff --git a/src/tester.ts b/src/tester.ts index 1d757a7..340123b 100644 --- a/src/tester.ts +++ b/src/tester.ts @@ -1,42 +1,51 @@ -import vm from 'vm'; -import assert from 'assert'; +import vm from "vm"; +import assert from "assert"; -export interface TestCase { input: any[], expected: any }; -export interface TestResult extends TestCase { result: any, valid: boolean }; - -export default function testCode(code: string, testCases: TestCase[]): [boolean, TestResult[]] { - const context: Record = {}; - vm.createContext(context); - - const beforeKeys = new Set(Object.keys(context)); - - const script = new vm.Script(code); - script.runInContext(context); - - const afterKeys = Object.keys(context); - const newKeys = afterKeys.filter(k => !beforeKeys.has(k)); - - // Find the last function defined - const funcs = newKeys - .map(k => context[k]) - .filter(v => typeof v === 'function'); - - if (funcs.length === 0) { - throw new Error("No function was defined in the code."); +export interface TestCase { + input: any[]; + expected: any; +} +export interface TestResult extends TestCase { + result: any; + valid: boolean; +} + +export default function testCode( + code: string, + testCases: TestCase[] +): [boolean, TestResult[]] { + const context: Record = {}; + vm.createContext(context); + + const beforeKeys = new Set(Object.keys(context)); + + const script = new vm.Script(code); + script.runInContext(context); + + const afterKeys = Object.keys(context); + const newKeys = afterKeys.filter((k) => !beforeKeys.has(k)); + + // Find the last function defined + const funcs = newKeys + .map((k) => context[k]) + .filter((v) => typeof v === "function"); + + if (funcs.length === 0) { + throw new Error("No function was defined in the code."); + } + + const targetFn = funcs[funcs.length - 1]; + + const tests = testCases.map((t) => { + const result = targetFn(...t.input); + + try { + assert.strictEqual(result, t.expected); + return { ...t, valid: true, result }; + } catch { + return { ...t, valid: false, result }; } - - const targetFn = funcs[funcs.length - 1]; - - const tests = testCases.map((t) => { - const result = targetFn(...t.input); - - try { - assert.strictEqual(result, t.expected); - return { ...t, valid: true, result }; - } catch { - return { ...t, valid: false, result }; - } - }); + }); - return [tests.every(t => t.valid), tests]; + return [tests.every((t) => t.valid), tests]; } diff --git a/src/utils.ts b/src/utils.ts index b81504c..7e23aa8 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,17 +1,23 @@ export function format(timeSeconds: number): string { - if (timeSeconds > 86400) { - const days = Math.floor(timeSeconds / 86400); - const hours = Math.floor(timeSeconds / 3600); - const minutes = Math.floor(timeSeconds / 60); - return `${days}:${hours - (days * 24)}:${minutes - (hours * 60)}:${(timeSeconds - (minutes * 60)).toFixed(3)}`; - } else if (timeSeconds >= 3600) { - const hours = Math.floor(timeSeconds / 3600); - const minutes = Math.floor(timeSeconds / 60); - return `${hours}:${minutes - (hours * 60)}:${(timeSeconds - (minutes * 60)).toFixed(3)}`; - } else if (timeSeconds >= 60) { - const minutes = Math.floor(timeSeconds / 60); - return `${minutes}:${(timeSeconds - (minutes * 60)).toFixed(3)}`; - } else { - return `${timeSeconds}`; - } -} \ No newline at end of file + if (timeSeconds > 86400) { + const days = Math.floor(timeSeconds / 86400); + const hours = Math.floor(timeSeconds / 3600); + const minutes = Math.floor(timeSeconds / 60); + return `${days}:${hours - days * 24}:${minutes - hours * 60}:${( + timeSeconds - + minutes * 60 + ).toFixed(3)}`; + } else if (timeSeconds >= 3600) { + const hours = Math.floor(timeSeconds / 3600); + const minutes = Math.floor(timeSeconds / 60); + return `${hours}:${minutes - hours * 60}:${( + timeSeconds - + minutes * 60 + ).toFixed(3)}`; + } else if (timeSeconds >= 60) { + const minutes = Math.floor(timeSeconds / 60); + return `${minutes}:${(timeSeconds - minutes * 60).toFixed(3)}`; + } else { + return `${timeSeconds}`; + } +} diff --git a/timer.svg b/timer.svg new file mode 100644 index 0000000..a24ee08 --- /dev/null +++ b/timer.svg @@ -0,0 +1 @@ + \ No newline at end of file