-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathcli.rs
103 lines (90 loc) · 2.39 KB
/
cli.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
use std::{collections::BTreeSet, sync::LazyLock};
// XXX: This really needs proc macros to have any semblance of code-reuse. I
// reckon that this isn't worth the effort; when the CLI gets more complicated
// one should just accept the additional transitive dependencies and switch to
// clap.
pub static HELP: LazyLock<String> = LazyLock::new(|| {
[
"rq: A tiny functional language to filter and manipulate JSON.",
&USAGE,
&OPTIONS,
"POSITIONAL ARGUMENTS:
«EXPR» A function in rq's expression language.
«JSON» JSON! Can either—as indicated—be piped via stdin,
or given as a file argument.
repl The literal string \"repl\"; starts a REPL.",
]
.into_iter()
.intersperse("\n\n")
.collect()
});
static USAGE: LazyLock<String> = LazyLock::new(|| {
let flatten = CLI_OPTIONS.iter().find(|o| o.long == "--flatten").unwrap();
let help = CLI_OPTIONS.iter().find(|o| o.long == "--help").unwrap();
format!(
"USAGE:
rq [EXPR] < [JSON]
rq {} < [JSON]
rq {}
rq repl",
flatten.usage(),
help.usage()
)
});
static OPTIONS: LazyLock<String> = LazyLock::new(|| {
let opts: String = CLI_OPTIONS
.iter()
.map(|opt| opt.help())
.intersperse("\n".to_string())
.collect();
format!("OPTIONS:\n{opts}")
});
#[derive(PartialEq, Eq, PartialOrd, Ord)]
struct CliOption {
long: String,
short: String,
help: String,
}
impl CliOption {
fn usage(&self) -> String { format!("[{}|{}]", self.short, self.long) }
fn help(&self) -> String { format!(" {},{} {}", self.short, self.long, self.help) }
}
macro_rules! mk_option {
($long:literal, $short:literal, $help:literal $(,)?) => {{
CliOption {
long: format!("--{}", $long),
short: format!("-{}", $short),
help: $help.to_string(),
}
}};
}
macro_rules! mk_options {
($(($long:literal, $short:literal, $help:literal $(,)?)),+ $(,)?) => {
static CLI_OPTIONS: LazyLock<BTreeSet<CliOption>> = LazyLock::new (|| {
BTreeSet::from([
$(mk_option!($long, $short, $help)),+
])});
};
}
mk_options!(
("help", "h", "Show this help text."),
("flatten", "f", "Flatten the given JSON into a list.")
);
macro_rules! Help {
() => {
"--help" | "-h"
};
}
pub(crate) use Help;
macro_rules! Flatten {
() => {
"--flatten" | "-f"
};
}
pub(crate) use Flatten;
macro_rules! Fatten {
() => {
"--fatten" | "-F"
};
}
pub(crate) use Fatten;