Skip to content

Commit 9b33df0

Browse files
Vigilansjdneo
authored andcommitted
Top voted solution webview (LeetCode-OpenSource#193)
1 parent 9164acb commit 9b33df0

File tree

6 files changed

+283
-29
lines changed

6 files changed

+283
-29
lines changed

package-lock.json

+57-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+22-2
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,11 @@
109109
"dark": "resources/dark/search.svg"
110110
}
111111
},
112+
{
113+
"command": "leetcode.showSolution",
114+
"title": "Show Top Voted Solution",
115+
"category": "LeetCode"
116+
},
112117
{
113118
"command": "leetcode.testSolution",
114119
"title": "Test in LeetCode",
@@ -171,6 +176,12 @@
171176
"when": "view == leetCodeExplorer && viewItem == problem",
172177
"group": "leetcode@1"
173178
},
179+
{
180+
181+
"command": "leetcode.showSolution",
182+
"when": "view == leetCodeExplorer && viewItem == problem",
183+
"group": "leetcode@1"
184+
},
174185
{
175186
"command": "leetcode.previewProblem",
176187
"when": "view == leetCodeExplorer && viewItem == problem",
@@ -182,6 +193,11 @@
182193
"command": "leetcode.showProblem",
183194
"when": "never"
184195
},
196+
{
197+
198+
"command": "leetcode.showSolution",
199+
"when": "never"
200+
},
185201
{
186202
"command": "leetcode.previewProblem",
187203
"when": "never"
@@ -288,7 +304,9 @@
288304
},
289305
"devDependencies": {
290306
"@types/fs-extra": "5.0.0",
307+
"@types/highlight.js": "^9.12.3",
291308
"@types/lodash.kebabcase": "^4.1.5",
309+
"@types/markdown-it": "0.0.7",
292310
"@types/mocha": "^2.2.42",
293311
"@types/node": "^7.0.43",
294312
"@types/require-from-string": "^1.2.0",
@@ -298,8 +316,10 @@
298316
},
299317
"dependencies": {
300318
"fs-extra": "^6.0.1",
301-
"vsc-leetcode-cli": "2.6.2",
319+
"highlight.js": "^9.15.6",
302320
"lodash.kebabcase": "^4.1.1",
303-
"require-from-string": "^2.0.2"
321+
"markdown-it": "^8.4.2",
322+
"require-from-string": "^2.0.2",
323+
"vsc-leetcode-cli": "2.6.2"
304324
}
305325
}

src/commands/show.ts

+49-20
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { LeetCodeNode } from "../explorer/LeetCodeNode";
88
import { leetCodeChannel } from "../leetCodeChannel";
99
import { leetCodeExecutor } from "../leetCodeExecutor";
1010
import { leetCodeManager } from "../leetCodeManager";
11+
import { leetCodeSolutionProvider } from "../leetCodeSolutionProvider";
1112
import { IProblem, IQuickItemEx, languages, ProblemState } from "../shared";
1213
import { DialogOptions, DialogType, promptForOpenOutputChannel, promptForSignIn } from "../utils/uiUtils";
1314
import { selectWorkspaceFolder } from "../utils/workspaceUtils";
@@ -39,18 +40,60 @@ export async function searchProblem(): Promise<void> {
3940
await showProblemInternal(choice.value);
4041
}
4142

