Handle the possibility of a title-less headline.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
use nom::branch::alt;
|
||||
use nom::bytes::complete::is_a;
|
||||
use nom::character::complete::anychar;
|
||||
use nom::character::complete::line_ending;
|
||||
use nom::character::complete::none_of;
|
||||
@@ -9,9 +10,11 @@ use nom::combinator::not;
|
||||
use nom::combinator::opt;
|
||||
use nom::combinator::peek;
|
||||
use nom::combinator::recognize;
|
||||
use nom::combinator::verify;
|
||||
use nom::multi::many0;
|
||||
use nom::multi::many_till;
|
||||
use nom::sequence::tuple;
|
||||
use nom::Slice;
|
||||
|
||||
use super::org_source::OrgSource;
|
||||
use crate::context::parser_with_context;
|
||||
@@ -212,6 +215,9 @@ fn text_until_eol<'r, 's>(
|
||||
Ok(line.trim())
|
||||
}
|
||||
|
||||
/// Return a tuple of (input, output) from a nom parser.
|
||||
///
|
||||
/// This is similar to recognize except it returns the input instead of the portion of the input that was consumed.
|
||||
pub(crate) fn include_input<'s, F, O>(
|
||||
mut inner: F,
|
||||
) -> impl FnMut(OrgSource<'s>) -> Res<OrgSource<'s>, (OrgSource<'s>, O)>
|
||||
@@ -223,3 +229,44 @@ where
|
||||
Ok((remaining, (input, output)))
|
||||
}
|
||||
}
|
||||
|
||||
/// Match single space or tab.
|
||||
///
|
||||
/// In org-mode syntax, spaces and tabs are interchangeable.
|
||||
pub(crate) fn org_space<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, char> {
|
||||
one_of(" \t")(input)
|
||||
}
|
||||
|
||||
/// Matches a single space, tab, line ending, or end of file.
|
||||
///
|
||||
/// In org-mode syntax there are often delimiters that could be any whitespace at all or the end of file.
|
||||
pub(crate) fn org_space_or_line_ending<'s>(
|
||||
input: OrgSource<'s>,
|
||||
) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
||||
alt((recognize(one_of(" \t")), org_line_ending))(input)
|
||||
}
|
||||
|
||||
/// Match as many spaces and tabs as possible. No minimum match.
|
||||
///
|
||||
/// In org-mode syntax, spaces and tabs are interchangeable.
|
||||
pub(crate) fn org_spaces0<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
||||
let found = is_a(" \t")(input);
|
||||
if found.is_ok() {
|
||||
return found;
|
||||
}
|
||||
Ok((input, input.slice(..0)))
|
||||
}
|
||||
|
||||
/// Match as many spaces and tabs as possible. Minimum 1 character.
|
||||
///
|
||||
/// In org-mode syntax, spaces and tabs are interchangeable.
|
||||
pub(crate) fn org_spaces1<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
||||
verify(is_a(" \t"), |res: &OrgSource<'_>| res.len() > 0)(input)
|
||||
}
|
||||
|
||||
/// Match a line break or the end of the file.
|
||||
///
|
||||
/// In org-mode syntax, the end of the file can serve the same purpose as a line break syntactically.
|
||||
pub(crate) fn org_line_ending<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
||||
alt((line_ending, eof))(input)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user