Skip to main content

ashlar_command/
macros.rs

1//! `cmd!` / `query!`: the shape of existing app command tables, so they port by search and
2//! replace.
3
4/// A mutating command:
5/// `cmd!(id, label, [menu…], shortcut, params, enabled, run)`.
6///
7/// `params` is a legacy text doc (`r#"{"name":str}"#`) or a typed list
8/// (`[Param::string("name").required()]`, built in a `const` so the table can be `static`).
9/// `run` returns the host's [`crate::Host::Error`].
10///
11/// ```
12/// use ashlar_command::{CommandError, CommandSpec, Host, Journal, Param, always, cmd};
13/// struct Doc { title: String, journal: Journal }
14/// impl Host for Doc {
15///     type Error = CommandError;
16///     fn journal(&mut self) -> &mut Journal { &mut self.journal }
17/// }
18/// let spec: CommandSpec<Doc> = cmd!("doc.rename", "Rename…", ["Edit"], Some("Mod+R"), [Param::string("title").required()], always, |d, p| {
19///     d.title = p["title"].as_str().unwrap_or_default().to_string();
20///     Ok(serde_json::Value::Null)
21/// });
22/// assert!(spec.mutates);
23/// ```
24#[macro_export]
25macro_rules! cmd {
26    ($id:literal, $label:literal, [$($m:literal),* $(,)?], $sc:expr, [$($p:expr),* $(,)?], $en:expr, $run:expr $(,)?) => {
27        $crate::CommandSpec {
28            id: $id,
29            label: $label,
30            menu: &[$($m),*],
31            shortcut: $sc,
32            params: $crate::Params::Static({
33                const PARAMS: &[$crate::Param] = &[$($p),*];
34                PARAMS
35            }),
36            enabled: $en,
37            run: $run,
38            mutates: true,
39        }
40    };
41    ($id:literal, $label:literal, [$($m:literal),* $(,)?], $sc:expr, $params:literal, $en:expr, $run:expr $(,)?) => {
42        $crate::CommandSpec {
43            id: $id,
44            label: $label,
45            menu: &[$($m),*],
46            shortcut: $sc,
47            params: $crate::Params::Text($params),
48            enabled: $en,
49            run: $run,
50            mutates: true,
51        }
52    };
53}
54
55/// A pure query (always enabled, not in menus, not journaled):
56/// `query!(id, label, params, run)`.
57#[macro_export]
58macro_rules! query {
59    ($id:literal, $label:literal, [$($p:expr),* $(,)?], $run:expr $(,)?) => {
60        $crate::CommandSpec {
61            id: $id,
62            label: $label,
63            menu: &[],
64            shortcut: None,
65            params: $crate::Params::Static({
66                const PARAMS: &[$crate::Param] = &[$($p),*];
67                PARAMS
68            }),
69            enabled: $crate::always,
70            run: $run,
71            mutates: false,
72        }
73    };
74    ($id:literal, $label:literal, $params:literal, $run:expr $(,)?) => {
75        $crate::CommandSpec {
76            id: $id,
77            label: $label,
78            menu: &[],
79            shortcut: None,
80            params: $crate::Params::Text($params),
81            enabled: $crate::always,
82            run: $run,
83            mutates: false,
84        }
85    };
86}