// // Promise wrappers around Nova's callback-based panels, plus the small file // helpers used to surface logs, diffs, and artifacts in the editor. // const log = require("./util/log.js"); function input(message, options = {}) { return new Promise((resolve) => { nova.workspace.showInputPanel(message, options, (value) => resolve(value ?? null)); }); } function palette(message, options = {}) { return new Promise((resolve) => { nova.workspace.showInputPalette(message, options, (value) => resolve(value ?? null)); }); } /** * Shows a choice palette over `items` and resolves to the chosen item. * `label` maps an item to its display string. */ function choose(items, { placeholder, label = String } = {}) { return new Promise((resolve) => { const labels = items.map((item) => label(item)); nova.workspace.showChoicePalette( labels, { placeholder: placeholder }, (value, index) => { if (value === null || index === null || index === undefined) resolve(null); else resolve(items[index]); }, ); }); } /** Resolves to the index of the chosen button, or null when dismissed. */ function actions(message, buttons) { return new Promise((resolve) => { nova.workspace.showActionPanel(message, { buttons: buttons }, (index) => resolve(index ?? null), ); }); } async function confirm(message, confirmLabel = "OK") { const index = await actions(message, [confirmLabel, "Cancel"]); return index === 0; } function info(message) { nova.workspace.showInformativeMessage(message); } function warn(message) { nova.workspace.showWarningMessage(message); } function error(message) { nova.workspace.showErrorMessage(String(message && message.message ? message.message : message)); } /** Creates `dir` and every missing parent. */ function mkdirp(dir) { const parts = nova.path.split(nova.path.normalize(dir)); let current = nova.path.isAbsolute(dir) ? "/" : ""; for (const part of parts) { if (!part || part === "/") continue; current = nova.path.join(current, part); if (!nova.fs.access(current, nova.fs.F_OK)) { nova.fs.mkdir(current); } } } function writeText(path, contents) { mkdirp(nova.path.dirname(path)); const file = nova.fs.open(path, "w", "utf-8"); try { file.write(contents); } finally { file.close(); } return path; } function writeBinary(path, buffer) { mkdirp(nova.path.dirname(path)); const file = nova.fs.open(path, "wb"); try { file.write(new Uint8Array(buffer)); } finally { file.close(); } return path; } /** * Opens `contents` in the editor. When `path` is given the text is saved there * first so the tab is a real file; otherwise it opens as an untitled document. */ async function openText(contents, { path = null, syntax = null } = {}) { if (path) { try { writeText(path, contents); return await nova.workspace.openFile(path); } catch (writeError) { log.error("could not save to", path, String(writeError)); // Fall through to an untitled tab rather than losing the content. } } return await nova.workspace.openNewTextDocument({ content: contents, syntax: syntax }); } exports.input = input; exports.palette = palette; exports.choose = choose; exports.actions = actions; exports.confirm = confirm; exports.info = info; exports.warn = warn; exports.error = error; exports.mkdirp = mkdirp; exports.writeText = writeText; exports.writeBinary = writeBinary; exports.openText = openText;