diff --git a/src/parser/headline.rs b/src/parser/headline.rs index 4e94726..6b51f2b 100644 --- a/src/parser/headline.rs +++ b/src/parser/headline.rs @@ -56,20 +56,9 @@ fn _heading<'b, 'g, 'r, 's>( parent_star_count: HeadlineLevel, ) -> Res, Heading<'s>> { not(|i| context.check_exit_matcher(i))(input)?; - let ( - remaining, - ( - headline_level, - star_count, - maybe_todo_keyword, - maybe_priority, - maybe_comment, - title, - heading_tags, - ), - ) = headline(context, input, parent_star_count)?; + let (remaining, pre_headline) = headline(context, input, parent_star_count)?; let section_matcher = parser_with_context!(section)(context); - let heading_matcher = parser_with_context!(heading(star_count))(context); + let heading_matcher = parser_with_context!(heading(pre_headline.star_count))(context); let (remaining, maybe_section) = opt(map(section_matcher, DocumentElement::Section))(remaining)?; let (remaining, _ws) = opt(tuple((start_of_line, many0(blank_line))))(remaining)?; @@ -85,22 +74,24 @@ fn _heading<'b, 'g, 'r, 's>( } else { remaining }; - let is_archived = heading_tags.contains(&"ARCHIVE"); + let is_archived = pre_headline.tags.contains(&"ARCHIVE"); let source = get_consumed(input, remaining); Ok(( remaining, Heading { source: source.into(), - level: headline_level, - todo_keyword: maybe_todo_keyword.map(|(todo_keyword_type, todo_keyword)| { - (todo_keyword_type, Into::<&str>::into(todo_keyword)) - }), - priority_cookie: maybe_priority.map(|(_, priority)| priority), - title, - tags: heading_tags, + level: pre_headline.headline_level, + todo_keyword: pre_headline + .todo_keyword + .map(|(todo_keyword_type, todo_keyword)| { + (todo_keyword_type, Into::<&str>::into(todo_keyword)) + }), + priority_cookie: pre_headline.priority_cookie.map(|(_, priority)| priority), + title: pre_headline.title, + tags: pre_headline.tags, children, - is_comment: maybe_comment.is_some(), + is_comment: pre_headline.comment.is_some(), is_archived, is_footnote_section: false, // TODO }, @@ -113,23 +104,25 @@ pub(crate) fn detect_headline<'s>(input: OrgSource<'s>) -> Res, () Ok((input, ())) } +/// Fields from a not-yet-fully-parsed Headline. +/// +/// This struct exists to give names to the fields of a partially-parsed Headline to avoid returning a large tuple of nameless fields. +struct PreHeadline<'s> { + headline_level: HeadlineLevel, + star_count: HeadlineLevel, + todo_keyword: Option<(TodoKeywordType, OrgSource<'s>)>, + priority_cookie: Option<(OrgSource<'s>, PriorityCookie)>, + comment: Option>, + title: Vec>, + tags: Vec<&'s str>, +} + #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] fn headline<'b, 'g, 'r, 's>( context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, parent_star_count: HeadlineLevel, -) -> Res< - OrgSource<'s>, - ( - HeadlineLevel, - HeadlineLevel, - Option<(TodoKeywordType, OrgSource<'s>)>, - Option<(OrgSource<'s>, PriorityCookie)>, - Option>, - Vec>, - Vec<&'s str>, - ), -> { +) -> Res, PreHeadline<'s>> { let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode { class: ExitClass::Document, exit_matcher: &headline_title_end, @@ -172,23 +165,23 @@ fn headline<'b, 'g, 'r, 's>( Ok(( remaining, - ( + PreHeadline { headline_level, star_count, - maybe_todo_keyword.map(|(_, todo, _)| todo), - maybe_priority, - maybe_comment.map(|(_, comment, _)| comment), - maybe_title + todo_keyword: maybe_todo_keyword.map(|(_, todo, _)| todo), + priority_cookie: maybe_priority, + comment: maybe_comment.map(|(_, comment, _)| comment), + title: maybe_title .map(|(_, (_, title))| title) .unwrap_or(Vec::new()), - maybe_tags + tags: maybe_tags .map(|(_ws, tags)| { tags.into_iter() .map(|single_tag| Into::<&str>::into(single_tag)) .collect() }) .unwrap_or(Vec::new()), - ), + }, )) }