Move headlines into their own file.
This commit is contained in:
parent
40f22034da
commit
3cc2294387
@ -1,23 +1,13 @@
|
|||||||
use nom::branch::alt;
|
|
||||||
use nom::bytes::complete::tag;
|
|
||||||
use nom::character::complete::anychar;
|
|
||||||
use nom::character::complete::line_ending;
|
|
||||||
use nom::character::complete::space0;
|
|
||||||
use nom::character::complete::space1;
|
|
||||||
use nom::combinator::all_consuming;
|
use nom::combinator::all_consuming;
|
||||||
use nom::combinator::eof;
|
|
||||||
use nom::combinator::map;
|
|
||||||
use nom::combinator::not;
|
|
||||||
use nom::combinator::opt;
|
use nom::combinator::opt;
|
||||||
use nom::combinator::recognize;
|
use nom::combinator::recognize;
|
||||||
use nom::combinator::verify;
|
use nom::combinator::verify;
|
||||||
use nom::multi::many0;
|
use nom::multi::many0;
|
||||||
use nom::multi::many1;
|
|
||||||
use nom::multi::many1_count;
|
|
||||||
use nom::multi::many_till;
|
use nom::multi::many_till;
|
||||||
use nom::multi::separated_list1;
|
|
||||||
use nom::sequence::tuple;
|
use nom::sequence::tuple;
|
||||||
|
|
||||||
|
use super::headline::detect_headline;
|
||||||
|
use super::headline::heading;
|
||||||
use super::in_buffer_settings::apply_in_buffer_settings;
|
use super::in_buffer_settings::apply_in_buffer_settings;
|
||||||
use super::in_buffer_settings::scan_for_in_buffer_settings;
|
use super::in_buffer_settings::scan_for_in_buffer_settings;
|
||||||
use super::org_source::OrgSource;
|
use super::org_source::OrgSource;
|
||||||
@ -25,7 +15,6 @@ use super::token::AllTokensIterator;
|
|||||||
use super::token::Token;
|
use super::token::Token;
|
||||||
use super::util::exit_matcher_parser;
|
use super::util::exit_matcher_parser;
|
||||||
use super::util::get_consumed;
|
use super::util::get_consumed;
|
||||||
use super::util::start_of_line;
|
|
||||||
use crate::context::parser_with_context;
|
use crate::context::parser_with_context;
|
||||||
use crate::context::Context;
|
use crate::context::Context;
|
||||||
use crate::context::ContextElement;
|
use crate::context::ContextElement;
|
||||||
@ -39,19 +28,15 @@ use crate::error::MyError;
|
|||||||
use crate::error::Res;
|
use crate::error::Res;
|
||||||
use crate::parser::comment::comment;
|
use crate::parser::comment::comment;
|
||||||
use crate::parser::element_parser::element;
|
use crate::parser::element_parser::element;
|
||||||
use crate::parser::object_parser::standard_set_object;
|
|
||||||
use crate::parser::org_source::convert_error;
|
use crate::parser::org_source::convert_error;
|
||||||
use crate::parser::planning::planning;
|
use crate::parser::planning::planning;
|
||||||
use crate::parser::property_drawer::property_drawer;
|
use crate::parser::property_drawer::property_drawer;
|
||||||
use crate::parser::util::blank_line;
|
use crate::parser::util::blank_line;
|
||||||
use crate::parser::util::maybe_consume_trailing_whitespace_if_not_exiting;
|
use crate::parser::util::maybe_consume_trailing_whitespace_if_not_exiting;
|
||||||
use crate::types::Document;
|
use crate::types::Document;
|
||||||
use crate::types::DocumentElement;
|
|
||||||
use crate::types::Element;
|
use crate::types::Element;
|
||||||
use crate::types::Heading;
|
|
||||||
use crate::types::Object;
|
use crate::types::Object;
|
||||||
use crate::types::Section;
|
use crate::types::Section;
|
||||||
use crate::types::TodoKeywordType;
|
|
||||||
|
|
||||||
/// Parse a full org-mode document.
|
/// Parse a full org-mode document.
|
||||||
///
|
///
|
||||||
@ -245,7 +230,7 @@ fn zeroth_section<'b, 'g, 'r, 's>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||||
fn section<'b, 'g, 'r, 's>(
|
pub fn section<'b, 'g, 'r, 's>(
|
||||||
context: RefContext<'b, 'g, 'r, 's>,
|
context: RefContext<'b, 'g, 'r, 's>,
|
||||||
mut input: OrgSource<'s>,
|
mut input: OrgSource<'s>,
|
||||||
) -> Res<OrgSource<'s>, Section<'s>> {
|
) -> Res<OrgSource<'s>, Section<'s>> {
|
||||||
@ -306,192 +291,6 @@ fn section_end<'b, 'g, 'r, 's>(
|
|||||||
recognize(detect_headline)(input)
|
recognize(detect_headline)(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
const fn heading(
|
|
||||||
parent_stars: usize,
|
|
||||||
) -> impl for<'b, 'g, 'r, 's> Fn(
|
|
||||||
RefContext<'b, 'g, 'r, 's>,
|
|
||||||
OrgSource<'s>,
|
|
||||||
) -> Res<OrgSource<'s>, Heading<'s>> {
|
|
||||||
move |context, input: OrgSource<'_>| _heading(context, input, parent_stars)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
|
||||||
fn _heading<'b, 'g, 'r, 's>(
|
|
||||||
context: RefContext<'b, 'g, 'r, 's>,
|
|
||||||
input: OrgSource<'s>,
|
|
||||||
parent_stars: usize,
|
|
||||||
) -> Res<OrgSource<'s>, Heading<'s>> {
|
|
||||||
not(|i| context.check_exit_matcher(i))(input)?;
|
|
||||||
let (remaining, (star_count, _ws, maybe_todo_keyword, title, heading_tags)) =
|
|
||||||
headline(context, input, parent_stars)?;
|
|
||||||
let section_matcher = parser_with_context!(section)(context);
|
|
||||||
let heading_matcher = parser_with_context!(heading(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)?;
|
|
||||||
let (remaining, mut children) =
|
|
||||||
many0(map(heading_matcher, DocumentElement::Heading))(remaining)?;
|
|
||||||
if let Some(section) = maybe_section {
|
|
||||||
children.insert(0, section);
|
|
||||||
}
|
|
||||||
let remaining = if children.is_empty() {
|
|
||||||
// Support empty headings
|
|
||||||
let (remain, _ws) = many0(blank_line)(remaining)?;
|
|
||||||
remain
|
|
||||||
} else {
|
|
||||||
remaining
|
|
||||||
};
|
|
||||||
|
|
||||||
let source = get_consumed(input, remaining);
|
|
||||||
Ok((
|
|
||||||
remaining,
|
|
||||||
Heading {
|
|
||||||
source: source.into(),
|
|
||||||
stars: star_count,
|
|
||||||
todo_keyword: maybe_todo_keyword.map(|((todo_keyword_type, todo_keyword), _ws)| {
|
|
||||||
(todo_keyword_type, Into::<&str>::into(todo_keyword))
|
|
||||||
}),
|
|
||||||
title,
|
|
||||||
tags: heading_tags,
|
|
||||||
children,
|
|
||||||
},
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
|
||||||
fn detect_headline<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, ()> {
|
|
||||||
tuple((start_of_line, many1(tag("*")), space1))(input)?;
|
|
||||||
Ok((input, ()))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[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_stars: usize,
|
|
||||||
) -> Res<
|
|
||||||
OrgSource<'s>,
|
|
||||||
(
|
|
||||||
usize,
|
|
||||||
OrgSource<'s>,
|
|
||||||
Option<((TodoKeywordType, OrgSource<'s>), OrgSource<'s>)>,
|
|
||||||
Vec<Object<'s>>,
|
|
||||||
Vec<&'s str>,
|
|
||||||
),
|
|
||||||
> {
|
|
||||||
let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode {
|
|
||||||
class: ExitClass::Document,
|
|
||||||
exit_matcher: &headline_title_end,
|
|
||||||
});
|
|
||||||
let parser_context = context.with_additional_node(&parser_context);
|
|
||||||
|
|
||||||
let (
|
|
||||||
remaining,
|
|
||||||
(_sol, star_count, ws, maybe_todo_keyword, title, maybe_tags, _ws, _line_ending),
|
|
||||||
) = tuple((
|
|
||||||
start_of_line,
|
|
||||||
verify(many1_count(tag("*")), |star_count| {
|
|
||||||
*star_count > parent_stars
|
|
||||||
}),
|
|
||||||
space1,
|
|
||||||
opt(tuple((
|
|
||||||
parser_with_context!(heading_keyword)(&parser_context),
|
|
||||||
space1,
|
|
||||||
))),
|
|
||||||
many1(parser_with_context!(standard_set_object)(&parser_context)),
|
|
||||||
opt(tuple((space0, tags))),
|
|
||||||
space0,
|
|
||||||
alt((line_ending, eof)),
|
|
||||||
))(input)?;
|
|
||||||
Ok((
|
|
||||||
remaining,
|
|
||||||
(
|
|
||||||
star_count,
|
|
||||||
ws,
|
|
||||||
maybe_todo_keyword,
|
|
||||||
title,
|
|
||||||
maybe_tags
|
|
||||||
.map(|(_ws, tags)| {
|
|
||||||
tags.into_iter()
|
|
||||||
.map(|single_tag| Into::<&str>::into(single_tag))
|
|
||||||
.collect()
|
|
||||||
})
|
|
||||||
.unwrap_or(Vec::new()),
|
|
||||||
),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
|
||||||
fn headline_title_end<'b, 'g, 'r, 's>(
|
|
||||||
_context: RefContext<'b, 'g, 'r, 's>,
|
|
||||||
input: OrgSource<'s>,
|
|
||||||
) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
|
||||||
recognize(tuple((
|
|
||||||
opt(tuple((space0, tags, space0))),
|
|
||||||
alt((line_ending, eof)),
|
|
||||||
)))(input)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
|
||||||
fn tags<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, Vec<OrgSource<'s>>> {
|
|
||||||
let (remaining, (_open, tags, _close)) =
|
|
||||||
tuple((tag(":"), separated_list1(tag(":"), single_tag), tag(":")))(input)?;
|
|
||||||
Ok((remaining, tags))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
|
||||||
fn single_tag<'r, 's>(input: OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
|
||||||
recognize(many1(verify(anychar, |c| {
|
|
||||||
c.is_alphanumeric() || "_@#%".contains(*c)
|
|
||||||
})))(input)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
|
||||||
fn heading_keyword<'b, 'g, 'r, 's>(
|
|
||||||
context: RefContext<'b, 'g, 'r, 's>,
|
|
||||||
input: OrgSource<'s>,
|
|
||||||
) -> Res<OrgSource<'s>, (TodoKeywordType, OrgSource<'s>)> {
|
|
||||||
let global_settings = context.get_global_settings();
|
|
||||||
if global_settings.in_progress_todo_keywords.is_empty()
|
|
||||||
&& global_settings.complete_todo_keywords.is_empty()
|
|
||||||
{
|
|
||||||
alt((
|
|
||||||
map(tag("TODO"), |capture| (TodoKeywordType::Todo, capture)),
|
|
||||||
map(tag("DONE"), |capture| (TodoKeywordType::Done, capture)),
|
|
||||||
))(input)
|
|
||||||
} else {
|
|
||||||
for todo_keyword in global_settings
|
|
||||||
.in_progress_todo_keywords
|
|
||||||
.iter()
|
|
||||||
.map(String::as_str)
|
|
||||||
{
|
|
||||||
let result = tag::<_, _, CustomError<_>>(todo_keyword)(input);
|
|
||||||
match result {
|
|
||||||
Ok((remaining, ent)) => {
|
|
||||||
return Ok((remaining, (TodoKeywordType::Todo, ent)));
|
|
||||||
}
|
|
||||||
Err(_) => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for todo_keyword in global_settings
|
|
||||||
.complete_todo_keywords
|
|
||||||
.iter()
|
|
||||||
.map(String::as_str)
|
|
||||||
{
|
|
||||||
let result = tag::<_, _, CustomError<_>>(todo_keyword)(input);
|
|
||||||
match result {
|
|
||||||
Ok((remaining, ent)) => {
|
|
||||||
return Ok((remaining, (TodoKeywordType::Done, ent)));
|
|
||||||
}
|
|
||||||
Err(_) => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(nom::Err::Error(CustomError::MyError(MyError(
|
|
||||||
"NoTodoKeyword".into(),
|
|
||||||
))))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'s> Document<'s> {
|
impl<'s> Document<'s> {
|
||||||
pub fn iter_tokens<'r>(&'r self) -> impl Iterator<Item = Token<'r, 's>> {
|
pub fn iter_tokens<'r>(&'r self) -> impl Iterator<Item = Token<'r, 's>> {
|
||||||
AllTokensIterator::new(Token::Document(self))
|
AllTokensIterator::new(Token::Document(self))
|
||||||
|
222
src/parser/headline.rs
Normal file
222
src/parser/headline.rs
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
use nom::branch::alt;
|
||||||
|
use nom::bytes::complete::tag;
|
||||||
|
use nom::character::complete::anychar;
|
||||||
|
use nom::character::complete::line_ending;
|
||||||
|
use nom::character::complete::space0;
|
||||||
|
use nom::character::complete::space1;
|
||||||
|
use nom::combinator::eof;
|
||||||
|
use nom::combinator::map;
|
||||||
|
use nom::combinator::not;
|
||||||
|
use nom::combinator::opt;
|
||||||
|
use nom::combinator::recognize;
|
||||||
|
use nom::combinator::verify;
|
||||||
|
use nom::multi::many0;
|
||||||
|
use nom::multi::many1;
|
||||||
|
use nom::multi::many1_count;
|
||||||
|
use nom::multi::separated_list1;
|
||||||
|
use nom::sequence::tuple;
|
||||||
|
|
||||||
|
use super::document::section;
|
||||||
|
use super::org_source::OrgSource;
|
||||||
|
use super::util::get_consumed;
|
||||||
|
use super::util::start_of_line;
|
||||||
|
use crate::context::parser_with_context;
|
||||||
|
use crate::context::ContextElement;
|
||||||
|
use crate::context::ExitClass;
|
||||||
|
use crate::context::ExitMatcherNode;
|
||||||
|
use crate::context::RefContext;
|
||||||
|
use crate::error::CustomError;
|
||||||
|
use crate::error::MyError;
|
||||||
|
use crate::error::Res;
|
||||||
|
use crate::parser::object_parser::standard_set_object;
|
||||||
|
use crate::parser::util::blank_line;
|
||||||
|
use crate::types::DocumentElement;
|
||||||
|
use crate::types::Heading;
|
||||||
|
use crate::types::Object;
|
||||||
|
use crate::types::TodoKeywordType;
|
||||||
|
|
||||||
|
pub const fn heading(
|
||||||
|
parent_stars: usize,
|
||||||
|
) -> impl for<'b, 'g, 'r, 's> Fn(
|
||||||
|
RefContext<'b, 'g, 'r, 's>,
|
||||||
|
OrgSource<'s>,
|
||||||
|
) -> Res<OrgSource<'s>, Heading<'s>> {
|
||||||
|
move |context, input: OrgSource<'_>| _heading(context, input, parent_stars)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||||
|
fn _heading<'b, 'g, 'r, 's>(
|
||||||
|
context: RefContext<'b, 'g, 'r, 's>,
|
||||||
|
input: OrgSource<'s>,
|
||||||
|
parent_stars: usize,
|
||||||
|
) -> Res<OrgSource<'s>, Heading<'s>> {
|
||||||
|
not(|i| context.check_exit_matcher(i))(input)?;
|
||||||
|
let (remaining, (star_count, _ws, maybe_todo_keyword, title, heading_tags)) =
|
||||||
|
headline(context, input, parent_stars)?;
|
||||||
|
let section_matcher = parser_with_context!(section)(context);
|
||||||
|
let heading_matcher = parser_with_context!(heading(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)?;
|
||||||
|
let (remaining, mut children) =
|
||||||
|
many0(map(heading_matcher, DocumentElement::Heading))(remaining)?;
|
||||||
|
if let Some(section) = maybe_section {
|
||||||
|
children.insert(0, section);
|
||||||
|
}
|
||||||
|
let remaining = if children.is_empty() {
|
||||||
|
// Support empty headings
|
||||||
|
let (remain, _ws) = many0(blank_line)(remaining)?;
|
||||||
|
remain
|
||||||
|
} else {
|
||||||
|
remaining
|
||||||
|
};
|
||||||
|
|
||||||
|
let source = get_consumed(input, remaining);
|
||||||
|
Ok((
|
||||||
|
remaining,
|
||||||
|
Heading {
|
||||||
|
source: source.into(),
|
||||||
|
stars: star_count,
|
||||||
|
todo_keyword: maybe_todo_keyword.map(|((todo_keyword_type, todo_keyword), _ws)| {
|
||||||
|
(todo_keyword_type, Into::<&str>::into(todo_keyword))
|
||||||
|
}),
|
||||||
|
title,
|
||||||
|
tags: heading_tags,
|
||||||
|
children,
|
||||||
|
},
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||||
|
pub fn detect_headline<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, ()> {
|
||||||
|
tuple((start_of_line, many1(tag("*")), space1))(input)?;
|
||||||
|
Ok((input, ()))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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_stars: usize,
|
||||||
|
) -> Res<
|
||||||
|
OrgSource<'s>,
|
||||||
|
(
|
||||||
|
usize,
|
||||||
|
OrgSource<'s>,
|
||||||
|
Option<((TodoKeywordType, OrgSource<'s>), OrgSource<'s>)>,
|
||||||
|
Vec<Object<'s>>,
|
||||||
|
Vec<&'s str>,
|
||||||
|
),
|
||||||
|
> {
|
||||||
|
let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode {
|
||||||
|
class: ExitClass::Document,
|
||||||
|
exit_matcher: &headline_title_end,
|
||||||
|
});
|
||||||
|
let parser_context = context.with_additional_node(&parser_context);
|
||||||
|
|
||||||
|
let (
|
||||||
|
remaining,
|
||||||
|
(_sol, star_count, ws, maybe_todo_keyword, title, maybe_tags, _ws, _line_ending),
|
||||||
|
) = tuple((
|
||||||
|
start_of_line,
|
||||||
|
verify(many1_count(tag("*")), |star_count| {
|
||||||
|
*star_count > parent_stars
|
||||||
|
}),
|
||||||
|
space1,
|
||||||
|
opt(tuple((
|
||||||
|
parser_with_context!(heading_keyword)(&parser_context),
|
||||||
|
space1,
|
||||||
|
))),
|
||||||
|
many1(parser_with_context!(standard_set_object)(&parser_context)),
|
||||||
|
opt(tuple((space0, tags))),
|
||||||
|
space0,
|
||||||
|
alt((line_ending, eof)),
|
||||||
|
))(input)?;
|
||||||
|
Ok((
|
||||||
|
remaining,
|
||||||
|
(
|
||||||
|
star_count,
|
||||||
|
ws,
|
||||||
|
maybe_todo_keyword,
|
||||||
|
title,
|
||||||
|
maybe_tags
|
||||||
|
.map(|(_ws, tags)| {
|
||||||
|
tags.into_iter()
|
||||||
|
.map(|single_tag| Into::<&str>::into(single_tag))
|
||||||
|
.collect()
|
||||||
|
})
|
||||||
|
.unwrap_or(Vec::new()),
|
||||||
|
),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||||
|
fn headline_title_end<'b, 'g, 'r, 's>(
|
||||||
|
_context: RefContext<'b, 'g, 'r, 's>,
|
||||||
|
input: OrgSource<'s>,
|
||||||
|
) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
||||||
|
recognize(tuple((
|
||||||
|
opt(tuple((space0, tags, space0))),
|
||||||
|
alt((line_ending, eof)),
|
||||||
|
)))(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||||
|
fn tags<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, Vec<OrgSource<'s>>> {
|
||||||
|
let (remaining, (_open, tags, _close)) =
|
||||||
|
tuple((tag(":"), separated_list1(tag(":"), single_tag), tag(":")))(input)?;
|
||||||
|
Ok((remaining, tags))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||||
|
fn single_tag<'r, 's>(input: OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
||||||
|
recognize(many1(verify(anychar, |c| {
|
||||||
|
c.is_alphanumeric() || "_@#%".contains(*c)
|
||||||
|
})))(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||||
|
fn heading_keyword<'b, 'g, 'r, 's>(
|
||||||
|
context: RefContext<'b, 'g, 'r, 's>,
|
||||||
|
input: OrgSource<'s>,
|
||||||
|
) -> Res<OrgSource<'s>, (TodoKeywordType, OrgSource<'s>)> {
|
||||||
|
let global_settings = context.get_global_settings();
|
||||||
|
if global_settings.in_progress_todo_keywords.is_empty()
|
||||||
|
&& global_settings.complete_todo_keywords.is_empty()
|
||||||
|
{
|
||||||
|
alt((
|
||||||
|
map(tag("TODO"), |capture| (TodoKeywordType::Todo, capture)),
|
||||||
|
map(tag("DONE"), |capture| (TodoKeywordType::Done, capture)),
|
||||||
|
))(input)
|
||||||
|
} else {
|
||||||
|
for todo_keyword in global_settings
|
||||||
|
.in_progress_todo_keywords
|
||||||
|
.iter()
|
||||||
|
.map(String::as_str)
|
||||||
|
{
|
||||||
|
let result = tag::<_, _, CustomError<_>>(todo_keyword)(input);
|
||||||
|
match result {
|
||||||
|
Ok((remaining, ent)) => {
|
||||||
|
return Ok((remaining, (TodoKeywordType::Todo, ent)));
|
||||||
|
}
|
||||||
|
Err(_) => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for todo_keyword in global_settings
|
||||||
|
.complete_todo_keywords
|
||||||
|
.iter()
|
||||||
|
.map(String::as_str)
|
||||||
|
{
|
||||||
|
let result = tag::<_, _, CustomError<_>>(todo_keyword)(input);
|
||||||
|
match result {
|
||||||
|
Ok((remaining, ent)) => {
|
||||||
|
return Ok((remaining, (TodoKeywordType::Done, ent)));
|
||||||
|
}
|
||||||
|
Err(_) => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(nom::Err::Error(CustomError::MyError(MyError(
|
||||||
|
"NoTodoKeyword".into(),
|
||||||
|
))))
|
||||||
|
}
|
||||||
|
}
|
@ -14,6 +14,7 @@ mod fixed_width_area;
|
|||||||
mod footnote_definition;
|
mod footnote_definition;
|
||||||
mod footnote_reference;
|
mod footnote_reference;
|
||||||
mod greater_block;
|
mod greater_block;
|
||||||
|
mod headline;
|
||||||
mod horizontal_rule;
|
mod horizontal_rule;
|
||||||
mod in_buffer_settings;
|
mod in_buffer_settings;
|
||||||
mod inline_babel_call;
|
mod inline_babel_call;
|
||||||
|
Loading…
Reference in New Issue
Block a user