Skip to content

Commit 5c4711a

Browse files
committed
Add parse_todo_multiline
1 parent 234f444 commit 5c4711a

File tree

1 file changed

+72
-7
lines changed

1 file changed

+72
-7
lines changed

src/commands/parser.rs

+72-7
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
use nom::{
22
bytes::complete::{tag, take_until},
3-
character::complete::{newline, not_line_ending},
4-
combinator::opt,
5-
multi::many0,
3+
character::complete::{anychar, char, newline, not_line_ending, none_of},
4+
combinator::{fail, opt},
5+
multi::{many0, many_till},
6+
sequence::tuple,
67
*,
78
};
89

@@ -15,13 +16,18 @@ pub struct Todo {
1516
pub text: String,
1617
}
1718

18-
fn parse_todo<'a>(todo_tag: &'a str, input: &'a str) -> IResult<&'a str, Todo> {
19+
fn parse_header<'a>(todo_tag: &'a str, input: &'a str) -> IResult<&'a str, ()> {
1920
// remove everything prior to the tag
2021
let (input, _) = take_until(todo_tag)(input)?;
21-
22+
// detect todo_tag
2223
let (input, _) = tag(todo_tag)(input)?;
23-
let (input, text) = not_line_ending(input)?;
24+
Ok((input, ()))
25+
}
26+
27+
fn parse_todo<'a>(todo_tag: &'a str, input: &'a str) -> IResult<&'a str, Todo> {
28+
let (input, _) = parse_header(todo_tag, input)?;
2429

30+
let (input, text) = not_line_ending(input)?;
2531
// discard optional line ending
2632
let (input, _) = opt(newline)(input)?;
2733

@@ -34,6 +40,47 @@ fn parse_todo<'a>(todo_tag: &'a str, input: &'a str) -> IResult<&'a str, Todo> {
3440
))
3541
}
3642

43+
fn parse_todo_multiline<'a>(todo_tag: &'a str, input: &'a str) -> IResult<&'a str, Todo> {
44+
let (input, _) = parse_header(todo_tag, input)?;
45+
46+
println!("{:?}", input);
47+
48+
//let parse_line = many_till(anychar::<T, E>, tuple((char('\\'), newline)));
49+
50+
let (input, (vector, _)) = many_till(
51+
many_till(anychar, tuple((char('\\'), newline))),
52+
many_till(anychar, tuple((none_of("\\"), newline))),
53+
)(input)?;
54+
55+
println!("{:?}", vector);
56+
57+
let result: String = vector.into_iter().map(| (line, _) | line.iter().collect::<String>()).collect();
58+
59+
// for (v, _) in vector {
60+
// let line:String = v.iter().collect();
61+
62+
// }
63+
64+
// let (input, text) = not_line_ending(input)?;
65+
66+
// match text.chars().last() {
67+
// Some('\\') => todo!(),
68+
// _ => fail::<&str, Todo, nom::error::Error<&str>>("")?,
69+
// };
70+
71+
// discard optional line ending
72+
// let (input, _) = opt(newline)(input)?;
73+
74+
Ok((
75+
input,
76+
Todo {
77+
tag: todo_tag.to_owned(),
78+
text: result,
79+
},
80+
))
81+
}
82+
83+
3784
fn parse_todos(file_content: &str) -> IResult<&str, Vec<Todo>> {
3885
let line_parser = |file_content| parse_todo("TODO:", file_content);
3986
let (input, todos) = many0(line_parser)(file_content)?;
@@ -49,9 +96,27 @@ pub fn parse_file(file_content: &str) -> Vec<Todo> {
4996

5097
#[cfg(test)]
5198
mod test {
52-
use crate::commands::parser::{parse_todo, parse_todos, Todo};
99+
use crate::commands::parser::{parse_todo, parse_todos, parse_todo_multiline, Todo};
53100

54101
#[test]
102+
fn multiline_todos() {
103+
let input =
104+
"TODO: todo1 \\n\
105+
todo2\n\
106+
line1";
107+
108+
assert_eq!(
109+
parse_todo_multiline("TODO:", input),
110+
Ok((
111+
"line1",
112+
Todo {
113+
tag: "TODO:".to_owned(),
114+
text: " todo1 todo".to_owned()
115+
},
116+
))
117+
);
118+
}
119+
55120
fn todos() {
56121
let input = "line 1\n\
57122
TODO: todo1\n\

0 commit comments

Comments
 (0)