From a154c782854a77d2130cfd78e2565c4a54461f45 Mon Sep 17 00:00:00 2001 From: "sheche@microsoft.com" Date: Wed, 1 Aug 2018 21:10:05 +0800 Subject: [PATCH 1/5] extract leetcode command - part 1 --- src/commands/list.ts | 5 ++-- src/commands/session.ts | 7 +++--- src/leetCodeExecutor.ts | 53 +++++++++++++++++++++++++++++++++++++++++ src/leetCodeManager.ts | 2 +- src/shared.ts | 9 +------ src/utils/cpUtils.ts | 5 +--- src/utils/wslUtils.ts | 19 +++++++++++---- 7 files changed, 77 insertions(+), 23 deletions(-) create mode 100644 src/leetCodeExecutor.ts diff --git a/src/commands/list.ts b/src/commands/list.ts index fd425796..83f836a4 100644 --- a/src/commands/list.ts +++ b/src/commands/list.ts @@ -1,6 +1,7 @@ "use strict"; import * as vscode from "vscode"; +import { leetCodeExecutor } from "../leetCodeExecutor"; import { leetCodeManager } from "../leetCodeManager"; import { leetCodeBinaryPath, ProblemState, UserStatus } from "../shared"; import { executeCommand } from "../utils/cpUtils"; @@ -22,8 +23,8 @@ export async function listProblems(): Promise { return []; } const leetCodeConfig: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("leetcode"); - const showLocked: boolean | undefined = leetCodeConfig.get("showLocked"); - const result: string = await executeCommand("node", showLocked ? [leetCodeBinaryPath, "list"] : [leetCodeBinaryPath, "list", "-q", "L"]); + const showLocked: boolean = !!leetCodeConfig.get("showLocked"); + const result: string = await leetCodeExecutor.listProblems(showLocked); const problems: IProblem[] = []; const lines: string[] = result.split("\n"); const reg: RegExp = /^(.)\s(.{1,2})\s(.)\s\[\s*(\d*)\]\s*(.*)\s*(Easy|Medium|Hard)\s*\((\s*\d+\.\d+ %)\)/; diff --git a/src/commands/session.ts b/src/commands/session.ts index b3f3e431..4a7fa232 100644 --- a/src/commands/session.ts +++ b/src/commands/session.ts @@ -1,6 +1,7 @@ "use strict"; import * as vscode from "vscode"; +import { leetCodeExecutor } from "../leetCodeExecutor"; import { leetCodeManager } from "../leetCodeManager"; import { IQuickItemEx, leetCodeBinaryPath } from "../shared"; import { executeCommand } from "../utils/cpUtils"; @@ -12,7 +13,7 @@ export async function getSessionList(): Promise { promptForSignIn(); return []; } - const result: string = await executeCommand("node", [leetCodeBinaryPath, "session"]); + const result: string = await leetCodeExecutor.listSessions(); const lines: string[] = result.split("\n"); const sessions: ISession[] = []; const reg: RegExp = /(.?)\s*(\d+)\s+(.*)\s+(\d+ \(\s*\d+\.\d+ %\))\s+(\d+ \(\s*\d+\.\d+ %\))/; @@ -41,7 +42,7 @@ export async function selectSession(): Promise { return; } try { - await executeCommand("node", [leetCodeBinaryPath, "session", "-e", choice.value]); + await leetCodeExecutor.enableSession(choice.value); vscode.window.showInformationMessage(`Successfully switched to session '${choice.label}'.`); await vscode.commands.executeCommand("leetcode.refreshExplorer"); } catch (error) { @@ -81,7 +82,7 @@ export async function createSession(): Promise { return; } try { - await executeCommand("node", [leetCodeBinaryPath, "session", "-c", session]); + await leetCodeExecutor.createSession(session); vscode.window.showInformationMessage("New session created, you can switch to it by clicking the status bar."); } catch (error) { await promptForOpenOutputChannel("Failed to create session. Please open the output channel for details.", DialogType.error); diff --git a/src/leetCodeExecutor.ts b/src/leetCodeExecutor.ts new file mode 100644 index 00000000..b43318f0 --- /dev/null +++ b/src/leetCodeExecutor.ts @@ -0,0 +1,53 @@ +"use strict"; + +import * as path from "path"; +import * as wsl from "./utils/wslUtils"; + +export interface ILeetCodeExecutor { + listProblems(showLocked: boolean): Promise; + + listSessions(): Promise; + enableSession(name: string): Promise; + createSession(name: string): Promise; +} + +class LeetCodeExecutor implements ILeetCodeExecutor { + private leetCodeBinaryPath: string; + private leetCodeBinaryPathInWsl: string; + + constructor() { + this.leetCodeBinaryPath = `"${path.join(__dirname, "..", "..", "node_modules", "leetcode-cli", "bin", "leetcode")}"`; + this.leetCodeBinaryPathInWsl = ""; + } + + public async getLeetCodeBinaryPath(): Promise { + if (wsl.useWsl()) { + if (!this.leetCodeBinaryPathInWsl) { + this.leetCodeBinaryPathInWsl = await wsl.toWslPath(this.leetCodeBinaryPath); + } + return this.leetCodeBinaryPathInWsl; + } + return this.leetCodeBinaryPath; + } + + public async listProblems(showLocked: boolean): Promise { + return await wsl.executeCommandEx("node", showLocked ? + [await this.getLeetCodeBinaryPath(), "list"] : + [await this.getLeetCodeBinaryPath(), "list", "-q", "L"], + ); + } + + public async listSessions(): Promise { + return await wsl.executeCommandEx("node", [await this.getLeetCodeBinaryPath(), "session"]); + } + + public async enableSession(name: string): Promise { + return await wsl.executeCommandEx("node", [await this.getLeetCodeBinaryPath(), "session", "-e", name]); + } + + public async createSession(name: string): Promise { + return await wsl.executeCommandEx("node", [await this.getLeetCodeBinaryPath(), "session", "-c", name]); + } +} + +export const leetCodeExecutor: ILeetCodeExecutor = new LeetCodeExecutor(); diff --git a/src/leetCodeManager.ts b/src/leetCodeManager.ts index 542b365d..6e0de436 100644 --- a/src/leetCodeManager.ts +++ b/src/leetCodeManager.ts @@ -47,7 +47,7 @@ class LeetCodeManager extends EventEmitter implements ILeetCodeManager { let result: string = ""; const childProc: cp.ChildProcess = wsl.useWsl() - ? cp.spawn("wsl", ["node", leetCodeBinaryPath, "user", "-l"], { shell: true }) + ? cp.spawn("wsl", ["node", await wsl.toWslPath(leetCodeBinaryPath), "user", "-l"], { shell: true }) : cp.spawn("node", [leetCodeBinaryPath, "user", "-l"], { shell: true }); childProc.stdout.on("data", (data: string | Buffer) => { diff --git a/src/shared.ts b/src/shared.ts index 0c85a68b..6a2317f6 100644 --- a/src/shared.ts +++ b/src/shared.ts @@ -2,15 +2,8 @@ import * as path from "path"; import * as vscode from "vscode"; -import * as wsl from "./utils/wslUtils"; -let binPath: string = path.join(__dirname, "..", "..", "node_modules", "leetcode-cli", "bin", "leetcode"); - -if (wsl.useWsl()) { - binPath = wsl.toWslPath(binPath); -} - -export const leetCodeBinaryPath: string = `"${binPath}"`; +export const leetCodeBinaryPath: string = `"${path.join(__dirname, "..", "..", "node_modules", "leetcode-cli", "bin", "leetcode")}"`; export interface IQuickItemEx extends vscode.QuickPickItem { value: T; diff --git a/src/utils/cpUtils.ts b/src/utils/cpUtils.ts index c8393ebb..75e7f6ce 100644 --- a/src/utils/cpUtils.ts +++ b/src/utils/cpUtils.ts @@ -3,15 +3,12 @@ import * as cp from "child_process"; import * as vscode from "vscode"; import { leetCodeChannel } from "../leetCodeChannel"; -import * as wsl from "./wslUtils"; export async function executeCommand(command: string, args: string[], options: cp.SpawnOptions = { shell: true }): Promise { return new Promise((resolve: (res: string) => void, reject: (e: Error) => void): void => { let result: string = ""; - const childProc: cp.ChildProcess = wsl.useWsl() - ? cp.spawn("wsl", [command].concat(args), options) - : cp.spawn(command, args, options); + const childProc: cp.ChildProcess = cp.spawn(command, args, options); childProc.stdout.on("data", (data: string | Buffer) => { data = data.toString(); diff --git a/src/utils/wslUtils.ts b/src/utils/wslUtils.ts index d2b0d566..b09c9c4f 100644 --- a/src/utils/wslUtils.ts +++ b/src/utils/wslUtils.ts @@ -2,17 +2,26 @@ import * as cp from "child_process"; import * as vscode from "vscode"; +import { executeCommand } from "./cpUtils"; + +const wslCommand: string = "wsl"; export function useWsl(): boolean { const leetCodeConfig: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("leetcode"); - return process.platform === "win32" && leetCodeConfig.get("useWsl") === true; } -export function toWslPath(path: string): string { - return cp.execFileSync("wsl", ["wslpath", "-u", `${path.replace(/\\/g, "/")}`]).toString().trim(); +export async function toWslPath(path: string): Promise { + return await executeCommand(wslCommand, ["wslpath", "-u", `"${path}"`]).toString().trim(); +} + +export async function toWinPath(path: string): Promise { + return await executeCommand(wslCommand, ["wslpath", "-w", `"${path}"`]).toString().trim(); } -export function toWinPath(path: string): string { - return cp.execFileSync("wsl", ["wslpath", "-w", path]).toString().trim(); +export async function executeCommandEx(command: string, args: string[], options: cp.SpawnOptions = { shell: true }): Promise { + if (useWsl()) { + return await executeCommand(wslCommand, [command].concat(args), options); + } + return await executeCommand(command, args, options); } From 262e8ba533e0b78853e1e8a1c49c337004d9c925 Mon Sep 17 00:00:00 2001 From: Sheng Chen Date: Mon, 6 Aug 2018 19:38:31 +0800 Subject: [PATCH 2/5] improve - part 2 --- src/commands/list.ts | 3 +-- src/commands/session.ts | 3 +-- src/commands/show.ts | 8 +++---- src/commands/submit.ts | 5 ++--- src/commands/test.ts | 10 ++++----- src/leetCodeExecutor.ts | 46 +++++++++++++++++++++++++++++++++++++---- src/leetCodeManager.ts | 11 +++++----- src/shared.ts | 2 -- src/utils/wslUtils.ts | 13 +++++++++--- 9 files changed, 71 insertions(+), 30 deletions(-) diff --git a/src/commands/list.ts b/src/commands/list.ts index 83f836a4..4656a230 100644 --- a/src/commands/list.ts +++ b/src/commands/list.ts @@ -3,8 +3,7 @@ import * as vscode from "vscode"; import { leetCodeExecutor } from "../leetCodeExecutor"; import { leetCodeManager } from "../leetCodeManager"; -import { leetCodeBinaryPath, ProblemState, UserStatus } from "../shared"; -import { executeCommand } from "../utils/cpUtils"; +import { ProblemState, UserStatus } from "../shared"; import { DialogType, promptForOpenOutputChannel } from "../utils/uiUtils"; export interface IProblem { diff --git a/src/commands/session.ts b/src/commands/session.ts index 4a7fa232..04da3239 100644 --- a/src/commands/session.ts +++ b/src/commands/session.ts @@ -3,8 +3,7 @@ import * as vscode from "vscode"; import { leetCodeExecutor } from "../leetCodeExecutor"; import { leetCodeManager } from "../leetCodeManager"; -import { IQuickItemEx, leetCodeBinaryPath } from "../shared"; -import { executeCommand } from "../utils/cpUtils"; +import { IQuickItemEx } from "../shared"; import { DialogType, promptForOpenOutputChannel, promptForSignIn } from "../utils/uiUtils"; export async function getSessionList(): Promise { diff --git a/src/commands/show.ts b/src/commands/show.ts index 808f00be..e50fa821 100644 --- a/src/commands/show.ts +++ b/src/commands/show.ts @@ -2,10 +2,10 @@ import * as fse from "fs-extra"; import * as vscode from "vscode"; +import { leetCodeExecutor } from "../leetCodeExecutor"; import { LeetCodeNode } from "../leetCodeExplorer"; import { leetCodeManager } from "../leetCodeManager"; -import { IQuickItemEx, languages, leetCodeBinaryPath, ProblemState } from "../shared"; -import { executeCommandWithProgress } from "../utils/cpUtils"; +import { IQuickItemEx, languages, ProblemState } from "../shared"; import { DialogOptions, DialogType, promptForOpenOutputChannel, promptForSignIn } from "../utils/uiUtils"; import { selectWorkspaceFolder } from "../utils/workspaceUtils"; import * as wsl from "../utils/wslUtils"; @@ -50,11 +50,11 @@ async function showProblemInternal(id: string): Promise { const outdir: string = await selectWorkspaceFolder(); await fse.ensureDir(outdir); - const result: string = await executeCommandWithProgress("Fetching problem data...", "node", [leetCodeBinaryPath, "show", id, "-gx", "-l", language, "-o", `"${outdir}"`]); + const result: string = await leetCodeExecutor.showProblem(id, language, outdir); const reg: RegExp = /\* Source Code:\s*(.*)/; const match: RegExpMatchArray | null = result.match(reg); if (match && match.length >= 2) { - const filePath: string = wsl.useWsl() ? wsl.toWinPath(match[1].trim()) : match[1].trim(); + const filePath: string = wsl.useWsl() ? await wsl.toWinPath(match[1].trim()) : match[1].trim(); await vscode.window.showTextDocument(vscode.Uri.file(filePath), { preview: false }); } else { diff --git a/src/commands/submit.ts b/src/commands/submit.ts index ee67720a..1eaeb2b3 100644 --- a/src/commands/submit.ts +++ b/src/commands/submit.ts @@ -1,9 +1,8 @@ "use strict"; import * as vscode from "vscode"; +import { leetCodeExecutor } from "../leetCodeExecutor"; import { leetCodeManager } from "../leetCodeManager"; -import { leetCodeBinaryPath } from "../shared"; -import { executeCommandWithProgress } from "../utils/cpUtils"; import { DialogType, promptForOpenOutputChannel, promptForSignIn, showResultFile } from "../utils/uiUtils"; import { getActivefilePath } from "../utils/workspaceUtils"; @@ -19,7 +18,7 @@ export async function submitSolution(uri?: vscode.Uri): Promise { } try { - const result: string = await executeCommandWithProgress("Submitting to LeetCode...", "node", [leetCodeBinaryPath, "submit", `"${filePath}"`]); + const result: string = await leetCodeExecutor.submitSolution(filePath); await showResultFile(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 2df1878e..4d22b5e9 100644 --- a/src/commands/test.ts +++ b/src/commands/test.ts @@ -2,9 +2,9 @@ import * as fse from "fs-extra"; import * as vscode from "vscode"; +import { leetCodeExecutor } from "../leetCodeExecutor"; import { leetCodeManager } from "../leetCodeManager"; -import { IQuickItemEx, leetCodeBinaryPath, UserStatus } from "../shared"; -import { executeCommandWithProgress } from "../utils/cpUtils"; +import { IQuickItemEx, UserStatus } from "../shared"; import { DialogType, promptForOpenOutputChannel, showFileSelectDialog, showResultFile } from "../utils/uiUtils"; import { getActivefilePath } from "../utils/workspaceUtils"; @@ -47,7 +47,7 @@ export async function testSolution(uri?: vscode.Uri): Promise { let result: string | undefined; switch (choice.value) { case ":default": - result = await executeCommandWithProgress("Submitting to LeetCode...", "node", [leetCodeBinaryPath, "test", `"${filePath}"`]); + result = await leetCodeExecutor.testSolution(filePath); break; case ":direct": const testString: string | undefined = await vscode.window.showInputBox({ @@ -57,7 +57,7 @@ export async function testSolution(uri?: vscode.Uri): Promise { ignoreFocusOut: true, }); if (testString) { - result = await executeCommandWithProgress("Submitting to LeetCode...", "node", [leetCodeBinaryPath, "test", `"${filePath}"`, "-t", `"${testString.replace(/"/g, "")}"`]); + result = await leetCodeExecutor.testSolution(filePath, testString.replace(/"/g, "")); } break; case ":file": @@ -65,7 +65,7 @@ export async function testSolution(uri?: vscode.Uri): Promise { if (testFile && testFile.length) { const input: string = await fse.readFile(testFile[0].fsPath, "utf-8"); if (input.trim()) { - result = await executeCommandWithProgress("Submitting to LeetCode...", "node", [leetCodeBinaryPath, "test", `"${filePath}"`, "-t", `"${input.replace(/"/g, "").replace(/\r?\n/g, "\\n")}"`]); + result = await leetCodeExecutor.testSolution(filePath, input.replace(/"/g, "").replace(/\r?\n/g, "\\n")); } else { vscode.window.showErrorMessage("The selected test file must not be empty."); } diff --git a/src/leetCodeExecutor.ts b/src/leetCodeExecutor.ts index b43318f0..0749dea4 100644 --- a/src/leetCodeExecutor.ts +++ b/src/leetCodeExecutor.ts @@ -4,11 +4,26 @@ import * as path from "path"; import * as wsl from "./utils/wslUtils"; export interface ILeetCodeExecutor { + getLeetCodeBinaryPath(): Promise; + + /* section for user command */ + getUserInfo(): Promise; + signOut(): Promise; + // TODO: implement login when leetcode-cli support login in batch mode. + // signIn(): Promise; + + /* section for problem command */ listProblems(showLocked: boolean): Promise; + showProblem(id: string, language: string, outdir: string): Promise; + /* section for session command */ listSessions(): Promise; enableSession(name: string): Promise; createSession(name: string): Promise; + + /* section for solution command */ + submitSolution(filePath: string): Promise; + testSolution(filePath: string, testString?: string): Promise; } class LeetCodeExecutor implements ILeetCodeExecutor { @@ -16,18 +31,26 @@ class LeetCodeExecutor implements ILeetCodeExecutor { private leetCodeBinaryPathInWsl: string; constructor() { - this.leetCodeBinaryPath = `"${path.join(__dirname, "..", "..", "node_modules", "leetcode-cli", "bin", "leetcode")}"`; + this.leetCodeBinaryPath = path.join(__dirname, "..", "..", "node_modules", "leetcode-cli", "bin", "leetcode"); this.leetCodeBinaryPathInWsl = ""; } public async getLeetCodeBinaryPath(): Promise { if (wsl.useWsl()) { if (!this.leetCodeBinaryPathInWsl) { - this.leetCodeBinaryPathInWsl = await wsl.toWslPath(this.leetCodeBinaryPath); + this.leetCodeBinaryPathInWsl = `${await wsl.toWslPath(this.leetCodeBinaryPath)}`; } - return this.leetCodeBinaryPathInWsl; + return `"${this.leetCodeBinaryPathInWsl}"`; } - return this.leetCodeBinaryPath; + return `"${this.leetCodeBinaryPath}"`; + } + + public async getUserInfo(): Promise { + return await wsl.executeCommandEx("node", [await this.getLeetCodeBinaryPath(), "user"]); + } + + public async signOut(): Promise { + return await await wsl.executeCommandEx("node", [await this.getLeetCodeBinaryPath(), "user", "-L"]); } public async listProblems(showLocked: boolean): Promise { @@ -37,6 +60,10 @@ class LeetCodeExecutor implements ILeetCodeExecutor { ); } + public async showProblem(id: string, language: string, outdir: string): Promise { + return await wsl.executeCommandWithProgressEx("Fetching problem data...", "node", [await this.getLeetCodeBinaryPath(), "show", id, "-gx", "-l", language, "-o", `"${outdir}"`]); + } + public async listSessions(): Promise { return await wsl.executeCommandEx("node", [await this.getLeetCodeBinaryPath(), "session"]); } @@ -48,6 +75,17 @@ class LeetCodeExecutor implements ILeetCodeExecutor { public async createSession(name: string): Promise { return await wsl.executeCommandEx("node", [await this.getLeetCodeBinaryPath(), "session", "-c", name]); } + + public async submitSolution(filePath: string): Promise { + return await wsl.executeCommandWithProgressEx("Submitting to LeetCode...", "node", [await this.getLeetCodeBinaryPath(), "submit", `"${filePath}"`]); + } + + public async testSolution(filePath: string, testString?: string): Promise { + if (testString) { + return await wsl.executeCommandWithProgressEx("Submitting to LeetCode...", "node", [await this.getLeetCodeBinaryPath(), "test", `"${filePath}"`, "-t", `"${testString}"`]); + } + return await wsl.executeCommandWithProgressEx("Submitting to LeetCode...", "node", [await this.getLeetCodeBinaryPath(), "test", `"${filePath}"`]); + } } export const leetCodeExecutor: ILeetCodeExecutor = new LeetCodeExecutor(); diff --git a/src/leetCodeManager.ts b/src/leetCodeManager.ts index 6e0de436..24ad4ebc 100644 --- a/src/leetCodeManager.ts +++ b/src/leetCodeManager.ts @@ -4,9 +4,8 @@ import * as cp from "child_process"; import { EventEmitter } from "events"; import * as vscode from "vscode"; import { leetCodeChannel } from "./leetCodeChannel"; +import { leetCodeExecutor } from "./leetCodeExecutor"; import { UserStatus } from "./shared"; -import { leetCodeBinaryPath } from "./shared"; -import { executeCommand } from "./utils/cpUtils"; import { DialogType, promptForOpenOutputChannel } from "./utils/uiUtils"; import * as wsl from "./utils/wslUtils"; @@ -30,7 +29,7 @@ class LeetCodeManager extends EventEmitter implements ILeetCodeManager { public async getLoginStatus(): Promise { try { - const result: string = await executeCommand("node", [leetCodeBinaryPath, "user"]); + const result: string = await leetCodeExecutor.getUserInfo(); this.currentUser = result.slice("You are now login as".length).trim(); this.userStatus = UserStatus.SignedIn; } catch (error) { @@ -46,8 +45,10 @@ class LeetCodeManager extends EventEmitter implements ILeetCodeManager { const userName: string | undefined = await new Promise(async (resolve: (res: string | undefined) => void, reject: (e: Error) => void): Promise => { let result: string = ""; + const leetCodeBinaryPath: string = await leetCodeExecutor.getLeetCodeBinaryPath(); + const childProc: cp.ChildProcess = wsl.useWsl() - ? cp.spawn("wsl", ["node", await wsl.toWslPath(leetCodeBinaryPath), "user", "-l"], { shell: true }) + ? cp.spawn("wsl", ["node", leetCodeBinaryPath, "user", "-l"], { shell: true }) : cp.spawn("node", [leetCodeBinaryPath, "user", "-l"], { shell: true }); childProc.stdout.on("data", (data: string | Buffer) => { @@ -102,7 +103,7 @@ class LeetCodeManager extends EventEmitter implements ILeetCodeManager { public async signOut(): Promise { try { - await executeCommand("node", [leetCodeBinaryPath, "user", "-L"]); + await leetCodeExecutor.signOut(); vscode.window.showInformationMessage("Successfully signed out."); this.currentUser = undefined; this.userStatus = UserStatus.SignedOut; diff --git a/src/shared.ts b/src/shared.ts index 6a2317f6..37ae1b04 100644 --- a/src/shared.ts +++ b/src/shared.ts @@ -3,8 +3,6 @@ import * as path from "path"; import * as vscode from "vscode"; -export const leetCodeBinaryPath: string = `"${path.join(__dirname, "..", "..", "node_modules", "leetcode-cli", "bin", "leetcode")}"`; - export interface IQuickItemEx extends vscode.QuickPickItem { value: T; } diff --git a/src/utils/wslUtils.ts b/src/utils/wslUtils.ts index b09c9c4f..0e3a65aa 100644 --- a/src/utils/wslUtils.ts +++ b/src/utils/wslUtils.ts @@ -2,7 +2,7 @@ import * as cp from "child_process"; import * as vscode from "vscode"; -import { executeCommand } from "./cpUtils"; +import { executeCommand, executeCommandWithProgress } from "./cpUtils"; const wslCommand: string = "wsl"; @@ -12,11 +12,11 @@ export function useWsl(): boolean { } export async function toWslPath(path: string): Promise { - return await executeCommand(wslCommand, ["wslpath", "-u", `"${path}"`]).toString().trim(); + return (await executeCommand(wslCommand, ["wslpath", "-u", `"${path.replace(/\\/g, "/")}"`])).trim(); } export async function toWinPath(path: string): Promise { - return await executeCommand(wslCommand, ["wslpath", "-w", `"${path}"`]).toString().trim(); + return (await executeCommand(wslCommand, ["wslpath", "-w", `"${path}"`])).trim(); } export async function executeCommandEx(command: string, args: string[], options: cp.SpawnOptions = { shell: true }): Promise { @@ -25,3 +25,10 @@ export async function executeCommandEx(command: string, args: string[], options: } return await executeCommand(command, args, options); } + +export async function executeCommandWithProgressEx(message: string, command: string, args: string[], options: cp.SpawnOptions = { shell: true }): Promise { + if (useWsl()) { + return await executeCommandWithProgress(message, wslCommand, [command].concat(args), options); + } + return await executeCommandWithProgress(message, command, args, options); +} From 60299f3d6329e2e4d00d00ab6bb8fa410bf05965 Mon Sep 17 00:00:00 2001 From: Sheng Chen Date: Tue, 7 Aug 2018 19:02:19 +0800 Subject: [PATCH 3/5] move wsl logic into leetCodeExecutor --- src/leetCodeExecutor.ts | 36 ++++++++++++++++++++++++++---------- src/utils/wslUtils.ts | 23 +++-------------------- 2 files changed, 29 insertions(+), 30 deletions(-) diff --git a/src/leetCodeExecutor.ts b/src/leetCodeExecutor.ts index 0749dea4..a9c044b8 100644 --- a/src/leetCodeExecutor.ts +++ b/src/leetCodeExecutor.ts @@ -1,6 +1,8 @@ "use strict"; +import * as cp from "child_process"; import * as path from "path"; +import { executeCommand, executeCommandWithProgress } from "./utils/cpUtils"; import * as wsl from "./utils/wslUtils"; export interface ILeetCodeExecutor { @@ -46,45 +48,59 @@ class LeetCodeExecutor implements ILeetCodeExecutor { } public async getUserInfo(): Promise { - return await wsl.executeCommandEx("node", [await this.getLeetCodeBinaryPath(), "user"]); + return await this.executeCommandEx("node", [await this.getLeetCodeBinaryPath(), "user"]); } public async signOut(): Promise { - return await await wsl.executeCommandEx("node", [await this.getLeetCodeBinaryPath(), "user", "-L"]); + return await await this.executeCommandEx("node", [await this.getLeetCodeBinaryPath(), "user", "-L"]); } public async listProblems(showLocked: boolean): Promise { - return await wsl.executeCommandEx("node", showLocked ? + return await this.executeCommandEx("node", showLocked ? [await this.getLeetCodeBinaryPath(), "list"] : [await this.getLeetCodeBinaryPath(), "list", "-q", "L"], ); } public async showProblem(id: string, language: string, outdir: string): Promise { - return await wsl.executeCommandWithProgressEx("Fetching problem data...", "node", [await this.getLeetCodeBinaryPath(), "show", id, "-gx", "-l", language, "-o", `"${outdir}"`]); + return await this.executeCommandWithProgressEx("Fetching problem data...", "node", [await this.getLeetCodeBinaryPath(), "show", id, "-gx", "-l", language, "-o", `"${outdir}"`]); } public async listSessions(): Promise { - return await wsl.executeCommandEx("node", [await this.getLeetCodeBinaryPath(), "session"]); + return await this.executeCommandEx("node", [await this.getLeetCodeBinaryPath(), "session"]); } public async enableSession(name: string): Promise { - return await wsl.executeCommandEx("node", [await this.getLeetCodeBinaryPath(), "session", "-e", name]); + return await this.executeCommandEx("node", [await this.getLeetCodeBinaryPath(), "session", "-e", name]); } public async createSession(name: string): Promise { - return await wsl.executeCommandEx("node", [await this.getLeetCodeBinaryPath(), "session", "-c", name]); + return await this.executeCommandEx("node", [await this.getLeetCodeBinaryPath(), "session", "-c", name]); } public async submitSolution(filePath: string): Promise { - return await wsl.executeCommandWithProgressEx("Submitting to LeetCode...", "node", [await this.getLeetCodeBinaryPath(), "submit", `"${filePath}"`]); + return await this.executeCommandWithProgressEx("Submitting to LeetCode...", "node", [await this.getLeetCodeBinaryPath(), "submit", `"${filePath}"`]); } public async testSolution(filePath: string, testString?: string): Promise { if (testString) { - return await wsl.executeCommandWithProgressEx("Submitting to LeetCode...", "node", [await this.getLeetCodeBinaryPath(), "test", `"${filePath}"`, "-t", `"${testString}"`]); + return await this.executeCommandWithProgressEx("Submitting to LeetCode...", "node", [await this.getLeetCodeBinaryPath(), "test", `"${filePath}"`, "-t", `"${testString}"`]); } - return await wsl.executeCommandWithProgressEx("Submitting to LeetCode...", "node", [await this.getLeetCodeBinaryPath(), "test", `"${filePath}"`]); + return await this.executeCommandWithProgressEx("Submitting to LeetCode...", "node", [await this.getLeetCodeBinaryPath(), "test", `"${filePath}"`]); + } + + private async executeCommandEx(command: string, args: string[], options: cp.SpawnOptions = { shell: true }): Promise { + if (wsl.useWsl()) { + return await executeCommand("wsl", [command].concat(args), options); + } + return await executeCommand(command, args, options); + } + + private async executeCommandWithProgressEx(message: string, command: string, args: string[], options: cp.SpawnOptions = { shell: true }): Promise { + if (wsl.useWsl()) { + return await executeCommandWithProgress(message, "wsl", [command].concat(args), options); + } + return await executeCommandWithProgress(message, command, args, options); } } diff --git a/src/utils/wslUtils.ts b/src/utils/wslUtils.ts index 0e3a65aa..6b1efcc3 100644 --- a/src/utils/wslUtils.ts +++ b/src/utils/wslUtils.ts @@ -1,10 +1,7 @@ "use strict"; -import * as cp from "child_process"; import * as vscode from "vscode"; -import { executeCommand, executeCommandWithProgress } from "./cpUtils"; - -const wslCommand: string = "wsl"; +import { executeCommand } from "./cpUtils"; export function useWsl(): boolean { const leetCodeConfig: vscode.WorkspaceConfiguration = vscode.workspace.getConfiguration("leetcode"); @@ -12,23 +9,9 @@ export function useWsl(): boolean { } export async function toWslPath(path: string): Promise { - return (await executeCommand(wslCommand, ["wslpath", "-u", `"${path.replace(/\\/g, "/")}"`])).trim(); + return (await executeCommand("wsl", ["wslpath", "-u", `"${path.replace(/\\/g, "/")}"`])).trim(); } export async function toWinPath(path: string): Promise { - return (await executeCommand(wslCommand, ["wslpath", "-w", `"${path}"`])).trim(); -} - -export async function executeCommandEx(command: string, args: string[], options: cp.SpawnOptions = { shell: true }): Promise { - if (useWsl()) { - return await executeCommand(wslCommand, [command].concat(args), options); - } - return await executeCommand(command, args, options); -} - -export async function executeCommandWithProgressEx(message: string, command: string, args: string[], options: cp.SpawnOptions = { shell: true }): Promise { - if (useWsl()) { - return await executeCommandWithProgress(message, wslCommand, [command].concat(args), options); - } - return await executeCommandWithProgress(message, command, args, options); + return (await executeCommand("wsl", ["wslpath", "-w", `"${path}"`])).trim(); } From 8c52f42f37bcc48b0f79210545169e629ec456d3 Mon Sep 17 00:00:00 2001 From: Sheng Chen Date: Tue, 7 Aug 2018 19:04:47 +0800 Subject: [PATCH 4/5] remove unused imports --- src/shared.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/shared.ts b/src/shared.ts index 37ae1b04..9a5184ee 100644 --- a/src/shared.ts +++ b/src/shared.ts @@ -1,6 +1,5 @@ "use strict"; -import * as path from "path"; import * as vscode from "vscode"; export interface IQuickItemEx extends vscode.QuickPickItem { From 526cedd1eb52c6383fe1342c9d3b744bde784b39 Mon Sep 17 00:00:00 2001 From: Sheng Chen Date: Wed, 8 Aug 2018 21:04:41 +0800 Subject: [PATCH 5/5] fix bug --- src/extension.ts | 4 ++-- src/leetCodeExecutor.ts | 20 ++++++++++++++++++++ src/utils/nodeUtils.ts | 22 ---------------------- 3 files changed, 22 insertions(+), 24 deletions(-) delete mode 100644 src/utils/nodeUtils.ts diff --git a/src/extension.ts b/src/extension.ts index b8b298b9..78182b67 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -6,13 +6,13 @@ import * as show from "./commands/show"; import * as submit from "./commands/submit"; import * as test from "./commands/test"; import { leetCodeChannel } from "./leetCodeChannel"; +import { leetCodeExecutor } from "./leetCodeExecutor"; import { LeetCodeNode, LeetCodeTreeDataProvider } from "./leetCodeExplorer"; import { leetCodeManager } from "./leetCodeManager"; import { leetCodeStatusBarItem } from "./leetCodeStatusBarItem"; -import { isNodeInstalled } from "./utils/nodeUtils"; export async function activate(context: vscode.ExtensionContext): Promise { - if (!await isNodeInstalled()) { + if (!await leetCodeExecutor.meetRequirements()) { return; } leetCodeManager.getLoginStatus(); diff --git a/src/leetCodeExecutor.ts b/src/leetCodeExecutor.ts index a9c044b8..20353c03 100644 --- a/src/leetCodeExecutor.ts +++ b/src/leetCodeExecutor.ts @@ -1,11 +1,15 @@ "use strict"; import * as cp from "child_process"; +import * as opn from "opn"; import * as path from "path"; +import * as vscode from "vscode"; import { executeCommand, executeCommandWithProgress } from "./utils/cpUtils"; +import { DialogOptions } from "./utils/uiUtils"; import * as wsl from "./utils/wslUtils"; export interface ILeetCodeExecutor { + meetRequirements(): Promise; getLeetCodeBinaryPath(): Promise; /* section for user command */ @@ -47,6 +51,22 @@ class LeetCodeExecutor implements ILeetCodeExecutor { return `"${this.leetCodeBinaryPath}"`; } + public async meetRequirements(): Promise { + try { + await this.executeCommandEx("node", ["-v"]); + return true; + } catch (error) { + const choice: vscode.MessageItem | undefined = await vscode.window.showErrorMessage( + "LeetCode extension needs Node.js installed in environment path", + DialogOptions.open, + ); + if (choice === DialogOptions.open) { + opn("https://nodejs.org"); + } + return false; + } + } + public async getUserInfo(): Promise { return await this.executeCommandEx("node", [await this.getLeetCodeBinaryPath(), "user"]); } diff --git a/src/utils/nodeUtils.ts b/src/utils/nodeUtils.ts deleted file mode 100644 index 98df8705..00000000 --- a/src/utils/nodeUtils.ts +++ /dev/null @@ -1,22 +0,0 @@ -"use strict"; - -import * as opn from "opn"; -import * as vscode from "vscode"; -import { executeCommand } from "./cpUtils"; -import { DialogOptions } from "./uiUtils"; - -export async function isNodeInstalled(): Promise { - try { - await executeCommand("node", ["-v"]); - return true; - } catch (error) { - const choice: vscode.MessageItem | undefined = await vscode.window.showErrorMessage( - "LeetCode extension need Node.js installed in environment path", - DialogOptions.open, - ); - if (choice === DialogOptions.open) { - opn("https://nodejs.org"); - } - return false; - } -} 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