91 lines
3.2 KiB
Rust
91 lines
3.2 KiB
Rust
use nom::branch::alt;
|
|
use nom::bytes::complete::is_not;
|
|
use nom::bytes::complete::tag_no_case;
|
|
use nom::character::complete::anychar;
|
|
use nom::character::complete::space1;
|
|
use nom::combinator::map;
|
|
use nom::multi::many0;
|
|
use nom::multi::many_till;
|
|
use nom::multi::separated_list0;
|
|
|
|
use super::keyword::filtered_keyword;
|
|
use super::keyword_todo::todo_keywords;
|
|
use super::OrgSource;
|
|
use crate::context::HeadlineLevelFilter;
|
|
use crate::error::Res;
|
|
use crate::types::Keyword;
|
|
use crate::GlobalSettings;
|
|
|
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
|
pub(crate) fn scan_for_in_buffer_settings<'s>(
|
|
input: OrgSource<'s>,
|
|
) -> Res<OrgSource<'s>, Vec<Keyword<'s>>> {
|
|
// TODO: Optimization idea: since this is slicing the OrgSource at each character, it might be more efficient to do a parser that uses a search function like take_until, and wrap it in a function similar to consumed but returning the input along with the normal output, then pass all of that into a verify that confirms we were at the start of a line using the input we just returned.
|
|
|
|
let keywords = many0(map(
|
|
many_till(anychar, filtered_keyword(in_buffer_settings_key)),
|
|
|(_, kw)| kw,
|
|
))(input);
|
|
keywords
|
|
}
|
|
|
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
|
fn in_buffer_settings_key<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
|
alt((
|
|
tag_no_case("archive"),
|
|
tag_no_case("category"),
|
|
tag_no_case("columns"),
|
|
tag_no_case("filetags"),
|
|
tag_no_case("link"),
|
|
tag_no_case("priorities"),
|
|
tag_no_case("property"),
|
|
tag_no_case("seq_todo"),
|
|
tag_no_case("setupfile"),
|
|
tag_no_case("startup"),
|
|
tag_no_case("tags"),
|
|
tag_no_case("todo"),
|
|
tag_no_case("typ_todo"),
|
|
))(input)
|
|
}
|
|
|
|
pub(crate) fn apply_in_buffer_settings<'g, 's, 'sf>(
|
|
keywords: Vec<Keyword<'sf>>,
|
|
original_settings: &'g GlobalSettings<'g, 's>,
|
|
) -> Result<GlobalSettings<'g, 's>, String> {
|
|
let mut new_settings = original_settings.clone();
|
|
|
|
// Todo Keywords
|
|
for kw in keywords.iter().filter(|kw| {
|
|
kw.key.eq_ignore_ascii_case("todo")
|
|
|| kw.key.eq_ignore_ascii_case("seq_todo")
|
|
|| kw.key.eq_ignore_ascii_case("typ_todo")
|
|
}) {
|
|
let (_, (in_progress_words, complete_words)) =
|
|
todo_keywords(kw.value).map_err(|err| err.to_string())?;
|
|
new_settings
|
|
.in_progress_todo_keywords
|
|
.extend(in_progress_words.into_iter().map(str::to_string));
|
|
new_settings
|
|
.complete_todo_keywords
|
|
.extend(complete_words.into_iter().map(str::to_string));
|
|
}
|
|
|
|
// Startup settings
|
|
for kw in keywords
|
|
.iter()
|
|
.filter(|kw| kw.key.eq_ignore_ascii_case("startup"))
|
|
{
|
|
let (_remaining, settings) =
|
|
separated_list0(space1::<&str, nom::error::Error<_>>, is_not(" \t"))(kw.value)
|
|
.map_err(|err: nom::Err<_>| err.to_string())?;
|
|
if settings.contains(&"odd") {
|
|
new_settings.odd_levels_only = HeadlineLevelFilter::Odd;
|
|
}
|
|
if settings.contains(&"oddeven") {
|
|
new_settings.odd_levels_only = HeadlineLevelFilter::OddEven;
|
|
}
|
|
}
|
|
|
|
Ok(new_settings)
|
|
}
|