Fix a few edge cases with priority parsing.

This adds tests and fixes a few edge cases with priority parsing. In
particular, the test added in a99702a4da,
"** DONE [#B]::" differs from org-element. org-element parses the
priority, while orgize does not.
This commit is contained in:
Alex Roper 2020-05-13 20:16:57 -07:00
parent 5e4457e26e
commit 3e032dac20

View file

@ -5,9 +5,8 @@ use std::collections::HashMap;
use memchr::memrchr2; use memchr::memrchr2;
use nom::{ use nom::{
branch::alt,
bytes::complete::{tag, take_until, take_while}, bytes::complete::{tag, take_until, take_while},
character::complete::{anychar, line_ending, space1}, character::complete::{anychar, space1},
combinator::{map, opt, verify}, combinator::{map, opt, verify},
error::{make_error, ErrorKind}, error::{make_error, ErrorKind},
multi::fold_many0, multi::fold_many0,
@ -124,10 +123,6 @@ impl Default for Title<'_> {
} }
} }
fn white_spaces_or_eol(input: &str) -> IResult<&str, &str, ()> {
alt((space1, line_ending))(input)
}
#[inline] #[inline]
fn parse_title<'a>( fn parse_title<'a>(
input: &'a str, input: &'a str,
@ -145,14 +140,13 @@ fn parse_title<'a>(
}), }),
))(input)?; ))(input)?;
let (input, priority) = opt(delimited( let (input, priority) = opt(preceded(
space1, space1,
delimited( delimited(
tag("[#"), tag("[#"),
verify(anychar, |c: &char| c.is_ascii_uppercase()), verify(anychar, |c: &char| c.is_ascii_uppercase()),
tag("]"), tag("]"),
), ),
white_spaces_or_eol,
))(input)?; ))(input)?;
let (input, tail) = line(input)?; let (input, tail) = line(input)?;
let tail = tail.trim(); let tail = tail.trim();
@ -332,25 +326,55 @@ fn parse_title_() {
); );
// https://github.com/PoiScript/orgize/issues/20 // https://github.com/PoiScript/orgize/issues/20
assert_eq!( for raw in &["", "::", " ::", "hello", " hello"] {
parse_title("** DONE [#B]::", &DEFAULT_CONFIG), for keyword in &[Some(Cow::Borrowed("DONE")), None] {
Ok(( for raw_tags in &["", " :test:", "\t:a:b:"] {
"", let mut s = String::from("** ");
( if let Some(keyword) = keyword {
Title { s += keyword;
level: 2, s.push(' ');
keyword: Some("DONE".into()), }
priority: None, s += "[#B]";
raw: "[#B]::".into(), s += &raw;
tags: vec![], s += &raw_tags;
planning: None,
properties: HashMap::new(), // A title with an empty (or whitespace only) raw will have its
post_blank: 0, // tags interpreted as the title, rather than as tags. This is
}, // intended behavior, and consistent with org-element.
"[#B]::" let mut raw = raw.to_string();
) let tags: Vec<_> = if raw.trim().is_empty() {
)) raw += raw_tags;
); Vec::new()
} else {
raw_tags
.trim()
.split(':')
.filter_map(|t| if !t.is_empty() { Some(t.into()) } else { None })
.collect()
};
assert_eq!(
parse_title(&s, &DEFAULT_CONFIG),
Ok((
"",
(
Title {
level: 2,
keyword: keyword.clone(),
priority: Some('B'),
raw: Cow::Borrowed(raw.trim()),
tags,
planning: None,
properties: HashMap::new(),
post_blank: 0,
},
raw.trim(),
)
))
);
}
}
}
assert_eq!( assert_eq!(
parse_title("**** Title :tag:a2%", &DEFAULT_CONFIG), parse_title("**** Title :tag:a2%", &DEFAULT_CONFIG),