hledger_parser/directive/
include.rs

1use chumsky::prelude::*;
2
3mod format;
4
5use crate::component::whitespace::whitespace;
6use crate::directive::include::format::format;
7use crate::state::State;
8use crate::utils::end_of_line;
9
10pub use crate::directive::include::format::Format;
11
12#[derive(Clone, Debug, PartialEq)]
13pub struct Include {
14    pub format: Option<Format>,
15    pub path: std::path::PathBuf,
16}
17
18#[must_use]
19pub fn include<'a>() -> impl Parser<'a, &'a str, Include, extra::Full<Rich<'a, char>, State, ()>> {
20    let path = any()
21        .and_is(text::newline().not())
22        .and_is(just(";").not())
23        .repeated()
24        .collect::<Vec<_>>();
25    just("include")
26        .ignore_then(whitespace().repeated().at_least(1))
27        .ignore_then(format().then_ignore(just(":")).or_not())
28        .then(path)
29        .then_ignore(end_of_line())
30        .map(|(format, path)| Include {
31            format,
32            path: std::path::PathBuf::from(path.iter().collect::<String>().trim_end()),
33        })
34}
35
36#[cfg(test)]
37mod tests {
38    use super::*;
39
40    #[test]
41    fn ok_without_format() {
42        let result = include()
43            .then_ignore(end())
44            .parse("include path")
45            .into_result();
46        assert_eq!(
47            result,
48            Ok(Include {
49                format: None,
50                path: std::path::PathBuf::from("path")
51            })
52        );
53    }
54
55    #[test]
56    fn ok_with_comment() {
57        let result = include()
58            .then_ignore(end())
59            .parse("include path  ; with a comment !")
60            .into_result();
61        assert_eq!(
62            result,
63            Ok(Include {
64                format: None,
65                path: std::path::PathBuf::from("path")
66            })
67        );
68    }
69
70    #[test]
71    fn ok_with_spaces() {
72        let result = include()
73            .then_ignore(end())
74            .parse("include Path with space.csv")
75            .into_result();
76        assert_eq!(
77            result,
78            Ok(Include {
79                format: None,
80                path: std::path::PathBuf::from("Path with space.csv")
81            })
82        );
83    }
84
85    #[test]
86    fn ok_with_format() {
87        let result = include()
88            .then_ignore(end())
89            .parse("include rules:path")
90            .into_result();
91        assert_eq!(
92            result,
93            Ok(Include {
94                format: Some(Format::Rules),
95                path: std::path::PathBuf::from("path")
96            })
97        );
98    }
99
100    #[test]
101    fn ok_trailing() {
102        let result = include()
103            .then_ignore(end())
104            .parse("include path   ")
105            .into_result();
106        assert_eq!(
107            result,
108            Ok(Include {
109                format: None,
110                path: std::path::PathBuf::from("path")
111            })
112        );
113    }
114}