Introduce a struct for the partially-parsed headline.

We are returning so many fields from that parser that managing a tuple is becoming unreadable. The struct should add some structure 😉 to the code.
This commit is contained in:
Tom Alexander 2023-10-02 11:16:05 -04:00
parent 5a254392cb
commit de5788d8f3
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE

View File

@ -56,20 +56,9 @@ fn _heading<'b, 'g, 'r, 's>(
parent_star_count: HeadlineLevel,
) -> Res<OrgSource<'s>, 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<OrgSource<'s>, ()
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<OrgSource<'s>>,
title: Vec<Object<'s>>,
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<OrgSource<'s>>,
Vec<Object<'s>>,
Vec<&'s str>,
),
> {
) -> Res<OrgSource<'s>, 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()),
),
},
))
}