dialog

tape
@profile(t1);
import dialog from "dialog";
import io from "io";

pub fn main() -> i32 {
    let images = [dialog.Filter { name: "Images"; patterns: ["*.png", "*.jpg"]; },
                  dialog.Filter { name: "All files"; patterns: ["*"]; }];
    let p: string = dialog.open_file(dialog.Options { title: "Attach a picture"; filters: images[0..2]; }) or {
        if (err == dialog.DialogError.Cancelled) { return 0; }
        io.println("no dialog: {err}");
        return 1;
    };
    io.println("chosen: {p}");
    return 0;
}

The user’s own file dialog, with their places and recent folders. Each call waits for the answer and gives absolute paths. Cancelling is DialogError.Cancelled, its own error: usually you just return.

FunctionGives
dialog.open_file(o) -> string or DialogErrorOne existing file
dialog.open_files(o) -> collections.Vec_string or DialogErrorOne or more existing files
dialog.open_folder(o) -> string or DialogErrorAn existing folder (filters aren’t used)
dialog.save_file(o) -> string or DialogErrorWhere to save: the folder exists, the file may not. If it does, the dialog has already asked the user before replacing it

Options (every field has a default, so dialog.Options { .. } is a plain dialog):

FieldIs
title: []const u8 = ""The dialog’s title; the system’s own when empty
folder: []const u8 = ""Where it starts; the system’s choice (often the last folder used) when empty
name: []const u8 = ""The file name save_file suggests
filters: []const Filter = []The file types offered, the first chosen at the start; every file when none
parent: i64 = 0The window it is modal over (uwm.native_handle); 0 is your ui window while ui.run has one open

A Filter is a name and its patterns: Filter { name: "Text"; patterns: ["*.txt", "*.md"]; }; "*" is every file. A filter with no patterns, an empty name or pattern, or a tab, newline or ; in one traps.

tape
fn save_as(text: []const u8) {
    let txt = [dialog.Filter { name: "Text"; patterns: ["*.txt"]; }];
    let to: string = dialog.save_file(dialog.Options { name: "notes.txt"; filters: txt[0..1]; })
        or { return; };
    fs.write_file(to, text) or { };
}

Errors

DialogError:

VariantWhen
CancelledThe user closed the dialog without choosing
UnsupportedNo system dialog here: Linux without the desktop portal. Show your own widgets dialog instead
FailedThe dialog failed
OutOfMemoryOut of memory

Platforms

  • Windows: the common item dialogs, modal over the window.
  • macOS: the open and save panels, modal for the whole application. The panels have no file type menu: every filter’s extensions are allowed together.
  • Linux: the desktop portal’s file chooser (xdg-desktop-portal with your desktop’s backend) on the session bus, through dbus, over your X11 window; the call waits for the user as on the other systems (while it waits, your status icon still answers and notifications’ clicks are kept). Unsupported without a session bus or a portal: show your own widgets dialog then.

The library is shell100 (.dll, .dylib, .so), next to tape; tape build copies it beside your program.

Last modified: