From 9f283a84db8f01dcd85265ba76d9241af183d4ea Mon Sep 17 00:00:00 2001 From: David Czihak Date: Sun, 10 May 2026 22:00:06 +0200 Subject: Feat: Full localization, reactive task list, 0.2.0 changelog --- Zig.novaextension/Scripts/main.js | 200 ++++++++++++++++++++------------------ 1 file changed, 105 insertions(+), 95 deletions(-) (limited to 'Zig.novaextension/Scripts') diff --git a/Zig.novaextension/Scripts/main.js b/Zig.novaextension/Scripts/main.js index 70e4169..17edb72 100644 --- a/Zig.novaextension/Scripts/main.js +++ b/Zig.novaextension/Scripts/main.js @@ -18,6 +18,7 @@ const CONFIG_KEYS = { zlsDebug: `${EXTENSION_ID}.zls.debug`, lldbDapDebug: `${EXTENSION_ID}.debug-adapter.debug`, discoverSteps: `${EXTENSION_ID}.tasks.discover-steps`, + showCurrentFile: `${EXTENSION_ID}.tasks.show-current-file`, }; // --- LIFECYCLE --------------------------------------------------------------- @@ -291,10 +292,7 @@ function buildZigArgv(config, options) { function resolveCleanPaths(cwd) { const showWarning = () => { nova.workspace.showWarningMessage( - localizeText( - "warning.clean.unsafe_cwd", - "Refusing to clean: the working directory must be inside this workspace.", - ), + localize("warning.clean.unsafe-cwd"), ); }; @@ -532,31 +530,6 @@ const stepCache = { // --- LOCALIZATION ------------------------------------------------------------- -/** - * Resolve a localized string, substituting `{variable}` placeholders - * - * @param {string} key - Key - * @param {string} fallback - Fallback text - * @param {*} variables - Dictionary of variable names and values - */ -function localizeText(key, fallback, variables) { - let text = nova.localize(key, null); - - if (key === text) { - return fallback !== undefined ? String(fallback) : key; - } - - if (!variables || typeof variables !== "object") { - return text; - } - - for (const [name, value] of Object.entries(variables)) { - text = text.split(`{${name}}`).join(String(value)); - } - - return text; -} - function localize(key, variables) { let text = nova.localize(key, null); @@ -707,10 +680,7 @@ async function resolveZigExecutable() { const zigPath = await resolveExecutable(CONFIG_KEYS.zigPath, "zig"); if (!zigPath) { nova.workspace.showWarningMessage( - localizeText( - "warning.zig.not-found", - "Zig was not found. Install it or set a Zig executable path in Zig extension settings.", - ), + localize("warning.zig.not-found"), ); return null; } @@ -913,10 +883,7 @@ function registerCommands() { if (!command) { workspace.showWarningMessage( - localizeText( - "warning.terminal.launch_failed", - "Unable to launch the Zig task in Terminal.", - ), + localize("warning.terminal.launch-failed"), ); return; } @@ -925,10 +892,7 @@ function registerCommands() { buildShellCommand(command, args, cwd), ); if (result.status !== 0) { - const prefix = localizeText( - "warning.terminal.open_failed", - "Unable to open Terminal for the Zig task.", - ); + const prefix = localize("warning.terminal.open-failed"); const suffix = result.stderr ? ` ${result.stderr}` : ""; workspace.showWarningMessage(`${prefix}${suffix}`); } @@ -1055,10 +1019,7 @@ class ZigLanguageServer { if (!zlsPath) { this.warnMissingTool( "zls", - localizeText( - "warning.zls.not-found", - "ZLS was not found. Install it or set a ZLS executable path in Zig extension settings.", - ), + localize("warning.zls.not-found"), ); return; } @@ -1083,7 +1044,7 @@ class ZigLanguageServer { const client = new LanguageClient( LANGUAGE_CLIENT_ID, - localizeText("name.language_server", "Zig Language Server"), + localize("name.language-server"), serverOptions, clientOptions, ); @@ -1107,11 +1068,7 @@ class ZigLanguageServer { if (error) { console.error(`[${LANGUAGE_CLIENT_ID}] ${error.message}`); nova.workspace.showWarningMessage( - localizeText( - "warning.zls.stopped_unexpectedly", - "The Zig Language Server stopped unexpectedly ({executable}).", - { executable: zlsPath || "zls" }, - ), + localize("warning.zls.stopped-unexpectedly", { executable: zlsPath || "zls" }), ); } }); @@ -1136,11 +1093,7 @@ class ZigLanguageServer { } catch (error) { console.error(`[${LANGUAGE_CLIENT_ID}] Failed to start ZLS`, error); nova.workspace.showWarningMessage( - localizeText( - "warning.zls.start_failed", - "Unable to start the Zig language server at {path}.", - { path: zlsPath }, - ), + localize("warning.zls.start-failed", { path: zlsPath }), ); this.stop(); } @@ -1218,9 +1171,79 @@ class ZigTaskAssistant { identifier: TASK_ASSISTANT_ID, name: localize("autotasks.title"), }); + this.watchers = []; + this.configDisposables = []; + this.pathChangeDisposable = nova.workspace.onDidChangePath(() => { + this.stopWatching(); + this.startWatching(); + }); + this.startWatching(); + this.observeTaskConfig(); + } + + observeTaskConfig() { + const reload = () => { + if (typeof nova.workspace.reloadTasks === "function") { + try { + nova.workspace.reloadTasks(TASK_ASSISTANT_ID); + } catch (_) {} + } + }; + for (const key of [CONFIG_KEYS.discoverSteps, CONFIG_KEYS.showCurrentFile]) { + this.configDisposables.push(nova.config.onDidChange(key, reload)); + this.configDisposables.push(nova.workspace.config.onDidChange(key, reload)); + } + } + + startWatching() { + const cwd = nova.workspace.path; + if (!cwd) return; + const reload = () => { + console.log(`[${TASK_ASSISTANT_ID}] build file changed, refreshing steps`); + stepCache.invalidate(cwd); + if (typeof nova.workspace.reloadTasks === "function") { + try { + nova.workspace.reloadTasks(TASK_ASSISTANT_ID); + } catch (_) {} + } + }; + for (const name of ["build.zig", "build.zig.zon"]) { + try { + this.watchers.push(nova.fs.watch(nova.path.join(cwd, name), reload)); + } catch (_) {} + } + } + + stopWatching() { + for (const w of this.watchers) { + if (w && typeof w.dispose === "function") { + try { + w.dispose(); + } catch (_) {} + } + } + this.watchers = []; } dispose() { + this.stopWatching(); + for (const d of this.configDisposables) { + if (d && typeof d.dispose === "function") { + try { + d.dispose(); + } catch (_) {} + } + } + this.configDisposables = []; + if ( + this.pathChangeDisposable && + typeof this.pathChangeDisposable.dispose === "function" + ) { + try { + this.pathChangeDisposable.dispose(); + } catch (_) {} + this.pathChangeDisposable = null; + } if (this.disposable && typeof this.disposable.dispose === "function") { this.disposable.dispose(); this.disposable = null; @@ -1230,25 +1253,27 @@ class ZigTaskAssistant { provideTasks() { const tasks = []; - const currentFile = new Task(localize("autotasks.current-file.name")); - currentFile.image = "zig-script"; - currentFile.setAction( - Task.Run, - new TaskResolvableAction({ - data: { - type: "current-file-run", - }, - }), - ); - currentFile.setAction( - Task.Clean, - new TaskResolvableAction({ - data: { - type: "current-file-clean", - }, - }), - ); - tasks.push(currentFile); + if (getBooleanConfigValue(CONFIG_KEYS.showCurrentFile, true)) { + const currentFile = new Task(localize("autotasks.current-file.name")); + currentFile.image = "zig-script"; + currentFile.setAction( + Task.Run, + new TaskResolvableAction({ + data: { + type: "current-file-run", + }, + }), + ); + currentFile.setAction( + Task.Clean, + new TaskResolvableAction({ + data: { + type: "current-file-clean", + }, + }), + ); + tasks.push(currentFile); + } const workspacePath = nova.workspace.path; if ( @@ -1329,10 +1354,7 @@ class ZigTaskAssistant { console.log(`[${TASK_ASSISTANT_ID}] resolveCleanAction: cwd=${cwd}`); if (!cwd) { nova.workspace.showWarningMessage( - localizeText( - "warning.clean.missing_cwd", - "Choose a workspace or working directory before cleaning Zig build artifacts.", - ), + localize("warning.clean.missing-cwd"), ); return null; } @@ -1481,10 +1503,7 @@ class ZigTaskAssistant { const cwd = filePath ? nova.path.dirname(filePath) : null; if (!filePath || !cwd) { nova.workspace.showWarningMessage( - localizeText( - "warning.current_file.focus_editor_for_run", - "Focus a Zig editor before running Current Zig File.", - ), + localize("warning.current-file.focus-editor-for-run"), ); return null; } @@ -1497,10 +1516,7 @@ class ZigTaskAssistant { const startDir = activeZigFileDirectory(); if (!startDir) { nova.workspace.showWarningMessage( - localizeText( - "warning.current_file.focus_editor_for_clean", - "Focus a Zig editor before cleaning Current Zig File artifacts.", - ), + localize("warning.current-file.focus-editor-for-clean"), ); return null; } @@ -1514,10 +1530,7 @@ class ZigTaskAssistant { const lldbDapPath = await resolveLldbDapExecutable(); if (!lldbDapPath) { nova.workspace.showWarningMessage( - localizeText( - "warning.lldb_dap.not-found", - "lldb-dap was not found. Install Xcode Command Line Tools or set an LLDB DAP executable path in Zig extension settings.", - ), + localize("warning.lldb-dap.not-found"), ); return null; } @@ -1535,10 +1548,7 @@ class ZigTaskAssistant { } if (!programPath) { nova.workspace.showWarningMessage( - localizeText( - "warning.debug.choose_program", - "Choose a program path before running Zig Debug.", - ), + localize("warning.debug.choose-program"), ); return null; } -- cgit v1.3