8000 feat: Add 'show solution' in editor context menu & code lens · haijunjiang/vscode-leetcode@7239ff1 · GitHub
[go: up one dir, main page]

Skip to content

Commit 7239ff1

Browse files
committed
feat: Add 'show solution' in editor context menu & code lens
1 parent a521cf5 commit 7239ff1

9 files changed

+55
-46
lines changed

package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,10 @@
221221
{
222222
"command": "leetcode.submitSolution",
223223
"group": "leetcode@2"
224+
},
225+
{
226+
"command": "leetcode.showSolution",
227+
"group": "leetcode@3"
224228
}
225229
]
226230
},

src/codelens/CustomCodeLensProvider.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ export class CustomCodeLensProvider implements vscode.CodeLensProvider {
2525
title: "Test",
2626
command: "leetcode.testSolution",
2727
}),
28+
new vscode.CodeLens(range, {
29+
title: "Solution",
30+
command: "leetcode.showSolution",
31+
arguments: [document.uri],
32+
}),
2833
];
2934
}
3035
}

src/commands/show.ts

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ import { leetCodePreviewProvider } from "../webview/leetCodePreviewProvider";
1717
import { leetCodeSolutionProvider } from "../webview/leetCodeSolutionProvider";
1818
import * as list from "./list";
1919

