nom_kconfig/attribute/
prompt.rs1use 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::char,
7 character::complete::{alphanumeric1, line_ending, multispace1, not_line_ending, one_of},
8 combinator::{eof, map, recognize, verify},
9 multi::many1,
10 sequence::{delimited, terminated, tuple},
11 IResult,
12};
13#[cfg(feature = "deserialize")]
14use serde::Deserialize;
15#[cfg(feature = "serialize")]
16use serde::Serialize;
17
18#[derive(Debug, Clone, PartialEq)]
21#[cfg_attr(feature = "hash", derive(Hash))]
22#[cfg_attr(feature = "serialize", derive(Serialize))]
23#[cfg_attr(feature = "deserialize", derive(Deserialize))]
24pub struct Prompt {
25 pub prompt: String,
26 #[cfg_attr(
27 any(feature = "serialize", feature = "deserialize"),
28 serde(skip_serializing_if = "Option::is_none")
29 )]
30 pub r#if: Option<Expression>,
31}
32
33#[cfg(feature = "display")]
34use std::fmt::Display;
35#[cfg(feature = "display")]
36impl Display for Prompt {
37 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
38 match &self.r#if {
39 Some(i) => write!(f, r#""{}" if {}"#, self.prompt, i),
40 None => write!(f, r#""{}""#, self.prompt),
41 }
42 }
43}
44
45pub fn parse_prompt(input: KconfigInput) -> IResult<KconfigInput, Prompt> {
46 map(
47 tuple((ws(tag("prompt")), parse_prompt_value, parse_if_attribute)),
48 |(_, p, i)| Prompt {
49 prompt: p.to_string(),
50 r#if: i,
51 },
52 )(input)
53}
54
55pub 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 recognize(one_of("&#*|!É{}^<>%[]()+'=,:;μ-?._$/")),
74 ))))),
75 char('"'),
76 ),
77 delimited(ws(char('\'')), take_until("'"), char('\'')),
78 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 )(input)
86}