hledger_parser/directive/
include.rs1use 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}