diff --git a/package.json b/package.json index 4634a113..8a8e99aa 100644 --- a/package.json +++ b/package.json @@ -215,12 +215,16 @@ ], "editor/context": [ { - "command": "leetcode.testSolution", + "command": "leetcode.previewProblem", "group": "leetcode@1" }, { - "command": "leetcode.submitSolution", + "command": "leetcode.testSolution", "group": "leetcode@2" + }, + { + "command": "leetcode.submitSolution", + "group": "leetcode@3" } ] }, diff --git a/src/codelens/CustomCodeLensProvider.ts b/src/codelens/CustomCodeLensProvider.ts index 001ccc0b..405b0728 100644 --- a/src/codelens/CustomCodeLensProvider.ts +++ b/src/codelens/CustomCodeLensProvider.ts @@ -25,6 +25,10 @@ export class CustomCodeLensProvider implements vscode.CodeLensProvider { title: "Test", command: "leetcode.testSolution", }), + new vscode.CodeLens(range, { + title: "Description", + command: "leetcode.previewProblem", + }), ]; } } diff --git a/src/commands/show.ts b/src/commands/show.ts index 8447e8da..fe2e860a 100644 --- a/src/commands/show.ts +++ b/src/commands/show.ts @@ -6,20 +6,37 @@ import * as path from "path"; import * as unescapeJS from "unescape-js"; import * as vscode from "vscode"; import { LeetCodeNode } from "../explorer/LeetCodeNode"; +import { leetCodeTreeDataProvider } from "../explorer/leetCodeTreeDataProvider"; import { leetCodeChannel } from "../leetCodeChannel"; import { leetCodeExecutor } from "../leetCodeExecutor"; import { leetCodeManager } from "../leetCodeManager"; import { IProblem, IQuickItemEx, languages, ProblemState } from "../shared"; import { DialogOptions, DialogType, promptForOpenOutputChannel, promptForSignIn } from "../utils/uiUtils"; -import { selectWorkspaceFolder } from "../utils/workspaceUtils"; +import { getActiveFilePath, selectWorkspaceFolder } from "../utils/workspaceUtils"; import * as wsl from "../utils/wslUtils"; import { leetCodePreviewProvider } from "../webview/leetCodePreviewProvider"; import { leetCodeSolutionProvider } from "../webview/leetCodeSolutionProvider"; import * as list from "./list"; -export async function previewProblem(node: IProblem, isSideMode: boolean = false): Promise { - const descString: string = await leetCodeExecutor.getDescription(node); - leetCodePreviewProvider.show(descString, node, isSideMode); +export async function previewProblem(source: IProblem | vscode.Uri | undefined, isSideMode: boolean = false): Promise { + try { + let problem: IProblem; + let descString: string; + if (source && "difficulty" in source) { + problem = source; + descString = await leetCodeExecutor.getDescription(problem.id); + } else { + const filename: string = (await getActiveFilePath(source))!; + const [meta, desc] = splitMetaOutput(await leetCodeExecutor.getDescription(filename)); + problem = leetCodeTreeDataProvider.getProblem(meta.id)!; + descString = desc; + isSideMode = true; + } + leetCodePreviewProvider.show(descString, problem, isSideMode); + } catch (error) { + leetCodeChannel.appendLine(error.toString()); + await promptForOpenOutputChannel("Failed to preview the problem. Please open the output channel for details.", DialogType.error); + } } export async function showProblem(node?: LeetCodeNode): Promise { @@ -146,6 +163,11 @@ async function parseProblemsToPicks(p: Promise): Promise { +class LeetCodeTreeDataProvider implements vscode.TreeDataProvider { + + private context: vscode.ExtensionContext; + private problemPool: Map; // maintains the ownership of all problems. private treeData: { Difficulty: Map, @@ -25,13 +28,19 @@ export class LeetCodeTreeDataProvider implements vscode.TreeDataProvider = this.onDidChangeTreeDataEvent.event; - constructor(private context: vscode.ExtensionContext) { } + public initialize(context: vscode.ExtensionContext): void { + this.context = context; + } public async refresh(): Promise { await this.getProblemData(); this.onDidChangeTreeDataEvent.fire(); } + public getProblem(id: string): IProblem | undefined { + return this.problemPool.get(id); + } + public getTreeItem(element: LeetCodeNode): vscode.TreeItem | Thenable { if (element.id === "notSignIn") { return { @@ -102,6 +111,7 @@ export class LeetCodeTreeDataProvider implements vscode.TreeDataProvider { // clear cache + this.problemPool = new Map(); this.treeData = { Difficulty: new Map(), Tag: new Map(), @@ -109,6 +119,8 @@ export class LeetCodeTreeDataProvider implements vscode.TreeDataProvider throw new Error("The environment doesn't meet requirements."); } + leetCodeTreeDataProvider.initialize(context); + leetCodeManager.on("statusChanged", () => { leetCodeStatusBarController.updateStatusBar(leetCodeManager.getStatus(), leetCodeManager.getUser()); leetCodeTreeDataProvider.refresh(); }); - const leetCodeTreeDataProvider: LeetCodeTreeDataProvider = new LeetCodeTreeDataProvider(context); - context.subscriptions.push( leetCodeStatusBarController, leetCodeChannel, @@ -51,7 +51,7 @@ export async function activate(context: vscode.ExtensionContext): Promise vscode.commands.registerCommand("leetcode.signout", () => leetCodeManager.signOut()), vscode.commands.registerCommand("leetcode.selectSessions", () => session.selectSession()), vscode.commands.registerCommand("leetcode.createSession", () => session.createSession()), - vscode.commands.registerCommand("leetcode.previewProblem", (node: LeetCodeNode) => show.previewProblem(node)), + vscode.commands.registerCommand("leetcode.previewProblem", (source: LeetCodeNode | vscode.Uri) => show.previewProblem(source)), vscode.commands.registerCommand("leetcode.showProblem", (node: LeetCodeNode) => show.showProblem(node)), vscode.commands.registerCommand("leetcode.searchProblem", () => show.searchProblem()), vscode.commands.registerCommand("leetcode.showSolution", (node: LeetCodeNode) => show.showSolution(node)), diff --git a/src/leetCodeExecutor.ts b/src/leetCodeExecutor.ts index 27b896c1..5bedbfb3 100644 --- a/src/leetCodeExecutor.ts +++ b/src/leetCodeExecutor.ts @@ -108,12 +108,12 @@ class LeetCodeExecutor implements Disposable { } public async showSolution(problemNode: IProblem, language: string): Promise { - const solution: string = await this.executeCommandWithProgressEx("Fetching top voted solution from discussions...", this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "show", problemNode.id, "--solution", "-l", language]); + const solution: string = await this.executeCommandWithProgressEx("Fetching top voted solution from discussions...", "node", [await this.getLeetCodeBinaryPath(), "show", problemNode.id, "--solution", "-l", language]); return solution; } - public async getDescription(problemNode: IProblem): Promise { - return await this.executeCommandWithProgressEx("Fetching problem description...", this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "show", problemNode.id, "-x"]); + public async getDescription(keyword: string): Promise { + return await this.executeCommandWithProgressEx("Fetching problem description...", this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "show", keyword, "-x"]); } public async listSessions(): Promise {