Use a single function for finding all keywords.
This commit is contained in:
parent
d38e198258
commit
275b4b53d1
@ -1392,6 +1392,8 @@ fn compare_keyword<'s>(
|
|||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO: Compare key and value
|
||||||
|
|
||||||
Ok(DiffResult {
|
Ok(DiffResult {
|
||||||
status: this_status,
|
status: this_status,
|
||||||
name: emacs_name.to_owned(),
|
name: emacs_name.to_owned(),
|
||||||
|
@ -18,6 +18,7 @@ use nom::multi::many_till;
|
|||||||
use nom::multi::separated_list1;
|
use nom::multi::separated_list1;
|
||||||
use nom::sequence::tuple;
|
use nom::sequence::tuple;
|
||||||
|
|
||||||
|
use super::in_buffer_settings::scan_for_in_buffer_settings;
|
||||||
use super::org_source::OrgSource;
|
use super::org_source::OrgSource;
|
||||||
use super::setup_file::scan_for_setup_file;
|
use super::setup_file::scan_for_setup_file;
|
||||||
use super::token::AllTokensIterator;
|
use super::token::AllTokensIterator;
|
||||||
@ -92,6 +93,8 @@ pub fn parse_with_settings<'g, 's>(
|
|||||||
/// Parse a full org-mode document.
|
/// Parse a full org-mode document.
|
||||||
///
|
///
|
||||||
/// Use this entry point when you want to have direct control over the starting context or if you want to use this integrated with other nom parsers. For general-purpose usage, the `parse` and `parse_with_settings` functions are a lot simpler.
|
/// Use this entry point when you want to have direct control over the starting context or if you want to use this integrated with other nom parsers. For general-purpose usage, the `parse` and `parse_with_settings` functions are a lot simpler.
|
||||||
|
///
|
||||||
|
/// This will not prevent additional settings from being learned during parsing, for example when encountering a "#+TODO".
|
||||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn document<'b, 'g, 'r, 's>(
|
pub fn document<'b, 'g, 'r, 's>(
|
||||||
@ -109,24 +112,42 @@ fn document_org_source<'b, 'g, 'r, 's>(
|
|||||||
input: OrgSource<'s>,
|
input: OrgSource<'s>,
|
||||||
) -> Res<OrgSource<'s>, Document<'s>> {
|
) -> Res<OrgSource<'s>, Document<'s>> {
|
||||||
let setup_file = scan_for_setup_file(input);
|
let setup_file = scan_for_setup_file(input);
|
||||||
if setup_file.is_ok() {
|
let setup_file = if setup_file.is_ok() {
|
||||||
let (_remaining, setup_file) = setup_file.expect("If-statement proves this is okay.");
|
let (_remaining, setup_file) = setup_file.expect("If-statement proves this is okay.");
|
||||||
let setup_file_contents = context
|
let setup_file_contents = context
|
||||||
.get_global_settings()
|
.get_global_settings()
|
||||||
.file_access
|
.file_access
|
||||||
.read_file(Into::<&str>::into(setup_file))
|
.read_file(Into::<&str>::into(setup_file))
|
||||||
.map_err(|err| nom::Err::<CustomError<OrgSource<'_>>>::Failure(err.into()))?;
|
.map_err(|err| nom::Err::<CustomError<OrgSource<'_>>>::Failure(err.into()))?;
|
||||||
let parsed_setup_file = _document(context, setup_file_contents.as_str().into());
|
Some(setup_file_contents)
|
||||||
if parsed_setup_file.is_err() {
|
} else {
|
||||||
return Err(nom::Err::Error(CustomError::MyError(MyError(
|
None
|
||||||
"Failed to parse the setup file.".into(),
|
};
|
||||||
))));
|
let setup_file_settings = setup_file
|
||||||
}
|
.as_ref()
|
||||||
let (_remaining, parsed_setup_file) =
|
.map(|input| input.as_str().into())
|
||||||
parsed_setup_file.expect("The if-statement proves this is ok.");
|
.map(scan_for_in_buffer_settings)
|
||||||
|
.map_or(Ok(None), |r| r.map(Some))
|
||||||
println!("TODO: Process setup_file: {:#?}", parsed_setup_file);
|
.map_err(|_err| {
|
||||||
|
nom::Err::Error(CustomError::MyError(MyError(
|
||||||
|
"TODO: make this take an owned string so I can dump err.to_string() into it."
|
||||||
|
.into(),
|
||||||
|
)))
|
||||||
|
})?;
|
||||||
|
let (_, document_settings) = scan_for_in_buffer_settings(input)?;
|
||||||
|
let mut final_settings = Vec::with_capacity(
|
||||||
|
document_settings.len()
|
||||||
|
+ match setup_file_settings {
|
||||||
|
Some((_, ref setup_file_settings)) => setup_file_settings.len(),
|
||||||
|
None => 0,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if let Some((_, setup_file_settings)) = setup_file_settings {
|
||||||
|
final_settings.extend(setup_file_settings.into_iter());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: read the keywords into settings and apply them to the GlobalSettings.
|
||||||
|
|
||||||
let (remaining, document) =
|
let (remaining, document) =
|
||||||
_document(context, input).map(|(rem, out)| (Into::<&str>::into(rem), out))?;
|
_document(context, input).map(|(rem, out)| (Into::<&str>::into(rem), out))?;
|
||||||
{
|
{
|
||||||
|
28
src/parser/in_buffer_settings.rs
Normal file
28
src/parser/in_buffer_settings.rs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
use nom::branch::alt;
|
||||||
|
use nom::bytes::complete::tag_no_case;
|
||||||
|
use nom::character::complete::anychar;
|
||||||
|
use nom::combinator::map;
|
||||||
|
use nom::multi::many0;
|
||||||
|
use nom::multi::many_till;
|
||||||
|
|
||||||
|
use super::keyword::filtered_keyword;
|
||||||
|
use super::OrgSource;
|
||||||
|
use crate::error::Res;
|
||||||
|
use crate::types::Keyword;
|
||||||
|
|
||||||
|
pub 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("todo"), tag_no_case("setupfile")))(input)
|
||||||
|
}
|
@ -7,6 +7,7 @@ use nom::character::complete::anychar;
|
|||||||
use nom::character::complete::line_ending;
|
use nom::character::complete::line_ending;
|
||||||
use nom::character::complete::space0;
|
use nom::character::complete::space0;
|
||||||
use nom::character::complete::space1;
|
use nom::character::complete::space1;
|
||||||
|
use nom::combinator::consumed;
|
||||||
use nom::combinator::eof;
|
use nom::combinator::eof;
|
||||||
use nom::combinator::not;
|
use nom::combinator::not;
|
||||||
use nom::combinator::peek;
|
use nom::combinator::peek;
|
||||||
@ -16,6 +17,7 @@ use nom::sequence::tuple;
|
|||||||
|
|
||||||
use super::org_source::BracketDepth;
|
use super::org_source::BracketDepth;
|
||||||
use super::org_source::OrgSource;
|
use super::org_source::OrgSource;
|
||||||
|
use crate::context::Matcher;
|
||||||
use crate::context::RefContext;
|
use crate::context::RefContext;
|
||||||
use crate::error::CustomError;
|
use crate::error::CustomError;
|
||||||
use crate::error::MyError;
|
use crate::error::MyError;
|
||||||
@ -29,19 +31,26 @@ const ORG_ELEMENT_AFFILIATED_KEYWORDS: [&'static str; 13] = [
|
|||||||
];
|
];
|
||||||
const ORG_ELEMENT_DUAL_KEYWORDS: [&'static str; 2] = ["caption", "results"];
|
const ORG_ELEMENT_DUAL_KEYWORDS: [&'static str; 2] = ["caption", "results"];
|
||||||
|
|
||||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
pub fn filtered_keyword<F: Matcher>(
|
||||||
pub fn keyword<'b, 'g, 'r, 's>(
|
key_parser: F,
|
||||||
_context: RefContext<'b, 'g, 'r, 's>,
|
) -> impl for<'s> Fn(OrgSource<'s>) -> Res<OrgSource<'s>, Keyword<'s>> {
|
||||||
|
move |input| _filtered_keyword(&key_parser, input)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(
|
||||||
|
feature = "tracing",
|
||||||
|
tracing::instrument(ret, level = "debug", skip(key_parser))
|
||||||
|
)]
|
||||||
|
fn _filtered_keyword<'s, F: Matcher>(
|
||||||
|
key_parser: F,
|
||||||
input: OrgSource<'s>,
|
input: OrgSource<'s>,
|
||||||
) -> Res<OrgSource<'s>, Keyword<'s>> {
|
) -> Res<OrgSource<'s>, Keyword<'s>> {
|
||||||
start_of_line(input)?;
|
start_of_line(input)?;
|
||||||
// TODO: When key is a member of org-element-parsed-keywords, value can contain the standard set objects, excluding footnote references.
|
// TODO: When key is a member of org-element-parsed-keywords, value can contain the standard set objects, excluding footnote references.
|
||||||
let (remaining, rule) = recognize(tuple((
|
let (remaining, (consumed_input, (_, _, parsed_key, _, parsed_value, _))) = consumed(tuple((
|
||||||
space0,
|
space0,
|
||||||
tag("#+"),
|
tag("#+"),
|
||||||
not(peek(tag_no_case("call"))),
|
key_parser,
|
||||||
not(peek(tag_no_case("begin"))),
|
|
||||||
is_not(" \t\r\n:"),
|
|
||||||
tag(":"),
|
tag(":"),
|
||||||
alt((recognize(tuple((space1, is_not("\r\n")))), space0)),
|
alt((recognize(tuple((space1, is_not("\r\n")))), space0)),
|
||||||
alt((line_ending, eof)),
|
alt((line_ending, eof)),
|
||||||
@ -49,33 +58,36 @@ pub fn keyword<'b, 'g, 'r, 's>(
|
|||||||
Ok((
|
Ok((
|
||||||
remaining,
|
remaining,
|
||||||
Keyword {
|
Keyword {
|
||||||
source: rule.into(),
|
source: consumed_input.into(),
|
||||||
|
key: parsed_key.into(),
|
||||||
|
value: parsed_value.into(),
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||||
|
pub fn keyword<'b, 'g, 'r, 's>(
|
||||||
|
_context: RefContext<'b, 'g, 'r, 's>,
|
||||||
|
input: OrgSource<'s>,
|
||||||
|
) -> Res<OrgSource<'s>, Keyword<'s>> {
|
||||||
|
filtered_keyword(regular_keyword_key)(input)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||||
pub fn affiliated_keyword<'b, 'g, 'r, 's>(
|
pub fn affiliated_keyword<'b, 'g, 'r, 's>(
|
||||||
_context: RefContext<'b, 'g, 'r, 's>,
|
_context: RefContext<'b, 'g, 'r, 's>,
|
||||||
input: OrgSource<'s>,
|
input: OrgSource<'s>,
|
||||||
) -> Res<OrgSource<'s>, Keyword<'s>> {
|
) -> Res<OrgSource<'s>, Keyword<'s>> {
|
||||||
start_of_line(input)?;
|
filtered_keyword(affiliated_key)(input)
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: When key is a member of org-element-parsed-keywords, value can contain the standard set objects, excluding footnote references.
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||||
let (remaining, rule) = recognize(tuple((
|
fn regular_keyword_key<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
||||||
space0,
|
recognize(tuple((
|
||||||
tag("#+"),
|
not(peek(tag_no_case("call"))),
|
||||||
affiliated_key,
|
not(peek(tag_no_case("begin"))),
|
||||||
tag(":"),
|
is_not(" \t\r\n:"),
|
||||||
alt((recognize(tuple((space1, is_not("\r\n")))), space0)),
|
)))(input)
|
||||||
alt((line_ending, eof)),
|
|
||||||
)))(input)?;
|
|
||||||
Ok((
|
|
||||||
remaining,
|
|
||||||
Keyword {
|
|
||||||
source: rule.into(),
|
|
||||||
},
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||||
|
@ -15,6 +15,7 @@ mod footnote_definition;
|
|||||||
mod footnote_reference;
|
mod footnote_reference;
|
||||||
mod greater_block;
|
mod greater_block;
|
||||||
mod horizontal_rule;
|
mod horizontal_rule;
|
||||||
|
mod in_buffer_settings;
|
||||||
mod inline_babel_call;
|
mod inline_babel_call;
|
||||||
mod inline_source_block;
|
mod inline_source_block;
|
||||||
mod keyword;
|
mod keyword;
|
||||||
|
@ -1,31 +1,22 @@
|
|||||||
use nom::branch::alt;
|
|
||||||
use nom::bytes::complete::is_not;
|
|
||||||
use nom::bytes::complete::tag_no_case;
|
use nom::bytes::complete::tag_no_case;
|
||||||
use nom::character::complete::anychar;
|
use nom::character::complete::anychar;
|
||||||
use nom::character::complete::line_ending;
|
use nom::combinator::map;
|
||||||
use nom::character::complete::space1;
|
|
||||||
use nom::combinator::eof;
|
|
||||||
use nom::multi::many_till;
|
use nom::multi::many_till;
|
||||||
use nom::sequence::tuple;
|
|
||||||
|
|
||||||
|
use super::keyword::filtered_keyword;
|
||||||
use super::OrgSource;
|
use super::OrgSource;
|
||||||
use crate::error::Res;
|
use crate::error::Res;
|
||||||
use crate::parser::util::start_of_line;
|
|
||||||
|
|
||||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||||
pub fn scan_for_setup_file<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
pub fn scan_for_setup_file<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, &'s str> {
|
||||||
let (remaining, setup) = many_till(anychar, setup_file)(input)
|
let (remaining, setup) = map(
|
||||||
.map(|(remaining, (_, setup_file))| (remaining, setup_file))?;
|
many_till(anychar, filtered_keyword(setupfile_key)),
|
||||||
|
|(_, kw)| kw.value,
|
||||||
|
)(input)?;
|
||||||
Ok((remaining, setup))
|
Ok((remaining, setup))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup_file<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||||
let (remaining, (_, _, _, setup_file, _)) = tuple((
|
fn setupfile_key<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
||||||
start_of_line,
|
tag_no_case("setupfile")(input)
|
||||||
tag_no_case("#+SETUPFILE:"),
|
|
||||||
space1,
|
|
||||||
is_not("\r\n"),
|
|
||||||
alt((line_ending, eof)),
|
|
||||||
))(input)?;
|
|
||||||
Ok((remaining, setup_file))
|
|
||||||
}
|
}
|
||||||
|
@ -87,6 +87,8 @@ pub struct HorizontalRule<'s> {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Keyword<'s> {
|
pub struct Keyword<'s> {
|
||||||
pub source: &'s str,
|
pub source: &'s str,
|
||||||
|
pub key: &'s str,
|
||||||
|
pub value: &'s str,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user