From 7239ff122e277781f8e91df8d50942ece3846417 Mon Sep 17 00:00:00 2001 From: Sheng Chen Date: Wed, 8 May 2019 19:47:05 +0800 Subject: [PATCH 1/3] feat: Add 'show solution' in editor context menu & code lens --- package.json | 4 ++++ src/codelens/CustomCodeLensProvider.ts | 5 ++++ src/commands/show.ts | 29 +++++++++++------------ src/extension.ts | 2 +- src/leetCodeExecutor.ts | 4 ++-- src/utils/uiUtils.ts | 5 ++++ src/utils/workspaceUtils.ts | 4 ++++ src/webview/leetCodePreviewProvider.ts | 17 ++++---------- src/webview/leetCodeSolutionProvider.ts | 31 ++++++++++++------------- 9 files changed, 55 insertions(+), 46 deletions(-) diff --git a/package.json b/package.json index 63f95049..753f79a1 100644 --- a/package.json +++ b/package.json @@ -221,6 +221,10 @@ { "command": "leetcode.submitSolution", "group": "leetcode@2" + }, + { + "command": "leetcode.showSolution", + "group": "leetcode@3" } ] }, diff --git a/src/codelens/CustomCodeLensProvider.ts b/src/codelens/CustomCodeLensProvider.ts index 001ccc0b..96493472 100644 --- a/src/codelens/CustomCodeLensProvider.ts +++ b/src/codelens/CustomCodeLensProvider.ts @@ -25,6 +25,11 @@ export class CustomCodeLensProvider implements vscode.CodeLensProvider { title: "Test", command: "leetcode.testSolution", }), + new vscode.CodeLens(range, { + title: "Solution", + command: "leetcode.showSolution", + arguments: [document.uri], + }), ]; } } diff --git a/src/commands/show.ts b/src/commands/show.ts index 24d3b50f..1e8dac7b 100644 --- a/src/commands/show.ts +++ b/src/commands/show.ts @@ -17,9 +17,9 @@ 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 { +export async function previewProblem(node: IProblem): Promise { const descString: string = await leetCodeExecutor.getDescription(node); - leetCodePreviewProvider.show(descString, node, isSideMode); + leetCodePreviewProvider.show(descString, node); } export async function showProblem(node?: LeetCodeNode): Promise { @@ -47,17 +47,24 @@ export async function searchProblem(): Promise { await showProblemInternal(choice.value); } -export async function showSolution(node?: LeetCodeNode): Promise { - if (!node) { +export async function showSolution(input: LeetCodeNode | vscode.Uri): Promise { + let problemInput: string | undefined; + if (input instanceof LeetCodeNode) { + problemInput = input.id; + } else if (input instanceof vscode.Uri) { + problemInput = `"${input.fsPath}"`; + } else { + vscode.window.showErrorMessage("Invalid input to fetch the solution data"); return; } + const language: string | undefined = await fetchProblemLanguage(); if (!language) { return; } try { - const solution: string = await leetCodeExecutor.showSolution(node, language); - leetCodeSolutionProvider.show(unescapeJS(solution), node); + const solution: string = await leetCodeExecutor.showSolution(problemInput, language); + leetCodeSolutionProvider.show(unescapeJS(solution)); } catch (error) { leetCodeChannel.appendLine(error.toString()); await promptForOpenOutputChannel("Failed to fetch the top voted solution. Please open the output channel for details.", DialogType.error); @@ -117,7 +124,7 @@ async function showProblemInternal(node: IProblem): Promise { const filePath: string = wsl.useWsl() ? await wsl.toWinPath(originFilePath) : originFilePath; await Promise.all([ vscode.window.showTextDocument(vscode.Uri.file(filePath), { preview: false, viewColumn: vscode.ViewColumn.One }), - movePreviewAsideIfNeeded(node), + previewProblem(node), promptHintMessage( "hint.commentDescription", 'You can generate the code file with problem description in the comments by enabling "leetcode.showCommentDescription".', @@ -130,14 +137,6 @@ async function showProblemInternal(node: IProblem): Promise { } } -async function movePreviewAsideIfNeeded(node: IProblem): Promise { - if (vscode.workspace.getConfiguration("leetcode").get("enableSideMode", true)) { - return previewProblem(node, true); - } else { - return Promise.resolve(); - } -} - async function parseProblemsToPicks(p: Promise): Promise>> { return new Promise(async (resolve: (res: Array>) => void): Promise => { const picks: Array> = (await p).map((problem: IProblem) => Object.assign({}, { diff --git a/src/extension.ts b/src/extension.ts index 2ebefd9b..978d90ae 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -56,7 +56,7 @@ export async function activate(context: vscode.ExtensionContext): Promise vscode.commands.registerCommand("leetcode.previewProblem", (node: LeetCodeNode) => show.previewProblem(node)), 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)), + vscode.commands.registerCommand("leetcode.showSolution", (input: LeetCodeNode | vscode.Uri) => show.showSolution(input)), vscode.commands.registerCommand("leetcode.refreshExplorer", () => leetCodeTreeDataProvider.refresh()), vscode.commands.registerCommand("leetcode.testSolution", (uri?: vscode.Uri) => test.testSolution(uri)), vscode.commands.registerCommand("leetcode.submitSolution", (uri?: vscode.Uri) => submit.submitSolution(uri)), diff --git a/src/leetCodeExecutor.ts b/src/leetCodeExecutor.ts index 27b896c1..ac110190 100644 --- a/src/leetCodeExecutor.ts +++ b/src/leetCodeExecutor.ts @@ -107,8 +107,8 @@ class LeetCodeExecutor implements Disposable { return filePath; } - 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]); + public async showSolution(input: string, language: string): Promise { + const solution: string = await this.executeCommandWithProgressEx("Fetching top voted solution from discussions...", this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "show", input, "--solution", "-l", language]); return solution; } diff --git a/src/utils/uiUtils.ts b/src/utils/uiUtils.ts index 845865e8..0774dc4a 100644 --- a/src/utils/uiUtils.ts +++ b/src/utils/uiUtils.ts @@ -96,6 +96,11 @@ export async function openUrl(url: string): Promise { vscode.commands.executeCommand("vscode.open", vscode.Uri.parse(url)); } +export async function hideSideBar(): Promise { + await vscode.commands.executeCommand("workbench.action.focusSideBar"); + await vscode.commands.executeCommand("workbench.action.toggleSidebarVisibility"); +} + export enum DialogType { info = "info", warning = "warning", diff --git a/src/utils/workspaceUtils.ts b/src/utils/workspaceUtils.ts index 425074df..a21438b4 100644 --- a/src/utils/workspaceUtils.ts +++ b/src/utils/workspaceUtils.ts @@ -44,3 +44,7 @@ export async function getActiveFilePath(uri?: vscode.Uri): Promise("enableSideMode", true); +} diff --git a/src/webview/leetCodePreviewProvider.ts b/src/webview/leetCodePreviewProvider.ts index 8d186b29..cc48579d 100644 --- a/src/webview/leetCodePreviewProvider.ts +++ b/src/webview/leetCodePreviewProvider.ts @@ -3,6 +3,8 @@ import { commands, ViewColumn } from "vscode"; import { IProblem } from "../shared"; +import { hideSideBar } from "../utils/uiUtils"; +import { isSideViewEnabled } from "../utils/workspaceUtils"; import { ILeetCodeWebviewOption, LeetCodeWebview } from "./LeetCodeWebview"; import { markdownEngine } from "./markdownEngine"; @@ -13,17 +15,13 @@ class LeetCodePreviewProvider extends LeetCodeWebview { private description: IDescription; private sideMode: boolean = false; - public isSideMode(): boolean { - return this.sideMode; - } - - public show(descString: string, node: IProblem, isSideMode: boolean = false): void { + public show(descString: string, node: IProblem): void { this.description = this.parseDescription(descString, node); this.node = node; - this.sideMode = isSideMode; + this.sideMode = isSideViewEnabled(); this.showWebviewInternal(); if (this.sideMode) { - this.hideSideBar(); // For better view area + hideSideBar(); // For better view area } } @@ -134,11 +132,6 @@ class LeetCodePreviewProvider extends LeetCodeWebview { } } - private async hideSideBar(): Promise { - await commands.executeCommand("workbench.action.focusSideBar"); - await commands.executeCommand("workbench.action.toggleSidebarVisibility"); - } - private parseDescription(descString: string, problem: IProblem): IDescription { const [ /* title */, , diff --git a/src/webview/leetCodeSolutionProvider.ts b/src/webview/leetCodeSolutionProvider.ts index 952af2cd..2eb56bae 100644 --- a/src/webview/leetCodeSolutionProvider.ts +++ b/src/webview/leetCodeSolutionProvider.ts @@ -2,33 +2,33 @@ // Licensed under the MIT license. import { ViewColumn } from "vscode"; -import { IProblem } from "../shared"; -import { leetCodePreviewProvider } from "./leetCodePreviewProvider"; +import { isSideViewEnabled } from "../utils/workspaceUtils"; import { ILeetCodeWebviewOption, LeetCodeWebview } from "./LeetCodeWebview"; import { markdownEngine } from "./markdownEngine"; class LeetCodeSolutionProvider extends LeetCodeWebview { protected readonly viewType: string = "leetcode.solution"; + private problemName: string; private solution: Solution; - public show(solutionString: string, problem: IProblem): void { - this.solution = this.parseSolution(solutionString, problem); + public show(solutionString: string): void { + this.solution = this.parseSolution(solutionString); this.showWebviewInternal(); } protected getWebviewOption(): ILeetCodeWebviewOption { - if (!leetCodePreviewProvider.isSideMode()) { - return { - title: `${this.solution.problem}: Solution`, - viewColumn: ViewColumn.One, - }; - } else { + if (isSideViewEnabled()) { return { title: "Solution", viewColumn: ViewColumn.Two, preserveFocus: true, }; + } else { + return { + title: `Solution: ${this.problemName}`, + viewColumn: ViewColumn.One, + }; } } @@ -66,17 +66,17 @@ class LeetCodeSolutionProvider extends LeetCodeWebview { delete this.solution; } - private parseSolution(raw: string, problem: IProblem): Solution { + private parseSolution(raw: string): Solution { + raw = raw.slice(1); // skip first empty line + [this.problemName, raw] = raw.split(/\n\n([^]+)/); // parse problem name and skip one line const solution: Solution = new Solution(); // [^] matches everything including \n, yet can be replaced by . in ES2018's `m` flag - raw = raw.slice(1); // skip first empty line - [solution.title, raw] = raw.split(/\n\n([^]+)/); // parse title and skip one line - [solution.url, raw] = raw.split(/\n\n([^]+)/); // parse url and skip one line + [solution.title, raw] = raw.split(/\n\n([^]+)/); + [solution.url, raw] = raw.split(/\n\n([^]+)/); [solution.lang, raw] = raw.match(/\* Lang:\s+(.+)\n([^]+)/)!.slice(1); [solution.author, raw] = raw.match(/\* Author:\s+(.+)\n([^]+)/)!.slice(1); [solution.votes, raw] = raw.match(/\* Votes:\s+(\d+)\n\n([^]+)/)!.slice(1); solution.body = raw; - solution.problem = problem.name; return solution; } } @@ -89,7 +89,6 @@ class Solution { public author: string = ""; public votes: string = ""; public body: string = ""; // Markdown supported - public problem: string = ""; } export const leetCodeSolutionProvider: LeetCodeSolutionProvider = new LeetCodeSolutionProvider(); From 855a648543222f788121d5aff86a4e860041b810 Mon Sep 17 00:00:00 2001 From: Sheng Chen Date: Thu, 9 May 2019 10:09:26 +0800 Subject: [PATCH 2/3] shrink the scope of the PR --- src/codelens/CustomCodeLensProvider.ts | 2 ++ src/commands/show.ts | 12 +++++++++--- src/utils/uiUtils.ts | 5 ----- src/utils/workspaceUtils.ts | 4 ---- src/webview/leetCodePreviewProvider.ts | 17 ++++++++++++----- src/webview/leetCodeSolutionProvider.ts | 4 ++-- 6 files changed, 25 insertions(+), 19 deletions(-) diff --git a/src/codelens/CustomCodeLensProvider.ts b/src/codelens/CustomCodeLensProvider.ts index 96493472..3ee7270d 100644 --- a/src/codelens/CustomCodeLensProvider.ts +++ b/src/codelens/CustomCodeLensProvider.ts @@ -20,10 +20,12 @@ export class CustomCodeLensProvider implements vscode.CodeLensProvider { new vscode.CodeLens(range, { title: "Submit", command: "leetcode.submitSolution", + arguments: [document.uri], }), new vscode.CodeLens(range, { title: "Test", command: "leetcode.testSolution", + arguments: [document.uri], }), new vscode.CodeLens(range, { title: "Solution", diff --git a/src/commands/show.ts b/src/commands/show.ts index 1e8dac7b..77256dbf 100644 --- a/src/commands/show.ts +++ b/src/commands/show.ts @@ -17,9 +17,9 @@ import { leetCodePreviewProvider } from "../webview/leetCodePreviewProvider"; import { leetCodeSolutionProvider } from "../webview/leetCodeSolutionProvider"; import * as list from "./list"; -export async function previewProblem(node: IProblem): Promise { +export async function previewProblem(node: IProblem, isSideMode: boolean = false): Promise { const descString: string = await leetCodeExecutor.getDescription(node); - leetCodePreviewProvider.show(descString, node); + leetCodePreviewProvider.show(descString, node, isSideMode); } export async function showProblem(node?: LeetCodeNode): Promise { @@ -124,7 +124,7 @@ async function showProblemInternal(node: IProblem): Promise { const filePath: string = wsl.useWsl() ? await wsl.toWinPath(originFilePath) : originFilePath; await Promise.all([ vscode.window.showTextDocument(vscode.Uri.file(filePath), { preview: false, viewColumn: vscode.ViewColumn.One }), - previewProblem(node), + movePreviewAsideIfNeeded(node), promptHintMessage( "hint.commentDescription", 'You can generate the code file with problem description in the comments by enabling "leetcode.showCommentDescription".', @@ -137,6 +137,12 @@ async function showProblemInternal(node: IProblem): Promise { } } +async function movePreviewAsideIfNeeded(node: IProblem): Promise { + if (vscode.workspace.getConfiguration("leetcode").get("enableSideMode", true)) { + return previewProblem(node, true); + } +} + async function parseProblemsToPicks(p: Promise): Promise>> { return new Promise(async (resolve: (res: Array>) => void): Promise => { const picks: Array> = (await p).map((problem: IProblem) => Object.assign({}, { diff --git a/src/utils/uiUtils.ts b/src/utils/uiUtils.ts index 0774dc4a..845865e8 100644 --- a/src/utils/uiUtils.ts +++ b/src/utils/uiUtils.ts @@ -96,11 +96,6 @@ export async function openUrl(url: string): Promise { vscode.commands.executeCommand("vscode.open", vscode.Uri.parse(url)); } -export async function hideSideBar(): Promise { - await vscode.commands.executeCommand("workbench.action.focusSideBar"); - await vscode.commands.executeCommand("workbench.action.toggleSidebarVisibility"); -} - export enum DialogType { info = "info", warning = "warning", diff --git a/src/utils/workspaceUtils.ts b/src/utils/workspaceUtils.ts index a21438b4..425074df 100644 --- a/src/utils/workspaceUtils.ts +++ b/src/utils/workspaceUtils.ts @@ -44,7 +44,3 @@ export async function getActiveFilePath(uri?: vscode.Uri): Promise("enableSideMode", true); -} diff --git a/src/webview/leetCodePreviewProvider.ts b/src/webview/leetCodePreviewProvider.ts index cc48579d..8d186b29 100644 --- a/src/webview/leetCodePreviewProvider.ts +++ b/src/webview/leetCodePreviewProvider.ts @@ -3,8 +3,6 @@ import { commands, ViewColumn } from "vscode"; import { IProblem } from "../shared"; -import { hideSideBar } from "../utils/uiUtils"; -import { isSideViewEnabled } from "../utils/workspaceUtils"; import { ILeetCodeWebviewOption, LeetCodeWebview } from "./LeetCodeWebview"; import { markdownEngine } from "./markdownEngine"; @@ -15,13 +13,17 @@ class LeetCodePreviewProvider extends LeetCodeWebview { private description: IDescription; private sideMode: boolean = false; - public show(descString: string, node: IProblem): void { + public isSideMode(): boolean { + return this.sideMode; + } + + public show(descString: string, node: IProblem, isSideMode: boolean = false): void { this.description = this.parseDescription(descString, node); this.node = node; - this.sideMode = isSideViewEnabled(); + this.sideMode = isSideMode; this.showWebviewInternal(); if (this.sideMode) { - hideSideBar(); // For better view area + this.hideSideBar(); // For better view area } } @@ -132,6 +134,11 @@ class LeetCodePreviewProvider extends LeetCodeWebview { } } + private async hideSideBar(): Promise { + await commands.executeCommand("workbench.action.focusSideBar"); + await commands.executeCommand("workbench.action.toggleSidebarVisibility"); + } + private parseDescription(descString: string, problem: IProblem): IDescription { const [ /* title */, , diff --git a/src/webview/leetCodeSolutionProvider.ts b/src/webview/leetCodeSolutionProvider.ts index 2eb56bae..0681c291 100644 --- a/src/webview/leetCodeSolutionProvider.ts +++ b/src/webview/leetCodeSolutionProvider.ts @@ -2,7 +2,7 @@ // Licensed under the MIT license. import { ViewColumn } from "vscode"; -import { isSideViewEnabled } from "../utils/workspaceUtils"; +import { leetCodePreviewProvider } from "./leetCodePreviewProvider"; import { ILeetCodeWebviewOption, LeetCodeWebview } from "./LeetCodeWebview"; import { markdownEngine } from "./markdownEngine"; @@ -18,7 +18,7 @@ class LeetCodeSolutionProvider extends LeetCodeWebview { } protected getWebviewOption(): ILeetCodeWebviewOption { - if (isSideViewEnabled()) { + if (!leetCodePreviewProvider.isSideMode()) { return { title: "Solution", viewColumn: ViewColumn.Two, From 1e13e1c30b4cc468f0c7617b279fb300182aa983 Mon Sep 17 00:00:00 2001 From: Sheng Chen Date: Thu, 9 May 2019 10:10:35 +0800 Subject: [PATCH 3/3] Correct the if check --- src/webview/leetCodeSolutionProvider.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/webview/leetCodeSolutionProvider.ts b/src/webview/leetCodeSolutionProvider.ts index 0681c291..59c548d6 100644 --- a/src/webview/leetCodeSolutionProvider.ts +++ b/src/webview/leetCodeSolutionProvider.ts @@ -18,7 +18,7 @@ class LeetCodeSolutionProvider extends LeetCodeWebview { } protected getWebviewOption(): ILeetCodeWebviewOption { - if (!leetCodePreviewProvider.isSideMode()) { + if (leetCodePreviewProvider.isSideMode()) { return { title: "Solution", viewColumn: ViewColumn.Two, pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy