Compare commits

..

No commits in common. "129228c5c5d6f8b47165d3f4d33588d8aeee837f" and "ba15999534cc6700823354b99e4a874fee3b4c49" have entirely different histories.

11 changed files with 38 additions and 263 deletions

View File

@ -1,6 +0,0 @@
- foo ::
- bar ::
baz

View File

@ -1,3 +0,0 @@
1. foo
- bar
- lorem :: ipsum

View File

@ -1,2 +0,0 @@
# Since this is an ordered list, the text before the " :: " is NOT parsed as a tag.
1. foo :: bar

View File

@ -1,11 +1 @@
# Should be a link:
https://en.wikipedia.org/wiki/Shebang_(Unix)
# No closing parenthesis, so link ends at underscore.
https://en.wikipedia.org/wiki/Shebang_(Unix
# Parenthesis only allowed to depth of 2 so link ends at underscore.
https://en.wikipedia.org/wiki/Shebang_(((Unix)))
# Even though they eventually become balanced, we hit negative parenthesis depth so link ends at )
https://en.wikipedia.org/wiki/Shebang)Unix(

View File

@ -1 +0,0 @@
[[https://en.wikipedia.org/wiki/Shebang_(Unix)]]

View File

@ -1,13 +0,0 @@
foo_(bar)
foo_(b(ar)
foo_(b{ar)
foo_{b(ar}
foo_(b(a)r)
foo_b(a)r
foo_(b+ar)

View File

@ -732,10 +732,6 @@ fn compare_plain_list<'s>(
Ok(_) => {}
};
// TODO compare :type
//
// :type is an unquoted atom of either descriptive, ordered, or unordered
for (emacs_child, rust_child) in children.iter().skip(2).zip(rust.children.iter()) {
child_status.push(compare_plain_list_item(source, emacs_child, rust_child)?);
}

View File

@ -5,24 +5,17 @@ use nom::character::complete::anychar;
use nom::character::complete::none_of;
use nom::character::complete::one_of;
use nom::combinator::eof;
use nom::combinator::not;
use nom::combinator::peek;
use nom::combinator::recognize;
use nom::combinator::verify;
use nom::multi::many0;
use nom::multi::many1;
use nom::multi::many_till;
use nom::sequence::tuple;
use super::org_source::BracketDepth;
use super::org_source::OrgSource;
use super::util::maybe_consume_object_trailing_whitespace_if_not_exiting;
use crate::context::parser_with_context;
use crate::context::ContextElement;
use crate::context::ContextMatcher;
use crate::context::ExitClass;
use crate::context::ExitMatcherNode;
use crate::context::Matcher;
use crate::context::RefContext;
use crate::error::CustomError;
use crate::error::MyError;
@ -137,77 +130,17 @@ fn path_plain<'b, 'g, 'r, 's>(
context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
let path_plain_end = path_plain_end(input.get_parenthesis_depth());
// TODO: "optionally containing parenthesis-wrapped non-whitespace non-bracket substrings up to a depth of two. The string must end with either a non-punctation non-whitespace character, a forwards slash, or a parenthesis-wrapped substring"
let parser_context = ContextElement::ExitMatcherNode(ExitMatcherNode {
class: ExitClass::Gamma,
exit_matcher: &path_plain_end,
});
let parser_context = context.with_additional_node(&parser_context);
let (remaining, _components) = many1(alt((
parser_with_context!(path_plain_no_parenthesis)(&parser_context),
parser_with_context!(path_plain_parenthesis)(&parser_context),
)))(input)?;
let exit_matcher = parser_with_context!(exit_matcher_parser)(&parser_context);
let source = get_consumed(input, remaining);
Ok((remaining, source))
}
fn path_plain_end(starting_parenthesis_depth: BracketDepth) -> impl ContextMatcher {
move |context, input: OrgSource<'_>| _path_plain_end(context, input, starting_parenthesis_depth)
}
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn _path_plain_end<'b, 'g, 'r, 's>(
context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>,
starting_parenthesis_depth: BracketDepth,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
let (remaining, _leading_punctuation) = many0(verify(anychar, |c| {
!" \t\r\n[]<>()/".contains(*c) && c.is_ascii_punctuation()
}))(input)?;
let disallowed_character = recognize(one_of(" \t\r\n[]<>"))(remaining);
if disallowed_character.is_ok() {
return disallowed_character;
}
let current_depth = remaining.get_parenthesis_depth() - starting_parenthesis_depth;
if current_depth == 0 {
let close_parenthesis =
tag::<&str, OrgSource<'_>, CustomError<OrgSource<'_>>>(")")(remaining);
if close_parenthesis.is_ok() {
return close_parenthesis;
}
let open_parenthesis_without_match = recognize(tuple((
peek(tag("(")),
not(parser_with_context!(path_plain_parenthesis)(context)),
)))(remaining);
if open_parenthesis_without_match.is_ok() {
return open_parenthesis_without_match;
}
}
// many0 punctuation
Err(nom::Err::Error(CustomError::MyError(MyError(
"No path plain end".into(),
))))
}
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn path_plain_no_parenthesis<'b, 'g, 'r, 's>(
context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
let (remaining, path) = recognize(verify(
many_till(
anychar,
alt((
peek(path_plain_no_parenthesis_disallowed_character),
parser_with_context!(exit_matcher_parser)(context),
)),
),
many_till(anychar, peek(exit_matcher)),
|(children, _exit_contents)| !children.is_empty(),
))(input)?;
@ -215,65 +148,14 @@ fn path_plain_no_parenthesis<'b, 'g, 'r, 's>(
}
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn path_plain_no_parenthesis_disallowed_character<'s>(
fn path_plain_end<'b, 'g, 'r, 's>(
_context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
recognize(verify(anychar, |c| {
c.is_whitespace() || "()[]<>".contains(*c)
}))(input)
}
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn path_plain_parenthesis<'b, 'g, 'r, 's>(
context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
let (remaining, _opening) = tag("(")(input)?;
let starting_depth = remaining.get_parenthesis_depth();
let (remaining, _path) = recognize(verify(
many_till(
anychar,
alt((
peek(path_plain_parenthesis_end(starting_depth)),
parser_with_context!(exit_matcher_parser)(context),
)),
),
|(children, _exit_contents)| !children.is_empty(),
))(remaining)?;
let (remaining, _opening) = tag(")")(remaining)?;
let source = get_consumed(input, remaining);
Ok((remaining, source))
}
fn path_plain_parenthesis_end(starting_parenthesis_depth: BracketDepth) -> impl Matcher {
move |input: OrgSource<'_>| _path_plain_parenthesis_end(input, starting_parenthesis_depth)
}
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn _path_plain_parenthesis_end<'s>(
input: OrgSource<'s>,
starting_parenthesis_depth: BracketDepth,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
let current_depth = input.get_parenthesis_depth() - starting_parenthesis_depth;
if current_depth < 0 {
// This shouldn't be possible because if depth is 0 then a closing parenthesis should end the link.
unreachable!("Exceeded plain link parenthesis depth.")
}
if current_depth == 0 {
let close_parenthesis = tag::<&str, OrgSource<'_>, CustomError<OrgSource<'_>>>(")")(input);
if close_parenthesis.is_ok() {
return close_parenthesis;
}
}
if current_depth == 1 {
let open_parenthesis = tag::<&str, OrgSource<'_>, CustomError<OrgSource<'_>>>("(")(input);
if open_parenthesis.is_ok() {
return open_parenthesis;
}
}
Err(nom::Err::Error(CustomError::MyError(MyError(
"No closing parenthesis".into(),
))))
recognize(many_till(
verify(anychar, |c| {
*c != '/' && (c.is_ascii_punctuation() || c.is_whitespace())
}),
one_of(" \t\r\n()[]<>"),
))(input)
}

View File

@ -57,7 +57,7 @@ pub(crate) fn detect_plain_list<'b, 'g, 'r, 's>(
parser_with_context!(bullet)(context),
alt((space1, line_ending, eof)),
)),
|(_start, indent, (_bullet_type, bull), _after_whitespace)| {
|(_start, indent, bull, _after_whitespace)| {
Into::<&str>::into(bull) != "*" || indent.len() > 0
},
)(input)
@ -151,9 +151,9 @@ fn plain_list_item<'b, 'g, 'r, 's>(
) -> Res<OrgSource<'s>, PlainListItem<'s>> {
start_of_line(input)?;
let (remaining, (indent_level, _leading_whitespace)) = indentation_level(context, input)?;
let (remaining, (bullet_type, bull)) = verify(
let (remaining, bull) = verify(
parser_with_context!(bullet)(context),
|(_bullet_type, bull)| Into::<&str>::into(bull) != "*" || indent_level > 0,
|bull: &OrgSource<'_>| Into::<&str>::into(bull) != "*" || indent_level > 0,
)(remaining)?;
let (remaining, _maybe_counter_set) = opt(tuple((
@ -165,33 +165,15 @@ fn plain_list_item<'b, 'g, 'r, 's>(
let (remaining, maybe_checkbox) = opt(tuple((space1, item_checkbox)))(remaining)?;
let (remaining, maybe_tag) = if let BulletType::Unordered = bullet_type {
opt(tuple((space1, parser_with_context!(item_tag)(context))))(remaining)?
} else {
(remaining, None)
};
let exit_matcher = plain_list_item_end(indent_level);
let contexts = [
ContextElement::ConsumeTrailingWhitespace(true),
ContextElement::ExitMatcherNode(ExitMatcherNode {
class: ExitClass::Beta,
exit_matcher: &exit_matcher,
}),
];
let parser_context = context.with_additional_node(&contexts[0]);
let parser_context = parser_context.with_additional_node(&contexts[1]);
let (remaining, maybe_tag) =
opt(tuple((space1, parser_with_context!(item_tag)(context))))(remaining)?;
let maybe_contentless_item: Res<OrgSource<'_>, ()> = peek(parser_with_context!(
detect_contentless_item_contents
)(&parser_context))(remaining);
)(context))(remaining);
match maybe_contentless_item {
Ok((_rem, _ws)) => {
let (remaining, _trailing_ws) = if context.should_consume_trailing_whitespace() {
recognize(alt((recognize(many1(blank_line)), eof)))(remaining)?
} else {
recognize(alt((blank_line, eof)))(remaining)?
};
let (remaining, _trailing_ws) = opt(blank_line)(remaining)?;
let source = get_consumed(input, remaining);
return Ok((
remaining,
@ -209,7 +191,17 @@ fn plain_list_item<'b, 'g, 'r, 's>(
}
Err(_) => {}
};
let (remaining, _ws) = item_tag_post_gap(&parser_context, remaining)?;
let (remaining, _ws) = item_tag_post_gap(context, remaining)?;
let exit_matcher = plain_list_item_end(indent_level);
let contexts = [
ContextElement::ConsumeTrailingWhitespace(true),
ContextElement::ExitMatcherNode(ExitMatcherNode {
class: ExitClass::Beta,
exit_matcher: &exit_matcher,
}),
];
let parser_context = context.with_additional_node(&contexts[0]);
let parser_context = parser_context.with_additional_node(&contexts[1]);
let (mut remaining, (mut children, _exit_contents)) = many_till(
include_input(parser_with_context!(element(true))(&parser_context)),
@ -249,28 +241,19 @@ fn plain_list_item<'b, 'g, 'r, 's>(
));
}
#[derive(Debug)]
enum BulletType {
Ordered,
Unordered,
}
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn bullet<'b, 'g, 'r, 's>(
context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, (BulletType, OrgSource<'s>)> {
) -> Res<OrgSource<'s>, OrgSource<'s>> {
alt((
map(tag("*"), |bull| (BulletType::Unordered, bull)),
map(tag("-"), |bull| (BulletType::Unordered, bull)),
map(tag("+"), |bull| (BulletType::Unordered, bull)),
map(
recognize(tuple((
parser_with_context!(counter)(context),
alt((tag("."), tag(")"))),
))),
|bull| (BulletType::Ordered, bull),
),
tag("*"),
tag("-"),
tag("+"),
recognize(tuple((
parser_with_context!(counter)(context),
alt((tag("."), tag(")"))),
))),
))(input)
}

View File

@ -23,7 +23,6 @@ use crate::context::ContextElement;
use crate::context::ContextMatcher;
use crate::context::ExitClass;
use crate::context::ExitMatcherNode;
use crate::context::Matcher;
use crate::context::RefContext;
use crate::error::CustomError;
use crate::error::MyError;
@ -113,10 +112,6 @@ fn script_body<'b, 'g, 'r, 's>(
map(parser_with_context!(script_with_braces)(context), |body| {
ScriptBody::WithBraces(body.into())
}),
map(
parser_with_context!(script_with_parenthesis)(context),
|body| ScriptBody::Braceless(body.into()),
),
))(input)
}
@ -204,49 +199,3 @@ fn _script_with_braces_end<'b, 'g, 'r, 's>(
}
tag("}")(input)
}
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn script_with_parenthesis<'b, 'g, 'r, 's>(
context: RefContext<'b, 'g, 'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
let (remaining, _) = tag("(")(input)?;
let exit_with_depth = script_with_parenthesis_end(remaining.get_parenthesis_depth());
let (remaining, _) = many_till(
anychar,
alt((
peek(exit_with_depth),
parser_with_context!(exit_matcher_parser)(context),
)),
)(remaining)?;
let (remaining, _) = tag(")")(remaining)?;
let source = get_consumed(input, remaining);
Ok((remaining, source))
}
fn script_with_parenthesis_end(starting_parenthesis_depth: BracketDepth) -> impl Matcher {
move |input: OrgSource<'_>| _script_with_parenthesis_end(input, starting_parenthesis_depth)
}
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn _script_with_parenthesis_end<'s>(
input: OrgSource<'s>,
starting_parenthesis_depth: BracketDepth,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
let current_depth = input.get_parenthesis_depth() - starting_parenthesis_depth;
if current_depth < 0 {
// This shouldn't be possible because if depth is 0 then a closing bracket should end the citation.
unreachable!("Exceeded citation key suffix bracket depth.")
}
if current_depth == 0 {
let close_parenthesis = tag::<&str, OrgSource<'_>, CustomError<OrgSource<'_>>>(")")(input);
if close_parenthesis.is_ok() {
return close_parenthesis;
}
}
Err(nom::Err::Error(CustomError::MyError(MyError(
"No script parenthesis end.".into(),
))))
}

View File

@ -312,7 +312,7 @@ fn post<'b, 'g, 'r, 's>(
_context: RefContext<'b, 'g, '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, ()))
}