Merge branch 'footnote_reference_properties'

This commit is contained in:
Tom Alexander 2023-10-09 15:33:13 -04:00
commit ced35e1694
Signed by: talexander
GPG Key ID: D3A179C9A53C0EDE
7 changed files with 154 additions and 51 deletions

View File

@ -54,6 +54,7 @@ use crate::types::ExportSnippet;
use crate::types::FixedWidthArea; use crate::types::FixedWidthArea;
use crate::types::FootnoteDefinition; use crate::types::FootnoteDefinition;
use crate::types::FootnoteReference; use crate::types::FootnoteReference;
use crate::types::FootnoteReferenceType;
use crate::types::GetStandardProperties; use crate::types::GetStandardProperties;
use crate::types::Heading; use crate::types::Heading;
use crate::types::HorizontalRule; use crate::types::HorizontalRule;
@ -2584,20 +2585,24 @@ fn compare_bold<'b, 's>(
emacs: &'b Token<'s>, emacs: &'b Token<'s>,
rust: &'b Bold<'s>, rust: &'b Bold<'s>,
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> { ) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
let children = emacs.as_list()?;
let mut this_status = DiffStatus::Good; let mut this_status = DiffStatus::Good;
let mut child_status = Vec::new(); let mut child_status = Vec::new();
let mut message = None; let mut message = None;
compare_children(
source,
emacs,
&rust.children,
&mut child_status,
&mut this_status,
&mut message,
)?;
if let Some((new_status, new_message)) = compare_properties!(emacs)? { if let Some((new_status, new_message)) = compare_properties!(emacs)? {
this_status = new_status; this_status = new_status;
message = new_message; message = new_message;
} }
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())?);
}
Ok(DiffResult { Ok(DiffResult {
status: this_status, status: this_status,
name: rust.get_elisp_name(), name: rust.get_elisp_name(),
@ -2614,20 +2619,24 @@ fn compare_italic<'b, 's>(
emacs: &'b Token<'s>, emacs: &'b Token<'s>,
rust: &'b Italic<'s>, rust: &'b Italic<'s>,
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> { ) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
let children = emacs.as_list()?;
let mut this_status = DiffStatus::Good; let mut this_status = DiffStatus::Good;
let mut child_status = Vec::new(); let mut child_status = Vec::new();
let mut message = None; let mut message = None;
compare_children(
source,
emacs,
&rust.children,
&mut child_status,
&mut this_status,
&mut message,
)?;
if let Some((new_status, new_message)) = compare_properties!(emacs)? { if let Some((new_status, new_message)) = compare_properties!(emacs)? {
this_status = new_status; this_status = new_status;
message = new_message; message = new_message;
} }
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())?);
}
Ok(DiffResult { Ok(DiffResult {
status: this_status, status: this_status,
name: rust.get_elisp_name(), name: rust.get_elisp_name(),
@ -2644,20 +2653,24 @@ fn compare_underline<'b, 's>(
emacs: &'b Token<'s>, emacs: &'b Token<'s>,
rust: &'b Underline<'s>, rust: &'b Underline<'s>,
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> { ) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
let children = emacs.as_list()?;
let mut this_status = DiffStatus::Good; let mut this_status = DiffStatus::Good;
let mut child_status = Vec::new(); let mut child_status = Vec::new();
let mut message = None; let mut message = None;
compare_children(
source,
emacs,
&rust.children,
&mut child_status,
&mut this_status,
&mut message,
)?;
if let Some((new_status, new_message)) = compare_properties!(emacs)? { if let Some((new_status, new_message)) = compare_properties!(emacs)? {
this_status = new_status; this_status = new_status;
message = new_message; message = new_message;
} }
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())?);
}
Ok(DiffResult { Ok(DiffResult {
status: this_status, status: this_status,
name: rust.get_elisp_name(), name: rust.get_elisp_name(),
@ -2677,6 +2690,8 @@ fn compare_verbatim<'b, 's>(
let mut this_status = DiffStatus::Good; let mut this_status = DiffStatus::Good;
let mut message = None; let mut message = None;
assert_no_children(emacs, &mut this_status, &mut message)?;
if let Some((new_status, new_message)) = compare_properties!( if let Some((new_status, new_message)) = compare_properties!(
emacs, emacs,
rust, rust,
@ -2709,6 +2724,8 @@ fn compare_code<'b, 's>(
let mut this_status = DiffStatus::Good; let mut this_status = DiffStatus::Good;
let mut message = None; let mut message = None;
assert_no_children(emacs, &mut this_status, &mut message)?;
if let Some((new_status, new_message)) = compare_properties!( if let Some((new_status, new_message)) = compare_properties!(
emacs, emacs,
rust, rust,
@ -2738,20 +2755,24 @@ fn compare_strike_through<'b, 's>(
emacs: &'b Token<'s>, emacs: &'b Token<'s>,
rust: &'b StrikeThrough<'s>, rust: &'b StrikeThrough<'s>,
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> { ) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
let children = emacs.as_list()?;
let mut this_status = DiffStatus::Good; let mut this_status = DiffStatus::Good;
let mut child_status = Vec::new(); let mut child_status = Vec::new();
let mut message = None; let mut message = None;
compare_children(
source,
emacs,
&rust.children,
&mut child_status,
&mut this_status,
&mut message,
)?;
if let Some((new_status, new_message)) = compare_properties!(emacs)? { if let Some((new_status, new_message)) = compare_properties!(emacs)? {
this_status = new_status; this_status = new_status;
message = new_message; message = new_message;
} }
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())?);
}
Ok(DiffResult { Ok(DiffResult {
status: this_status, status: this_status,
name: rust.get_elisp_name(), name: rust.get_elisp_name(),
@ -2768,11 +2789,19 @@ fn compare_regular_link<'b, 's>(
emacs: &'b Token<'s>, emacs: &'b Token<'s>,
rust: &'b RegularLink<'s>, rust: &'b RegularLink<'s>,
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> { ) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
let children = emacs.as_list()?;
let mut this_status = DiffStatus::Good; let mut this_status = DiffStatus::Good;
let mut child_status = Vec::new(); let mut child_status = Vec::new();
let mut message = None; let mut message = None;
compare_children(
source,
emacs,
&rust.children,
&mut child_status,
&mut this_status,
&mut message,
)?;
if let Some((new_status, new_message)) = compare_properties!( if let Some((new_status, new_message)) = compare_properties!(
emacs, emacs,
rust, rust,
@ -2820,10 +2849,6 @@ fn compare_regular_link<'b, 's>(
message = new_message; message = new_message;
} }
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())?);
}
Ok(DiffResult { Ok(DiffResult {
status: this_status, status: this_status,
name: rust.get_elisp_name(), name: rust.get_elisp_name(),
@ -2840,11 +2865,19 @@ fn compare_radio_link<'b, 's>(
emacs: &'b Token<'s>, emacs: &'b Token<'s>,
rust: &'b RadioLink<'s>, rust: &'b RadioLink<'s>,
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> { ) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
let children = emacs.as_list()?;
let mut this_status = DiffStatus::Good; let mut this_status = DiffStatus::Good;
let mut child_status = Vec::new(); let mut child_status = Vec::new();
let mut message = None; let mut message = None;
compare_children(
source,
emacs,
&rust.children,
&mut child_status,
&mut this_status,
&mut message,
)?;
if let Some((new_status, new_message)) = compare_properties!( if let Some((new_status, new_message)) = compare_properties!(
emacs, emacs,
rust, rust,
@ -2883,10 +2916,6 @@ fn compare_radio_link<'b, 's>(
message = new_message; message = new_message;
} }
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())?);
}
Ok(DiffResult { Ok(DiffResult {
status: this_status, status: this_status,
name: rust.get_elisp_name(), name: rust.get_elisp_name(),
@ -2903,7 +2932,6 @@ fn compare_radio_target<'b, 's>(
emacs: &'b Token<'s>, emacs: &'b Token<'s>,
rust: &'b RadioTarget<'s>, rust: &'b RadioTarget<'s>,
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> { ) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
let children = emacs.as_list()?;
let mut this_status = DiffStatus::Good; let mut this_status = DiffStatus::Good;
let mut child_status = Vec::new(); let mut child_status = Vec::new();
let mut message = None; let mut message = None;
@ -2930,10 +2958,6 @@ fn compare_radio_target<'b, 's>(
message = new_message; message = new_message;
} }
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())?);
}
Ok(DiffResult { Ok(DiffResult {
status: this_status, status: this_status,
name: rust.get_elisp_name(), name: rust.get_elisp_name(),
@ -2953,6 +2977,8 @@ fn compare_plain_link<'b, 's>(
let mut this_status = DiffStatus::Good; let mut this_status = DiffStatus::Good;
let mut message = None; let mut message = None;
assert_no_children(emacs, &mut this_status, &mut message)?;
if let Some((new_status, new_message)) = compare_properties!( if let Some((new_status, new_message)) = compare_properties!(
emacs, emacs,
rust, rust,
@ -3019,6 +3045,8 @@ fn compare_angle_link<'b, 's>(
let mut this_status = DiffStatus::Good; let mut this_status = DiffStatus::Good;
let mut message = None; let mut message = None;
assert_no_children(emacs, &mut this_status, &mut message)?;
if let Some((new_status, new_message)) = compare_properties!( if let Some((new_status, new_message)) = compare_properties!(
emacs, emacs,
rust, rust,
@ -3085,6 +3113,8 @@ fn compare_org_macro<'b, 's>(
let mut this_status = DiffStatus::Good; let mut this_status = DiffStatus::Good;
let mut message = None; let mut message = None;
assert_no_children(emacs, &mut this_status, &mut message)?;
if let Some((new_status, new_message)) = compare_properties!( if let Some((new_status, new_message)) = compare_properties!(
emacs, emacs,
rust, rust,
@ -3131,6 +3161,8 @@ fn compare_entity<'b, 's>(
let mut this_status = DiffStatus::Good; let mut this_status = DiffStatus::Good;
let mut message = None; let mut message = None;
assert_no_children(emacs, &mut this_status, &mut message)?;
if let Some((new_status, new_message)) = compare_properties!( if let Some((new_status, new_message)) = compare_properties!(
emacs, emacs,
rust, rust,
@ -3199,6 +3231,8 @@ fn compare_latex_fragment<'b, 's>(
let mut this_status = DiffStatus::Good; let mut this_status = DiffStatus::Good;
let mut message = None; let mut message = None;
assert_no_children(emacs, &mut this_status, &mut message)?;
if let Some((new_status, new_message)) = compare_properties!( if let Some((new_status, new_message)) = compare_properties!(
emacs, emacs,
rust, rust,
@ -3263,20 +3297,49 @@ fn compare_export_snippet<'b, 's>(
} }
fn compare_footnote_reference<'b, 's>( fn compare_footnote_reference<'b, 's>(
_source: &'s str, source: &'s str,
emacs: &'b Token<'s>, emacs: &'b Token<'s>,
rust: &'b FootnoteReference<'s>, rust: &'b FootnoteReference<'s>,
) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> { ) -> Result<DiffEntry<'b, 's>, Box<dyn std::error::Error>> {
let this_status = DiffStatus::Good; let mut child_status = Vec::new();
let message = None; let mut this_status = DiffStatus::Good;
let mut message = None;
// TODO: Compare :label :type compare_children(
source,
emacs,
&rust.definition,
&mut child_status,
&mut this_status,
&mut message,
)?;
if let Some((new_status, new_message)) = compare_properties!(
emacs,
rust,
(
EmacsField::Required(":label"),
|r| r.label,
compare_property_quoted_string
),
(
EmacsField::Required(":type"),
|r| Some(match r.get_type() {
FootnoteReferenceType::Standard => "standard",
FootnoteReferenceType::Inline => "inline",
}),
compare_property_unquoted_atom
)
)? {
this_status = new_status;
message = new_message;
}
Ok(DiffResult { Ok(DiffResult {
status: this_status, status: this_status,
name: rust.get_elisp_name(), name: rust.get_elisp_name(),
message, message,
children: Vec::new(), children: child_status,
rust_source: rust.get_source(), rust_source: rust.get_source(),
emacs_token: emacs, emacs_token: emacs,
} }

View File

@ -33,6 +33,11 @@ pub(crate) enum ContextElement<'r, 's> {
/// The value stored is the start of the element after the affiliated keywords. In this way, we can ensure that we do not exit an element immediately after the affiliated keyword had been consumed. /// The value stored is the start of the element after the affiliated keywords. In this way, we can ensure that we do not exit an element immediately after the affiliated keyword had been consumed.
HasAffiliatedKeyword(HasAffiliatedKeywordInner<'r, 's>), HasAffiliatedKeyword(HasAffiliatedKeywordInner<'r, 's>),
/// Indicate the position that we started parsing a text section.
///
/// This value is stored because "<<<" is not a valid prefix for text markup UNLESS it is starting a radio target. Likewise "[" is not a valid prefix for text markup UNLESS it is the start of a regular link description.
StartTextSection(OrgSource<'s>),
/// This is just here to use the 's lifetime until I'm sure we can eliminate it from ContextElement. /// This is just here to use the 's lifetime until I'm sure we can eliminate it from ContextElement.
#[allow(dead_code)] #[allow(dead_code)]
Placeholder(PhantomData<&'s str>), Placeholder(PhantomData<&'s str>),

View File

@ -103,11 +103,15 @@ pub(crate) fn radio_target<'b, 'g, 'r, 's>(
input: OrgSource<'s>, input: OrgSource<'s>,
) -> Res<OrgSource<'s>, RadioTarget<'s>> { ) -> Res<OrgSource<'s>, RadioTarget<'s>> {
let (remaining, _opening) = tag("<<<")(input)?; let (remaining, _opening) = tag("<<<")(input)?;
let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode { let contexts = [
ContextElement::ExitMatcherNode(ExitMatcherNode {
class: ExitClass::Gamma, class: ExitClass::Gamma,
exit_matcher: &radio_target_end, exit_matcher: &radio_target_end,
}); }),
let parser_context = context.with_additional_node(&parser_context); ContextElement::StartTextSection(remaining),
];
let parser_context = context.with_additional_node(&contexts[0]);
let parser_context = parser_context.with_additional_node(&contexts[1]);
let (remaining, (raw_value, children)) = consumed(verify( let (remaining, (raw_value, children)) = consumed(verify(
map( map(

View File

@ -397,11 +397,15 @@ fn description<'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>, Vec<Object<'s>>> { ) -> Res<OrgSource<'s>, Vec<Object<'s>>> {
let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode { let contexts = [
ContextElement::ExitMatcherNode(ExitMatcherNode {
class: ExitClass::Beta, class: ExitClass::Beta,
exit_matcher: &description_end, exit_matcher: &description_end,
}); }),
let parser_context = context.with_additional_node(&parser_context); ContextElement::StartTextSection(input),
];
let parser_context = context.with_additional_node(&contexts[0]);
let parser_context = parser_context.with_additional_node(&contexts[1]);
let (remaining, (children, _exit_contents)) = verify( let (remaining, (children, _exit_contents)) = verify(
many_till( many_till(
parser_with_context!(regular_link_description_set_object)(&parser_context), parser_with_context!(regular_link_description_set_object)(&parser_context),

View File

@ -283,7 +283,7 @@ fn _text_markup_string<'b, 'g, 'r, 's, 'c>(
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn pre<'b, 'g, 'r, 's>( fn pre<'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>, ()> { ) -> Res<OrgSource<'s>, ()> {
if start_of_line(input).is_ok() { if start_of_line(input).is_ok() {
@ -292,6 +292,16 @@ fn pre<'b, 'g, 'r, 's>(
if preceded_by_whitespace(true)(input).is_ok() { if preceded_by_whitespace(true)(input).is_ok() {
return Ok((input, ())); return Ok((input, ()));
} }
let radio_target_start = context
.iter()
.find_map(|c| match c {
ContextElement::StartTextSection(text) => Some(text),
_ => None,
})
.map(|text| text.get_byte_offset());
if Some(input.get_byte_offset()) == radio_target_start {
return Ok((input, ()));
}
let preceding_character = input.get_preceding_character(); let preceding_character = input.get_preceding_character();
match preceding_character { match preceding_character {
// If None, we are at the start of the file which is technically the beginning of a line. // If None, we are at the start of the file which is technically the beginning of a line.

View File

@ -69,6 +69,7 @@ pub use object::DayOfMonthInner;
pub use object::Entity; pub use object::Entity;
pub use object::ExportSnippet; pub use object::ExportSnippet;
pub use object::FootnoteReference; pub use object::FootnoteReference;
pub use object::FootnoteReferenceType;
pub use object::Hour; pub use object::Hour;
pub use object::HourInner; pub use object::HourInner;
pub use object::InlineBabelCall; pub use object::InlineBabelCall;

View File

@ -764,3 +764,19 @@ impl<'s> OrgMacro<'s> {
.map(|arg| coalesce_whitespace_escaped('\\', |c| ",".contains(c))(*arg)) .map(|arg| coalesce_whitespace_escaped('\\', |c| ",".contains(c))(*arg))
} }
} }
#[derive(Debug, PartialEq)]
pub enum FootnoteReferenceType {
Standard,
Inline,
}
impl<'s> FootnoteReference<'s> {
pub fn get_type(&self) -> FootnoteReferenceType {
if self.definition.is_empty() {
FootnoteReferenceType::Standard
} else {
FootnoteReferenceType::Inline
}
}
}