20-
export async function previewProblem(node: IProblem, isSideMode: boolean = false): Promise<void> {
20+
export async function previewProblem(node: IProblem): Promise<void> {
2121
const descString: string = await leetCodeExecutor.getDescription(node);
22-
leetCodePreviewProvider.show(descString, node, isSideMode);
22+
leetCodePreviewProvider.show(descString, node);
2323
}
2424

2525
export async function showProblem(node?: LeetCodeNode): Promise<void> {
@@ -47,17 +47,24 @@ export async function searchProblem(): Promise<void> {
4747
await showProblemInternal(choice.value);
4848
}
4949

50-
export async function showSolution(node?: LeetCodeNode): Promise<void> {
51-
if (!node) {
50+
export async function showSolution(input: LeetCodeNode | vscode.Uri): Promise<void> {
51+
let problemInput: string | undefined;
52+
if (input instanceof LeetCodeNode) {
53+
problemInput = input.id;
54+
} else if (input instanceof vscode.Uri) {
55+
problemInput = `"${input.fsPath}"`;
56+
} else {
57+
vscode.window.showErrorMessage("Invalid input to fetch the solution data");
5258
return;
5359
}
60+
5461
const language: string | undefined = await fetchProblemLanguage();
5562
if (!language) {
5663
return;
5764
}
5865
try {
59-
const solution: string = await leetCodeExecutor.showSolution(node, language);
60-
leetCodeSolutionProvider.show(unescapeJS(solution), node);
66+
const solution: string = await leetCodeExecutor.showSolution(problemInput, language);
67+
leetCodeSolutionProvider.show(unescapeJS(solution));
6168
} catch (error) {
6269
leetCodeChannel.appendLine(error.toString());
6370
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<void> {
117124
const filePath: string = wsl.useWsl() ? await wsl.toWinPath(originFilePath) : originFilePath;
118125
await Promise.all([
119126
vscode.window.showTextDocument(vscode.Uri.file(filePath), { preview: false, viewColumn: vscode.ViewColumn.One }),
120-
movePreviewAsideIfNeeded(node),
127+
previewProblem(node),
121128
promptHintMessage(
122129
"hint.commentDescription",
123130
'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<void> {
130137
}
131138
}
132139

133-
async function movePreviewAsideIfNeeded(node: IProblem): Promise<void> {
134-
if (vscode.workspace.getConfiguration("leetcode").get<boolean>("enableSideMode", true)) {
135-
return previewProblem(node, true);
136-
} else {
137-
return Promise.resolve();
138-
}
139-
}
140-
141140
async function parseProblemsToPicks(p: Promise<IProblem[]>): Promise<Array<IQuickItemEx<IProblem>>> {
142141
return new Promise(async (resolve: (res: Array<IQuickItemEx<IProblem>>) => void): Promise<void> => {
143142
const picks: Array<IQuickItemEx<IProblem>> = (await p).map((problem: IProblem) => Object.assign({}, {

src/extension.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ export async function activate(context: vscode.ExtensionContext): Promise<void>
5656
vscode.commands.registerCommand("leetcode.previewProblem", (node: LeetCodeNode) => show.previewProblem(node)),
5757
vscode.commands.registerCommand("leetcode.showProblem", (node: LeetCodeNode) => show.showProblem(node)),
5858
vscode.commands.registerCommand("leetcode.searchProblem", () => show.searchProblem()),
59-
vscode.commands.registerCommand("leetcode.showSolution", (node: LeetCodeNode) => show.showSolution(node)),
59+
vscode.commands.registerCommand("leetcode.showSolution", (input: LeetCodeNode | vscode.Uri) => show.showSolution(input)),
6060
vscode.commands.registerCommand("leetcode.refreshExplorer", () => leetCodeTreeDataProvider.refresh()),
6161
vscode.commands.registerCommand("leetcode.testSolution", (uri?: vscode.Uri) => test.testSolution(uri)),
6262
vscode.commands.registerCommand("leetcode.submitSolution", (uri?: vscode.Uri) => submit.submitSolution(uri)),

src/leetCodeExecutor.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,8 @@ class LeetCodeExecutor implements Disposable {
107107
return filePath;
108108
}
109109

110-
public async showSolution(problemNode: IProblem, language: string): Promise<string> {
111-
const solution: string = await this.executeCommandWithProgressEx("Fetching top voted solution from discussions...", this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "show", problemNode.id, "--solution", "-l", language]);
110+
public async showSolution(input: string, language: string): Promise<string> {
111+
const solution: string = await this.executeCommandWithProgressEx("Fetching top voted solution from discussions...", this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "show", input, "--solution", "-l", language]);
112112
return solution;
113113
}
114114

src/utils/uiUtils.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,11 @@ export async function openUrl(url: string): Promise<void> {
9696
vscode.commands.executeCommand("vscode.open", vscode.Uri.parse(url));
9797
}
9898

99+
export async function hideSideBar(): Promise<void> {
100+
await vscode.commands.executeCommand("workbench.action.focusSideBar");
101+
await vscode.commands.executeCommand("workbench.action.toggleSidebarVisibility");
102+
}
103+
99104
export enum DialogType {
100105
info = "info",
101106
warning = "warning",

src/utils/workspaceUtils.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,7 @@ export async function getActiveFilePath(uri?: vscode.Uri): Promise<string | unde
4444
export function getWorkspaceConfiguration(): vscode.WorkspaceConfiguration {
4545
return vscode.workspace.getConfiguration("leetcode");
4646
}
47+
48+
export function isSideViewEnabled(): boolean {
49+
return getWorkspaceConfiguration().get<boolean>("enableSideMode", true);
50+
}

src/webview/leetCodePreviewProvider.ts

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
import { commands, ViewColumn } from "vscode";
55
import { IProblem } from "../shared";
6+
import { hideSideBar } from "../utils/uiUtils";
7+
import { isSideViewEnabled } from "../utils/workspaceUtils";
68
import { ILeetCodeWebviewOption, LeetCodeWebview } from "./LeetCodeWebview";
79
import { markdownEngine } from "./markdownEngine";
810

@@ -13,17 +15,13 @@ class LeetCodePreviewProvider extends LeetCodeWebview {
1315
private description: IDescription;
1416
private sideMode: boolean = false;
1517

16-
public isSideMode(): boolean {
17-
return this.sideMode;
18-
}
19-
20-
public show(descString: string, node: IProblem, isSideMode: boolean = false): void {
18+
public show(descString: string, node: IProblem): void {
2119
this.description = this.parseDescription(descString, node);
2220
this.node = node;
23-
this.sideMode = isSideMode;
21+
this.sideMode = isSideViewEnabled();
2422
this.showWebviewInternal();
2523
if (this.sideMode) {
26-
this.hideSideBar(); // For better view area
24+
hideSideBar(); // For better view area
2725
}
2826
}
2927

@@ -134,11 +132,6 @@ class LeetCodePreviewProvider extends LeetCodeWebview {
134132
}
135133
}
136134

137-
private async hideSideBar(): Promise<void> {
138-
await commands.executeCommand("workbench.action.focusSideBar");
139-
await commands.executeCommand("workbench.action.toggleSidebarVisibility");
140-
}
141-
142135
private parseDescription(descString: string, problem: IProblem): IDescription {
143136
const [
144137
/* title */, ,

src/webview/leetCodeSolutionProvider.ts

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,33 +2,33 @@
22
// Licensed under the MIT license.
33

44
import { ViewColumn } from "vscode";
5-
import { IProblem } from "../shared";
6-
import { leetCodePreviewProvider } from "./leetCodePreviewProvider";
5+
import { isSideViewEnabled } from "../utils/workspaceUtils";
76
import { ILeetCodeWebviewOption, LeetCodeWebview } from "./LeetCodeWebview";
87
import { markdownEngine } from "./markdownEngine";
98

109
class LeetCodeSolutionProvider extends LeetCodeWebview {
1110

1211
protected readonly viewType: string = "leetcode.solution";
12+
private problemName: string;
1313
private solution: Solution;
1414

15-
public show(solutionString: string, problem: IProblem): void {
16-
this.solution = this.parseSolution(solutionString, problem);
15+
public show(solutionString: string): void {
16+
this.solution = this.parseSolution(solutionString);
1717
this.showWebviewInternal();
1818
}
1919

2020
protected getWebviewOption(): ILeetCodeWebviewOption {
21-
if (!leetCodePreviewProvider.isSideMode()) {
22-
return {
23-
title: `${this.solution.problem}: Solution`,
24-
viewColumn: ViewColumn.One,
25-
};
26-
} else {
21+
if (isSideViewEnabled()) {
2722
return {
2823
title: "Solution",
2924
viewColumn: ViewColumn.Two,
3025
preserveFocus: true,
3126
};
27+
} else {
28+
return {
29+
title: `Solution: ${this.problemName}`,
30+
viewColumn: ViewColumn.One,
31+
};
3232
}
3333
}
3434

@@ -66,17 +66,17 @@ class LeetCodeSolutionProvider extends LeetCodeWebview {
6666
delete this.solution;
6767
}
6868

69-
private parseSolution(raw: string, problem: IProblem): Solution {
69+
private parseSolution(raw: string): Solution {
70+
raw = raw.slice(1); // skip first empty line
71+
[this.problemName, raw] = raw.split(/\n\n([^]+)/); // parse problem name and skip one line
7072
const solution: Solution = new Solution();
7173
// [^] matches everything including \n, yet can be replaced by . in ES2018's `m` flag
72-
raw = raw.slice(1); // skip first empty line
73-
[solution.title, raw] = raw.split(/\n\n([^]+)/); // parse title and skip one line
74-
[solution.url, raw] = raw.split(/\n\n([^]+)/); // parse url and skip one line
74+
[solution.title, raw] = raw.split(/\n\n([^]+)/);
75+
[solution.url, raw] = raw.split(/\n\n([^]+)/);
7576
[solution.lang, raw] = raw.match(/\* Lang:\s+(.+)\n([^]+)/)!.slice(1);
7677
[solution.author, raw] = raw.match(/\* Author:\s+(.+)\n([^]+)/)!.slice(1);
7778
[solution.votes, raw] = raw.match(/\* Votes:\s+(\d+)\n\n([^]+)/)!.slice(1);
7879
solution.body = raw;
79-
solution.problem = problem.name;
8080
return solution;
8181
}
8282
}
@@ -89,7 +89,6 @@ class Solution {
8989
public author: string = "";
9090
public votes: string = "";
9191
public body: string = ""; // Markdown supported
92-
public problem: string = "";
9392
}
9493

9594
export const leetCodeSolutionProvider: LeetCodeSolutionProvider = new LeetCodeSolutionProvider();

0 commit comments

Comments
 (0)
0