Compare commits

..

No commits in common. "08e4c646e5b275022e9b3ea6060a1e7be2672f0a" and "d90ff5891bc044c9c39409ae5baad90953d195f2" have entirely different histories.

18 changed files with 34 additions and 221 deletions

View File

@ -40,10 +40,9 @@ RUN mkdir /foreign_documents
FROM tester as foreign-document-test
RUN apk add --no-cache bash coreutils
RUN apk add --no-cache bash
RUN mkdir /foreign_documents
COPY --from=build-org-mode /root/org-mode /foreign_documents/org-mode
COPY --from=build-emacs /root/emacs /foreign_documents/emacs
COPY --from=build-org-mode /root/org-mode/doc /foreign_documents/org-mode
COPY foreign_document_test_entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]

View File

@ -5,8 +5,6 @@ set -euo pipefail
IFS=$'\n\t'
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
REALPATH=$(command -v uu-realpath || command -v realpath)
function log {
(>&2 echo "${@}")
}
@ -25,57 +23,8 @@ function main {
fi
PARSE="${CARGO_TARGET_DIR}/release-lto/parse"
run_compare_function "org-mode" compare_all_org_document "/foreign_documents/org-mode"
run_compare_function "emacs" compare_all_org_document "/foreign_documents/emacs"
}
function green_text {
(IFS=' '; printf '\x1b[38;2;0;255;0m%s\x1b[0m' "${*}")
}
function red_text {
(IFS=' '; printf '\x1b[38;2;255;0;0m%s\x1b[0m' "${*}")
}
function yellow_text {
(IFS=' '; printf '\x1b[38;2;255;255;0m%s\x1b[0m' "${*}")
}
function indent {
local depth="$1"
local scaled_depth=$((depth * 2))
shift 1
local prefix=$(printf -- "%${scaled_depth}s")
while read l; do
(IFS=' '; printf -- '%s%s\n' "$prefix" "$l")
done
}
function run_compare_function {
local name="$1"
local stdoutput
shift 1
set +e
stdoutput=$("${@}")
local status=$?
set -e
if [ "$status" -eq 0 ]; then
echo "$(green_text "GOOD") $name"
indent 1 <<<"$stdoutput"
else
echo "$(red_text "FAIL") $name"
indent 1 <<<"$stdoutput"
return 1
fi
}
function compare_all_org_document {
local root_dir="$1"
local target_document
find "$root_dir" -type f -iname '*.org' | while read target_document; do
local relative_path=$($REALPATH --relative-to "$root_dir" "$target_document")
(run_compare "$relative_path" "$target_document")
done
run_compare "org-mode/org-guide.org" "/foreign_documents/org-mode/org-guide.org"
run_compare "org-mode/org-manual.org" "/foreign_documents/org-mode/org-manual.org"
}
function run_compare {
@ -93,4 +42,16 @@ function run_compare {
fi
}
function green_text {
(IFS=' '; printf '\x1b[38;2;0;255;0m%s\x1b[0m' "${*}")
}
function red_text {
(IFS=' '; printf '\x1b[38;2;255;0;0m%s\x1b[0m' "${*}")
}
function yellow_text {
(IFS=' '; printf '\x1b[38;2;255;255;0m%s\x1b[0m' "${*}")
}
main "${@}"

View File

@ -1,2 +0,0 @@
3. [@3] foo
4. bar

View File

@ -1,6 +0,0 @@
* Overwrite
:PROPERTIES:
:header-args: :var foo="lorem"
:header-args:emacs-lisp: :var bar="ipsum"
:header-args:emacs-lisp+: :results silent :var baz=7
:END:

View File

@ -1,7 +0,0 @@
# This test is to prove that the parser works with affiliated keywords that have both a shorter and longer version.
#+results:
#+result:
#+begin_latex
\foo
#+end_latex

View File

@ -1 +0,0 @@
#+call: foo(bar="baz")

View File

@ -1,2 +0,0 @@
#+begin_src
#+end_src

View File

@ -1,4 +0,0 @@
# There are trailing spaces after the begin and end src lines
#+begin_src
echo "this is a source block."
#+end_src

View File

@ -36,7 +36,6 @@ 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;
@ -307,7 +306,6 @@ fn compare_element<'s>(
Element::FixedWidthArea(obj) => compare_fixed_width_area(source, emacs, obj),
Element::HorizontalRule(obj) => compare_horizontal_rule(source, emacs, obj),
Element::Keyword(obj) => compare_keyword(source, emacs, obj),
Element::BabelCall(obj) => compare_babel_call(source, emacs, obj),
Element::LatexEnvironment(obj) => compare_latex_environment(source, emacs, obj),
};
match compare_result {
@ -735,8 +733,6 @@ fn compare_plain_list_item<'s>(
contents_status,
)?);
// TODO: compare :bullet :checkbox :counter :pre-blank
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
@ -937,7 +933,7 @@ fn compare_property_drawer<'s>(
rust: &'s PropertyDrawer<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
let children = emacs.as_list()?;
let mut child_status = Vec::new();
let child_status = Vec::new();
let mut this_status = DiffStatus::Good;
let mut message = None;
let emacs_name = "property-drawer";
@ -953,8 +949,9 @@ fn compare_property_drawer<'s>(
Ok(_) => {}
};
for (emacs_child, rust_child) in children.iter().skip(2).zip(rust.children.iter()) {
child_status.push(compare_node_property(source, emacs_child, rust_child)?);
for (_emacs_child, _rust_child) in children.iter().skip(2).zip(rust.children.iter()) {
// TODO: What are node properties and are they the only legal child of property drawers?
// child_status.push(compare_element(source, emacs_child, rust_child)?);
}
Ok(DiffResult {
@ -968,40 +965,6 @@ fn compare_property_drawer<'s>(
.into())
}
fn compare_node_property<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s NodeProperty<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
let child_status = Vec::new();
let mut this_status = DiffStatus::Good;
let mut message = None;
let emacs_name = "node-property";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
// TODO: Compare :key :value
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message,
children: child_status,
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
}
fn compare_table<'s>(
source: &'s str,
emacs: &'s Token<'s>,
@ -1259,8 +1222,6 @@ fn compare_src_block<'s>(
Ok(_) => {}
};
// TODO: Compare :language :switches :parameters :number-lines :preserve-indent :retain-labels :use-labels :label-fmt :value
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
@ -1486,52 +1447,6 @@ fn compare_keyword<'s>(
.into())
}
fn compare_babel_call<'s>(
source: &'s str,
emacs: &'s Token<'s>,
rust: &'s Keyword<'s>,
) -> Result<DiffEntry<'s>, Box<dyn std::error::Error>> {
let child_status = Vec::new();
let mut this_status = DiffStatus::Good;
let mut message = None;
let emacs_name = "babel-call";
if assert_name(emacs, emacs_name).is_err() {
this_status = DiffStatus::Bad;
}
match assert_bounds(source, emacs, rust) {
Err(err) => {
this_status = DiffStatus::Bad;
message = Some(err.to_string())
}
Ok(_) => {}
};
// TODO: compare :call :inside-header :arguments :end-header
let value = unquote(
get_property(emacs, ":value")?
.ok_or("Emacs keywords should have a :value")?
.as_atom()?,
)?;
if value != rust.value {
this_status = DiffStatus::Bad;
message = Some(format!(
"Mismatchs keyword values (emacs != rust) {:?} != {:?}",
value, rust.value
))
}
Ok(DiffResult {
status: this_status,
name: emacs_name.to_owned(),
message,
children: child_status,
rust_source: rust.get_source(),
emacs_token: emacs,
}
.into())
}
fn compare_latex_environment<'s>(
source: &'s str,
emacs: &'s Token<'s>,

