Skip to main content

nifty_check/
functions.rs

1//! The built-in functions and the arguments each one takes. The checker dispatches on
2//! [`Function::kind`], and tools such as the language server read the same table.
3
4use nifty_runtime::{DownloadCommand, DownloadField};
5
6use crate::elements::{BoundType, Param, ParamKind, named, positional, required};
7
8/// A built-in function such as `download`, called from functions and button actions.
9#[derive(Debug)]
10pub struct Function {
11    pub name: &'static str,
12    pub kind: FunctionKind,
13    pub params: &'static [Param],
14    /// The type of the value a call gives; `None` for functions called for what they do.
15    pub value: Option<BoundType>,
16    pub summary: &'static str,
17}
18
19/// Which function a table entry is, for the checker to dispatch on.
20#[derive(Clone, Copy, Debug, PartialEq, Eq)]
21pub enum FunctionKind {
22    Download,
23    PickFile,
24    PickFiles,
25    PickFolder,
26    PickSavePath,
27    OpenWindow,
28    CloseWindow,
29    FormatBytes,
30    /// `cancel_download` and the other functions that ask something of a running download.
31    DownloadCommand(DownloadCommand),
32}
33
34/// Saves a file from the web in the background, reporting into two bound states.
35pub const DOWNLOAD: &str = "download";
36
37/// How many connections a download fetches its file over at once.
38pub const CONNECTIONS: &str = "connections";
39/// The number of connections a download opens unless its call asks for more.
40pub const DEFAULT_CONNECTIONS: i64 = 1;
41/// Headers a download sends with each request, each written `Name: value`.
42pub const HEADERS: &str = "headers";
43/// How many times in a row a download tries a connection again after a failure that may
44/// pass.
45pub const RETRIES: &str = "retries";
46/// The retries a download makes unless its call asks for some.
47pub const DEFAULT_RETRIES: i64 = 0;
48
49/// A size in bytes as text, such as `1.5 MB`.
50pub const FORMAT_BYTES: &str = "format_bytes";
51
52/// Opens a window by its name.
53pub const OPEN_WINDOW: &str = "open_window";
54
55/// The settings file dialogs share: the text shown above the files, the extensions
56/// allowed, and the folder they open in.
57pub const TITLE: &str = "title";
58pub const TYPES: &str = "types";
59pub const FROM: &str = "from";
60/// The file name a save dialog suggests, or a download saves as.
61pub const NAME: &str = "name";
62
63const TITLE_PARAM: Param = named(TITLE, ParamKind::Text);
64const TYPES_PARAM: Param = named(TYPES, ParamKind::TextList);
65const FROM_PARAM: Param = named(FROM, ParamKind::Text);
66const WINDOW_PARAM: Param = positional("window", ParamKind::Window);
67const DOWNLOAD_ID_PARAM: Param = positional("id", ParamKind::Text);
68
69/// The type of state `field` of a download's reports is written into.
70pub(crate) const fn download_bound_type(field: DownloadField) -> BoundType {
71    if field.is_text() {
72        BoundType::String
73    } else {
74        BoundType::Int
75    }
76}
77
78/// The row of `cancel_download` and the other functions that ask something of a running
79/// download by its id.
80const fn download_command(command: DownloadCommand, summary: &'static str) -> Function {
81    Function {
82        name: command.function(),
83        kind: FunctionKind::DownloadCommand(command),
84        params: &[DOWNLOAD_ID_PARAM],
85        value: None,
86        summary,
87    }
88}
89
90/// The setting that binds `field` of a download's reports.
91const fn download_binding(field: DownloadField) -> Param {
92    let kind = ParamKind::Binding(download_bound_type(field));
93    if field.is_required() {
94        required(field.name(), kind)
95    } else {
96        named(field.name(), kind)
97    }
98}
99
100pub const FUNCTIONS: &[Function] = &[
101    Function {
102        name: DOWNLOAD,
103        kind: FunctionKind::Download,
104        params: &[
105            positional("url", ParamKind::Text),
106            required("to", ParamKind::Text),
107            download_binding(DownloadField::Progress),
108            download_binding(DownloadField::Status),
109            download_binding(DownloadField::Received),
110            download_binding(DownloadField::Total),
111            download_binding(DownloadField::Speed),
112            download_binding(DownloadField::Id),
113            named(NAME, ParamKind::Text),
114            named(CONNECTIONS, ParamKind::Number),
115            named(HEADERS, ParamKind::TextList),
116            named(RETRIES, ParamKind::Number),
117        ],
118        value: None,
119        summary: "Saves the file at a web address into a folder, in the background.",
120    },
121    Function {
122        name: "pick_file",
123        kind: FunctionKind::PickFile,
124        params: &[
125            positional("path", ParamKind::Binding(BoundType::String)),
126            TITLE_PARAM,
127            TYPES_PARAM,
128            FROM_PARAM,
129        ],
130        value: None,
131        summary: "Asks the user to choose a file, and writes its path into the bound state.",
132    },
133    Function {
134        name: "pick_files",
135        kind: FunctionKind::PickFiles,
136        params: &[
137            positional("paths", ParamKind::Binding(BoundType::Strings)),
138            TITLE_PARAM,
139            TYPES_PARAM,
140            FROM_PARAM,
141        ],
142        value: None,
143        summary: "Asks the user to choose files, and writes their paths into the bound list.",
144    },
145    Function {
146        name: "pick_folder",
147        kind: FunctionKind::PickFolder,
148        params: &[
149            positional("folder", ParamKind::Binding(BoundType::String)),
150            TITLE_PARAM,
151            FROM_PARAM,
152        ],
153        value: None,
154        summary: "Asks the user to choose a folder, and writes its path into the bound state.",
155    },
156    Function {
157        name: "pick_save_path",
158        kind: FunctionKind::PickSavePath,
159        params: &[
160            positional("path", ParamKind::Binding(BoundType::String)),
161            TITLE_PARAM,
162            TYPES_PARAM,
163            named(NAME, ParamKind::Text),
164            FROM_PARAM,
165        ],
166        value: None,
167        summary: "Asks the user where to save a file, and writes that path into the bound state.",
168    },
169    Function {
170        name: OPEN_WINDOW,
171        kind: FunctionKind::OpenWindow,
172        params: &[WINDOW_PARAM],
173        value: None,
174        summary: "Opens the window with this name, or brings it to the front if it's open.",
175    },
176    Function {
177        name: "close_window",
178        kind: FunctionKind::CloseWindow,
179        params: &[WINDOW_PARAM],
180        value: None,
181        summary: "Closes the window with this name, if it's open.",
182    },
183    Function {
184        name: FORMAT_BYTES,
185        kind: FunctionKind::FormatBytes,
186        params: &[positional("bytes", ParamKind::Number)],
187        value: Some(BoundType::String),
188        summary: "A size in bytes as text, such as `1.5 MB`.",
189    },
190    download_command(
191        DownloadCommand::Cancel,
192        "Stops the download with this id for good, removing what it saved so far.",
193    ),
194    download_command(
195        DownloadCommand::Pause,
196        "Pauses the download with this id, keeping what it saved so far.",
197    ),
198    download_command(
199        DownloadCommand::Resume,
200        "Carries on with the paused download with this id from where it stopped.",
201    ),
202];
203
204/// The function called `name`, if it is built in.
205#[must_use]
206pub fn function(name: &str) -> Option<&'static Function> {
207    FUNCTIONS.iter().find(|function| function.name == name)
208}