42-
async function showProblemInternal(node: IProblem): Promise<void> {
43+
export async function showSolution(node?: LeetCodeNode): Promise<void> {
44+
if (!node) {
45+
return;
46+
}
47+
const language: string | undefined = await fetchProblemLanguage();
48+
if (!language) {
49+
return;
50+
}
4351
try {
44-
const leetCodeConfig: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("leetcode");
45-
let defaultLanguage: string | undefined = leetCodeConfig.get<string>("defaultLanguage");
46-
if (defaultLanguage && languages.indexOf(defaultLanguage) < 0) {
47-
defaultLanguage = undefined;
52+
let solution: string = await leetCodeExecutor.showSolution(node, language);
53+
// remove backslash in espaced \'...\'(generated by leetcode's database)
54+
solution = solution.replace(/\\'/g, "'");
55+
await leetCodeSolutionProvider.show(solution, node);
56+
} catch (error) {
57+
await promptForOpenOutputChannel("Failed to fetch the top voted solution. Please open the output channel for details.", DialogType.error);
58+
}
59+
}
60+
61+
// SUGGESTION: group config retriving into one file
62+
async function fetchProblemLanguage(): Promise<string | undefined> {
63+
const leetCodeConfig: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("leetcode");
64+
let defaultLanguage: string | undefined = leetCodeConfig.get<string>("defaultLanguage");
65+
if (defaultLanguage && languages.indexOf(defaultLanguage) < 0) {
66+
defaultLanguage = undefined;
67+
}
68+
const language: string | undefined = defaultLanguage || await vscode.window.showQuickPick(languages, { placeHolder: "Select the language you want to use" });
69+
// fire-and-forget default language query
70+
(async (): Promise<void> => {
71+
if (!defaultLanguage && leetCodeConfig.get<boolean>("showSetDefaultLanguageHint")) {
72+
const choice: vscode.MessageItem | undefined = await vscode.window.showInformationMessage(
73+
`Would you like to set '${language}' as your default language?`,
74+
DialogOptions.yes,
75+
DialogOptions.no,
76+
DialogOptions.never,
77+
);
78+
if (choice === DialogOptions.yes) {
79+
leetCodeConfig.update("defaultLanguage", language, true /* UserSetting */);
80+
} else if (choice === DialogOptions.never) {
81+
leetCodeConfig.update("showSetDefaultLanguageHint", false, true /* UserSetting */);
82+
}
4883
}
49-
const language: string | undefined = defaultLanguage || await vscode.window.showQuickPick(languages, { placeHolder: "Select the language you want to use" });
84+
})();
85+
return language;
86+
}
87+
88+
async function showProblemInternal(node: IProblem): Promise<void> {
89+
try {
90+
const language: string | undefined = await fetchProblemLanguage();
5091
if (!language) {
5192
return;
5293
}
5394

95+
// SUGGESTION: group config retriving into one file
96+
const leetCodeConfig: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("leetcode");
5497
let outDir: string = await selectWorkspaceFolder();
5598
let relativePath: string = (leetCodeConfig.get<string>("outputFolder") || "").trim();
5699
const matchResult: RegExpMatchArray | null = relativePath.match(/\$\{(.*?)\}/);
@@ -69,20 +112,6 @@ async function showProblemInternal(node: IProblem): Promise<void> {
69112
const originFilePath: string = await leetCodeExecutor.showProblem(node, language, outDir);
70113
const filePath: string = wsl.useWsl() ? await wsl.toWinPath(originFilePath) : originFilePath;
71114
await vscode.window.showTextDocument(vscode.Uri.file(filePath), { preview: false });
72-
73-
if (!defaultLanguage && leetCodeConfig.get<boolean>("showSetDefaultLanguageHint")) {
74-
const choice: vscode.MessageItem | undefined = await vscode.window.showInformationMessage(
75-
`Would you like to set '${language}' as your default language?`,
76-
DialogOptions.yes,
77-
DialogOptions.no,
78-
DialogOptions.never,
79-
);
80-
if (choice === DialogOptions.yes) {
81-
leetCodeConfig.update("defaultLanguage", language, true /* UserSetting */);
82-
} else if (choice === DialogOptions.never) {
83-
leetCodeConfig.update("showSetDefaultLanguageHint", false, true /* UserSetting */);
84-
}
85-
}
86115
} catch (error) {
87116
await promptForOpenOutputChannel("Failed to show the problem. Please open the output channel for details.", DialogType.error);
88117
}

src/extension.ts

+4
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { leetCodeExecutor } from "./leetCodeExecutor";
1717
import { leetCodeManager } from "./leetCodeManager";
1818
import { leetCodePreviewProvider } from "./leetCodePreviewProvider";
1919
import { leetCodeResultProvider } from "./leetCodeResultProvider";
20+
import { leetCodeSolutionProvider } from "./leetCodeSolutionProvider";
2021
import { leetCodeStatusBarItem } from "./leetCodeStatusBarItem";
2122

2223
export async function activate(context: vscode.ExtensionContext): Promise<void> {
@@ -32,12 +33,14 @@ export async function activate(context: vscode.ExtensionContext): Promise<void>
3233
const leetCodeTreeDataProvider: LeetCodeTreeDataProvider = new LeetCodeTreeDataProvider(context);
3334
leetCodePreviewProvider.initialize(context);
3435
leetCodeResultProvider.initialize(context);
36+
leetCodeSolutionProvider.initialize(context);
3537

3638
context.subscriptions.push(
3739
leetCodeStatusBarItem,
3840
leetCodeChannel,
3941
leetCodePreviewProvider,
4042
leetCodeResultProvider,
43+
leetCodeSolutionProvider,
4144
vscode.window.createTreeView("leetCodeExplorer", { treeDataProvider: leetCodeTreeDataProvider, showCollapseAll: true }),
4245
vscode.languages.registerCodeLensProvider({ scheme: "file" }, codeLensProvider),
4346
vscode.commands.registerCommand("leetcode.deleteCache", () => cache.deleteCache()),
@@ -49,6 +52,7 @@ export async function activate(context: vscode.ExtensionContext): Promise<void>
4952
vscode.commands.registerCommand("leetcode.previewProblem", (node: LeetCodeNode) => leetCodePreviewProvider.preview(node)),
5053
vscode.commands.registerCommand("leetcode.showProblem", (node: LeetCodeNode) => show.showProblem(node)),
5154
vscode.commands.registerCommand("leetcode.searchProblem", () => show.searchProblem()),
55+
vscode.commands.registerCommand("leetcode.showSolution", (node: LeetCodeNode) => show.showSolution(node)),
5256
vscode.commands.registerCommand("leetcode.refreshExplorer", () => leetCodeTreeDataProvider.refresh()),
5357
vscode.commands.registerCommand("leetcode.testSolution", (uri?: vscode.Uri) => test.testSolution(uri)),
5458
vscode.commands.registerCommand("leetcode.submitSolution", (uri?: vscode.Uri) => submit.submitSolution(uri)),

src/leetCodeExecutor.ts

+11-4
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,12 @@ class LeetCodeExecutor {
4848
}
4949
return false;
5050
}
51-
try { // Check company plugin
52-
await this.executeCommandEx("node", [await this.getLeetCodeBinaryPath(), "plugin", "-e", "company"]);
53-
} catch (error) { // Download company plugin and activate
54-
await this.executeCommandEx("node", [await this.getLeetCodeBinaryPath(), "plugin", "-i", "company"]);
51+
for (const plugin of ["company", "solution.discuss"]) {
52+
try { // Check plugin
53+
await this.executeCommandEx("node", [await this.getLeetCodeBinaryPath(), "plugin", "-e", plugin]);
54+
} catch (error) { // Download plugin and activate
55+
await this.executeCommandEx("node", [await this.getLeetCodeBinaryPath(), "plugin", "-i", plugin]);
56+
}
5557
}
5658
return true;
5759
}
@@ -87,6 +89,11 @@ class LeetCodeExecutor {
8789
return filePath;
8890
}
8991

92+
public async showSolution(problemNode: IProblem, language: string): Promise<string> {
93+
const solution: string = await this.executeCommandWithProgressEx("Fetching top voted solution from discussions...", "node", [await this.getLeetCodeBinaryPath(), "show", problemNode.id, "--solution", "-l", language]);
94+
return solution;
95+
}
96+
9097
public async getDescription(problemNode: IProblem): Promise<string> {
9198
return await this.executeCommandWithProgressEx("Fetching problem description...", "node", [await this.getLeetCodeBinaryPath(), "show", problemNode.id, "-x"]);
9299
}

0 commit comments

Comments
 (0)