diff --git a/README.md b/README.md
index 21b3afaf..7e89a880 100644
--- a/README.md
+++ b/README.md
@@ -141,6 +141,7 @@
| `leetcode.outputFolder`| Specify the relative path to save the problem files. Besides using customized path, there are also several reserved words which can be used here:
- `${tag}`: Categorize the problem according to their tags.
- `${language}`: Categorize the problem according to their language.
- `${difficulty}`: Categorize the problem according to their difficulty.
| N/A |
| `leetcode.enableStatusBar` | Specify whether the LeetCode status bar will be shown or not. | `true` |
| `leetcode.enableShortcuts` | Specify whether the submit and test shortcuts in editor or not. | `true` |
+| `leetcode.enableSideMode` | Specify whether `preview`, `solution` and `submission` tab should be grouped into the second editor column when solving a problem. | `true` |
| `leetcode.nodePath` | Specify the `Node.js` executable path. | `node` |
## Want Help?
diff --git a/docs/README_zh-CN.md b/docs/README_zh-CN.md
index 070f5d61..554103b7 100644
--- a/docs/README_zh-CN.md
+++ b/docs/README_zh-CN.md
@@ -141,6 +141,7 @@
| `leetcode.outputFolder` | 指定保存文件时所用的相对文件夹路径。除了用户自定义路径外,也可以使用保留项,包括:- `${tag}`: 根据题目的类别进行分类。
- `${language}`: 根据题目的语言进行分类。
- `${difficulty}`: 根据题目的难度进行分类。
| N/A |
| `leetcode.enableStatusBar` | 指定是否在 VS Code 下方显示插件状态栏。 | `true` |
| `leetcode.enableShortcuts` | 指定是否在 VS Code 编辑文件下方显示提交和测试的快捷按钮。 | `true` |
+| `leetcode.enableSideMode` | 指定在解决一道题时,是否将`问题预览`、`高票答案`与`提交结果`窗口集中在编辑器的第二栏。 | `true` |
| `leetcode.nodePath` | 指定 `Node.js` 可执行文件的路径。 | `node` |
## 需要帮助?
diff --git a/package-lock.json b/package-lock.json
index 92f93c1a..9db2eaa5 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1782,9 +1782,9 @@
}
},
"vsc-leetcode-cli": {
- "version": "2.6.3",
- "resolved": "https://registry.npmjs.org/vsc-leetcode-cli/-/vsc-leetcode-cli-2.6.3.tgz",
- "integrity": "sha512-o6rR4FRaYFV6JBV3bLEvi/OCgRknxRZyC2MQY/ayS9emDNjS/9wr1LDoWJn6tDIR7JwOFLSSTQcpc3DwMsFtkA==",
+ "version": "2.6.4",
+ "resolved": "https://registry.npmjs.org/vsc-leetcode-cli/-/vsc-leetcode-cli-2.6.4.tgz",
+ "integrity": "sha512-vHcy2WQmQlcm2jB2m5Z+2RfuW0/4S+WjOhXE7twn2lvMgb9jqq3h+MYVHr1ijxraRwiCb5sGknz0T17zkob3gA==",
"requires": {
"ansi-styles": "3.2.1",
"cheerio": "0.20.0",
diff --git a/package.json b/package.json
index 1971214b..6df14382 100644
--- a/package.json
+++ b/package.json
@@ -301,6 +301,12 @@
"scope": "application",
"description": "Show the submit and test shortcuts in editor or not."
},
+ "leetcode.enableSideMode": {
+ "type": "boolean",
+ "default": true,
+ "scope": "application",
+ "description": "Determine whether to group all webview pages into the second editor column when solving problems."
+ },
"leetcode.nodePath": {
"type": "string",
"default": "node",
@@ -338,6 +344,6 @@
"markdown-it": "^8.4.2",
"require-from-string": "^2.0.2",
"unescape-js": "^1.1.1",
- "vsc-leetcode-cli": "2.6.3"
+ "vsc-leetcode-cli": "2.6.4"
}
}
diff --git a/src/commands/show.ts b/src/commands/show.ts
index a72c31bf..1f7b7e52 100644
--- a/src/commands/show.ts
+++ b/src/commands/show.ts
@@ -13,9 +13,15 @@ import { IProblem, IQuickItemEx, languages, ProblemState } from "../shared";
import { DialogOptions, DialogType, promptForOpenOutputChannel, promptForSignIn } from "../utils/uiUtils";
import { 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 showProblem(node?: LeetCodeNode): Promise {
if (!node) {
return;
@@ -51,7 +57,7 @@ export async function showSolution(node?: LeetCodeNode): Promise {
}
try {
const solution: string = await leetCodeExecutor.showSolution(node, language);
- await leetCodeSolutionProvider.show(unescapeJS(solution), node);
+ leetCodeSolutionProvider.show(unescapeJS(solution), node);
} catch (error) {
leetCodeChannel.appendLine(error.toString());
await promptForOpenOutputChannel("Failed to fetch the top voted solution. Please open the output channel for details.", DialogType.error);
@@ -95,7 +101,7 @@ async function showProblemInternal(node: IProblem): Promise {
// SUGGESTION: group config retriving into one file
const leetCodeConfig: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("leetcode");
let outDir: string = await selectWorkspaceFolder();
- let relativePath: string = (leetCodeConfig.get("outputFolder") || "").trim();
+ let relativePath: string = (leetCodeConfig.get("outputFolder", "")).trim();
const matchResult: RegExpMatchArray | null = relativePath.match(/\$\{(.*?)\}/);
if (matchResult) {
const resolvedPath: string | undefined = await resolveRelativePath(matchResult[1].toLocaleLowerCase(), node, language);
@@ -111,12 +117,23 @@ async function showProblemInternal(node: IProblem): Promise {
const originFilePath: string = await leetCodeExecutor.showProblem(node, language, outDir);
const filePath: string = wsl.useWsl() ? await wsl.toWinPath(originFilePath) : originFilePath;
- await vscode.window.showTextDocument(vscode.Uri.file(filePath), { preview: false, viewColumn: vscode.ViewColumn.One });
+ await Promise.all([
+ vscode.window.showTextDocument(vscode.Uri.file(filePath), { preview: false, viewColumn: vscode.ViewColumn.One }),
+ movePreviewAsideIfNeeded(node),
+ ]);
} catch (error) {
await promptForOpenOutputChannel("Failed to show the problem. Please open the output channel for details.", DialogType.error);
}
}
+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/commands/submit.ts b/src/commands/submit.ts
index 2035ec11..f6e2d989 100644
--- a/src/commands/submit.ts
+++ b/src/commands/submit.ts
@@ -21,7 +21,7 @@ export async function submitSolution(uri?: vscode.Uri): Promise {
try {
const result: string = await leetCodeExecutor.submitSolution(filePath);
- await leetCodeSubmissionProvider.show(result);
+ leetCodeSubmissionProvider.show(result);
} catch (error) {
await promptForOpenOutputChannel("Failed to submit the solution. Please open the output channel for details.", DialogType.error);
}
diff --git a/src/commands/test.ts b/src/commands/test.ts
index 558f7409..262f7339 100644
--- a/src/commands/test.ts
+++ b/src/commands/test.ts
@@ -81,7 +81,7 @@ export async function testSolution(uri?: vscode.Uri): Promise {
if (!result) {
return;
}
- await leetCodeSubmissionProvider.show(result);
+ leetCodeSubmissionProvider.show(result);
} catch (error) {
await promptForOpenOutputChannel("Failed to test the solution. Please open the output channel for details.", DialogType.error);
}
diff --git a/src/extension.ts b/src/extension.ts
index 60138085..877ff90c 100644
--- a/src/extension.ts
+++ b/src/extension.ts
@@ -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) => leetCodePreviewProvider.show(node)),
+ 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)),
diff --git a/src/webview/LeetCodeWebview.ts b/src/webview/LeetCodeWebview.ts
index 7b0e9b8d..adac21e8 100644
--- a/src/webview/LeetCodeWebview.ts
+++ b/src/webview/LeetCodeWebview.ts
@@ -1,11 +1,12 @@
// Copyright (c) jdneo. All rights reserved.
// Licensed under the MIT license.
-import { ConfigurationChangeEvent, Disposable, ViewColumn, WebviewPanel, window, workspace } from "vscode";
+import { commands, ConfigurationChangeEvent, Disposable, ViewColumn, WebviewPanel, window, workspace } from "vscode";
import { markdownEngine } from "./markdownEngine";
export abstract class LeetCodeWebview implements Disposable {
+ protected readonly viewType: string = "leetcode.webview";
protected panel: WebviewPanel | undefined;
private listeners: Disposable[] = [];
@@ -16,9 +17,9 @@ export abstract class LeetCodeWebview implements Disposable {
}
protected showWebviewInternal(): void {
- const { viewType, title, viewColumn, preserveFocus } = this.getWebviewOption();
+ const { title, viewColumn, preserveFocus } = this.getWebviewOption();
if (!this.panel) {
- this.panel = window.createWebviewPanel(viewType, title, { viewColumn, preserveFocus }, {
+ this.panel = window.createWebviewPanel(this.viewType, title, { viewColumn, preserveFocus }, {
enableScripts: true,
enableCommandUris: true,
enableFindWidget: true,
@@ -30,7 +31,14 @@ export abstract class LeetCodeWebview implements Disposable {
workspace.onDidChangeConfiguration(this.onDidChangeConfiguration, this, this.listeners);
} else {
this.panel.title = title;
- this.panel.reveal(viewColumn, preserveFocus);
+ if (viewColumn === ViewColumn.Two) {
+ // Make sure second group exists. See vscode#71608 issue
+ commands.executeCommand("workbench.action.focusSecondEditorGroup").then(() => {
+ this.panel!.reveal(viewColumn, preserveFocus);
+ });
+ } else {
+ this.panel.reveal(viewColumn, preserveFocus);
+ }
}
this.panel.webview.html = this.getWebviewContent();
}
@@ -57,7 +65,6 @@ export abstract class LeetCodeWebview implements Disposable {
}
export interface ILeetCodeWebviewOption {
- viewType: string;
title: string;
viewColumn: ViewColumn;
preserveFocus?: boolean;
diff --git a/src/webview/leetCodePreviewProvider.ts b/src/webview/leetCodePreviewProvider.ts
index 9189d769..11b32fc4 100644
--- a/src/webview/leetCodePreviewProvider.ts
+++ b/src/webview/leetCodePreviewProvider.ts
@@ -2,28 +2,44 @@
// Licensed under the MIT license.
import { commands, ViewColumn } from "vscode";
-import { leetCodeExecutor } from "../leetCodeExecutor";
import { IProblem } from "../shared";
import { ILeetCodeWebviewOption, LeetCodeWebview } from "./LeetCodeWebview";
import { markdownEngine } from "./markdownEngine";
class LeetCodePreviewProvider extends LeetCodeWebview {
+ protected readonly viewType: string = "leetcode.preview";
private node: IProblem;
private description: IDescription;
+ private sideMode: boolean = false;
- public async show(node: IProblem): Promise {
- this.description = this.parseDescription(await leetCodeExecutor.getDescription(node), node);
+ 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 = isSideMode;
this.showWebviewInternal();
+ if (this.sideMode) {
+ this.hideSideBar(); // For better view area
+ }
}
protected getWebviewOption(): ILeetCodeWebviewOption {
- return {
- viewType: "leetcode.preview",
- title: `${this.node.name}: Preview`,
- viewColumn: ViewColumn.One,
- };
+ if (!this.sideMode) {
+ return {
+ title: `${this.node.name}: Preview`,
+ viewColumn: ViewColumn.One,
+ };
+ } else {
+ return {
+ title: "Description",
+ viewColumn: ViewColumn.Two,
+ preserveFocus: true,
+ };
+ }
}
protected getWebviewContent(): string {
@@ -84,7 +100,7 @@ class LeetCodePreviewProvider extends LeetCodeWebview {
${markdownEngine.getStyles()}
- ${button.style}
+ ${!this.sideMode ? button.style : ""}
${head}
@@ -92,10 +108,10 @@ class LeetCodePreviewProvider extends LeetCodeWebview {
${tags}
${companies}
${body}
- ${button.element}
+ ${!this.sideMode ? button.element : ""}
@@ -106,6 +122,7 @@ class LeetCodePreviewProvider extends LeetCodeWebview {
super.onDidDisposeWebview();
delete this.node;
delete this.description;
+ this.sideMode = false;
}
protected async onDidReceiveMessage(message: IWebViewMessage): Promise {
@@ -117,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 b433d5ba..952af2cd 100644
--- a/src/webview/leetCodeSolutionProvider.ts
+++ b/src/webview/leetCodeSolutionProvider.ts
@@ -3,24 +3,33 @@
import { ViewColumn } from "vscode";
import { IProblem } from "../shared";
+import { leetCodePreviewProvider } from "./leetCodePreviewProvider";
import { ILeetCodeWebviewOption, LeetCodeWebview } from "./LeetCodeWebview";
import { markdownEngine } from "./markdownEngine";
class LeetCodeSolutionProvider extends LeetCodeWebview {
+ protected readonly viewType: string = "leetcode.solution";
private solution: Solution;
- public async show(solutionString: string, problem: IProblem): Promise {
+ public show(solutionString: string, problem: IProblem): void {
this.solution = this.parseSolution(solutionString, problem);
this.showWebviewInternal();
}
protected getWebviewOption(): ILeetCodeWebviewOption {
- return {
- viewType: "leetcode.solution",
- title: `${this.solution.problem}: Solution`,
- viewColumn: ViewColumn.One,
- };
+ if (!leetCodePreviewProvider.isSideMode()) {
+ return {
+ title: `${this.solution.problem}: Solution`,
+ viewColumn: ViewColumn.One,
+ };
+ } else {
+ return {
+ title: "Solution",
+ viewColumn: ViewColumn.Two,
+ preserveFocus: true,
+ };
+ }
}
protected getWebviewContent(): string {
diff --git a/src/webview/leetCodeSubmissionProvider.ts b/src/webview/leetCodeSubmissionProvider.ts
index d12e6f41..6905099e 100644
--- a/src/webview/leetCodeSubmissionProvider.ts
+++ b/src/webview/leetCodeSubmissionProvider.ts
@@ -7,16 +7,16 @@ import { markdownEngine } from "./markdownEngine";
class LeetCodeSubmissionProvider extends LeetCodeWebview {
+ protected readonly viewType: string = "leetcode.submission";
private result: string;
- public async show(result: string): Promise {
+ public show(result: string): void {
this.result = result;
this.showWebviewInternal();
}
protected getWebviewOption(): ILeetCodeWebviewOption {
return {
- viewType: "leetcode.submission",
title: "Submission",
viewColumn: ViewColumn.Two,
};