Manual

Manual · API

files

Folders, dialogs, reading and writing text — and the permissions macOS puts between an application and the disk.

Every command on this page carries a worked example.

chooseOpen function

files.chooseOpen(options)

The system's open dialog — a path, or null for Cancel.

Worked example
const path = files.chooseOpen({ types: ["csv"] });
if (path === null) { return; }   // Cancel

chooseSave function

files.chooseSave(options)

The system's save dialog — where to write, or null.

Worked example
const target = files.chooseSave({ suggestedName: "Export.csv" });
if (target !== null) {
    files.writeText(target, csvText);
}

asset function

files.asset(name) → file or null

A file the project ships. Everything in the project's `assets` folder travels inside the application — **folders included**, and then the name is the path inside it: `letters/reminder.txt`. This hands it over as the same object a file field gives you — **by name, never by path**: in a built application there is no folder to point at, and the same call works in the designer and at your customer's. Read-only; write with `writeText` into `applicationFolder()`.

Worked example
// A letter template that ships with the application:
const template = files.asset("Reminder.txt");
if (template) {
    form.body.value = template.text
        .replace("{name}", form.record.customer.name);
}

assetNames function

files.assetNames() → array of names

Everything the project ships, sorted — for a script that offers a choice rather than knowing one.

Worked example
// Every letter template the project carries:
const templates = files.assetNames().filter(n => n.endsWith(".txt"));
log(templates.length + " templates: " + templates.join(", "));
form.body.value = files.asset(templates[0]).text;

applicationFolder function

files.applicationFolder()

The application's own folder under Application Support — always writable, no questions asked.

Worked example
// The application's own notes file — writable without any dialog:
const path = files.applicationFolder() + "/lastRun.txt";
files.writeText(path, new Date().toISOString());

desktop function

files.desktop()

The user's desktop. macOS asks the user once, on first access — the rule surfaced honestly.

Worked example
// macOS asks once, the first time — after that this just answers:
files.writeText(files.desktop() + "/Report.txt", text);

documents function

files.documents()

The Documents folder — asks once on first access.

Worked example
const folder = files.documents();

downloads function

files.downloads()

The Downloads folder — asks once on first access.

Worked example
const newest = files.downloads() + "/prices.csv";
if (files.canRead(newest)) { importPrices(newest); }

home function

files.home()

The user's home folder.

Worked example
log(files.home());   // "/Users/anna"

temporary function

files.temporary()

A scratch folder that may vanish when the application quits — for intermediate files, never for data.

Worked example
// Scratch space — may vanish when the application quits:
const scratch = files.temporary() + "/preview.csv";

readText function

files.readText(path, { encoding })

The whole file as one text.

Run detectEncoding first on files you did not write — yesterday's exports are windows1252 more often than anybody hopes, and a wrong guess turns umlauts to rubble.
Worked example
const encoding = files.detectEncoding(path);
const whole = files.readText(path, { encoding });

readLines function

files.readLines(path, { encoding })

The file as an array of lines — what a loop wants.

Worked example
const path = files.chooseOpen();
if (path !== null) {
    const encoding = files.detectEncoding(path);   // "windows1252"?
    for (const line of files.readLines(path, { encoding })) {
        log(line);
    }
}

writeText function

files.writeText(path, text, { encoding })

Writes the text as the whole file.

Pair with chooseSave for user files; for the application's own, applicationFolder() never asks permission.
Worked example
for (const line of files.readLines(path, { encoding: "utf8" })) {
    if (line.trim() === "") { continue; }
    handle(line.split(";"));
}

detectEncoding function

files.detectEncoding(path)

What an old export really is — "windows1252" more often than anybody hopes. Hand the answer to readText.

Worked example
files.writeText(target, lines.join("\n"), { encoding: "utf8" });

canRead function

files.canRead(path)

Tries, honestly — true/false.

Worked example
const encoding = files.detectEncoding(path);   // "windows1252", "utf8", …
const text = files.readText(path, { encoding });

canWrite function

files.canWrite(path)

Tries with a probe file — true/false.

Worked example
if (!files.canRead(path)) {
    messages.showError("That file cannot be read.");
    return;
}

openPermissionSettings function

files.openPermissionSettings()

The System Settings pane where a refused folder permission can be undone — so your error dialog can offer the way out.

Worked example
if (!files.canWrite(folder)) {
    files.openPermissionSettings();
    return;
}