hledger_parser/directive/
year.rs

1use chumsky::prelude::*;
2
3use crate::component::whitespace::whitespace;
4use crate::state::State;
5use crate::utils::end_of_line;
6
7#[derive(Clone, Debug, PartialEq)]
8pub struct Year(pub i32);
9
10pub fn year<'a>() -> impl Parser<'a, &'a str, Year, extra::Full<Rich<'a, char>, State, ()>> {
11    just("Y")
12        .or(just("year").then_ignore(whitespace().repeated().at_least(1)))
13        .ignore_then(
14            any()
15                .filter(|c: &char| c.is_ascii_digit())
16                .repeated()
17                .at_least(1)
18                .collect::<String>()
19                .map_with(|p, e| {
20                    let state: &mut State = e.state();
21                    let year = p.parse::<i32>().unwrap();
22                    state.year = year;
23                    year
24                }),
25        )
26        .then_ignore(end_of_line())
27        .map(Year)
28}
29
30#[cfg(test)]
31mod tests {
32    use super::*;
33
34    #[test]
35    fn should_update_state() {
36        let mut state = State { year: 1 };
37        let result = year()
38            .then_ignore(end())
39            .parse_with_state("Y2024", &mut state)
40            .into_result();
41        assert_eq!(result, Ok(Year(2024)));
42        assert_eq!(state.year, 2024);
43    }
44
45    #[test]
46    fn deprecated_form() {
47        let result = year()
48            .then_ignore(end())
49            .parse("year 2024 ; just a comment")
50            .into_result();
51        assert_eq!(result, Ok(Year(2024)));
52    }
53
54    #[test]
55    fn ok_with_comment() {
56        let result = year()
57            .then_ignore(end())
58            .parse("Y2024 ; just a comment")
59            .into_result();
60        assert_eq!(result, Ok(Year(2024)));
61    }
62}