Skip to content

Commit 4ad07a8

Browse files
authored
feat: Add 'show solution' in editor context menu & code lens (LeetCode-OpenSource#313)
1 parent a521cf5 commit 4ad07a8

File tree

6 files changed

+39
-24
lines changed

6 files changed

+39
-24
lines changed

package.json

+4
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

+7
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,17 @@ export class CustomCodeLensProvider implements vscode.CodeLensProvider {
2020
new vscode.CodeLens(range, {
2121
title: "Submit",
2222
command: "leetcode.submitSolution",
23+
arguments: [document.uri],
2324
}),
2425
new vscode.CodeLens(range, {
2526
title: "Test",
2627
command: "leetcode.testSolution",
28+
arguments: [document.uri],
29+
}),
30+
new vscode.CodeLens(range, {
31+
title: "Solution",
32+
command: "leetcode.showSolution",
33+
arguments: [document.uri],
2734
}),
2835
];
2936
}

src/commands/show.ts

+11-6
Original file line numberDiff line numberDiff line change
@@ -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);
@@ -133,8 +140,6 @@ async function showProblemInternal(node: IProblem): Promise<void> {
133140
async function movePreviewAsideIfNeeded(node: IProblem): Promise<void> {
134141
if (vscode.workspace.getConfiguration("leetcode").get<boolean>("enableSideMode", true)) {
135142
return previewProblem(node, true);
136-
} else {
137-
return Promise.resolve();
138143
}
139144
}
140145

src/extension.ts

+1-1
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

+2-2
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/webview/leetCodeSolutionProvider.ts

+14-15
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";
65
import { leetCodePreviewProvider } from "./leetCodePreviewProvider";
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 (leetCodePreviewProvider.isSideMode()) {
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)