Unify the standard properties checks in diff.
Instead of copy+pasting them into each compare function, we now call a shared function from a handful of places.
This commit is contained in:
parent
dd8a8207ce
commit
d5b1014fe4
1066
src/compare/diff.rs
1066
src/compare/diff.rs
File diff suppressed because it is too large
Load Diff
474
src/compare/elisp_fact.rs
Normal file
474
src/compare/elisp_fact.rs
Normal file
@ -0,0 +1,474 @@
|
||||
use std::borrow::Cow;
|
||||
|
||||
use crate::types::AngleLink;
|
||||
use crate::types::BabelCall;
|
||||
use crate::types::Bold;
|
||||
use crate::types::Citation;
|
||||
use crate::types::CitationReference;
|
||||
use crate::types::Clock;
|
||||
use crate::types::Code;
|
||||
use crate::types::Comment;
|
||||
use crate::types::CommentBlock;
|
||||
use crate::types::DiarySexp;
|
||||
use crate::types::Document;
|
||||
use crate::types::Drawer;
|
||||
use crate::types::DynamicBlock;
|
||||
use crate::types::Element;
|
||||
use crate::types::Entity;
|
||||
use crate::types::ExampleBlock;
|
||||
use crate::types::ExportBlock;
|
||||
use crate::types::ExportSnippet;
|
||||
use crate::types::FixedWidthArea;
|
||||
use crate::types::FootnoteDefinition;
|
||||
use crate::types::FootnoteReference;
|
||||
use crate::types::GreaterBlock;
|
||||
use crate::types::Heading;
|
||||
use crate::types::HorizontalRule;
|
||||
use crate::types::InlineBabelCall;
|
||||
use crate::types::InlineSourceBlock;
|
||||
use crate::types::Italic;
|
||||
use crate::types::Keyword;
|
||||
use crate::types::LatexEnvironment;
|
||||
use crate::types::LatexFragment;
|
||||
use crate::types::LineBreak;
|
||||
use crate::types::NodeProperty;
|
||||
use crate::types::Object;
|
||||
use crate::types::OrgMacro;
|
||||
use crate::types::Paragraph;
|
||||
use crate::types::PlainLink;
|
||||
use crate::types::PlainList;
|
||||
use crate::types::PlainListItem;
|
||||
use crate::types::PlainText;
|
||||
use crate::types::Planning;
|
||||
use crate::types::PropertyDrawer;
|
||||
use crate::types::RadioLink;
|
||||
use crate::types::RadioTarget;
|
||||
use crate::types::RegularLink;
|
||||
use crate::types::Section;
|
||||
use crate::types::SrcBlock;
|
||||
use crate::types::StatisticsCookie;
|
||||
use crate::types::StrikeThrough;
|
||||
use crate::types::Subscript;
|
||||
use crate::types::Superscript;
|
||||
use crate::types::Table;
|
||||
use crate::types::TableCell;
|
||||
use crate::types::TableRow;
|
||||
use crate::types::Target;
|
||||
use crate::types::Timestamp;
|
||||
use crate::types::Underline;
|
||||
use crate::types::Verbatim;
|
||||
use crate::types::VerseBlock;
|
||||
|
||||
pub(crate) trait ElispFact<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str>;
|
||||
}
|
||||
|
||||
pub(crate) trait GetElispFact<'s> {
|
||||
fn get_elisp_fact(&'s self) -> &'s dyn ElispFact<'s>;
|
||||
}
|
||||
|
||||
impl<'s, I: ElispFact<'s>> GetElispFact<'s> for I {
|
||||
fn get_elisp_fact(&'s self) -> &'s dyn ElispFact<'s> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> GetElispFact<'s> for Element<'s> {
|
||||
fn get_elisp_fact(&'s self) -> &'s dyn ElispFact<'s> {
|
||||
match self {
|
||||
Element::Paragraph(inner) => inner,
|
||||
Element::PlainList(inner) => inner,
|
||||
Element::GreaterBlock(inner) => inner,
|
||||
Element::DynamicBlock(inner) => inner,
|
||||
Element::FootnoteDefinition(inner) => inner,
|
||||
Element::Comment(inner) => inner,
|
||||
Element::Drawer(inner) => inner,
|
||||
Element::PropertyDrawer(inner) => inner,
|
||||
Element::Table(inner) => inner,
|
||||
Element::VerseBlock(inner) => inner,
|
||||
Element::CommentBlock(inner) => inner,
|
||||
Element::ExampleBlock(inner) => inner,
|
||||
Element::ExportBlock(inner) => inner,
|
||||
Element::SrcBlock(inner) => inner,
|
||||
Element::Clock(inner) => inner,
|
||||
Element::DiarySexp(inner) => inner,
|
||||
Element::Planning(inner) => inner,
|
||||
Element::FixedWidthArea(inner) => inner,
|
||||
Element::HorizontalRule(inner) => inner,
|
||||
Element::Keyword(inner) => inner,
|
||||
Element::BabelCall(inner) => inner,
|
||||
Element::LatexEnvironment(inner) => inner,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> GetElispFact<'s> for Object<'s> {
|
||||
fn get_elisp_fact(&'s self) -> &'s dyn ElispFact<'s> {
|
||||
match self {
|
||||
Object::Bold(inner) => inner,
|
||||
Object::Italic(inner) => inner,
|
||||
Object::Underline(inner) => inner,
|
||||
Object::StrikeThrough(inner) => inner,
|
||||
Object::Code(inner) => inner,
|
||||
Object::Verbatim(inner) => inner,
|
||||
Object::PlainText(inner) => inner,
|
||||
Object::RegularLink(inner) => inner,
|
||||
Object::RadioLink(inner) => inner,
|
||||
Object::RadioTarget(inner) => inner,
|
||||
Object::PlainLink(inner) => inner,
|
||||
Object::AngleLink(inner) => inner,
|
||||
Object::OrgMacro(inner) => inner,
|
||||
Object::Entity(inner) => inner,
|
||||
Object::LatexFragment(inner) => inner,
|
||||
Object::ExportSnippet(inner) => inner,
|
||||
Object::FootnoteReference(inner) => inner,
|
||||
Object::Citation(inner) => inner,
|
||||
Object::CitationReference(inner) => inner,
|
||||
Object::InlineBabelCall(inner) => inner,
|
||||
Object::InlineSourceBlock(inner) => inner,
|
||||
Object::LineBreak(inner) => inner,
|
||||
Object::Target(inner) => inner,
|
||||
Object::StatisticsCookie(inner) => inner,
|
||||
Object::Subscript(inner) => inner,
|
||||
Object::Superscript(inner) => inner,
|
||||
Object::Timestamp(inner) => inner,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for Document<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"org-data".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for Section<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"section".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for Heading<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"headline".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for PlainList<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"plain-list".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for PlainListItem<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"item".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for GreaterBlock<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
match self.name.to_lowercase().as_str() {
|
||||
"center" => "center-block".into(),
|
||||
"quote" => "quote-block".into(),
|
||||
_ => "special-block".into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for DynamicBlock<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"dynamic-block".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for FootnoteDefinition<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"footnote-definition".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for Drawer<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"drawer".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for PropertyDrawer<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"property-drawer".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for NodeProperty<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"node-property".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for Table<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"table".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for TableRow<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"table-row".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for Paragraph<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"paragraph".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for TableCell<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"table-cell".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for Comment<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"comment".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for VerseBlock<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"verse-block".into()
|
||||
}
|
||||
}
|
||||
impl<'s> ElispFact<'s> for CommentBlock<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"comment-block".into()
|
||||
}
|
||||
}
|
||||
impl<'s> ElispFact<'s> for ExampleBlock<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"example-block".into()
|
||||
}
|
||||
}
|
||||
impl<'s> ElispFact<'s> for ExportBlock<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"export-block".into()
|
||||
}
|
||||
}
|
||||
impl<'s> ElispFact<'s> for SrcBlock<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"src-block".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for Clock<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"clock".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for DiarySexp<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"diary-sexp".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for Planning<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"planning".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for FixedWidthArea<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"fixed-width".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for HorizontalRule<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"horizontal-rule".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for Keyword<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"keyword".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for BabelCall<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"babel-call".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for LatexEnvironment<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"latex-environment".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for Bold<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"bold".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for Italic<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"italic".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for Underline<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"underline".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for StrikeThrough<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"strike-through".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for Code<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"code".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for Verbatim<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"verbatim".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for RegularLink<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"link".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for RadioLink<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"link".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for RadioTarget<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"radio-target".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for PlainLink<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"link".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for AngleLink<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"link".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for OrgMacro<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"macro".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for Entity<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"entity".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for LatexFragment<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"latex-fragment".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for ExportSnippet<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"export-snippet".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for FootnoteReference<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"footnote-reference".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for Citation<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"citation".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for CitationReference<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"citation-reference".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for InlineBabelCall<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"inline-babel-call".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for InlineSourceBlock<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"inline-src-block".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for LineBreak<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"line-break".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for Target<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"target".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for StatisticsCookie<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"statistics-cookie".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for Subscript<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"subscript".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for Superscript<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"superscript".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for Timestamp<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
"timestamp".into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> ElispFact<'s> for PlainText<'s> {
|
||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
||||
// plain text from upstream emacs does not actually have a name but this is included here to make rendering the status diff easier.
|
||||
"plain-text".into()
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
mod compare;
|
||||
mod diff;
|
||||
mod elisp_fact;
|
||||
mod parse;
|
||||
mod sexp;
|
||||
mod util;
|
||||
|
@ -1,4 +1,6 @@
|
||||
use super::elisp_fact::GetElispFact;
|
||||
use super::sexp::Token;
|
||||
use crate::types::GetStandardProperties;
|
||||
use crate::types::StandardProperties;
|
||||
|
||||
/// Check if the child string slice is a slice of the parent string slice.
|
||||
@ -24,10 +26,24 @@ fn get_rust_byte_offsets<'s, S: StandardProperties<'s> + ?Sized>(
|
||||
(offset, end)
|
||||
}
|
||||
|
||||
pub(crate) fn assert_name<'s>(
|
||||
pub(crate) fn compare_standard_properties<
|
||||
's,
|
||||
S: GetStandardProperties<'s> + GetElispFact<'s> + ?Sized,
|
||||
>(
|
||||
original_document: &'s str,
|
||||
emacs: &'s Token<'s>,
|
||||
name: &str,
|
||||
rust: &'s S,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
assert_name(emacs, rust.get_elisp_fact().get_elisp_name())?;
|
||||
assert_bounds(original_document, emacs, rust.get_standard_properties())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn assert_name<'s, S: AsRef<str>>(
|
||||
emacs: &'s Token<'s>,
|
||||
name: S,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let name = name.as_ref();
|
||||
let children = emacs.as_list()?;
|
||||
let first_child = children
|
||||
.first()
|
||||
@ -35,7 +51,7 @@ pub(crate) fn assert_name<'s>(
|
||||
.as_atom()?;
|
||||
if first_child != name {
|
||||
Err(format!(
|
||||
"Expected a {expected} cell, but found a {found} cell.",
|
||||
"AST node name mismatch. Expected a (rust) {expected} cell, but found a (emacs) {found} cell.",
|
||||
expected = name,
|
||||
found = first_child
|
||||
))?;
|
||||
|
@ -24,6 +24,7 @@ use crate::error::CustomError;
|
||||
use crate::error::MyError;
|
||||
use crate::error::Res;
|
||||
use crate::parser::util::start_of_line;
|
||||
use crate::types::BabelCall;
|
||||
use crate::types::Keyword;
|
||||
|
||||
const ORG_ELEMENT_AFFILIATED_KEYWORDS: [&'static str; 13] = [
|
||||
@ -103,8 +104,16 @@ pub(crate) fn affiliated_keyword<'b, 'g, 'r, 's>(
|
||||
pub(crate) fn babel_call_keyword<'b, 'g, 'r, 's>(
|
||||
_context: RefContext<'b, 'g, 'r, 's>,
|
||||
input: OrgSource<'s>,
|
||||
) -> Res<OrgSource<'s>, Keyword<'s>> {
|
||||
filtered_keyword(babel_call_key)(input)
|
||||
) -> Res<OrgSource<'s>, BabelCall<'s>> {
|
||||
let (remaining, kw) = filtered_keyword(babel_call_key)(input)?;
|
||||
Ok((
|
||||
remaining,
|
||||
BabelCall {
|
||||
source: kw.source,
|
||||
key: kw.key,
|
||||
value: kw.value,
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||
|
@ -4,6 +4,7 @@ use super::greater_element::GreaterBlock;
|
||||
use super::greater_element::PlainList;
|
||||
use super::greater_element::PropertyDrawer;
|
||||
use super::greater_element::Table;
|
||||
use super::lesser_element::BabelCall;
|
||||
use super::lesser_element::Clock;
|
||||
use super::lesser_element::Comment;
|
||||
use super::lesser_element::CommentBlock;
|
||||
@ -45,7 +46,7 @@ pub enum Element<'s> {
|
||||
FixedWidthArea(FixedWidthArea<'s>),
|
||||
HorizontalRule(HorizontalRule<'s>),
|
||||
Keyword(Keyword<'s>),
|
||||
BabelCall(Keyword<'s>),
|
||||
BabelCall(BabelCall<'s>),
|
||||
LatexEnvironment(LatexEnvironment<'s>),
|
||||
}
|
||||
|
||||
|
@ -2,9 +2,7 @@ use super::StandardProperties;
|
||||
|
||||
pub trait GetStandardProperties<'s> {
|
||||
// TODO: Can I eliminate this dynamic dispatch, perhaps using nominal generic structs? Low prioritiy since this is not used during parsing.
|
||||
fn get_standard_properties(&'s self) -> &'s dyn StandardProperties
|
||||
where
|
||||
Self: Sized;
|
||||
fn get_standard_properties(&'s self) -> &'s dyn StandardProperties;
|
||||
}
|
||||
|
||||
impl<'s, I: StandardProperties<'s>> GetStandardProperties<'s> for I {
|
||||
|
@ -91,6 +91,13 @@ pub struct Keyword<'s> {
|
||||
pub value: &'s str,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct BabelCall<'s> {
|
||||
pub source: &'s str,
|
||||
pub key: &'s str,
|
||||
pub value: &'s str,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct LatexEnvironment<'s> {
|
||||
pub source: &'s str,
|
||||
@ -187,6 +194,12 @@ impl<'s> StandardProperties<'s> for Keyword<'s> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> StandardProperties<'s> for BabelCall<'s> {
|
||||
fn get_source(&'s self) -> &'s str {
|
||||
self.source
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> StandardProperties<'s> for LatexEnvironment<'s> {
|
||||
fn get_source(&'s self) -> &'s str {
|
||||
self.source
|
||||
|
@ -27,6 +27,7 @@ pub use greater_element::PlainListItem;
|
||||
pub use greater_element::PropertyDrawer;
|
||||
pub use greater_element::Table;
|
||||
pub use greater_element::TableRow;
|
||||
pub use lesser_element::BabelCall;
|
||||
pub use lesser_element::Clock;
|
||||
pub use lesser_element::Comment;
|
||||
pub use lesser_element::CommentBlock;
|
||||
|
Loading…
x
Reference in New Issue
Block a user