hledger_parser/directive/
account.rs

1use chumsky::prelude::*;
2
3use crate::component::account_name::account_name;
4use crate::component::whitespace::whitespace;
5use crate::state::State;
6use crate::utils::end_of_line_prefixed;
7
8#[derive(Debug, Clone, PartialEq)]
9pub struct Account {
10    pub account_name: Vec<String>,
11}
12
13pub fn account<'a>() -> impl Parser<'a, &'a str, Account, extra::Full<Rich<'a, char>, State, ()>> {
14    just("account")
15        .ignore_then(whitespace().repeated().at_least(1))
16        .ignore_then(account_name())
17        .then_ignore(
18            end_of_line_prefixed(2), // The two-space requirement for same-line account comments is because ; is allowed in account names.
19        )
20        .map(|account_name| Account { account_name })
21}
22
23#[cfg(test)]
24mod tests {
25    use super::*;
26
27    #[test]
28    fn ok_simple() {
29        let result = account()
30            .then_ignore(end())
31            .parse("account one:two:three")
32            .into_result();
33        assert_eq!(
34            result,
35            Ok(Account {
36                account_name: vec![
37                    String::from("one"),
38                    String::from("two"),
39                    String::from("three"),
40                ]
41            })
42        );
43    }
44
45    #[test]
46    fn ok_with_padding() {
47        let result = account()
48            .then_ignore(end())
49            .parse("account     one:two:three   ")
50            .into_result();
51        assert_eq!(
52            result,
53            Ok(Account {
54                account_name: vec![
55                    String::from("one"),
56                    String::from("two"),
57                    String::from("three"),
58                ]
59            })
60        );
61    }
62
63    #[test]
64    fn ok_comment_merged() {
65        let result = account()
66            .then_ignore(end())
67            .parse("account     one:two:three ; comment ")
68            .into_result();
69        assert_eq!(
70            result,
71            Ok(Account {
72                account_name: vec![
73                    String::from("one"),
74                    String::from("two"),
75                    String::from("three ; comment"),
76                ]
77            })
78        );
79    }
80
81    #[test]
82    fn ok_with_comment() {
83        let result = account()
84            .then_ignore(end())
85            .parse("account     one:two:three   ; comment ")
86            .into_result();
87        assert_eq!(
88            result,
89            Ok(Account {
90                account_name: vec![
91                    String::from("one"),
92                    String::from("two"),
93                    String::from("three"),
94                ]
95            })
96        );
97    }
98
99    #[test]
100    fn err() {
101        let result = account()
102            .then_ignore(end())
103            .parse("acount     one:two:three   ; comment ")
104            .into_result();
105        assert!(result.is_err());
106    }
107}