11 Commits

Author SHA1 Message Date
Tom Alexander
9e2a323f6f Merge branch 'trailing_whitespace_at_end_of_file'
All checks were successful
rustfmt Build rustfmt has succeeded
rust-test Build rust-test has succeeded
rust-build Build rust-build has succeeded
2023-08-31 17:29:52 -04:00
Tom Alexander
0fcb3f73f9 Move handling of contentless item to handle contentless description item. 2023-08-31 17:25:42 -04:00
Tom Alexander
bfc9e7f58d When re-parsing last item in list, only disable white space consumption for last element in item. 2023-08-31 17:08:21 -04:00
Tom Alexander
b5f0521b56 Only consume trailing whitespace when not exiting for all objects. 2023-08-31 15:45:31 -04:00
Tom Alexander
2048d8f0b6 Support comments at the end of the line in diary sexp.
All checks were successful
rustfmt Build rustfmt has succeeded
rust-test Build rust-test has succeeded
rust-build Build rust-build has succeeded
2023-08-31 15:31:54 -04:00
Tom Alexander
466716881e Fix macros consuming whitespace even when the exit matcher is calling for an exit.
All checks were successful
rustfmt Build rustfmt has succeeded
rust-test Build rust-test has succeeded
rust-build Build rust-build has succeeded
2023-08-31 15:11:29 -04:00
Tom Alexander
eb9c582fa5 '>' is allowed as a post character in text markup.
All checks were successful
rustfmt Build rustfmt has succeeded
rust-test Build rust-test has succeeded
rust-build Build rust-build has succeeded
2023-08-29 23:57:15 -04:00
Tom Alexander
214e895d85 Support backslash at the end of a macro. 2023-08-29 23:42:16 -04:00
Tom Alexander
db3086743c Publish version 0.1.4.
All checks were successful
rustfmt Build rustfmt has succeeded
rust-test Build rust-test has succeeded
rust-build Build rust-build has succeeded
2023-08-29 23:28:17 -04:00
Tom Alexander
207a0546b0 Run full test suite despite default feature selection.
All checks were successful
rustfmt Build rustfmt has succeeded
rust-test Build rust-test has succeeded
rust-build Build rust-build has succeeded
2023-08-29 23:23:31 -04:00
Tom Alexander
e9480fd156 Disable the compare tests when the compare feature is disabled.
All checks were successful
rustfmt Build rustfmt has succeeded
rust-test Build rust-test has succeeded
rust-build Build rust-build has succeeded
2023-08-29 23:17:46 -04:00
31 changed files with 190 additions and 72 deletions

View File

@@ -110,7 +110,16 @@ spec:
- build-image - build-image
params: params:
- name: args - name: args
value: [--no-fail-fast, --lib, --test, test_loader] value:
[
--no-default-features,
--features,
compare,
--no-fail-fast,
--lib,
--test,
test_loader,
]
- name: docker-image - name: docker-image
value: "$(params.image-name):$(tasks.fetch-repository.results.commit)" value: "$(params.image-name):$(tasks.fetch-repository.results.commit)"
finally: finally:

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "organic" name = "organic"
version = "0.1.3" version = "0.1.4"
authors = ["Tom Alexander <tom@fizz.buzz>"] authors = ["Tom Alexander <tom@fizz.buzz>"]
description = "An org-mode parser." description = "An org-mode parser."
edition = "2021" edition = "2021"
@@ -13,9 +13,7 @@ resolver = "2"
include = [ include = [
"LICENSE", "LICENSE",
"**/*.rs", "**/*.rs",
"Cargo.toml", "Cargo.toml"
"tests/*",
"org_mode_samples/"
] ]
[lib] [lib]

View File

@@ -35,12 +35,12 @@ clean:
.PHONY: test .PHONY: test
test: test:
> cargo test --no-fail-fast --lib --test test_loader -- --test-threads $(TESTJOBS) > cargo test --no-default-features --features compare --no-fail-fast --lib --test test_loader -- --test-threads $(TESTJOBS)
.PHONY: dockertest .PHONY: dockertest
dockertest: dockertest:
> $(MAKE) -C docker/organic_test > $(MAKE) -C docker/organic_test
> docker run --init --rm -i -t -v "$$(readlink -f ./):/source:ro" --mount source=cargo-cache,target=/usr/local/cargo/registry --mount source=rust-cache,target=/target --env CARGO_TARGET_DIR=/target -w /source organic-test --no-fail-fast --lib --test test_loader -- --test-threads $(TESTJOBS) > docker run --init --rm -i -t -v "$$(readlink -f ./):/source:ro" --mount source=cargo-cache,target=/usr/local/cargo/registry --mount source=rust-cache,target=/target --env CARGO_TARGET_DIR=/target -w /source organic-test --no-default-features --features compare --no-fail-fast --lib --test test_loader -- --test-threads $(TESTJOBS)
.PHONY: dockerclean .PHONY: dockerclean
dockerclean: dockerclean:
@@ -49,11 +49,11 @@ dockerclean:
.PHONY: integrationtest .PHONY: integrationtest
integrationtest: integrationtest:
> cargo test --no-fail-fast --test test_loader -- --test-threads $(TESTJOBS) > cargo test --no-default-features --features compare --no-fail-fast --test test_loader -- --test-threads $(TESTJOBS)
.PHONY: unittest .PHONY: unittest
unittest: unittest:
> cargo test --lib -- --test-threads $(TESTJOBS) > cargo test --no-default-features --lib -- --test-threads $(TESTJOBS)
.PHONY: jaeger .PHONY: jaeger
jaeger: jaeger:

View File

