Honor the odd startup setting from org-mode files.
Some checks failed
rust-test Build rust-test has succeeded
rust-build Build rust-build has succeeded
rust-foreign-document-test Build rust-foreign-document-test has failed

This commit is contained in:
Tom Alexander 2023-09-15 22:44:39 -04:00
parent a74ea730f4
commit 1a704dd312
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE
5 changed files with 41 additions and 16 deletions

View File

@ -4,3 +4,4 @@
* Baz * Baz
*** Lorem *** Lorem
* Ipsum * Ipsum
**** Dolar

View File

@ -490,11 +490,11 @@ fn compare_heading<'s>(
let level = get_property(emacs, ":level")? let level = get_property(emacs, ":level")?
.ok_or("Level should not be nil")? .ok_or("Level should not be nil")?
.as_atom()?; .as_atom()?;
if rust.stars.to_string() != level { if rust.level.to_string() != level {
this_status = DiffStatus::Bad; this_status = DiffStatus::Bad;
message = Some(format!( message = Some(format!(
"Headline level do not match (emacs != rust): {} != {}", "Headline level do not match (emacs != rust): {} != {}",
level, rust.stars level, rust.level
)) ))
} }

View File

@ -1,4 +1,5 @@
use nom::branch::alt; use nom::branch::alt;
use nom::bytes::complete::is_a;
use nom::bytes::complete::tag; use nom::bytes::complete::tag;
use nom::character::complete::anychar; use nom::character::complete::anychar;
use nom::character::complete::space0; use nom::character::complete::space0;
@ -11,7 +12,6 @@ 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;
use nom::multi::many1_count;
use nom::multi::separated_list1; use nom::multi::separated_list1;
use nom::sequence::tuple; use nom::sequence::tuple;
@ -39,27 +39,27 @@ use crate::types::PriorityCookie;
use crate::types::TodoKeywordType; use crate::types::TodoKeywordType;
pub(crate) const fn heading( pub(crate) const fn heading(
parent_stars: usize, parent_level: usize,
) -> impl for<'b, 'g, 'r, 's> Fn( ) -> impl for<'b, 'g, 'r, 's> Fn(
RefContext<'b, 'g, 'r, 's>, RefContext<'b, 'g, 'r, 's>,
OrgSource<'s>, OrgSource<'s>,
) -> Res<OrgSource<'s>, Heading<'s>> { ) -> Res<OrgSource<'s>, Heading<'s>> {
move |context, input: OrgSource<'_>| _heading(context, input, parent_stars) move |context, input: OrgSource<'_>| _heading(context, input, parent_level)
} }
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn _heading<'b, 'g, 'r, 's>( fn _heading<'b, 'g, 'r, 's>(
context: RefContext<'b, 'g, 'r, 's>, context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>, input: OrgSource<'s>,
parent_stars: usize, parent_level: usize,
) -> Res<OrgSource<'s>, Heading<'s>> { ) -> Res<OrgSource<'s>, Heading<'s>> {
not(|i| context.check_exit_matcher(i))(input)?; not(|i| context.check_exit_matcher(i))(input)?;
let ( let (
remaining, remaining,
(star_count, maybe_todo_keyword, maybe_priority, maybe_comment, title, heading_tags), (headline_level, maybe_todo_keyword, maybe_priority, maybe_comment, title, heading_tags),
) = headline(context, input, parent_stars)?; ) = headline(context, input, parent_level)?;
let section_matcher = parser_with_context!(section)(context); 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(headline_level))(context);
let (remaining, maybe_section) = let (remaining, maybe_section) =
opt(map(section_matcher, DocumentElement::Section))(remaining)?; opt(map(section_matcher, DocumentElement::Section))(remaining)?;
let (remaining, _ws) = opt(tuple((start_of_line, many0(blank_line))))(remaining)?; let (remaining, _ws) = opt(tuple((start_of_line, many0(blank_line))))(remaining)?;
@ -82,7 +82,7 @@ fn _heading<'b, 'g, 'r, 's>(
remaining, remaining,
Heading { Heading {
source: source.into(), source: source.into(),
stars: star_count, level: headline_level,
todo_keyword: maybe_todo_keyword.map(|(todo_keyword_type, todo_keyword)| { todo_keyword: maybe_todo_keyword.map(|(todo_keyword_type, todo_keyword)| {
(todo_keyword_type, Into::<&str>::into(todo_keyword)) (todo_keyword_type, Into::<&str>::into(todo_keyword))
}), }),
@ -106,7 +106,7 @@ pub(crate) fn detect_headline<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, ()
fn headline<'b, 'g, 'r, 's>( fn headline<'b, 'g, 'r, 's>(
context: RefContext<'b, 'g, 'r, 's>, context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>, input: OrgSource<'s>,
parent_stars: usize, parent_level: usize,
) -> Res< ) -> Res<
OrgSource<'s>, OrgSource<'s>,
( (
@ -124,11 +124,12 @@ fn headline<'b, 'g, 'r, 's>(
}); });
let parser_context = context.with_additional_node(&parser_context); let parser_context = context.with_additional_node(&parser_context);
let (remaining, (_, star_count, _)) = tuple(( let (remaining, (_, (star_count, _), _)) = tuple((
start_of_line, start_of_line,
verify(many1_count(tag("*")), |star_count| { verify(
*star_count > parent_stars parser_with_context!(headline_level)(&parser_context),
}), |(level, _)| *level > parent_level,
),
peek(org_space), peek(org_space),
))(input)?; ))(input)?;
@ -255,3 +256,23 @@ fn priority_cookie<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, PriorityCooki
})?; })?;
Ok((remaining, cookie)) Ok((remaining, cookie))
} }
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn headline_level<'b, 'g, 'r, 's>(
context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, (usize, OrgSource<'s>)> {
let (remaining, stars) = is_a("*")(input)?;
let count = stars.len();
let level = match context.get_global_settings().odd_levels_only {
crate::context::HeadlineLevelFilter::Odd => {
if count % 2 == 0 {
(count + 2) / 2
} else {
(count + 1) / 2
}
}
crate::context::HeadlineLevelFilter::OddEven => count,
};
Ok((remaining, (level, stars)))
}

View File

@ -81,6 +81,9 @@ pub(crate) fn apply_in_buffer_settings<'g, 's, 'sf>(
if settings.contains(&"odd") { if settings.contains(&"odd") {
new_settings.odd_levels_only = HeadlineLevelFilter::Odd; new_settings.odd_levels_only = HeadlineLevelFilter::Odd;
} }
if settings.contains(&"oddeven") {
new_settings.odd_levels_only = HeadlineLevelFilter::OddEven;
}
} }
Ok(new_settings) Ok(new_settings)

View File

@ -14,7 +14,7 @@ pub struct Document<'s> {
#[derive(Debug)] #[derive(Debug)]
pub struct Heading<'s> { pub struct Heading<'s> {
pub source: &'s str, pub source: &'s str,
pub stars: usize, pub level: usize,
pub todo_keyword: Option<(TodoKeywordType, &'s str)>, pub todo_keyword: Option<(TodoKeywordType, &'s str)>,
pub priority_cookie: Option<PriorityCookie>, pub priority_cookie: Option<PriorityCookie>,
pub title: Vec<Object<'s>>, pub title: Vec<Object<'s>>,