nom_kconfig/attribute/
prompt.rs

1use super::expression::{parse_if_attribute, Expression};
2use crate::{util::ws, KconfigInput};
3use nom::{
4    branch::alt,
5    bytes::complete::{tag, take_until},
6    character::complete::{alphanumeric1, char, line_ending, multispace1, not_line_ending, one_of},
7    combinator::{eof, map, recognize, verify},
8    multi::many1,
9    sequence::{delimited, terminated},
10    IResult, Parser,
11};
12#[cfg(feature = "deserialize")]
13use serde::Deserialize;
14#[cfg(feature = "serialize")]
15use serde::Serialize;
16
17/// Every menu entry can have at most one prompt, which is used to display to the user.
18/// Optionally dependencies only for this prompt can be added with "if".
19#[derive(Debug, Clone, PartialEq)]
20#[cfg_attr(feature = "hash", derive(Hash))]
21#[cfg_attr(feature = "serialize", derive(Serialize))]
22#[cfg_attr(feature = "deserialize", derive(Deserialize))]
23pub struct Prompt {
24    pub prompt: String,
25    #[cfg_attr(
26        any(feature = "serialize", feature = "deserialize"),
27        serde(skip_serializing_if = "Option::is_none")
28    )]
29    pub r#if: Option<Expression>,
30}
31
32#[cfg(feature = "display")]
33use std::fmt::Display;
34#[cfg(feature = "display")]
35impl Display for Prompt {
36    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
37        match &self.r#if {
38            Some(i) => write!(f, r#""{}" if {}"#, self.prompt, i),
39            None => write!(f, r#""{}""#, self.prompt),
40        }
41    }
42}
43
44pub fn parse_prompt(input: KconfigInput) -> IResult<KconfigInput, Prompt> {
45    map(
46        (ws(tag("prompt")), parse_prompt_value, parse_if_attribute),
47        |(_, p, i)| Prompt {
48            prompt: p.to_string(),
49            r#if: i,
50        },
51    )
52    .parse(input)
53}
54
55/// Parses a `prompt` attribute.
56/// # Example
57/// ```
58/// use nom_kconfig::{assert_parsing_eq, attribute::parse_prompt_value};
59///
60/// assert_parsing_eq!(parse_prompt_value, "scripts/Kconfig.include", Ok(("", "scripts/Kconfig.include".to_string())))
61/// ```
62pub fn parse_prompt_value(input: KconfigInput) -> IResult<KconfigInput, String> {
63    map(
64        alt((
65            delimited(
66                ws(char('"')),
67                recognize(ws(many1(alt((
68                    alphanumeric1,
69                    multispace1,
70                    tag("\\\""),
71                    // TODO
72                    //recognize(anychar),
73                    recognize(one_of("&#*|!É{}^<>%[]()+'=,:;μ-?._$/")),
74                ))))),
75                char('"'),
76            ),
77            delimited(ws(char('\'')), take_until("'"), char('\'')),
78            // TODO linux v-3.2, in file /arch/arm/plat-tcc/Kconfig
79            verify(
80                terminated(not_line_ending, alt((line_ending, eof))),
81                |d: &KconfigInput| !d.trim().is_empty(),
82            ),
83        )),
84        |d: KconfigInput| d.fragment().to_owned().trim().to_string(),
85    )
86    .parse(input)
87}