getopts_macro/
lib.rs

1#![no_std]
2#![doc = include_str!("../README.md")]
3
4pub use getopts;
5
6/// Quick create [`getopts::Options`]
7///
8/// - `*` is require multi
9/// - `+` is require one
10/// - `=` is has arg
11/// - `?=` is has optional arg
12///
13/// # Examples
14/// ```
15/// use getopts_macro::{
16///     getopts_options,
17///     getopts::ParsingStyle,
18/// };
19///
20/// let _options = getopts_options! {
21///     -f --file=FILE              "input from file";
22///     -p --parse-config*=CONFIG   "parse config";
23///     -h --help*                  "help messages";
24///        --help-long*             "long help messages";
25///     .parsing_style(ParsingStyle::StopAtFirstFree)
26/// };
27/// ```
28#[macro_export]
29macro_rules! getopts_options {
30    (-$($t:tt)*) => {{
31        let mut options = $crate::getopts::Options::new();
32        $crate::getopts_options!(@with(options) -$($t)*);
33        options
34    }};
35    (@long $first:ident $($rest:ident)*) => {
36        ::core::concat!(
37            ::core::stringify!($first),
38            $(
39                "-",
40                ::core::stringify!($rest),
41            )*
42        )
43    };
44
45    (@with($o:ident)) => {};
46    (@with($o:ident) . $($t:tt)+) => {
47        $o.$($t)+;
48    };
49    (@with($o:ident) $t1:tt $t2:tt $desc:tt; $($rest:tt)*) => {
50        $crate::getopts_options!(@impl($o, $desc) $t1 $t2);
51        $crate::getopts_options!(@with($o) $($rest)*);
52    };
53    (@with($o:ident) $t1:tt $t2:tt $t3:tt $desc:tt; $($rest:tt)*) => {
54        $crate::getopts_options!(@impl($o, $desc) $t1 $t2 $t3);
55        $crate::getopts_options!(@with($o) $($rest)*);
56    };
57    (@with($o:ident) $t1:tt $t2:tt $t3:tt $t4:tt $desc:tt; $($rest:tt)*) => {
58        $crate::getopts_options!(@impl($o, $desc) $t1 $t2 $t3 $t4);
59        $crate::getopts_options!(@with($o) $($rest)*);
60    };
61    (@with($o:ident) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $desc:tt; $($rest:tt)*) => {
62        $crate::getopts_options!(@impl($o, $desc) $t1 $t2 $t3 $t4 $t5);
63        $crate::getopts_options!(@with($o) $($rest)*);
64    };
65    (@with($o:ident) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $desc:tt; $($rest:tt)*) => {
66        $crate::getopts_options!(@impl($o, $desc) $t1 $t2 $t3 $t4 $t5 $t6);
67        $crate::getopts_options!(@with($o) $($rest)*);
68    };
69    (@with($o:ident) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $desc:tt; $($rest:tt)*) => {
70        $crate::getopts_options!(@impl($o, $desc) $t1 $t2 $t3 $t4 $t5 $t6 $t7);
71        $crate::getopts_options!(@with($o) $($rest)*);
72    };
73    (@with($o:ident) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $desc:tt; $($rest:tt)*) => {
74        $crate::getopts_options!(@impl($o, $desc) $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8);
75        $crate::getopts_options!(@with($o) $($rest)*);
76    };
77    (@with($o:ident) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $desc:tt; $($rest:tt)*) => {
78        $crate::getopts_options!(@impl($o, $desc) $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9);
79        $crate::getopts_options!(@with($o) $($rest)*);
80    };
81    (@with($o:ident) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $desc:tt; $($rest:tt)*) => {
82        $crate::getopts_options!(@impl($o, $desc) $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10);
83        $crate::getopts_options!(@with($o) $($rest)*);
84    };
85    (@with($o:ident) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $t11:tt $desc:tt; $($rest:tt)*) => {
86        $crate::getopts_options!(@impl($o, $desc) $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11);
87        $crate::getopts_options!(@with($o) $($rest)*);
88    };
89    (@with($o:ident) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $t11:tt $t12:tt $desc:tt; $($rest:tt)*) => {
90        $crate::getopts_options!(@impl($o, $desc) $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11 $t12);
91        $crate::getopts_options!(@with($o) $($rest)*);
92    };
93    (@with($o:ident) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $t11:tt $t12:tt $t13:tt $desc:tt; $($rest:tt)*) => {
94        $crate::getopts_options!(@impl($o, $desc) $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11 $t12 $t13);
95        $crate::getopts_options!(@with($o) $($rest)*);
96    };
97    (@with($o:ident) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $t11:tt $t12:tt $t13:tt $t14:tt $desc:tt; $($rest:tt)*) => {
98        $crate::getopts_options!(@impl($o, $desc) $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11 $t12 $t13 $t14);
99        $crate::getopts_options!(@with($o) $($rest)*);
100    };
101    (@with($o:ident) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $t11:tt $t12:tt $t13:tt $t14:tt $t15:tt $desc:tt; $($rest:tt)*) => {
102        $crate::getopts_options!(@impl($o, $desc) $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11 $t12 $t13 $t14 $t15);
103        $crate::getopts_options!(@with($o) $($rest)*);
104    };
105    (@with($o:ident) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $t11:tt $t12:tt $t13:tt $t14:tt $t15:tt $t16:tt $desc:tt; $($rest:tt)*) => {
106        $crate::getopts_options!(@impl($o, $desc) $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11 $t12 $t13 $t14 $t15 $t16);
107        $crate::getopts_options!(@with($o) $($rest)*);
108    };
109    (@with($o:ident) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $t9:tt $t10:tt $t11:tt $t12:tt $t13:tt $t14:tt $t15:tt $t16:tt $t17:tt $desc:tt; $($rest:tt)*) => {
110        $crate::getopts_options!(@impl($o, $desc) $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8 $t9 $t10 $t11 $t12 $t13 $t14 $t15 $t16 $t17);
111        $crate::getopts_options!(@with($o) $($rest)*);
112    };
113
114    (@impl($o:ident, $desc:tt) -$short:ident --$($long:ident)-+) => {
115        $o.optflag(
116            ::core::stringify!($short),
117            $crate::getopts_options!(@long $($long)+),
118            $desc,
119        );
120    };
121    (@impl($o:ident, $desc:tt) -$short:ident --$($long:ident)-+ *) => {
122        $o.optflagmulti(
123            ::core::stringify!($short),
124            $crate::getopts_options!(@long $($long)+),
125            $desc,
126        );
127    };
128    (@impl($o:ident, $desc:tt) -$short:ident --$($long:ident)-+ = $hint:ident) => {
129        $o.optopt(
130            ::core::stringify!($short),
131            $crate::getopts_options!(@long $($long)+),
132            $desc,
133            ::core::stringify!($hint),
134        );
135    };
136    (@impl($o:ident, $desc:tt) -$short:ident --$($long:ident)-+ * = $hint:ident) => {
137        $o.optmulti(
138            ::core::stringify!($short),
139            $crate::getopts_options!(@long $($long)+),
140            $desc,
141            ::core::stringify!($hint),
142        );
143    };
144    (@impl($o:ident, $desc:tt) -$short:ident --$($long:ident)-+ *= $hint:ident) => {
145        $o.optmulti(
146            ::core::stringify!($short),
147            $crate::getopts_options!(@long $($long)+),
148            $desc,
149            ::core::stringify!($hint),
150        );
151    };
152    (@impl($o:ident, $desc:tt) -$short:ident --$($long:ident)-+ + = $hint:ident) => {
153        $o.reqopt(
154            ::core::stringify!($short),
155            $crate::getopts_options!(@long $($long)+),
156            $desc,
157            ::core::stringify!($hint),
158        );
159    };
160    (@impl($o:ident, $desc:tt) -$short:ident --$($long:ident)-+ += $hint:ident) => {
161        $o.reqopt(
162            ::core::stringify!($short),
163            $crate::getopts_options!(@long $($long)+),
164            $desc,
165            ::core::stringify!($hint),
166        );
167    };
168    (@impl($o:ident, $desc:tt) -$short:ident --$($long:ident)-+ ?= $hint:ident) => {
169        $o.optflagopt(
170            ::core::stringify!($short),
171            $crate::getopts_options!(@long $($long)+),
172            $desc,
173            ::core::stringify!($hint),
174        );
175    };
176
177
178    (@impl($o:ident, $desc:tt) -$short:ident) => {
179        $o.optflag(
180            ::core::stringify!($short),
181            "",
182            $desc,
183        );
184    };
185    (@impl($o:ident, $desc:tt) -$short:ident *) => {
186        $o.optflagmulti(
187            ::core::stringify!($short),
188            "",
189            $desc,
190        );
191    };
192    (@impl($o:ident, $desc:tt) -$short:ident = $hint:ident) => {
193        $o.optopt(
194            ::core::stringify!($short),
195            "",
196            $desc,
197            ::core::stringify!($hint),
198        );
199    };
200    (@impl($o:ident, $desc:tt) -$short:ident * = $hint:ident) => {
201        $o.optmulti(
202            ::core::stringify!($short),
203            "",
204            $desc,
205            ::core::stringify!($hint),
206        );
207    };
208    (@impl($o:ident, $desc:tt) -$short:ident *= $hint:ident) => {
209        $o.optmulti(
210            ::core::stringify!($short),
211            "",
212            $desc,
213            ::core::stringify!($hint),
214        );
215    };
216    (@impl($o:ident, $desc:tt) -$short:ident + = $hint:ident) => {
217        $o.reqopt(
218            ::core::stringify!($short),
219            "",
220            $desc,
221            ::core::stringify!($hint),
222        );
223    };
224    (@impl($o:ident, $desc:tt) -$short:ident += $hint:ident) => {
225        $o.reqopt(
226            ::core::stringify!($short),
227            "",
228            $desc,
229            ::core::stringify!($hint),
230        );
231    };
232    (@impl($o:ident, $desc:tt) -$short:ident ?= $hint:ident) => {
233        $o.optflagopt(
234            ::core::stringify!($short),
235            "",
236            $desc,
237            ::core::stringify!($hint),
238        );
239    };
240
241
242    (@impl($o:ident, $desc:tt) --$($long:ident)-+) => {
243        $o.optflag(
244            "",
245            $crate::getopts_options!(@long $($long)+),
246            $desc,
247        );
248    };
249    (@impl($o:ident, $desc:tt) --$($long:ident)-+ *) => {
250        $o.optflagmulti(
251            "",
252            $crate::getopts_options!(@long $($long)+),
253            $desc,
254        );
255    };
256    (@impl($o:ident, $desc:tt) --$($long:ident)-+ = $hint:ident) => {
257        $o.optopt(
258            "",
259            $crate::getopts_options!(@long $($long)+),
260            $desc,
261            ::core::stringify!($hint),
262        );
263    };
264    (@impl($o:ident, $desc:tt) --$($long:ident)-+ * = $hint:ident) => {
265        $o.optmulti(
266            "",
267            $crate::getopts_options!(@long $($long)+),
268            $desc,
269            ::core::stringify!($hint),
270        );
271    };
272    (@impl($o:ident, $desc:tt) --$($long:ident)-+ *= $hint:ident) => {
273        $o.optmulti(
274            "",
275            $crate::getopts_options!(@long $($long)+),
276            $desc,
277            ::core::stringify!($hint),
278        );
279    };
280    (@impl($o:ident, $desc:tt) --$($long:ident)-+ + = $hint:ident) => {
281        $o.reqopt(
282            "",
283            $crate::getopts_options!(@long $($long)+),
284            $desc,
285            ::core::stringify!($hint),
286        );
287    };
288    (@impl($o:ident, $desc:tt) --$($long:ident)-+ += $hint:ident) => {
289        $o.reqopt(
290            "",
291            $crate::getopts_options!(@long $($long)+),
292            $desc,
293            ::core::stringify!($hint),
294        );
295    };
296    (@impl($o:ident, $desc:tt) --$($long:ident)-+ ?= $hint:ident) => {
297        $o.optflagopt(
298            "",
299            $crate::getopts_options!(@long $($long)+),
300            $desc,
301            ::core::stringify!($hint),
302        );
303    };
304}
305
306#[test]
307fn test() {
308    let usage = getopts_options! {
309        -c --center-rule            "...";
310        -i --ignore*=NAME           "...";
311        -I --ignore-partial*=NAME   "...";
312        -S --fake-source-from=SRC   "...";
313        -s --sep?=PATTERN           "...";
314        -h --help*                  "...";
315        -m*                         "...";
316           --long                   "...";
317           --long-arg=A             "...";
318        .parsing_style(getopts::ParsingStyle::StopAtFirstFree)
319    }.short_usage("prog");
320    assert_eq!(usage, "Usage: prog [-c] [-i NAME].. [-I NAME].. [-S SRC] [-s [PATTERN]] [-h].. [-m].. [--long] [--long-arg A]");
321}