nom_config_in/entry/
choice.rs

1use nom::{
2    branch::alt,
3    bytes::complete::tag,
4    character::complete::{alphanumeric1, one_of},
5    combinator::{map, recognize},
6    multi::many1,
7    sequence::{delimited, pair, tuple},
8    IResult,
9};
10use serde::Serialize;
11
12use crate::{symbol::parse_constant_symbol, util::ws, ConfigInInput};
13
14use super::comment::parse_prompt_option;
15
16fn parse_choice_option_label(input: ConfigInInput) -> IResult<ConfigInInput, String> {
17    map(
18        recognize(many1(alt((alphanumeric1, recognize(one_of(",._()-/$+")))))),
19        |c: ConfigInInput| c.to_string(),
20    )(input)
21}
22
23fn parse_choice_option(input: ConfigInInput) -> IResult<ConfigInInput, ChoiceOption> {
24    map(
25        tuple((ws(parse_choice_option_label), ws(parse_constant_symbol))),
26        |(l, r)| ChoiceOption {
27            left: l,
28            right: r.to_string(),
29        },
30    )(input)
31}
32
33pub fn parse_choice(input: ConfigInInput) -> IResult<ConfigInInput, Choice> {
34    let (input, prompt) = tuple((ws(tag("choice")), ws(parse_prompt_option)))(input)?;
35    let (input, ok) = alt((
36        pair(
37            delimited(ws(tag("\"")), many1(ws(parse_choice_option)), ws(tag("\""))),
38            ws(parse_constant_symbol),
39        ),
40        delimited(
41            ws(tag("\"")),
42            pair(many1(ws(parse_choice_option)), ws(parse_constant_symbol)),
43            ws(tag("\"")),
44        ),
45    ))(input)?;
46    Ok((
47        input,
48        Choice {
49            prompt: prompt.1.to_string(),
50            entries: ok.0,
51            default: ok.1.to_string(),
52        },
53    ))
54}
55
56#[derive(Debug, Clone, Default, Serialize, PartialEq)]
57pub struct Choice {
58    pub prompt: String,
59    pub entries: Vec<ChoiceOption>,
60    pub default: String,
61}
62
63#[derive(Debug, Clone, Default, Serialize, PartialEq)]
64pub struct ChoiceOption {
65    pub left: String,
66    pub right: String,
67}