diff --git a/org_mode_samples/greater_element/drawer/name.org b/org_mode_samples/greater_element/drawer/name.org new file mode 100644 index 00000000..41b7c3d4 --- /dev/null +++ b/org_mode_samples/greater_element/drawer/name.org @@ -0,0 +1,10 @@ +* Headline +before +#+NAME: foo +:candle: +inside + +the drawer +:end: + +after diff --git a/org_mode_samples/greater_element/dynamic_block/name.org b/org_mode_samples/greater_element/dynamic_block/name.org new file mode 100644 index 00000000..4da2f796 --- /dev/null +++ b/org_mode_samples/greater_element/dynamic_block/name.org @@ -0,0 +1,7 @@ +#+NAME: foo +#+BEGIN: clocktable :scope file :maxlevel 2 +#+CAPTION: Clock summary at [2023-08-25 Fri 05:34] +| Headline | Time | +|--------------+--------| +| *Total time* | *0:00* | +#+END: diff --git a/org_mode_samples/greater_element/greater_block/center/name.org b/org_mode_samples/greater_element/greater_block/center/name.org new file mode 100644 index 00000000..e0f9c0cf --- /dev/null +++ b/org_mode_samples/greater_element/greater_block/center/name.org @@ -0,0 +1,4 @@ +#+NAME: foo +#+begin_center + +#+end_center diff --git a/org_mode_samples/greater_element/greater_block/quote/name.org b/org_mode_samples/greater_element/greater_block/quote/name.org new file mode 100644 index 00000000..fe2fa3a4 --- /dev/null +++ b/org_mode_samples/greater_element/greater_block/quote/name.org @@ -0,0 +1,4 @@ +#+NAME: foo +#+begin_quote + +#+end_quote diff --git a/org_mode_samples/greater_element/greater_block/special/name.org b/org_mode_samples/greater_element/greater_block/special/name.org new file mode 100644 index 00000000..6b513b12 --- /dev/null +++ b/org_mode_samples/greater_element/greater_block/special/name.org @@ -0,0 +1,6 @@ +#+NAME: foo +#+begin_defun +foo + +{{{bar(baz)}}} +#+end_defun diff --git a/org_mode_samples/greater_element/plain_list/name.org b/org_mode_samples/greater_element/plain_list/name.org new file mode 100644 index 00000000..d80b7ba8 --- /dev/null +++ b/org_mode_samples/greater_element/plain_list/name.org @@ -0,0 +1,2 @@ +#+NAME: foo +1. bar diff --git a/org_mode_samples/lesser_element/babel_call/name.org b/org_mode_samples/lesser_element/babel_call/name.org new file mode 100644 index 00000000..da7aea93 --- /dev/null +++ b/org_mode_samples/lesser_element/babel_call/name.org @@ -0,0 +1,2 @@ +#+NAME: foo +#+call: foo(bar="baz") diff --git a/org_mode_samples/lesser_element/keyword/babel_call.org b/org_mode_samples/lesser_element/babel_call/simple.org similarity index 100% rename from org_mode_samples/lesser_element/keyword/babel_call.org rename to org_mode_samples/lesser_element/babel_call/simple.org diff --git a/org_mode_samples/lesser_element/clock/name.org b/org_mode_samples/lesser_element/clock/name.org new file mode 100644 index 00000000..c169fbac --- /dev/null +++ b/org_mode_samples/lesser_element/clock/name.org @@ -0,0 +1,3 @@ +CLOCK: [2023-04-21 Fri 19:32]--[2023-04-21 Fri 19:35] => 0:03 +#+NAME: foo +CLOCK: [2023-04-21 Fri 19:43] diff --git a/org_mode_samples/lesser_element/comment/name.org b/org_mode_samples/lesser_element/comment/name.org new file mode 100644 index 00000000..815b8d48 --- /dev/null +++ b/org_mode_samples/lesser_element/comment/name.org @@ -0,0 +1,2 @@ +#+NAME: foo +# Comments cannot have affiliated keywords. diff --git a/org_mode_samples/lesser_element/diary_sexp/name.org b/org_mode_samples/lesser_element/diary_sexp/name.org new file mode 100644 index 00000000..34e6155b --- /dev/null +++ b/org_mode_samples/lesser_element/diary_sexp/name.org @@ -0,0 +1,2 @@ +#+NAME: foo +%%(foo) diff --git a/org_mode_samples/lesser_element/fixed_width_area/name.org b/org_mode_samples/lesser_element/fixed_width_area/name.org new file mode 100644 index 00000000..482c0d26 --- /dev/null +++ b/org_mode_samples/lesser_element/fixed_width_area/name.org @@ -0,0 +1,2 @@ +#+NAME: foo +: bar diff --git a/org_mode_samples/lesser_element/horizontal_rule/name.org b/org_mode_samples/lesser_element/horizontal_rule/name.org new file mode 100644 index 00000000..252fc4f1 --- /dev/null +++ b/org_mode_samples/lesser_element/horizontal_rule/name.org @@ -0,0 +1,2 @@ +#+NAME: foo +----- diff --git a/org_mode_samples/lesser_element/keyword/name.org b/org_mode_samples/lesser_element/keyword/name.org new file mode 100644 index 00000000..51bc2fad --- /dev/null +++ b/org_mode_samples/lesser_element/keyword/name.org @@ -0,0 +1,2 @@ +#+NAME: foo +#+FOO: BAR diff --git a/org_mode_samples/lesser_element/latex_environment/name.org b/org_mode_samples/lesser_element/latex_environment/name.org new file mode 100644 index 00000000..51a64715 --- /dev/null +++ b/org_mode_samples/lesser_element/latex_environment/name.org @@ -0,0 +1,4 @@ +#+NAME: foo +\begin{foo} +bar +\end{foo} diff --git a/src/compare/diff.rs b/src/compare/diff.rs index f4e82d01..a4ba0833 100644 --- a/src/compare/diff.rs +++ b/src/compare/diff.rs @@ -879,6 +879,16 @@ fn compare_plain_list<'b, 's>( let mut this_status = DiffStatus::Good; let mut message = None; + // Compare name + let name = get_property_quoted_string(emacs, ":name")?; + if name.as_ref().map(String::as_str) != rust.name { + this_status = DiffStatus::Bad; + message = Some(format!( + "Name mismatch (emacs != rust) {:?} != {:?}", + name, rust.name + )); + } + // Compare type // :type is an unquoted atom of either descriptive, ordered, or unordered let list_type = get_property_unquoted_atom(emacs, ":type")?; @@ -1037,8 +1047,18 @@ fn compare_center_block<'b, 's>( ) -> Result, Box> { let children = emacs.as_list()?; let mut child_status = Vec::new(); - let this_status = DiffStatus::Good; - let message = None; + let mut this_status = DiffStatus::Good; + let mut message = None; + + // Compare name + let name = get_property_quoted_string(emacs, ":name")?; + if name.as_ref().map(String::as_str) != rust.name { + this_status = DiffStatus::Bad; + message = Some(format!( + "Name mismatch (emacs != rust) {:?} != {:?}", + name, rust.name + )); + } for (emacs_child, rust_child) in children.iter().skip(2).zip(rust.children.iter()) { child_status.push(compare_ast_node(source, emacs_child, rust_child.into())?); @@ -1062,8 +1082,18 @@ fn compare_quote_block<'b, 's>( ) -> Result, Box> { let children = emacs.as_list()?; let mut child_status = Vec::new(); - let this_status = DiffStatus::Good; - let message = None; + let mut this_status = DiffStatus::Good; + let mut message = None; + + // Compare name + let name = get_property_quoted_string(emacs, ":name")?; + if name.as_ref().map(String::as_str) != rust.name { + this_status = DiffStatus::Bad; + message = Some(format!( + "Name mismatch (emacs != rust) {:?} != {:?}", + name, rust.name + )); + } for (emacs_child, rust_child) in children.iter().skip(2).zip(rust.children.iter()) { child_status.push(compare_ast_node(source, emacs_child, rust_child.into())?); @@ -1090,14 +1120,24 @@ fn compare_special_block<'b, 's>( let mut this_status = DiffStatus::Good; let mut message = None; - // Compare type - let special_block_type = - get_property_quoted_string(emacs, ":type")?.ok_or("Special blocks should have a name.")?; - if special_block_type != rust.name { + // Compare name + let name = get_property_quoted_string(emacs, ":name")?; + if name.as_ref().map(String::as_str) != rust.name { this_status = DiffStatus::Bad; message = Some(format!( "Name mismatch (emacs != rust) {:?} != {:?}", - special_block_type, rust.name + name, rust.name + )); + } + + // Compare type + let special_block_type = + get_property_quoted_string(emacs, ":type")?.ok_or("Special blocks should have a name.")?; + if special_block_type != rust.block_type { + this_status = DiffStatus::Bad; + message = Some(format!( + "Name mismatch (emacs != rust) {:?} != {:?}", + special_block_type, rust.block_type )); } @@ -1140,14 +1180,24 @@ fn compare_dynamic_block<'b, 's>( let mut this_status = DiffStatus::Good; let mut message = None; - // Compare block-name - let block_name = get_property_quoted_string(emacs, ":block-name")? - .ok_or("Dynamic blocks should have a name.")?; - if block_name != rust.name { + // Compare name + let name = get_property_quoted_string(emacs, ":name")?; + if name.as_ref().map(String::as_str) != rust.name { this_status = DiffStatus::Bad; message = Some(format!( "Name mismatch (emacs != rust) {:?} != {:?}", - block_name, rust.name + name, rust.name + )); + } + + // Compare block-name + let block_name = get_property_quoted_string(emacs, ":block-name")? + .ok_or("Dynamic blocks should have a name.")?; + if block_name != rust.block_name { + this_status = DiffStatus::Bad; + message = Some(format!( + "Name mismatch (emacs != rust) {:?} != {:?}", + block_name, rust.block_name )); } @@ -1191,6 +1241,16 @@ fn compare_footnote_definition<'b, 's>( let mut message = None; // TODO: Compare :pre-blank + // Compare name + let name = get_property_quoted_string(emacs, ":name")?; + if name.as_ref().map(String::as_str) != rust.name { + this_status = DiffStatus::Bad; + message = Some(format!( + "Name mismatch (emacs != rust) {:?} != {:?}", + name, rust.name + )); + } + // Compare label let label = get_property_quoted_string(emacs, ":label")? .ok_or("Footnote definitions should have a name.")?; @@ -1259,10 +1319,9 @@ fn compare_drawer<'b, 's>( let mut this_status = DiffStatus::Good; let mut message = None; - // Compare drawer-name - let name = - get_property_quoted_string(emacs, ":drawer-name")?.ok_or("Drawers should have a name.")?; - if name != rust.name { + // Compare name + let name = get_property_quoted_string(emacs, ":name")?; + if name.as_ref().map(String::as_str) != rust.name { this_status = DiffStatus::Bad; message = Some(format!( "Name mismatch (emacs != rust) {:?} != {:?}", @@ -1270,6 +1329,17 @@ fn compare_drawer<'b, 's>( )); } + // Compare drawer-name + let drawer_name = + get_property_quoted_string(emacs, ":drawer-name")?.ok_or("Drawers should have a name.")?; + if drawer_name != rust.drawer_name { + this_status = DiffStatus::Bad; + message = Some(format!( + "Drawer name mismatch (emacs != rust) {:?} != {:?}", + drawer_name, rust.drawer_name + )); + } + for (emacs_child, rust_child) in children.iter().skip(2).zip(rust.children.iter()) { child_status.push(compare_ast_node(source, emacs_child, rust_child.into())?); } @@ -1322,11 +1392,11 @@ fn compare_node_property<'b, 's>( // Compare key let key = get_property_quoted_string(emacs, ":key")?.ok_or("Node properties should have a key.")?; - if key != rust.name { + if key != rust.property_name { this_status = DiffStatus::Bad; message = Some(format!( "Key mismatch (emacs != rust) {:?} != {:?}", - key, rust.name + key, rust.property_name )); } @@ -1365,6 +1435,16 @@ fn compare_table<'b, 's>( let mut this_status = DiffStatus::Good; let mut message = None; + // Compare name + let name = get_property_quoted_string(emacs, ":name")?; + if name.as_ref().map(String::as_str) != rust.name { + this_status = DiffStatus::Bad; + message = Some(format!( + "Name mismatch (emacs != rust) {:?} != {:?}", + name, rust.name + )); + } + // Compare formulas // // :tblfm is either nil or a list () filled with quoted strings containing the value for any tblfm keywords at the end of the table. @@ -2004,11 +2084,21 @@ fn compare_diary_sexp<'b, 's>( emacs: &'b Token<'s>, rust: &'b DiarySexp<'s>, ) -> Result, Box> { - let this_status = DiffStatus::Good; - let message = None; + let mut this_status = DiffStatus::Good; + let mut message = None; // TODO: Compare :value + // Compare name + let name = get_property_quoted_string(emacs, ":name")?; + if name.as_ref().map(String::as_str) != rust.name { + this_status = DiffStatus::Bad; + message = Some(format!( + "Name mismatch (emacs != rust) {:?} != {:?}", + name, rust.name + )); + } + Ok(DiffResult { status: this_status, name: rust.get_elisp_name(), @@ -2097,11 +2187,21 @@ fn compare_fixed_width_area<'b, 's>( rust: &'b FixedWidthArea<'s>, ) -> Result, Box> { let child_status = Vec::new(); - let this_status = DiffStatus::Good; - let message = None; + let mut this_status = DiffStatus::Good; + let mut message = None; // TODO: Compare :value + // Compare name + let name = get_property_quoted_string(emacs, ":name")?; + if name.as_ref().map(String::as_str) != rust.name { + this_status = DiffStatus::Bad; + message = Some(format!( + "Name mismatch (emacs != rust) {:?} != {:?}", + name, rust.name + )); + } + Ok(DiffResult { status: this_status, name: rust.get_elisp_name(), @@ -2119,8 +2219,18 @@ fn compare_horizontal_rule<'b, 's>( rust: &'b HorizontalRule<'s>, ) -> Result, Box> { let child_status = Vec::new(); - let this_status = DiffStatus::Good; - let message = None; + let mut this_status = DiffStatus::Good; + let mut message = None; + + // Compare name + let name = get_property_quoted_string(emacs, ":name")?; + if name.as_ref().map(String::as_str) != rust.name { + this_status = DiffStatus::Bad; + message = Some(format!( + "Name mismatch (emacs != rust) {:?} != {:?}", + name, rust.name + )); + } Ok(DiffResult { status: this_status, @@ -2142,6 +2252,16 @@ fn compare_keyword<'b, 's>( let mut this_status = DiffStatus::Good; let mut message = None; + // Compare name + let name = get_property_quoted_string(emacs, ":name")?; + if name.as_ref().map(String::as_str) != rust.name { + this_status = DiffStatus::Bad; + message = Some(format!( + "Name mismatch (emacs != rust) {:?} != {:?}", + name, rust.name + )); + } + let key = unquote( get_property(emacs, ":key")? .ok_or("Emacs keywords should have a :key")? @@ -2188,6 +2308,17 @@ fn compare_babel_call<'b, 's>( let mut message = None; // TODO: Compare :call :inside-header :arguments :end-header + + // Compare name + let name = get_property_quoted_string(emacs, ":name")?; + if name.as_ref().map(String::as_str) != rust.name { + this_status = DiffStatus::Bad; + message = Some(format!( + "Name mismatch (emacs != rust) {:?} != {:?}", + name, rust.name + )); + } + let value = unquote( get_property(emacs, ":value")? .ok_or("Emacs keywords should have a :value")? @@ -2218,11 +2349,21 @@ fn compare_latex_environment<'b, 's>( rust: &'b LatexEnvironment<'s>, ) -> Result, Box> { let child_status = Vec::new(); - let this_status = DiffStatus::Good; - let message = None; + let mut this_status = DiffStatus::Good; + let mut message = None; // TODO: Compare :value + // Compare name + let name = get_property_quoted_string(emacs, ":name")?; + if name.as_ref().map(String::as_str) != rust.name { + this_status = DiffStatus::Bad; + message = Some(format!( + "Name mismatch (emacs != rust) {:?} != {:?}", + name, rust.name + )); + } + Ok(DiffResult { status: this_status, name: rust.get_elisp_name(), diff --git a/src/parser/diary_sexp.rs b/src/parser/diary_sexp.rs index ac1957bc..1a82ff07 100644 --- a/src/parser/diary_sexp.rs +++ b/src/parser/diary_sexp.rs @@ -3,9 +3,12 @@ use nom::bytes::complete::is_not; use nom::bytes::complete::tag; use nom::character::complete::line_ending; use nom::combinator::eof; +use nom::multi::many0; use nom::sequence::tuple; +use super::keyword::affiliated_keyword; use super::org_source::OrgSource; +use crate::context::parser_with_context; use crate::context::RefContext; use crate::error::Res; use crate::parser::util::get_consumed; @@ -14,9 +17,11 @@ use crate::types::DiarySexp; #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] pub(crate) fn diary_sexp<'b, 'g, 'r, 's>( - _context: RefContext<'b, 'g, 'r, 's>, + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, DiarySexp<'s>> { + let (input, affiliated_keywords) = + many0(parser_with_context!(affiliated_keyword)(context))(input)?; start_of_line(input)?; let (remaining, _clock) = tag("%%(")(input)?; let (remaining, _contents) = is_not("\r\n")(remaining)?; @@ -27,6 +32,7 @@ pub(crate) fn diary_sexp<'b, 'g, 'r, 's>( remaining, DiarySexp { source: source.into(), + name: None, // TODO }, )) } diff --git a/src/parser/drawer.rs b/src/parser/drawer.rs index 0d28e459..630488e9 100644 --- a/src/parser/drawer.rs +++ b/src/parser/drawer.rs @@ -7,9 +7,11 @@ use nom::character::complete::space0; use nom::combinator::eof; use nom::combinator::not; use nom::combinator::recognize; +use nom::multi::many0; use nom::multi::many_till; use nom::sequence::tuple; +use super::keyword::affiliated_keyword; use super::org_source::OrgSource; use crate::context::parser_with_context; use crate::context::ContextElement; @@ -41,6 +43,8 @@ pub(crate) fn drawer<'b, 'g, 'r, 's>( "Cannot nest objects of the same element".into(), )))); } + let (input, affiliated_keywords) = + many0(parser_with_context!(affiliated_keyword)(context))(input)?; start_of_line(input)?; let (remaining, _leading_whitespace) = space0(input)?; let (remaining, (_open_colon, drawer_name, _close_colon, _new_line)) = tuple(( @@ -90,7 +94,8 @@ pub(crate) fn drawer<'b, 'g, 'r, 's>( remaining, Drawer { source: source.into(), - name: drawer_name.into(), + name: None, // TODO + drawer_name: drawer_name.into(), children, }, )) diff --git a/src/parser/dynamic_block.rs b/src/parser/dynamic_block.rs index 53681487..1872c0f5 100644 --- a/src/parser/dynamic_block.rs +++ b/src/parser/dynamic_block.rs @@ -17,6 +17,7 @@ use nom::multi::many_till; use nom::sequence::preceded; use nom::sequence::tuple; +use super::keyword::affiliated_keyword; use super::org_source::OrgSource; use crate::context::parser_with_context; use crate::context::ContextElement; @@ -47,6 +48,9 @@ pub(crate) fn dynamic_block<'b, 'g, 'r, 's>( "Cannot nest objects of the same element".into(), )))); } + let (input, affiliated_keywords) = + many0(parser_with_context!(affiliated_keyword)(context))(input)?; + start_of_line(input)?; let (remaining, _leading_whitespace) = space0(input)?; let (remaining, (_, name, parameters, _, _)) = tuple(( @@ -97,7 +101,8 @@ pub(crate) fn dynamic_block<'b, 'g, 'r, 's>( remaining, DynamicBlock { source: source.into(), - name: name.into(), + name: None, // TODO + block_name: name.into(), parameters: parameters.map(|val| val.into()), children, }, diff --git a/src/parser/element_parser.rs b/src/parser/element_parser.rs index 5bc49339..5349650d 100644 --- a/src/parser/element_parser.rs +++ b/src/parser/element_parser.rs @@ -1,8 +1,5 @@ use nom::branch::alt; use nom::combinator::map; -use nom::combinator::not; -use nom::multi::many0; -use nom::sequence::tuple; use super::clock::clock; use super::comment::comment; @@ -79,8 +76,6 @@ fn _element<'b, 'g, 'r, 's>( let paragraph_matcher = parser_with_context!(paragraph)(context); let latex_environment_matcher = parser_with_context!(latex_environment)(context); - // TODO: Affiliated keywords cannot be on comments, clocks, headings, inlinetasks, items, node properties, planning, property drawers, sections, and table rows - let (remaining, mut affiliated_keywords) = many0(affiliated_keyword_matcher)(input)?; let (remaining, mut element) = match alt(( map(plain_list_matcher, Element::PlainList), greater_block_matcher, @@ -100,28 +95,20 @@ fn _element<'b, 'g, 'r, 's>( map(horizontal_rule_matcher, Element::HorizontalRule), map(latex_environment_matcher, Element::LatexEnvironment), map(babel_keyword_matcher, Element::BabelCall), - map( - map( - tuple((not(affiliated_keyword_matcher), keyword_matcher)), - |(_, kw)| kw, - ), - Element::Keyword, - ), - ))(remaining) + map(keyword_matcher, Element::Keyword), + ))(input) { the_ok @ Ok(_) => the_ok, Err(_) => { if can_be_paragraph { - match map(paragraph_matcher, Element::Paragraph)(remaining) { + match map(paragraph_matcher, Element::Paragraph)(input) { the_ok @ Ok(_) => the_ok, Err(_) => { // TODO: Because this function expects a single element, if there are multiple affiliated keywords before an element that cannot have affiliated keywords, we end up re-parsing the affiliated keywords many times. - affiliated_keywords.clear(); map(affiliated_keyword_matcher, Element::Keyword)(input) } } } else { - affiliated_keywords.clear(); map(affiliated_keyword_matcher, Element::Keyword)(input) } } @@ -149,6 +136,7 @@ fn _detect_element<'b, 'g, 'r, 's>( input: OrgSource<'s>, can_be_paragraph: bool, ) -> Res, ()> { + // TODO: What about affiliated keywords in the detect_* functions? if alt(( parser_with_context!(detect_plain_list)(context), detect_footnote_definition, diff --git a/src/parser/fixed_width_area.rs b/src/parser/fixed_width_area.rs index f5015914..0d67770e 100644 --- a/src/parser/fixed_width_area.rs +++ b/src/parser/fixed_width_area.rs @@ -10,6 +10,7 @@ use nom::multi::many0; use nom::sequence::preceded; use nom::sequence::tuple; +use super::keyword::affiliated_keyword; use super::org_source::OrgSource; use super::util::only_space1; use super::util::org_line_ending; @@ -26,6 +27,8 @@ pub(crate) fn fixed_width_area<'b, 'g, 'r, 's>( context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, FixedWidthArea<'s>> { + let (input, affiliated_keywords) = + many0(parser_with_context!(affiliated_keyword)(context))(input)?; let fixed_width_area_line_matcher = parser_with_context!(fixed_width_area_line)(context); let exit_matcher = parser_with_context!(exit_matcher_parser)(context); let (remaining, _first_line) = fixed_width_area_line_matcher(input)?; @@ -37,6 +40,7 @@ pub(crate) fn fixed_width_area<'b, 'g, 'r, 's>( remaining, FixedWidthArea { source: source.into(), + name: None, // TODO }, )) } diff --git a/src/parser/footnote_definition.rs b/src/parser/footnote_definition.rs index 857c0a0d..a7660ae9 100644 --- a/src/parser/footnote_definition.rs +++ b/src/parser/footnote_definition.rs @@ -11,6 +11,7 @@ use nom::multi::many1; use nom::multi::many_till; use nom::sequence::tuple; +use super::keyword::affiliated_keyword; use super::org_source::OrgSource; use super::util::include_input; use super::util::WORD_CONSTITUENT_CHARACTERS; @@ -41,6 +42,8 @@ pub(crate) fn footnote_definition<'b, 'g, 'r, 's>( "Cannot nest objects of the same element".into(), )))); } + let (input, affiliated_keywords) = + many0(parser_with_context!(affiliated_keyword)(context))(input)?; start_of_line(input)?; // Cannot be indented. let (remaining, (_, lbl, _, _, _)) = tuple(( @@ -85,6 +88,7 @@ pub(crate) fn footnote_definition<'b, 'g, 'r, 's>( remaining, FootnoteDefinition { source: source.into(), + name: None, // TODO label: lbl.into(), children: children.into_iter().map(|(_, item)| item).collect(), }, diff --git a/src/parser/greater_block.rs b/src/parser/greater_block.rs index d61fb21d..47c0bf7d 100644 --- a/src/parser/greater_block.rs +++ b/src/parser/greater_block.rs @@ -17,6 +17,7 @@ use nom::multi::many_till; use nom::sequence::preceded; use nom::sequence::tuple; +use super::keyword::affiliated_keyword; use super::org_source::OrgSource; use super::util::in_section; use crate::context::parser_with_context; @@ -45,6 +46,8 @@ pub(crate) fn greater_block<'b, 'g, 'r, 's>( context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Element<'s>> { + let (input, affiliated_keywords) = + many0(parser_with_context!(affiliated_keyword)(context))(input)?; start_of_line(input)?; let (remaining, _leading_whitespace) = space0(input)?; let (remaining, (_begin, name)) = tuple(( @@ -75,7 +78,11 @@ fn center_block<'b, 'g, 'r, 's>( greater_block_body(context, input, original_input, "center", "center block")?; Ok(( remaining, - Element::CenterBlock(CenterBlock { source, children }), + Element::CenterBlock(CenterBlock { + source, + name: None, // TODO + children, + }), )) } @@ -89,7 +96,11 @@ fn quote_block<'b, 'g, 'r, 's>( greater_block_body(context, input, original_input, "quote", "quote block")?; Ok(( remaining, - Element::QuoteBlock(QuoteBlock { source, children }), + Element::QuoteBlock(QuoteBlock { + source, + name: None, // TODO + children, + }), )) } @@ -122,8 +133,9 @@ fn _special_block<'c, 'b, 'g, 'r, 's>( remaining, Element::SpecialBlock(SpecialBlock { source, + name: None, // TODO children, - name, + block_type: name, parameters: parameters.map(|(_, parameters)| Into::<&str>::into(parameters)), }), )) diff --git a/src/parser/horizontal_rule.rs b/src/parser/horizontal_rule.rs index 9a7413ab..a471dc2a 100644 --- a/src/parser/horizontal_rule.rs +++ b/src/parser/horizontal_rule.rs @@ -5,10 +5,13 @@ use nom::character::complete::space0; use nom::combinator::eof; use nom::combinator::recognize; use nom::combinator::verify; +use nom::multi::many0; use nom::multi::many1_count; use nom::sequence::tuple; +use super::keyword::affiliated_keyword; use super::org_source::OrgSource; +use crate::context::parser_with_context; use crate::context::RefContext; use crate::error::Res; use crate::parser::util::start_of_line; @@ -16,9 +19,11 @@ use crate::types::HorizontalRule; #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] pub(crate) fn horizontal_rule<'b, 'g, 'r, 's>( - _context: RefContext<'b, 'g, 'r, 's>, + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, HorizontalRule<'s>> { + let (input, affiliated_keywords) = + many0(parser_with_context!(affiliated_keyword)(context))(input)?; start_of_line(input)?; let (remaining, rule) = recognize(tuple(( space0, @@ -30,6 +35,7 @@ pub(crate) fn horizontal_rule<'b, 'g, 'r, 's>( remaining, HorizontalRule { source: rule.into(), + name: None, // TODO }, )) } diff --git a/src/parser/keyword.rs b/src/parser/keyword.rs index 9253590f..4026ab33 100644 --- a/src/parser/keyword.rs +++ b/src/parser/keyword.rs @@ -13,11 +13,13 @@ use nom::combinator::not; use nom::combinator::peek; use nom::combinator::recognize; use nom::combinator::verify; +use nom::multi::many0; use nom::multi::many_till; use nom::sequence::tuple; use super::org_source::BracketDepth; use super::org_source::OrgSource; +use crate::context::parser_with_context; use crate::context::Matcher; use crate::context::RefContext; use crate::error::CustomError; @@ -61,6 +63,7 @@ fn _filtered_keyword<'s, F: Matcher>( remaining, Keyword { source: consumed_input.into(), + name: None, // TODO key: parsed_key.into(), value: "".into(), }, @@ -78,6 +81,7 @@ fn _filtered_keyword<'s, F: Matcher>( remaining, Keyword { source: consumed_input.into(), + name: None, // TODO key: parsed_key.into(), value: parsed_value.into(), }, @@ -86,9 +90,11 @@ fn _filtered_keyword<'s, F: Matcher>( #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] pub(crate) fn keyword<'b, 'g, 'r, 's>( - _context: RefContext<'b, 'g, 'r, 's>, + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Keyword<'s>> { + let (input, affiliated_keywords) = + many0(parser_with_context!(affiliated_keyword)(context))(input)?; filtered_keyword(regular_keyword_key)(input) } @@ -102,14 +108,17 @@ pub(crate) fn affiliated_keyword<'b, 'g, 'r, 's>( #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] pub(crate) fn babel_call_keyword<'b, 'g, 'r, 's>( - _context: RefContext<'b, 'g, 'r, 's>, + context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, BabelCall<'s>> { + let (input, affiliated_keywords) = + many0(parser_with_context!(affiliated_keyword)(context))(input)?; let (remaining, kw) = filtered_keyword(babel_call_key)(input)?; Ok(( remaining, BabelCall { source: kw.source, + name: None, // TODO key: kw.key, value: kw.value, }, diff --git a/src/parser/latex_environment.rs b/src/parser/latex_environment.rs index 9635ad8b..97469a3b 100644 --- a/src/parser/latex_environment.rs +++ b/src/parser/latex_environment.rs @@ -8,9 +8,11 @@ use nom::character::complete::space0; use nom::combinator::eof; use nom::combinator::peek; use nom::combinator::recognize; +use nom::multi::many0; use nom::multi::many_till; use nom::sequence::tuple; +use super::keyword::affiliated_keyword; use super::org_source::OrgSource; use super::util::get_consumed; use crate::context::parser_with_context; @@ -29,6 +31,8 @@ pub(crate) fn latex_environment<'b, 'g, 'r, 's>( context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, LatexEnvironment<'s>> { + let (input, affiliated_keywords) = + many0(parser_with_context!(affiliated_keyword)(context))(input)?; start_of_line(input)?; let (remaining, _leading_whitespace) = space0(input)?; let (remaining, (_opening, name, _open_close_brace, _ws, _line_ending)) = tuple(( @@ -54,6 +58,7 @@ pub(crate) fn latex_environment<'b, 'g, 'r, 's>( remaining, LatexEnvironment { source: source.into(), + name: None, // TODO }, )) } diff --git a/src/parser/paragraph.rs b/src/parser/paragraph.rs index 049fe784..591e4dbd 100644 --- a/src/parser/paragraph.rs +++ b/src/parser/paragraph.rs @@ -2,11 +2,13 @@ use nom::branch::alt; use nom::combinator::eof; use nom::combinator::recognize; use nom::combinator::verify; +use nom::multi::many0; use nom::multi::many1; use nom::multi::many_till; use nom::sequence::tuple; use super::element_parser::detect_element; +use super::keyword::affiliated_keyword; use super::org_source::OrgSource; use super::util::blank_line; use super::util::get_consumed; @@ -26,6 +28,9 @@ pub(crate) fn paragraph<'b, 'g, 'r, 's>( context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Paragraph<'s>> { + let (input, affiliated_keywords) = + many0(parser_with_context!(affiliated_keyword)(context))(input)?; + let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode { class: ExitClass::Gamma, exit_matcher: ¶graph_end, diff --git a/src/parser/plain_list.rs b/src/parser/plain_list.rs index 61f8b6b2..164ed9ca 100644 --- a/src/parser/plain_list.rs +++ b/src/parser/plain_list.rs @@ -19,6 +19,7 @@ use nom::multi::many_till; use nom::sequence::tuple; use super::element_parser::element; +use super::keyword::affiliated_keyword; use super::object_parser::standard_set_object; use super::org_source::OrgSource; use super::util::include_input; @@ -78,6 +79,9 @@ pub(crate) fn plain_list<'b, 'g, 'r, 's>( context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, PlainList<'s>> { + let (input, affiliated_keywords) = + many0(parser_with_context!(affiliated_keyword)(context))(input)?; + let contexts = [ ContextElement::Context("plain list"), ContextElement::ConsumeTrailingWhitespace(true), @@ -150,6 +154,7 @@ pub(crate) fn plain_list<'b, 'g, 'r, 's>( remaining, PlainList { source: source.into(), + name: None, // TODO list_type: first_item_list_type.expect("Plain lists require at least one element."), children: children.into_iter().map(|(_start, item)| item).collect(), }, diff --git a/src/parser/property_drawer.rs b/src/parser/property_drawer.rs index 06a4ac52..99f01778 100644 --- a/src/parser/property_drawer.rs +++ b/src/parser/property_drawer.rs @@ -120,7 +120,7 @@ fn node_property<'b, 'g, 'r, 's>( remaining, NodeProperty { source: source.into(), - name: Into::<&str>::into(name), + property_name: Into::<&str>::into(name), value: None, }, )) @@ -133,7 +133,7 @@ fn node_property<'b, 'g, 'r, 's>( remaining, NodeProperty { source: source.into(), - name: Into::<&str>::into(name), + property_name: Into::<&str>::into(name), value: Some(value.into()), }, )) diff --git a/src/parser/table.rs b/src/parser/table.rs index 1d27ed6d..e9445b78 100644 --- a/src/parser/table.rs +++ b/src/parser/table.rs @@ -13,6 +13,7 @@ use nom::multi::many1; use nom::multi::many_till; use nom::sequence::tuple; +use super::keyword::affiliated_keyword; use super::keyword::table_formula_keyword; use super::object_parser::table_cell_set_object; use super::org_source::OrgSource; @@ -38,6 +39,8 @@ pub(crate) fn org_mode_table<'b, 'g, 'r, 's>( context: RefContext<'b, 'g, 'r, 's>, input: OrgSource<'s>, ) -> Res, Table<'s>> { + let (input, affiliated_keywords) = + many0(parser_with_context!(affiliated_keyword)(context))(input)?; start_of_line(input)?; peek(tuple((space0, tag("|"))))(input)?; @@ -68,6 +71,7 @@ pub(crate) fn org_mode_table<'b, 'g, 'r, 's>( remaining, Table { source: source.into(), + name: None, // TODO formulas, children, }, diff --git a/src/types/greater_element.rs b/src/types/greater_element.rs index 17d7cd2e..7f2bede4 100644 --- a/src/types/greater_element.rs +++ b/src/types/greater_element.rs @@ -7,6 +7,7 @@ use super::StandardProperties; #[derive(Debug)] pub struct PlainList<'s> { pub source: &'s str, + pub name: Option<&'s str>, pub list_type: PlainListType, pub children: Vec>, } @@ -46,19 +47,22 @@ pub enum CheckboxType { #[derive(Debug)] pub struct CenterBlock<'s> { pub source: &'s str, + pub name: Option<&'s str>, pub children: Vec>, } #[derive(Debug)] pub struct QuoteBlock<'s> { pub source: &'s str, + pub name: Option<&'s str>, pub children: Vec>, } #[derive(Debug)] pub struct SpecialBlock<'s> { pub source: &'s str, - pub name: &'s str, + pub name: Option<&'s str>, + pub block_type: &'s str, pub parameters: Option<&'s str>, pub children: Vec>, } @@ -66,7 +70,8 @@ pub struct SpecialBlock<'s> { #[derive(Debug)] pub struct DynamicBlock<'s> { pub source: &'s str, - pub name: &'s str, + pub name: Option<&'s str>, + pub block_name: &'s str, pub parameters: Option<&'s str>, pub children: Vec>, } @@ -74,6 +79,7 @@ pub struct DynamicBlock<'s> { #[derive(Debug)] pub struct FootnoteDefinition<'s> { pub source: &'s str, + pub name: Option<&'s str>, pub label: &'s str, pub children: Vec>, } @@ -81,7 +87,8 @@ pub struct FootnoteDefinition<'s> { #[derive(Debug)] pub struct Drawer<'s> { pub source: &'s str, - pub name: &'s str, + pub name: Option<&'s str>, + pub drawer_name: &'s str, pub children: Vec>, } @@ -94,13 +101,14 @@ pub struct PropertyDrawer<'s> { #[derive(Debug)] pub struct NodeProperty<'s> { pub source: &'s str, - pub name: &'s str, + pub property_name: &'s str, pub value: Option<&'s str>, } #[derive(Debug)] pub struct Table<'s> { pub source: &'s str, + pub name: Option<&'s str>, pub formulas: Vec>, pub children: Vec>, } diff --git a/src/types/lesser_element.rs b/src/types/lesser_element.rs index 759ad996..a7cfa4d4 100644 --- a/src/types/lesser_element.rs +++ b/src/types/lesser_element.rs @@ -91,6 +91,7 @@ pub struct Clock<'s> { #[derive(Debug)] pub struct DiarySexp<'s> { pub source: &'s str, + pub name: Option<&'s str>, } #[derive(Debug)] @@ -104,16 +105,19 @@ pub struct Planning<'s> { #[derive(Debug)] pub struct FixedWidthArea<'s> { pub source: &'s str, + pub name: Option<&'s str>, } #[derive(Debug)] pub struct HorizontalRule<'s> { pub source: &'s str, + pub name: Option<&'s str>, } #[derive(Debug)] pub struct Keyword<'s> { pub source: &'s str, + pub name: Option<&'s str>, pub key: &'s str, pub value: &'s str, } @@ -121,6 +125,7 @@ pub struct Keyword<'s> { #[derive(Debug)] pub struct BabelCall<'s> { pub source: &'s str, + pub name: Option<&'s str>, pub key: &'s str, pub value: &'s str, } @@ -128,6 +133,7 @@ pub struct BabelCall<'s> { #[derive(Debug)] pub struct LatexEnvironment<'s> { pub source: &'s str, + pub name: Option<&'s str>, } /// A line number used in switches to lesser blocks.