diff --git a/build.rs b/build.rs index 0dba36e..c8b3c1d 100644 --- a/build.rs +++ b/build.rs @@ -75,9 +75,6 @@ fn is_expect_fail(name: &str) -> Option<&str> { "autogen_greater_element_drawer_drawer_with_headline_inside" => Some("Apparently lines with :end: become their own paragraph. This odd behavior needs to be investigated more."), "autogen_element_container_priority_footnote_definition_dynamic_block" => Some("Apparently broken begin lines become their own paragraph."), "autogen_lesser_element_paragraphs_paragraph_with_backslash_line_breaks" => Some("The text we're getting out of the parse tree is already processed to remove line breaks, so our comparison needs to take that into account."), - "autogen_greater_element_plain_list_trailing_whitespace_ownership_test_case_1" => Some("Seeing odd behavior about whitespace ownership."), // https://list.orgmode.org/9372527e-3852-419e-936a-7b4dd38cc847@app.fastmail.com/ - "autogen_greater_element_plain_list_trailing_whitespace_ownership_test_case_3" => Some("Seeing odd behavior about whitespace ownership."), // https://list.orgmode.org/9372527e-3852-419e-936a-7b4dd38cc847@app.fastmail.com/ - "autogen_greater_element_plain_list_trailing_whitespace_ownership_test_case_4" => Some("Seeing odd behavior about whitespace ownership."), // https://list.orgmode.org/9372527e-3852-419e-936a-7b4dd38cc847@app.fastmail.com/ _ => None, } } diff --git a/docker/organic_test/Dockerfile b/docker/organic_test/Dockerfile index 5de7e80..7027865 100644 --- a/docker/organic_test/Dockerfile +++ b/docker/organic_test/Dockerfile @@ -14,7 +14,7 @@ RUN make DESTDIR="/root/dist" install FROM build AS build-org-mode -ARG ORG_VERSION=299193bf091a63474fc8036bd31de51800a2555a +ARG ORG_VERSION=7bdec435ff5d86220d13c431e799c5ed44a57da1 COPY --from=build-emacs /root/dist/ / RUN mkdir /root/dist # Savannah does not allow fetching specific revisions, so we're going to have to put unnecessary load on their server by cloning main and then checking out the revision we want. diff --git a/src/compare/util.rs b/src/compare/util.rs index a3441d4..1e0cd85 100644 --- a/src/compare/util.rs +++ b/src/compare/util.rs @@ -42,6 +42,39 @@ pub fn assert_bounds<'s, S: Source<'s>>( emacs: &'s Token<'s>, rust: &'s S, ) -> Result<(), Box> { + let standard_properties = get_standard_properties(emacs)?; + let (begin, end) = ( + standard_properties + .begin + .ok_or("Token should have a begin.")?, + standard_properties + .end + .ok_or("Token should have a begin.")?, + ); + let (rust_begin, rust_end) = get_offsets(source, rust); + if (rust_begin + 1) != begin || (rust_end + 1) != end { + Err(format!("Rust bounds ({rust_begin}, {rust_end}) do not match emacs bounds ({emacs_begin}, {emacs_end})", rust_begin = rust_begin + 1, rust_end = rust_end + 1, emacs_begin=begin, emacs_end=end))?; + } + + Ok(()) +} + +struct StandardProperties { + begin: Option, + #[allow(dead_code)] + post_affiliated: Option, + #[allow(dead_code)] + contents_begin: Option, + #[allow(dead_code)] + contents_end: Option, + end: Option, + #[allow(dead_code)] + post_blank: Option, +} + +fn get_standard_properties<'s>( + emacs: &'s Token<'s>, +) -> Result> { let children = emacs.as_list()?; let attributes_child = children .iter() @@ -49,34 +82,60 @@ pub fn assert_bounds<'s, S: Source<'s>>( .ok_or("Should have an attributes child.")?; let attributes_map = attributes_child.as_map()?; let standard_properties = attributes_map.get(":standard-properties"); - let (begin, end) = if standard_properties.is_some() { - let std_props = standard_properties + Ok(if standard_properties.is_some() { + let mut std_props = standard_properties .expect("if statement proves its Some") - .as_vector()?; - let begin = std_props - .get(0) - .ok_or("Missing first element in standard properties")? - .as_atom()?; - let end = std_props - .get(1) - .ok_or("Missing first element in standard properties")? - .as_atom()?; - (begin, end) + .as_vector()? + .into_iter(); + let begin = maybe_token_to_usize(std_props.next())?; + let post_affiliated = maybe_token_to_usize(std_props.next())?; + let contents_begin = maybe_token_to_usize(std_props.next())?; + let contents_end = maybe_token_to_usize(std_props.next())?; + let end = maybe_token_to_usize(std_props.next())?; + let post_blank = maybe_token_to_usize(std_props.next())?; + StandardProperties { + begin, + post_affiliated, + contents_begin, + contents_end, + end, + post_blank, + } } else { - let begin = attributes_map - .get(":begin") - .ok_or("Missing :begin attribute.")? - .as_atom()?; - let end = attributes_map - .get(":end") - .ok_or("Missing :end attribute.")? - .as_atom()?; - (begin, end) - }; - let (rust_begin, rust_end) = get_offsets(source, rust); - if (rust_begin + 1).to_string() != begin || (rust_end + 1).to_string() != end { - Err(format!("Rust bounds ({rust_begin}, {rust_end}) do not match emacs bounds ({emacs_begin}, {emacs_end})", rust_begin = rust_begin + 1, rust_end = rust_end + 1, emacs_begin=begin, emacs_end=end))?; - } - - Ok(()) + let begin = maybe_token_to_usize(attributes_map.get(":begin").map(|token| *token))?; + let end = maybe_token_to_usize(attributes_map.get(":end").map(|token| *token))?; + let contents_begin = + maybe_token_to_usize(attributes_map.get(":contents-begin").map(|token| *token))?; + let contents_end = + maybe_token_to_usize(attributes_map.get(":contents-end").map(|token| *token))?; + let post_blank = + maybe_token_to_usize(attributes_map.get(":post-blank").map(|token| *token))?; + let post_affiliated = + maybe_token_to_usize(attributes_map.get(":post-affiliated").map(|token| *token))?; + StandardProperties { + begin, + post_affiliated, + contents_begin, + contents_end, + end, + post_blank, + } + }) +} + +fn maybe_token_to_usize( + token: Option<&Token<'_>>, +) -> Result, Box> { + Ok(token + .map(|token| token.as_atom()) + .map_or(Ok(None), |r| r.map(Some))? + .map(|val| { + if val == "nil" { + None + } else { + Some(val.parse::()) + } + }) + .flatten() // Outer option is whether or not the param exists, inner option is whether or not it is nil + .map_or(Ok(None), |r| r.map(Some))?) }