UNPKG

open-finder-dialog

Version:

Open a finder dialog window (finder prompt) programmatically. Only works on MacOS.

100 lines (92 loc) 3.54 kB
var __defProp = Object.defineProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); // index.ts import cp from "node:child_process"; import { detectTerminal } from "detect-terminal"; var escapeQuotedPath = /* @__PURE__ */ __name((input) => { return input.replace(/(?<!\\(?<!\\))"/g, "\\$&"); }, "escapeQuotedPath"); var isCanceled = /* @__PURE__ */ __name((v) => /cancell?ed/i.test(v), "isCanceled"); var buildCommand = /* @__PURE__ */ __name((allowMultiple, filters) => { const base = "choose file"; const withPrompt = ' with prompt "Select files to open"'; const ofType = filters.length > 0 ? ` of type {${filters.map((f) => `"${f}"`).join(", ")}}` : ""; const multi = allowMultiple ? " with multiple selections allowed" : ""; return base + withPrompt + ofType + multi; }, "buildCommand"); var openFinderDialog = /* @__PURE__ */ __name(async (initialDirectory = process.cwd(), options = {}) => { return new Promise((resolve, reject) => { const { filters = [], terminal = detectTerminal(), limit = 100 } = options; const maxFiles = Math.max(1, limit); const command = buildCommand(limit > 1, filters); const escapedPath = escapeQuotedPath(initialDirectory); const pathSeparator = "<__PATH_SEPARATOR__>"; const appleScript = ` set defaultPath to POSIX file "${escapedPath}" set limit to ${maxFiles} try -- Open the file dialog within SystemUIServer to bring it to focus tell application "SystemUIServer" activate delay 0.2 -- Allow SystemUIServer to activate set file_list to ${command} default location defaultPath if limit = 1 then set file_list to {file_list} end if end tell -- Apply the maximum-files rule if limit > 0 and (count of file_list) > limit then set file_list to items 1 thru limit of file_list end if -- Process the selected files set posixPaths to {} repeat with aFile in file_list set end of posixPaths to POSIX path of aFile & "${pathSeparator}" end repeat -- Return focus to ${terminal} tell application "${terminal}" activate end tell set text item delimiters to "" set posixPathsString to posixPaths as string return posixPathsString on error -- Return focus to terminal app even if the dialog is canceled tell application "${terminal}" activate end tell return "CANCELLED" end try `; const child = cp.spawn("osascript", ["-"]); let stdoutData = ""; let stderrData = ""; child.stdout.on("data", (data) => { stdoutData += data.toString(); }); child.stderr.on("data", (data) => { stderrData += data.toString(); }); child.on("close", (code) => { if (code !== 0 && stderrData) { reject(new Error(stderrData.trim())); return; } const output = stdoutData.trim(); if (isCanceled(output)) { resolve({ files: [], canceled: true }); return; } const files = output.split(pathSeparator).map((s) => s.trim()).filter((s) => s !== ""); resolve({ files, canceled: false }); }); child.stdin.write(appleScript); child.stdin.end(); }); }, "openFinderDialog"); var open_finder_dialog_default = openFinderDialog; export { open_finder_dialog_default as default, openFinderDialog }; //# sourceMappingURL=index.mjs.map