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}