View File

@ -12,7 +12,6 @@ use super::footnote_definition::footnote_definition;
use super::greater_block::greater_block;
use super::horizontal_rule::horizontal_rule;
use super::keyword::affiliated_keyword;
use super::keyword::babel_call_keyword;
use super::keyword::keyword;
use super::latex_environment::latex_environment;
use super::lesser_block::comment_block;
@ -68,7 +67,6 @@ fn _element<'b, 'g, 'r, 's>(
let horizontal_rule_matcher = parser_with_context!(horizontal_rule)(context);
let keyword_matcher = parser_with_context!(keyword)(context);
let affiliated_keyword_matcher = parser_with_context!(affiliated_keyword)(context);
let babel_keyword_matcher = parser_with_context!(babel_call_keyword)(context);
let paragraph_matcher = parser_with_context!(paragraph)(context);
let latex_environment_matcher = parser_with_context!(latex_environment)(context);
@ -92,7 +90,6 @@ fn _element<'b, 'g, 'r, 's>(
map(fixed_width_area_matcher, Element::FixedWidthArea),
map(horizontal_rule_matcher, Element::HorizontalRule),
map(latex_environment_matcher, Element::LatexEnvironment),
map(babel_keyword_matcher, Element::BabelCall),
map(keyword_matcher, Element::Keyword),
))(remaining)
{

View File

@ -26,8 +26,8 @@ use crate::parser::util::start_of_line;
use crate::types::Keyword;
const ORG_ELEMENT_AFFILIATED_KEYWORDS: [&'static str; 13] = [
"caption", "data", "headers", "header", "label", "name", "plot", "resname", "results",
"result", "source", "srcname", "tblname",
"caption", "data", "header", "headers", "label", "name", "plot", "resname", "result",
"results", "source", "srcname", "tblname",
];
const ORG_ELEMENT_DUAL_KEYWORDS: [&'static str; 2] = ["caption", "results"];
@ -98,19 +98,6 @@ pub fn affiliated_keyword<'b, 'g, 'r, 's>(
filtered_keyword(affiliated_key)(input)
}
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
pub 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)
}
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn babel_call_key<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
tag_no_case("call")(input)
}
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn regular_keyword_key<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
recognize(tuple((

View File

@ -7,7 +7,6 @@ use nom::character::complete::space1;
use nom::combinator::consumed;
use nom::combinator::eof;
use nom::combinator::opt;
use nom::combinator::recognize;
use nom::combinator::verify;
use nom::multi::many_till;
use nom::sequence::tuple;
@ -41,7 +40,7 @@ pub fn verse_block<'b, 'g, 'r, 's>(
) -> Res<OrgSource<'s>, VerseBlock<'s>> {
let (remaining, name) = lesser_block_begin("verse")(context, input)?;
let (remaining, parameters) = opt(tuple((space1, data)))(remaining)?;
let (remaining, _nl) = recognize(tuple((space0, line_ending)))(remaining)?;
let (remaining, _nl) = line_ending(remaining)?;
let lesser_block_end_specialized = lesser_block_end("verse");
let contexts = [
ContextElement::ConsumeTrailingWhitespace(true),
@ -96,7 +95,7 @@ pub fn comment_block<'b, 'g, 'r, 's>(
) -> Res<OrgSource<'s>, CommentBlock<'s>> {
let (remaining, name) = lesser_block_begin("comment")(context, input)?;
let (remaining, parameters) = opt(tuple((space1, data)))(remaining)?;
let (remaining, _nl) = recognize(tuple((space0, line_ending)))(remaining)?;
let (remaining, _nl) = line_ending(remaining)?;
let lesser_block_end_specialized = lesser_block_end("comment");
let contexts = [
ContextElement::ConsumeTrailingWhitespace(true),
@ -136,7 +135,7 @@ pub fn example_block<'b, 'g, 'r, 's>(
) -> Res<OrgSource<'s>, ExampleBlock<'s>> {
let (remaining, _name) = lesser_block_begin("example")(context, input)?;
let (remaining, parameters) = opt(tuple((space1, data)))(remaining)?;
let (remaining, _nl) = recognize(tuple((space0, line_ending)))(remaining)?;
let (remaining, _nl) = line_ending(remaining)?;
let lesser_block_end_specialized = lesser_block_end("example");
let contexts = [
ContextElement::ConsumeTrailingWhitespace(true),
@ -177,7 +176,7 @@ pub fn export_block<'b, 'g, 'r, 's>(
let (remaining, name) = lesser_block_begin("export")(context, input)?;
// https://orgmode.org/worg/org-syntax.html#Blocks claims that export blocks must have a single word for data but testing shows no data and multi-word data still parses as an export block.
let (remaining, parameters) = opt(tuple((space1, data)))(remaining)?;
let (remaining, _nl) = recognize(tuple((space0, line_ending)))(remaining)?;
let (remaining, _nl) = line_ending(remaining)?;
let lesser_block_end_specialized = lesser_block_end("export");
let contexts = [
ContextElement::ConsumeTrailingWhitespace(true),
@ -218,7 +217,7 @@ pub fn src_block<'b, 'g, 'r, 's>(
let (remaining, name) = lesser_block_begin("src")(context, input)?;
// https://orgmode.org/worg/org-syntax.html#Blocks claims that data is mandatory and must follow the LANGUAGE SWITCHES ARGUMENTS pattern but testing has shown that no data and incorrect data here will still parse to a src block.
let (remaining, parameters) = opt(tuple((space1, data)))(remaining)?;
let (remaining, _nl) = recognize(tuple((space0, line_ending)))(remaining)?;
let (remaining, _nl) = line_ending(remaining)?;
let lesser_block_end_specialized = lesser_block_end("src");
let contexts = [
ContextElement::ConsumeTrailingWhitespace(true),
@ -276,10 +275,9 @@ fn _lesser_block_end<'b, 'g, 'r, 's, 'c>(
) -> Res<OrgSource<'s>, OrgSource<'s>> {
start_of_line(input)?;
let (remaining, _leading_whitespace) = space0(input)?;
let (remaining, (_begin, _name, _ws, _ending)) = tuple((
let (remaining, (_begin, _name, _ws)) = tuple((
tag_no_case("#+end_"),
tag_no_case(current_name_lower),
space0,
alt((eof, line_ending)),
))(remaining)?;
let source = get_consumed(input, remaining);

View File

@ -147,11 +147,6 @@ pub fn plain_list_item<'b, 'g, 'r, 's>(
Into::<&str>::into(bull) != "*" || indent_level > 0
})(remaining)?;
let (remaining, _maybe_counter_set) =
opt(tuple((space1, tag("[@"), counter, tag("]"))))(remaining)?;
// TODO: parse checkbox
let (remaining, maybe_tag) = opt(tuple((
space1,
parser_with_context!(item_tag)(context),

View File

@ -169,8 +169,5 @@ fn node_property_name_end<'b, 'g, 'r, 's>(
_context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
recognize(tuple((
alt((tag("+:"), tag(":"))),
alt((space1, line_ending, eof)),
)))(input)
alt((tag("+:"), tag(":")))(input)
}

View File

@ -4,7 +4,6 @@ use crate::types::Document;
use crate::types::DocumentElement;
use crate::types::Element;
use crate::types::Heading;
use crate::types::NodeProperty;
use crate::types::Object;
use crate::types::PlainListItem;
use crate::types::Section;
@ -20,7 +19,6 @@ pub enum Token<'r, 's> {
PlainListItem(&'r PlainListItem<'s>),
TableRow(&'r TableRow<'s>),
TableCell(&'r TableCell<'s>),
NodeProperty(&'r NodeProperty<'s>),
}
impl<'r, 's> Token<'r, 's> {
@ -83,9 +81,7 @@ impl<'r, 's> Token<'r, 's> {
}
Element::Comment(_) => Box::new(std::iter::empty()),
Element::Drawer(inner) => Box::new(inner.children.iter().map(Token::Element)),
Element::PropertyDrawer(inner) => {
Box::new(inner.children.iter().map(Token::NodeProperty))
}
Element::PropertyDrawer(_) => Box::new(std::iter::empty()),
Element::Table(inner) => Box::new(inner.children.iter().map(Token::TableRow)),
Element::VerseBlock(inner) => Box::new(inner.children.iter().map(Token::Object)),
Element::CommentBlock(_) => Box::new(std::iter::empty()),
@ -98,13 +94,11 @@ impl<'r, 's> Token<'r, 's> {
Element::FixedWidthArea(_) => Box::new(std::iter::empty()),
Element::HorizontalRule(_) => Box::new(std::iter::empty()),
Element::Keyword(_) => Box::new(std::iter::empty()),
Element::BabelCall(_) => Box::new(std::iter::empty()),
Element::LatexEnvironment(_) => Box::new(std::iter::empty()),
},
Token::PlainListItem(elem) => Box::new(elem.children.iter().map(Token::Element)),
Token::TableRow(elem) => Box::new(elem.children.iter().map(Token::TableCell)),
Token::TableCell(elem) => Box::new(elem.children.iter().map(Token::Object)),
Token::NodeProperty(_) => Box::new(std::iter::empty()),
}
}
}

View File

@ -8,6 +8,7 @@ use nom::combinator::not;
use nom::combinator::opt;
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;
@ -159,9 +160,9 @@ pub fn text_until_exit<'b, 'g, 'r, 's>(
context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
recognize(many_till(
anychar,
parser_with_context!(exit_matcher_parser)(context),
recognize(verify(
many_till(anychar, parser_with_context!(exit_matcher_parser)(context)),
|(children, _exit_contents)| !children.is_empty(),
))(input)
}

View File

@ -44,7 +44,6 @@ pub enum Element<'s> {
FixedWidthArea(FixedWidthArea<'s>),
HorizontalRule(HorizontalRule<'s>),
Keyword(Keyword<'s>),
BabelCall(Keyword<'s>),
LatexEnvironment(LatexEnvironment<'s>),
}
@ -71,7 +70,6 @@ impl<'s> Source<'s> for Element<'s> {
Element::FixedWidthArea(obj) => obj.source,
Element::HorizontalRule(obj) => obj.source,
Element::Keyword(obj) => obj.source,
Element::BabelCall(obj) => obj.source,
Element::LatexEnvironment(obj) => obj.source,
}
}
@ -101,7 +99,6 @@ impl<'s> SetSource<'s> for Element<'s> {
Element::FixedWidthArea(obj) => obj.source = source,
Element::HorizontalRule(obj) => obj.source = source,
Element::Keyword(obj) => obj.source = source,
Element::BabelCall(obj) => obj.source = source,
Element::LatexEnvironment(obj) => obj.source = source,
}
}

View File

@ -114,12 +114,6 @@ impl<'s> Source<'s> for PropertyDrawer<'s> {
}
}
impl<'s> Source<'s> for NodeProperty<'s> {
fn get_source(&'s self) -> &'s str {
self.source
}
}
impl<'s> Source<'s> for Table<'s> {
fn get_source(&'s self) -> &'s str {
self.source