@@ -1,10 +1,16 @@
#[cfg(feature = "compare")]
use std::env; use std::env;
#[cfg(feature = "compare")]
use std::fs::File; use std::fs::File;
#[cfg(feature = "compare")]
use std::io::Write; use std::io::Write;
#[cfg(feature = "compare")]
use std::path::Path; use std::path::Path;
#[cfg(feature = "compare")]
use walkdir::WalkDir; use walkdir::WalkDir;
#[cfg(feature = "compare")]
fn main() { fn main() {
let out_dir = env::var("OUT_DIR").unwrap(); let out_dir = env::var("OUT_DIR").unwrap();
let destination = Path::new(&out_dir).join("tests.rs"); let destination = Path::new(&out_dir).join("tests.rs");
@@ -31,6 +37,10 @@ fn main() {
} }
} }
#[cfg(not(feature = "compare"))]
fn main() {}
#[cfg(feature = "compare")]
fn write_test(test_file: &mut File, test: &walkdir::DirEntry) { fn write_test(test_file: &mut File, test: &walkdir::DirEntry) {
let test_name = test let test_name = test
.path() .path()
@@ -55,6 +65,7 @@ fn write_test(test_file: &mut File, test: &walkdir::DirEntry) {
.unwrap(); .unwrap();
} }
#[cfg(feature = "compare")]
fn write_header(test_file: &mut File) { fn write_header(test_file: &mut File) {
write!( write!(
test_file, test_file,
@@ -70,6 +81,7 @@ use organic::parser::sexp::sexp_with_padding;
.unwrap(); .unwrap();
} }
#[cfg(feature = "compare")]
fn is_expect_fail(name: &str) -> Option<&str> { fn is_expect_fail(name: &str) -> Option<&str> {
match name { match name {
"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_greater_element_drawer_drawer_with_headline_inside" => Some("Apparently lines with :end: become their own paragraph. This odd behavior needs to be investigated more."),

View File

@@ -29,7 +29,7 @@ endif
.PHONY: run .PHONY: run
run: build run: build
docker run --rm --init -v "$$(readlink -f ../../):/source:ro" --workdir=/source --mount source=cargo-cache,target=/usr/local/cargo/registry --mount source=rust-cache,target=/target --env CARGO_TARGET_DIR=/target $(IMAGE_NAME) --no-fail-fast --lib --test test_loader docker run --rm --init -v "$$(readlink -f ../../):/source:ro" --workdir=/source --mount source=cargo-cache,target=/usr/local/cargo/registry --mount source=rust-cache,target=/target --env CARGO_TARGET_DIR=/target $(IMAGE_NAME) --no-default-features --features compare --no-fail-fast --lib --test test_loader
.PHONY: shell .PHONY: shell
shell: build shell: build

View File

@@ -0,0 +1 @@
- {{{foo(bar)}}} :: baz

View File

@@ -0,0 +1,2 @@
- foo

View File

@@ -0,0 +1 @@
%%(foo bar) ; baz

View File

@@ -0,0 +1 @@
foo ==>bar=.

View File

@@ -52,7 +52,7 @@ function launch_container {
set -euo pipefail set -euo pipefail
IFS=\$'\n\t' IFS=\$'\n\t'
cargo test --no-fail-fast --lib --test test_loader "$test" -- --show-output cargo test --no-default-features --features compare --no-fail-fast --lib --test test_loader "$test" -- --show-output
EOF EOF
) )

View File

@@ -12,7 +12,7 @@ function main {
local test local test
while read test; do while read test; do
cargo test --no-fail-fast --test test_loader "$test" -- --show-output cargo test --no-default-features --features compare --no-fail-fast --test test_loader "$test" -- --show-output
done<<<"$test_names" done<<<"$test_names"
} }

View File

@@ -5,6 +5,7 @@ use nom::combinator::recognize;
use nom::multi::many_till; use nom::multi::many_till;
use super::org_source::OrgSource; use super::org_source::OrgSource;
use super::util::maybe_consume_object_trailing_whitespace_if_not_exiting;
use super::Context; use super::Context;
use crate::error::Res; use crate::error::Res;
use crate::parser::exiting::ExitClass; use crate::parser::exiting::ExitClass;
@@ -26,6 +27,8 @@ pub fn angle_link<'r, 's>(
let (remaining, _separator) = tag(":")(remaining)?; let (remaining, _separator) = tag(":")(remaining)?;
let (remaining, path) = path_angle(context, remaining)?; let (remaining, path) = path_angle(context, remaining)?;
let (remaining, _) = tag(">")(remaining)?; let (remaining, _) = tag(">")(remaining)?;
let (remaining, _trailing_whitespace) =
maybe_consume_object_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining); let source = get_consumed(input, remaining);
Ok(( Ok((
remaining, remaining,

View File

@@ -2,7 +2,7 @@ use nom::branch::alt;
use nom::bytes::complete::tag; use nom::bytes::complete::tag;
use nom::bytes::complete::tag_no_case; use nom::bytes::complete::tag_no_case;
use nom::character::complete::anychar; use nom::character::complete::anychar;
use nom::character::complete::space0;
use nom::combinator::opt; use nom::combinator::opt;
use nom::combinator::recognize; use nom::combinator::recognize;
use nom::combinator::verify; use nom::combinator::verify;
@@ -14,6 +14,7 @@ use nom::sequence::tuple;
use super::citation_reference::must_balance_bracket; use super::citation_reference::must_balance_bracket;
use super::org_source::BracketDepth; use super::org_source::BracketDepth;
use super::org_source::OrgSource; use super::org_source::OrgSource;
use super::util::maybe_consume_object_trailing_whitespace_if_not_exiting;
use super::Context; use super::Context;
use crate::error::CustomError; use crate::error::CustomError;
use crate::error::Res; use crate::error::Res;
@@ -48,7 +49,8 @@ pub fn citation<'r, 's>(
parser_with_context!(global_suffix)(context), parser_with_context!(global_suffix)(context),
))))(remaining)?; ))))(remaining)?;
let (remaining, _) = tag("]")(remaining)?; let (remaining, _) = tag("]")(remaining)?;
let (remaining, _) = space0(remaining)?; let (remaining, _trailing_whitespace) =
maybe_consume_object_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining); let source = get_consumed(input, remaining);
Ok(( Ok((
remaining, remaining,

View File

@@ -1,9 +1,12 @@
use nom::branch::alt; use nom::branch::alt;
use nom::bytes::complete::tag; use nom::bytes::complete::tag;
use nom::character::complete::anychar;
use nom::character::complete::line_ending; use nom::character::complete::line_ending;
use nom::character::complete::space0; use nom::character::complete::space0;
use nom::combinator::eof; use nom::combinator::eof;
use nom::combinator::opt;
use nom::combinator::recognize; use nom::combinator::recognize;
use nom::multi::many_till;
use nom::sequence::tuple; use nom::sequence::tuple;
use super::org_source::OrgSource; use super::org_source::OrgSource;
@@ -24,6 +27,11 @@ pub fn diary_sexp<'r, 's>(
let (remaining, _clock) = tag("%%")(remaining)?; let (remaining, _clock) = tag("%%")(remaining)?;
let (remaining, _gap_whitespace) = space0(remaining)?; let (remaining, _gap_whitespace) = space0(remaining)?;
let (remaining, _sexp) = recognize(sexp)(remaining)?; let (remaining, _sexp) = recognize(sexp)(remaining)?;
let (remaining, _trailing_comment) = opt(tuple((
space0,
tag(";"),
many_till(anychar, alt((line_ending, eof))),
)))(remaining)?;
let (remaining, _trailing_whitespace) = let (remaining, _trailing_whitespace) =
recognize(tuple((space0, alt((line_ending, eof)))))(remaining)?; recognize(tuple((space0, alt((line_ending, eof)))))(remaining)?;

View File

@@ -2,12 +2,13 @@ use nom::branch::alt;
use nom::bytes::complete::tag; use nom::bytes::complete::tag;
use nom::bytes::complete::tag_no_case; use nom::bytes::complete::tag_no_case;
use nom::character::complete::satisfy; use nom::character::complete::satisfy;
use nom::character::complete::space0;
use nom::combinator::eof; use nom::combinator::eof;
use nom::combinator::peek; use nom::combinator::peek;
use nom::combinator::recognize; use nom::combinator::recognize;
use super::org_source::OrgSource; use super::org_source::OrgSource;
use super::util::maybe_consume_object_trailing_whitespace_if_not_exiting;
use super::Context; use super::Context;
use crate::error::CustomError; use crate::error::CustomError;
use crate::error::MyError; use crate::error::MyError;
@@ -440,7 +441,8 @@ pub fn entity<'r, 's>(
let (remaining, _) = tag("\\")(input)?; let (remaining, _) = tag("\\")(input)?;
let (remaining, entity_name) = name(context, remaining)?; let (remaining, entity_name) = name(context, remaining)?;
let (remaining, _) = alt((tag("{}"), peek(recognize(entity_end))))(remaining)?; let (remaining, _) = alt((tag("{}"), peek(recognize(entity_end))))(remaining)?;
let (remaining, _) = space0(remaining)?; let (remaining, _trailing_whitespace) =
maybe_consume_object_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining); let source = get_consumed(input, remaining);
Ok(( Ok((

View File

@@ -8,6 +8,7 @@ use nom::multi::many_till;
use nom::sequence::tuple; use nom::sequence::tuple;
use super::org_source::OrgSource; use super::org_source::OrgSource;
use super::util::maybe_consume_object_trailing_whitespace_if_not_exiting;
use super::Context; use super::Context;
use crate::error::Res; use crate::error::Res;
use crate::parser::exiting::ExitClass; use crate::parser::exiting::ExitClass;
@@ -35,6 +36,8 @@ pub fn export_snippet<'r, 's>(
parser_with_context!(contents)(&parser_context), parser_with_context!(contents)(&parser_context),
)))(remaining)?; )))(remaining)?;
let (remaining, _) = tag("@@")(remaining)?; let (remaining, _) = tag("@@")(remaining)?;
let (remaining, _trailing_whitespace) =
maybe_consume_object_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining); let source = get_consumed(input, remaining);
Ok(( Ok((
remaining, remaining,

View File

@@ -1,13 +1,13 @@
use nom::branch::alt; use nom::branch::alt;
use nom::bytes::complete::tag; use nom::bytes::complete::tag;
use nom::bytes::complete::tag_no_case; use nom::bytes::complete::tag_no_case;
use nom::character::complete::space0;
use nom::combinator::verify; use nom::combinator::verify;
use nom::multi::many_till; use nom::multi::many_till;
use super::org_source::BracketDepth; use super::org_source::BracketDepth;
use super::org_source::OrgSource; use super::org_source::OrgSource;
use super::parser_context::ContextElement; use super::parser_context::ContextElement;
use super::util::maybe_consume_object_trailing_whitespace_if_not_exiting;
use super::Context; use super::Context;
use crate::error::CustomError; use crate::error::CustomError;
use crate::error::MyError; use crate::error::MyError;
@@ -54,7 +54,8 @@ fn anonymous_footnote<'r, 's>(
)(remaining)?; )(remaining)?;
let (remaining, _) = tag("]")(remaining)?; let (remaining, _) = tag("]")(remaining)?;
let (remaining, _) = space0(remaining)?; let (remaining, _trailing_whitespace) =
maybe_consume_object_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining); let source = get_consumed(input, remaining);
Ok(( Ok((
remaining, remaining,
@@ -89,7 +90,8 @@ fn inline_footnote<'r, 's>(
)(remaining)?; )(remaining)?;
let (remaining, _) = tag("]")(remaining)?; let (remaining, _) = tag("]")(remaining)?;
let (remaining, _) = space0(remaining)?; let (remaining, _trailing_whitespace) =
maybe_consume_object_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining); let source = get_consumed(input, remaining);
Ok(( Ok((
remaining, remaining,
@@ -103,13 +105,14 @@ fn inline_footnote<'r, 's>(
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn footnote_reference_only<'r, 's>( fn footnote_reference_only<'r, 's>(
_context: Context<'r, 's>, context: Context<'r, 's>,
input: OrgSource<'s>, input: OrgSource<'s>,
) -> Res<OrgSource<'s>, FootnoteReference<'s>> { ) -> Res<OrgSource<'s>, FootnoteReference<'s>> {
let (remaining, _) = tag_no_case("[fn:")(input)?; let (remaining, _) = tag_no_case("[fn:")(input)?;
let (remaining, label_contents) = label(remaining)?; let (remaining, label_contents) = label(remaining)?;
let (remaining, _) = tag("]")(remaining)?; let (remaining, _) = tag("]")(remaining)?;
let (remaining, _) = space0(remaining)?; let (remaining, _trailing_whitespace) =
maybe_consume_object_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining); let source = get_consumed(input, remaining);
Ok(( Ok((
remaining, remaining,

View File

@@ -4,7 +4,7 @@ use nom::bytes::complete::tag_no_case;
use nom::character::complete::anychar; use nom::character::complete::anychar;
use nom::character::complete::line_ending; use nom::character::complete::line_ending;
use nom::character::complete::one_of; use nom::character::complete::one_of;
use nom::character::complete::space0;
use nom::combinator::opt; use nom::combinator::opt;
use nom::combinator::recognize; use nom::combinator::recognize;
use nom::combinator::verify; use nom::combinator::verify;
@@ -12,6 +12,7 @@ use nom::multi::many_till;
use super::org_source::BracketDepth; use super::org_source::BracketDepth;
use super::org_source::OrgSource; use super::org_source::OrgSource;
use super::util::maybe_consume_object_trailing_whitespace_if_not_exiting;
use super::Context; use super::Context;
use crate::error::CustomError; use crate::error::CustomError;
use crate::error::MyError; use crate::error::MyError;
@@ -34,7 +35,8 @@ pub fn inline_babel_call<'r, 's>(
let (remaining, _header1) = opt(parser_with_context!(header)(context))(remaining)?; let (remaining, _header1) = opt(parser_with_context!(header)(context))(remaining)?;
let (remaining, _argument) = argument(context, remaining)?; let (remaining, _argument) = argument(context, remaining)?;
let (remaining, _header2) = opt(parser_with_context!(header)(context))(remaining)?; let (remaining, _header2) = opt(parser_with_context!(header)(context))(remaining)?;
let (remaining, _) = space0(remaining)?; let (remaining, _trailing_whitespace) =
maybe_consume_object_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining); let source = get_consumed(input, remaining);
Ok(( Ok((
remaining, remaining,

View File

@@ -4,7 +4,7 @@ use nom::bytes::complete::tag_no_case;
use nom::character::complete::anychar; use nom::character::complete::anychar;
use nom::character::complete::line_ending; use nom::character::complete::line_ending;
use nom::character::complete::one_of; use nom::character::complete::one_of;
use nom::character::complete::space0;
use nom::combinator::opt; use nom::combinator::opt;
use nom::combinator::recognize; use nom::combinator::recognize;
use nom::combinator::verify; use nom::combinator::verify;
@@ -14,6 +14,7 @@ use tracing::span;
use super::org_source::BracketDepth; use super::org_source::BracketDepth;
use super::org_source::OrgSource; use super::org_source::OrgSource;
use super::util::maybe_consume_object_trailing_whitespace_if_not_exiting;
use super::Context; use super::Context;
use crate::error::CustomError; use crate::error::CustomError;
use crate::error::MyError; use crate::error::MyError;
@@ -35,7 +36,8 @@ pub fn inline_source_block<'r, 's>(
let (remaining, _) = lang(context, remaining)?; let (remaining, _) = lang(context, remaining)?;
let (remaining, _header1) = opt(parser_with_context!(header)(context))(remaining)?; let (remaining, _header1) = opt(parser_with_context!(header)(context))(remaining)?;
let (remaining, _body) = body(context, remaining)?; let (remaining, _body) = body(context, remaining)?;
let (remaining, _) = space0(remaining)?; let (remaining, _trailing_whitespace) =
maybe_consume_object_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining); let source = get_consumed(input, remaining);
Ok(( Ok((
remaining, remaining,

View File

@@ -5,7 +5,6 @@ use nom::character::complete::anychar;
use nom::character::complete::line_ending; use nom::character::complete::line_ending;
use nom::character::complete::none_of; use nom::character::complete::none_of;
use nom::character::complete::one_of; use nom::character::complete::one_of;
use nom::character::complete::space0;
use nom::combinator::peek; use nom::combinator::peek;
use nom::combinator::recognize; use nom::combinator::recognize;
use nom::combinator::verify; use nom::combinator::verify;
@@ -14,6 +13,7 @@ use nom::multi::many_till;
use nom::sequence::tuple; use nom::sequence::tuple;
use super::org_source::OrgSource; use super::org_source::OrgSource;
use super::util::maybe_consume_object_trailing_whitespace_if_not_exiting;
use super::Context; use super::Context;
use crate::error::CustomError; use crate::error::CustomError;
use crate::error::MyError; use crate::error::MyError;
@@ -36,7 +36,8 @@ pub fn latex_fragment<'r, 's>(
parser_with_context!(dollar_char_fragment)(context), parser_with_context!(dollar_char_fragment)(context),
parser_with_context!(bordered_dollar_fragment)(context), parser_with_context!(bordered_dollar_fragment)(context),
))(input)?; ))(input)?;
let (remaining, _) = space0(remaining)?; let (remaining, _trailing_whitespace) =
maybe_consume_object_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining); let source = get_consumed(input, remaining);
Ok(( Ok((
remaining, remaining,

View File

@@ -1,6 +1,5 @@
use nom::bytes::complete::tag; use nom::bytes::complete::tag;
use nom::character::complete::anychar; use nom::character::complete::anychar;
use nom::character::complete::space0;
use nom::combinator::not; use nom::combinator::not;
use nom::combinator::opt; use nom::combinator::opt;
use nom::combinator::peek; use nom::combinator::peek;
@@ -9,7 +8,9 @@ use nom::multi::many0;
use nom::multi::separated_list0; use nom::multi::separated_list0;
use super::org_source::OrgSource; use super::org_source::OrgSource;
use super::util::maybe_consume_object_trailing_whitespace_if_not_exiting;
use super::Context; use super::Context;
use crate::error::CustomError;
use crate::error::Res; use crate::error::Res;
use crate::parser::object::OrgMacro; use crate::parser::object::OrgMacro;
use crate::parser::parser_with_context::parser_with_context; use crate::parser::parser_with_context::parser_with_context;
@@ -25,7 +26,8 @@ pub fn org_macro<'r, 's>(
let (remaining, macro_name) = org_macro_name(context, remaining)?; let (remaining, macro_name) = org_macro_name(context, remaining)?;
let (remaining, macro_args) = opt(parser_with_context!(org_macro_args)(context))(remaining)?; let (remaining, macro_args) = opt(parser_with_context!(org_macro_args)(context))(remaining)?;
let (remaining, _) = tag("}}}")(remaining)?; let (remaining, _) = tag("}}}")(remaining)?;
let (remaining, _trailing_whitespace) = space0(remaining)?; let (remaining, _trailing_whitespace) =
maybe_consume_object_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining); let source = get_consumed(input, remaining);
Ok(( Ok((
@@ -86,6 +88,11 @@ fn org_macro_arg<'r, 's>(
} }
if next_char == '\\' { if next_char == '\\' {
escaping = true; escaping = true;
if peek(tag::<_, _, CustomError<_>>(")"))(new_remaining).is_ok() {
// Special case for backslash at the end of a macro
remaining = new_remaining;
break;
}
} }
if next_char == ',' || next_char == ')' { if next_char == ',' || next_char == ')' {
break; break;

View File

@@ -69,6 +69,7 @@ pub fn plain_list<'r, 's>(
) -> Res<OrgSource<'s>, PlainList<'s>> { ) -> Res<OrgSource<'s>, PlainList<'s>> {
let parser_context = context let parser_context = context
.with_additional_node(ContextElement::Context("plain list")) .with_additional_node(ContextElement::Context("plain list"))
.with_additional_node(ContextElement::ConsumeTrailingWhitespace(true))
.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { .with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode {
class: ExitClass::Beta, class: ExitClass::Beta,
exit_matcher: &plain_list_end, exit_matcher: &plain_list_end,
@@ -143,29 +144,32 @@ pub fn plain_list_item<'r, 's>(
Into::<&str>::into(bull) != "*" || indent_level > 0 Into::<&str>::into(bull) != "*" || indent_level > 0
})(remaining)?; })(remaining)?;
let maybe_contentless_item: Res<OrgSource<'_>, OrgSource<'_>> = eof(remaining); let (remaining, maybe_tag) = opt(tuple((
space1,
parser_with_context!(item_tag)(context),
tag(" ::"),
)))(remaining)?;
let maybe_contentless_item: Res<OrgSource<'_>, OrgSource<'_>> =
peek(recognize(tuple((many0(blank_line), eof))))(remaining);
match maybe_contentless_item { match maybe_contentless_item {
Ok((rem, _ws)) => { Ok((_rem, _ws)) => {
let source = get_consumed(input, rem); let (remaining, _trailing_ws) = opt(blank_line)(remaining)?;
let source = get_consumed(input, remaining);
return Ok(( return Ok((
rem, remaining,
PlainListItem { PlainListItem {
source: source.into(), source: source.into(),
indentation: indent_level, indentation: indent_level,
bullet: bull.into(), bullet: bull.into(),
tag: Vec::new(), tag: maybe_tag
.map(|(_ws, item_tag, _divider)| item_tag)
.unwrap_or(Vec::new()),
children: Vec::new(), children: Vec::new(),
}, },
)); ));
} }
Err(_) => {} Err(_) => {}
}; };
let (remaining, maybe_tag) = opt(tuple((
space1,
parser_with_context!(item_tag)(context),
tag(" ::"),
)))(remaining)?;
let (remaining, _ws) = item_tag_post_gap(context, remaining)?; let (remaining, _ws) = item_tag_post_gap(context, remaining)?;
let exit_matcher = plain_list_item_end(indent_level); let exit_matcher = plain_list_item_end(indent_level);
let parser_context = context let parser_context = context
@@ -175,14 +179,24 @@ pub fn plain_list_item<'r, 's>(
exit_matcher: &exit_matcher, exit_matcher: &exit_matcher,
})); }));
let (remaining, (children, _exit_contents)) = many_till( let (mut remaining, (mut children, _exit_contents)) = many_till(
parser_with_context!(element(true))(&parser_context), include_input(parser_with_context!(element(true))(&parser_context)),
alt((
peek(recognize(tuple((start_of_line, many0(blank_line), eof)))),
parser_with_context!(exit_matcher_parser)(&parser_context), parser_with_context!(exit_matcher_parser)(&parser_context),
)),
)(remaining)?; )(remaining)?;
if !children.is_empty() && !context.should_consume_trailing_whitespace() {
let final_item_context =
parser_context.with_additional_node(ContextElement::ConsumeTrailingWhitespace(false));
let (final_child_start, _original_final_child) = children
.pop()
.expect("if-statement already checked that children was non-empty.");
let (remain, reparsed_final_element) = include_input(parser_with_context!(element(true))(
&final_item_context,
))(final_child_start)?;
remaining = remain;
children.push(reparsed_final_element);
}
let (remaining, _trailing_ws) = let (remaining, _trailing_ws) =
maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?; maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?;
@@ -196,11 +210,23 @@ pub fn plain_list_item<'r, 's>(
tag: maybe_tag tag: maybe_tag
.map(|(_ws, item_tag, _divider)| item_tag) .map(|(_ws, item_tag, _divider)| item_tag)
.unwrap_or(Vec::new()), .unwrap_or(Vec::new()),
children, children: children.into_iter().map(|(_start, item)| item).collect(),
}, },
)); ));
} }
fn include_input<'s, F, O>(
mut inner: F,
) -> impl FnMut(OrgSource<'s>) -> Res<OrgSource<'s>, (OrgSource<'s>, O)>
where
F: FnMut(OrgSource<'s>) -> Res<OrgSource<'s>, O>,
{
move |input: OrgSource<'_>| {
let (remaining, output) = inner(input)?;
Ok((remaining, (input, output)))
}
}
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn bullet<'s>(i: OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> { fn bullet<'s>(i: OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
alt(( alt((

View File

@@ -6,6 +6,7 @@ use nom::combinator::verify;
use nom::multi::many_till; use nom::multi::many_till;
use super::org_source::OrgSource; use super::org_source::OrgSource;
use super::util::maybe_consume_object_trailing_whitespace_if_not_exiting;
use super::Context; use super::Context;
use super::Object; use super::Object;
use crate::error::CustomError; use crate::error::CustomError;
@@ -104,7 +105,8 @@ pub fn radio_target<'r, 's>(
)(remaining)?; )(remaining)?;
let (remaining, _closing) = tag(">>>")(remaining)?; let (remaining, _closing) = tag(">>>")(remaining)?;
let (remaining, _trailing_whitespace) = space0(remaining)?; let (remaining, _trailing_whitespace) =
maybe_consume_object_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining); let source = get_consumed(input, remaining);
Ok(( Ok((
remaining, remaining,

View File

@@ -3,13 +3,14 @@ use nom::bytes::complete::escaped;
use nom::bytes::complete::tag; use nom::bytes::complete::tag;
use nom::bytes::complete::take_till1; use nom::bytes::complete::take_till1;
use nom::character::complete::one_of; use nom::character::complete::one_of;
use nom::character::complete::space0;
use nom::combinator::verify; use nom::combinator::verify;
use nom::multi::many_till; use nom::multi::many_till;
use super::org_source::OrgSource; use super::org_source::OrgSource;
use super::parser_with_context::parser_with_context; use super::parser_with_context::parser_with_context;
use super::util::get_consumed; use super::util::get_consumed;
use super::util::maybe_consume_object_trailing_whitespace_if_not_exiting;
use super::Context; use super::Context;
use super::Object; use super::Object;
use super::RegularLink; use super::RegularLink;
@@ -39,7 +40,8 @@ pub fn regular_link_without_description<'r, 's>(
let (remaining, _opening_bracket) = tag("[[")(input)?; let (remaining, _opening_bracket) = tag("[[")(input)?;
let (remaining, _path) = pathreg(context, remaining)?; let (remaining, _path) = pathreg(context, remaining)?;
let (remaining, _closing_bracket) = tag("]]")(remaining)?; let (remaining, _closing_bracket) = tag("]]")(remaining)?;
let (remaining, _trailing_whitespace) = space0(remaining)?; let (remaining, _trailing_whitespace) =
maybe_consume_object_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining); let source = get_consumed(input, remaining);
Ok(( Ok((
remaining, remaining,
@@ -59,7 +61,8 @@ pub fn regular_link_with_description<'r, 's>(
let (remaining, _closing_bracket) = tag("][")(remaining)?; let (remaining, _closing_bracket) = tag("][")(remaining)?;
let (remaining, _description) = description(context, remaining)?; let (remaining, _description) = description(context, remaining)?;
let (remaining, _closing_bracket) = tag("]]")(remaining)?; let (remaining, _closing_bracket) = tag("]]")(remaining)?;
let (remaining, _trailing_whitespace) = space0(remaining)?; let (remaining, _trailing_whitespace) =
maybe_consume_object_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining); let source = get_consumed(input, remaining);
Ok(( Ok((
remaining, remaining,

View File

@@ -1,10 +1,10 @@
use nom::branch::alt; use nom::branch::alt;
use nom::bytes::complete::tag; use nom::bytes::complete::tag;
use nom::character::complete::space0;
use nom::combinator::recognize; use nom::combinator::recognize;
use nom::sequence::tuple; use nom::sequence::tuple;
use super::org_source::OrgSource; use super::org_source::OrgSource;
use super::util::maybe_consume_object_trailing_whitespace_if_not_exiting;
use super::Context; use super::Context;
use crate::error::Res; use crate::error::Res;
use crate::parser::parser_with_context::parser_with_context; use crate::parser::parser_with_context::parser_with_context;
@@ -23,12 +23,13 @@ pub fn statistics_cookie<'r, 's>(
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
pub fn percent_statistics_cookie<'r, 's>( pub fn percent_statistics_cookie<'r, 's>(
_context: Context<'r, 's>, context: Context<'r, 's>,
input: OrgSource<'s>, input: OrgSource<'s>,
) -> Res<OrgSource<'s>, StatisticsCookie<'s>> { ) -> Res<OrgSource<'s>, StatisticsCookie<'s>> {
let (remaining, source) = let (remaining, source) =
recognize(tuple((tag("["), nom::character::complete::u64, tag("%]"))))(input)?; recognize(tuple((tag("["), nom::character::complete::u64, tag("%]"))))(input)?;
let (remaining, _) = space0(remaining)?; let (remaining, _trailing_whitespace) =
maybe_consume_object_trailing_whitespace_if_not_exiting(context, remaining)?;
Ok(( Ok((
remaining, remaining,
StatisticsCookie { StatisticsCookie {
@@ -39,7 +40,7 @@ pub fn percent_statistics_cookie<'r, 's>(
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
pub fn fraction_statistics_cookie<'r, 's>( pub fn fraction_statistics_cookie<'r, 's>(
_context: Context<'r, 's>, context: Context<'r, 's>,
input: OrgSource<'s>, input: OrgSource<'s>,
) -> Res<OrgSource<'s>, StatisticsCookie<'s>> { ) -> Res<OrgSource<'s>, StatisticsCookie<'s>> {
let (remaining, source) = recognize(tuple(( let (remaining, source) = recognize(tuple((
@@ -49,7 +50,8 @@ pub fn fraction_statistics_cookie<'r, 's>(
nom::character::complete::u64, nom::character::complete::u64,
tag("]"), tag("]"),
)))(input)?; )))(input)?;
let (remaining, _) = space0(remaining)?; let (remaining, _trailing_whitespace) =
maybe_consume_object_trailing_whitespace_if_not_exiting(context, remaining)?;
Ok(( Ok((
remaining, remaining,
StatisticsCookie { StatisticsCookie {

View File

@@ -2,7 +2,7 @@ use nom::branch::alt;
use nom::bytes::complete::tag; use nom::bytes::complete::tag;
use nom::character::complete::anychar; use nom::character::complete::anychar;
use nom::character::complete::one_of; use nom::character::complete::one_of;
use nom::character::complete::space0;
use nom::combinator::map; use nom::combinator::map;
use nom::combinator::not; use nom::combinator::not;
use nom::combinator::opt; use nom::combinator::opt;
@@ -13,6 +13,7 @@ use nom::multi::many_till;
use super::org_source::BracketDepth; use super::org_source::BracketDepth;
use super::org_source::OrgSource; use super::org_source::OrgSource;
use super::util::maybe_consume_object_trailing_whitespace_if_not_exiting;
use super::Context; use super::Context;
use super::Object; use super::Object;
use crate::error::CustomError; use crate::error::CustomError;
@@ -37,7 +38,8 @@ pub fn subscript<'r, 's>(
let (remaining, _) = tag("_")(input)?; let (remaining, _) = tag("_")(input)?;
pre(context, input)?; pre(context, input)?;
let (remaining, _body) = script_body(context, remaining)?; let (remaining, _body) = script_body(context, remaining)?;
let (remaining, _) = space0(remaining)?; let (remaining, _trailing_whitespace) =
maybe_consume_object_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining); let source = get_consumed(input, remaining);
Ok(( Ok((
remaining, remaining,
@@ -56,7 +58,8 @@ pub fn superscript<'r, 's>(
let (remaining, _) = tag("^")(input)?; let (remaining, _) = tag("^")(input)?;
pre(context, input)?; pre(context, input)?;
let (remaining, _body) = script_body(context, remaining)?; let (remaining, _body) = script_body(context, remaining)?;
let (remaining, _) = space0(remaining)?; let (remaining, _trailing_whitespace) =
maybe_consume_object_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining); let source = get_consumed(input, remaining);
Ok(( Ok((
remaining, remaining,

View File

@@ -1,13 +1,14 @@
use nom::bytes::complete::tag; use nom::bytes::complete::tag;
use nom::character::complete::anychar; use nom::character::complete::anychar;
use nom::character::complete::one_of; use nom::character::complete::one_of;
use nom::character::complete::space0;
use nom::combinator::peek; use nom::combinator::peek;
use nom::combinator::recognize; use nom::combinator::recognize;
use nom::combinator::verify; use nom::combinator::verify;
use nom::multi::many_till; use nom::multi::many_till;
use super::org_source::OrgSource; use super::org_source::OrgSource;
use super::util::maybe_consume_object_trailing_whitespace_if_not_exiting;
use super::Context; use super::Context;
use crate::error::CustomError; use crate::error::CustomError;
use crate::error::MyError; use crate::error::MyError;
@@ -49,7 +50,8 @@ pub fn target<'r, 's>(
)))); ))));
} }
let (remaining, _) = tag(">>")(remaining)?; let (remaining, _) = tag(">>")(remaining)?;
let (remaining, _) = space0(remaining)?; let (remaining, _trailing_whitespace) =
maybe_consume_object_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining); let source = get_consumed(input, remaining);
Ok(( Ok((

View File

@@ -17,6 +17,7 @@ use tracing::span;
use super::org_source::OrgSource; use super::org_source::OrgSource;
use super::radio_link::RematchObject; use super::radio_link::RematchObject;
use super::util::maybe_consume_object_trailing_whitespace_if_not_exiting;
use super::Context; use super::Context;
use crate::error::CustomError; use crate::error::CustomError;
use crate::error::MyError; use crate::error::MyError;
@@ -204,7 +205,8 @@ fn _text_markup_object<'r, 's, 'x>(
} }
let (remaining, _close) = text_markup_end_specialized(context, remaining)?; let (remaining, _close) = text_markup_end_specialized(context, remaining)?;
let (remaining, _trailing_whitespace) = space0(remaining)?; let (remaining, _trailing_whitespace) =
maybe_consume_object_trailing_whitespace_if_not_exiting(context, remaining)?;
Ok((remaining, children)) Ok((remaining, children))
} }
@@ -254,7 +256,8 @@ fn _text_markup_string<'r, 's, 'x>(
} }
let (remaining, _close) = text_markup_end_specialized(context, remaining)?; let (remaining, _close) = text_markup_end_specialized(context, remaining)?;
let (remaining, _trailing_whitespace) = space0(remaining)?; let (remaining, _trailing_whitespace) =
maybe_consume_object_trailing_whitespace_if_not_exiting(context, remaining)?;
Ok((remaining, contents)) Ok((remaining, contents))
} }
@@ -277,7 +280,7 @@ pub fn pre<'r, 's>(_context: Context<'r, 's>, input: OrgSource<'s>) -> Res<OrgSo
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
pub fn post<'r, 's>(_context: Context<'r, 's>, input: OrgSource<'s>) -> Res<OrgSource<'s>, ()> { pub fn post<'r, 's>(_context: Context<'r, 's>, input: OrgSource<'s>) -> Res<OrgSource<'s>, ()> {
let (remaining, _) = alt((recognize(one_of(" \r\n\t-.,;:!?')}[\">")), line_ending))(input)?; let (remaining, _) = alt((recognize(one_of(" \r\n\t-.,;:!?')}[\"")), line_ending))(input)?;
Ok((remaining, ())) Ok((remaining, ()))
} }

View File

@@ -3,7 +3,6 @@ use nom::bytes::complete::tag;
use nom::character::complete::anychar; use nom::character::complete::anychar;
use nom::character::complete::digit1; use nom::character::complete::digit1;
use nom::character::complete::one_of; use nom::character::complete::one_of;
use nom::character::complete::space0;
use nom::character::complete::space1; use nom::character::complete::space1;
use nom::combinator::opt; use nom::combinator::opt;
use nom::combinator::recognize; use nom::combinator::recognize;
@@ -12,6 +11,7 @@ use nom::multi::many_till;
use nom::sequence::tuple; use nom::sequence::tuple;
use super::org_source::OrgSource; use super::org_source::OrgSource;
use super::util::maybe_consume_object_trailing_whitespace_if_not_exiting;
use super::Context; use super::Context;
use crate::error::Res; use crate::error::Res;
use crate::parser::exiting::ExitClass; use crate::parser::exiting::ExitClass;
@@ -49,7 +49,8 @@ fn diary_timestamp<'r, 's>(
let (remaining, _) = tag("<%%(")(input)?; let (remaining, _) = tag("<%%(")(input)?;
let (remaining, _body) = sexp(context, remaining)?; let (remaining, _body) = sexp(context, remaining)?;
let (remaining, _) = tag(")>")(remaining)?; let (remaining, _) = tag(")>")(remaining)?;
let (remaining, _) = space0(remaining)?; let (remaining, _trailing_whitespace) =
maybe_consume_object_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining); let source = get_consumed(input, remaining);
Ok(( Ok((
@@ -112,7 +113,8 @@ fn active_timestamp<'r, 's>(
)))(remaining)?; )))(remaining)?;
let (remaining, _) = tag(">")(remaining)?; let (remaining, _) = tag(">")(remaining)?;
let (remaining, _) = space0(remaining)?; let (remaining, _trailing_whitespace) =
maybe_consume_object_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining); let source = get_consumed(input, remaining);
Ok(( Ok((
@@ -145,7 +147,8 @@ fn inactive_timestamp<'r, 's>(
)))(remaining)?; )))(remaining)?;
let (remaining, _) = tag("]")(remaining)?; let (remaining, _) = tag("]")(remaining)?;
let (remaining, _) = space0(remaining)?; let (remaining, _trailing_whitespace) =
maybe_consume_object_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining); let source = get_consumed(input, remaining);
Ok(( Ok((
@@ -166,7 +169,8 @@ fn active_date_range_timestamp<'r, 's>(
let (remaining, _separator) = tag("--")(remaining)?; let (remaining, _separator) = tag("--")(remaining)?;
let (remaining, _second_timestamp) = active_timestamp(context, remaining)?; let (remaining, _second_timestamp) = active_timestamp(context, remaining)?;
let (remaining, _) = space0(remaining)?; let (remaining, _trailing_whitespace) =
maybe_consume_object_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining); let source = get_consumed(input, remaining);
Ok(( Ok((
@@ -206,7 +210,8 @@ fn active_time_range_timestamp<'r, 's>(
)))(remaining)?; )))(remaining)?;
let (remaining, _) = tag(">")(remaining)?; let (remaining, _) = tag(">")(remaining)?;
let (remaining, _) = space0(remaining)?; let (remaining, _trailing_whitespace) =
maybe_consume_object_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining); let source = get_consumed(input, remaining);
Ok(( Ok((
@@ -227,7 +232,8 @@ fn inactive_date_range_timestamp<'r, 's>(
let (remaining, _separator) = tag("--")(remaining)?; let (remaining, _separator) = tag("--")(remaining)?;
let (remaining, _second_timestamp) = inactive_timestamp(context, remaining)?; let (remaining, _second_timestamp) = inactive_timestamp(context, remaining)?;
let (remaining, _) = space0(remaining)?; let (remaining, _trailing_whitespace) =
maybe_consume_object_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining); let source = get_consumed(input, remaining);
Ok(( Ok((
@@ -267,7 +273,8 @@ fn inactive_time_range_timestamp<'r, 's>(
)))(remaining)?; )))(remaining)?;
let (remaining, _) = tag("]")(remaining)?; let (remaining, _) = tag("]")(remaining)?;
let (remaining, _) = space0(remaining)?; let (remaining, _trailing_whitespace) =
maybe_consume_object_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining); let source = get_consumed(input, remaining);
Ok(( Ok((

View File

@@ -68,6 +68,18 @@ pub fn element_trailing_whitespace<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s
alt((eof, recognize(many0(blank_line))))(input) alt((eof, recognize(many0(blank_line))))(input)
} }
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
pub fn maybe_consume_object_trailing_whitespace_if_not_exiting<'r, 's>(
context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, Option<OrgSource<'s>>> {
if exit_matcher_parser(context, input).is_err() {
opt(space0)(input)
} else {
Ok((input, None))
}
}
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))] #[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
pub fn maybe_consume_trailing_whitespace_if_not_exiting<'r, 's>( pub fn maybe_consume_trailing_whitespace_if_not_exiting<'r, 's>(
context: Context<'r, 's>, context: Context<'r, 's>,

View File

@@ -1 +1,2 @@
#[cfg(feature = "compare")]
include!(concat!(env!("OUT_DIR"), "/tests.rs")); include!(concat!(env!("OUT_DIR"), "/tests.rs"));