diff --git a/src/modules/LeetcodeConfig.ts b/src/modules/LeetcodeConfig.ts index bb7251c..49800a4 100644 --- a/src/modules/LeetcodeConfig.ts +++ b/src/modules/LeetcodeConfig.ts @@ -43,6 +43,12 @@ export interface LeetcodeConfig { agentPromptExplain?: string; /** Rich webview vs plain text editor when opening a problem from sidebar lists. */ problemViewMode?: "ui" | "text"; + /** Automatically apply LCEX font settings to the workspace when a .leetcode folder is present. */ + applyWorkspaceFontSettings?: boolean; + /** The font family to apply when applyWorkspaceFontSettings is true. Defaults to 'Fira Code iScript'. */ + editorFontFamily?: string; + /** Whether to apply cursive italic textMate rules for comments and keywords. Defaults to true. */ + editorCursiveItalics?: boolean; } const DEFAULTS: Required< @@ -77,6 +83,9 @@ const DEFAULTS: Required< "Load **lcex-dsa-analyze** and follow it. Analyze my current LeetCode solution implementation.", agentPromptExplain: "Explain my solution code for this LeetCode problem. Respond with: (1) Intuition — core idea in plain language; (2) Step-by-step dry run — walk through the algorithm with a small example, including loop/state changes; (3) Time and space complexity with brief justification. Do not rewrite the full solution unless needed for clarity.", + applyWorkspaceFontSettings: false, + editorFontFamily: "Fira Code iScript", + editorCursiveItalics: true, }; function isValidStudyPlanEntry(obj: unknown): obj is { slug: string; name: string } { @@ -334,6 +343,15 @@ export function parseLeetcodeConfig(workspaceFolders: readonly vscode.WorkspaceF if (parsed.problemViewMode === "ui" || parsed.problemViewMode === "text") { merged.problemViewMode = parsed.problemViewMode; } + if (parsed.applyWorkspaceFontSettings !== undefined && typeof parsed.applyWorkspaceFontSettings === "boolean") { + merged.applyWorkspaceFontSettings = parsed.applyWorkspaceFontSettings; + } + if (parsed.editorFontFamily !== undefined && typeof parsed.editorFontFamily === "string") { + merged.editorFontFamily = parsed.editorFontFamily; + } + if (parsed.editorCursiveItalics !== undefined && typeof parsed.editorCursiveItalics === "boolean") { + merged.editorCursiveItalics = parsed.editorCursiveItalics; + } } catch (e) { Logger.log(`LeetcodeConfig: failed to parse ${configPath}, using defaults: ${e}`); } @@ -390,5 +408,8 @@ export function getEffectiveConfig( problemViewMode: normalizeProblemViewMode( leetcode.problemViewMode ?? vscodeConfig.get("problemViewMode") ), + applyWorkspaceFontSettings: leetcode.applyWorkspaceFontSettings ?? DEFAULTS.applyWorkspaceFontSettings, + editorFontFamily: leetcode.editorFontFamily ?? DEFAULTS.editorFontFamily, + editorCursiveItalics: leetcode.editorCursiveItalics ?? DEFAULTS.editorCursiveItalics, }; } diff --git a/src/modules/LeetcodePracticeEditorSettings.ts b/src/modules/LeetcodePracticeEditorSettings.ts index 396aac5..9b4fdda 100644 --- a/src/modules/LeetcodePracticeEditorSettings.ts +++ b/src/modules/LeetcodePracticeEditorSettings.ts @@ -3,6 +3,7 @@ import * as path from "path"; import * as vscode from "vscode"; import type { SupportedLanguage } from "./interface/Problem"; import * as Logger from "./Logger"; +import { getEffectiveConfig } from "./LeetcodeConfig"; const MARKER = ".leetcode"; @@ -84,11 +85,18 @@ function workspaceJsonEqual(a: unknown, b: unknown): boolean { } /** - * Sets Fira Code iScript and italic token rules for LeetCode practice workspaces (folder with `.leetcode`). + * Sets the configured font and token rules for LeetCode practice workspaces (folder with `.leetcode`). * Only writes workspace-level settings when they differ from the LCEX defaults. */ export async function applyLcexEditorFontAndTokenSettingsIfNeeded(): Promise { - if (!workspaceHasLeetcodeMarker()) return; + const folders = vscode.workspace.workspaceFolders; + if (!folders?.length || !workspaceHasLeetcodeMarker()) return; + + const lcexCfg = getEffectiveConfig(folders); + if (!lcexCfg.applyWorkspaceFontSettings) return; + + const fontToApply = lcexCfg.editorFontFamily || "Fira Code iScript"; + const editorCfg = vscode.workspace.getConfiguration("editor", null); const target = vscode.ConfigurationTarget.Workspace; @@ -97,21 +105,30 @@ export async function applyLcexEditorFontAndTokenSettingsIfNeeded(): Promise>("tokenColorCustomizations"); const workspaceToken = tokenInspect?.workspaceValue ?? tokenInspect?.workspaceFolderValue; - const desiredToken = JSON.parse(JSON.stringify(LCEX_EDITOR_TOKEN_COLOR_CUSTOMIZATIONS)) as Record< - string, - unknown - >; - const needsFont = workspaceFont !== LCEX_EDITOR_FONT_FAMILY; - const needsToken = !workspaceJsonEqual(workspaceToken, desiredToken); + const needsFont = workspaceFont !== fontToApply; + + // Only apply italic settings if the user has enabled them + let desiredToken: Record = {}; + let needsToken = false; + if (lcexCfg.editorCursiveItalics) { + desiredToken = JSON.parse(JSON.stringify(LCEX_EDITOR_TOKEN_COLOR_CUSTOMIZATIONS)) as Record; + needsToken = !workspaceJsonEqual(workspaceToken, desiredToken); + } else if (workspaceToken && workspaceJsonEqual(workspaceToken, JSON.parse(JSON.stringify(LCEX_EDITOR_TOKEN_COLOR_CUSTOMIZATIONS)))) { + // If they were previously set by us, clear them out now that the font changed + needsToken = true; + desiredToken = {}; // or undefined, but VS Code API allows updating to {} + } if (!needsFont && !needsToken) return; try { if (needsFont) { - await editorCfg.update("fontFamily", LCEX_EDITOR_FONT_FAMILY, target); + await editorCfg.update("fontFamily", fontToApply, target); } if (needsToken) { - await editorCfg.update("tokenColorCustomizations", desiredToken, target); + // update with {} clears the properties we set if there were no others, + // wait, updating with undefined deletes the setting entirely, which is better. + await editorCfg.update("tokenColorCustomizations", Object.keys(desiredToken).length > 0 ? desiredToken : undefined, target); } } catch (e) { Logger.logError("LCEX editor font/token settings: failed to update workspace settings", e);