From f1bd7f2d1bfc6c1513dfe435979aabaea5ec3262 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Sun, 23 Apr 2023 16:12:34 -0400 Subject: [PATCH 1/9] Add support for rust-coreutils in integration test script. --- org_mode_samples/regular_link/simple.org | 3 +++ scripts/run_integration_test.bash | 4 +++- src/parser/mod.rs | 1 + src/parser/regular_link.rs | 11 +++++++++++ 4 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 org_mode_samples/regular_link/simple.org create mode 100644 src/parser/regular_link.rs diff --git a/org_mode_samples/regular_link/simple.org b/org_mode_samples/regular_link/simple.org new file mode 100644 index 0000000..ad63ddb --- /dev/null +++ b/org_mode_samples/regular_link/simple.org @@ -0,0 +1,3 @@ +[[https://fizz.buzz/]] + +[[https://fizz.buzz][super cool website]] diff --git a/scripts/run_integration_test.bash b/scripts/run_integration_test.bash index ca16183..7a96aab 100755 --- a/scripts/run_integration_test.bash +++ b/scripts/run_integration_test.bash @@ -4,6 +4,8 @@ set -euo pipefail IFS=$'\n\t' DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +REALPATH=$(command -v uu-realpath || command -v realpath) + samples_dir=$(readlink -f "$DIR/../org_mode_samples") function get_test_names { @@ -11,7 +13,7 @@ function get_test_names { do if [ -e "$test_file" ]; then test_file_full_path=$(readlink -f "$test_file") - relative_to_samples=$(realpath --relative-to "$samples_dir" "$test_file_full_path") + relative_to_samples=$($REALPATH --relative-to "$samples_dir" "$test_file_full_path") without_extension="${relative_to_samples%.org}" echo "${without_extension/\//_}" | tr '[:upper:]' '[:lower:]' else diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 0d5e2a6..208d9c6 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -26,6 +26,7 @@ mod plain_list; mod plain_text; mod planning; mod property_drawer; +mod regular_link; pub mod sexp; mod source; mod table; diff --git a/src/parser/regular_link.rs b/src/parser/regular_link.rs new file mode 100644 index 0000000..11b5989 --- /dev/null +++ b/src/parser/regular_link.rs @@ -0,0 +1,11 @@ +use super::Context; +use super::RegularLink; +use crate::error::Res; + +#[tracing::instrument(ret, level = "debug")] +pub fn regular_link<'r, 's>( + context: Context<'r, 's>, + input: &'s str, +) -> Res<&'s str, RegularLink<'s>> { + todo!() +} From 3600f46e3be0350de2a5f0ee9d78a2cbb09ad0b2 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Sun, 23 Apr 2023 16:17:52 -0400 Subject: [PATCH 2/9] Initial code structure for regular links. --- src/compare/diff.rs | 20 +++++++++++++++----- src/parser/object.rs | 6 ++++++ 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/compare/diff.rs b/src/compare/diff.rs index 1f13463..80df736 100644 --- a/src/compare/diff.rs +++ b/src/compare/diff.rs @@ -1071,13 +1071,23 @@ fn compare_strike_through<'s>( } fn compare_regular_link<'s>( - _source: &'s str, - _emacs: &'s Token<'s>, - _rust: &'s RegularLink<'s>, + source: &'s str, + emacs: &'s Token<'s>, + rust: &'s RegularLink<'s>, ) -> Result> { + let mut this_status = DiffStatus::Good; + let emacs_name = "link"; + if assert_name(emacs, emacs_name).is_err() { + this_status = DiffStatus::Bad; + } + + if assert_bounds(source, emacs, rust).is_err() { + this_status = DiffStatus::Bad; + } + Ok(DiffResult { - status: DiffStatus::Good, - name: "regular-link".to_owned(), + status: this_status, + name: emacs_name.to_owned(), message: None, children: Vec::new(), }) diff --git a/src/parser/object.rs b/src/parser/object.rs index 5a3ec31..370ed50 100644 --- a/src/parser/object.rs +++ b/src/parser/object.rs @@ -111,3 +111,9 @@ impl<'s> Source<'s> for Verbatim<'s> { self.source } } + +impl<'s> Source<'s> for RegularLink<'s> { + fn get_source(&'s self) -> &'s str { + self.source + } +} From 8a828195bd7f29af01947407991ee5d163bc9123 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Sun, 23 Apr 2023 16:53:02 -0400 Subject: [PATCH 3/9] Implement all of regular link except for pathreg. --- src/parser/object.rs | 5 +-- src/parser/object_parser.rs | 22 ++++++++++- src/parser/regular_link.rs | 76 +++++++++++++++++++++++++++++++++++++ 3 files changed, 98 insertions(+), 5 deletions(-) diff --git a/src/parser/object.rs b/src/parser/object.rs index 370ed50..932a0bd 100644 --- a/src/parser/object.rs +++ b/src/parser/object.rs @@ -2,17 +2,14 @@ use super::source::Source; #[derive(Debug)] pub enum Object<'s> { + RegularLink(RegularLink<'s>), Bold(Bold<'s>), Italic(Italic<'s>), Underline(Underline<'s>), StrikeThrough(StrikeThrough<'s>), Code(Code<'s>), Verbatim(Verbatim<'s>), - PlainText(PlainText<'s>), - - #[allow(dead_code)] - RegularLink(RegularLink<'s>), } #[derive(Debug)] diff --git a/src/parser/object_parser.rs b/src/parser/object_parser.rs index a4ba457..ff2fea1 100644 --- a/src/parser/object_parser.rs +++ b/src/parser/object_parser.rs @@ -4,6 +4,7 @@ use nom::combinator::not; use super::parser_with_context::parser_with_context; use super::plain_text::plain_text; +use super::regular_link::regular_link; use super::Context; use crate::error::Res; use crate::parser::object::Object; @@ -19,6 +20,10 @@ pub fn standard_set_object<'r, 's>( alt(( parser_with_context!(text_markup)(context), + map( + parser_with_context!(regular_link)(context), + Object::RegularLink, + ), map(parser_with_context!(plain_text)(context), Object::PlainText), ))(input) } @@ -43,5 +48,20 @@ pub fn any_object_except_plain_text<'r, 's>( input: &'s str, ) -> Res<&'s str, Object<'s>> { // Used for exit matchers so this does not check exit matcher condition. - alt((parser_with_context!(text_markup)(context),))(input) + alt(( + parser_with_context!(text_markup)(context), + map( + parser_with_context!(regular_link)(context), + Object::RegularLink, + ), + ))(input) +} + +#[tracing::instrument(ret, level = "debug")] +pub fn regular_link_description_object_set<'r, 's>( + context: Context<'r, 's>, + input: &'s str, +) -> Res<&'s str, Object<'s>> { + // TODO: minimal set of objects as well as export snippets, inline babel calls, inline source blocks, macros, and statistics cookies. It can also contain another link, but only when it is a plain or angle link. It can contain square brackets, but not ]] + alt((parser_with_context!(minimal_set_object)(context),))(input) } diff --git a/src/parser/regular_link.rs b/src/parser/regular_link.rs index 11b5989..9b3084f 100644 --- a/src/parser/regular_link.rs +++ b/src/parser/regular_link.rs @@ -1,11 +1,87 @@ +use nom::branch::alt; +use nom::bytes::complete::tag; +use nom::combinator::verify; +use nom::multi::many_till; + +use super::parser_with_context::parser_with_context; +use super::util::get_consumed; use super::Context; +use super::Object; use super::RegularLink; use crate::error::Res; +use crate::parser::exiting::ExitClass; +use crate::parser::object_parser::regular_link_description_object_set; +use crate::parser::parser_context::ContextElement; +use crate::parser::parser_context::ExitMatcherNode; +use crate::parser::util::exit_matcher_parser; #[tracing::instrument(ret, level = "debug")] pub fn regular_link<'r, 's>( context: Context<'r, 's>, input: &'s str, ) -> Res<&'s str, RegularLink<'s>> { + alt(( + parser_with_context!(regular_link_without_description)(context), + parser_with_context!(regular_link_with_description)(context), + ))(input) +} + +#[tracing::instrument(ret, level = "debug")] +pub fn regular_link_without_description<'r, 's>( + context: Context<'r, 's>, + input: &'s str, +) -> Res<&'s str, RegularLink<'s>> { + let (remaining, _opening_bracket) = tag("[[")(input)?; + let (remaining, _path) = pathreg(context, remaining)?; + let (remaining, _closing_bracket) = tag("]]")(remaining)?; + let source = get_consumed(input, remaining); + Ok((remaining, RegularLink { source })) +} + +#[tracing::instrument(ret, level = "debug")] +pub fn regular_link_with_description<'r, 's>( + context: Context<'r, 's>, + input: &'s str, +) -> Res<&'s str, RegularLink<'s>> { + let (remaining, _opening_bracket) = tag("[[")(input)?; + let (remaining, _path) = pathreg(context, remaining)?; + let (remaining, _closing_bracket) = tag("][")(remaining)?; + let (remaining, _description) = description(context, remaining)?; + let (remaining, _closing_bracket) = tag("]]")(remaining)?; + let source = get_consumed(input, remaining); + Ok((remaining, RegularLink { source })) +} + +#[tracing::instrument(ret, level = "debug")] +pub fn pathreg<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s str, &'s str> { + let (remaining, _opening_bracket) = tag("[[")(input)?; + // pathreg todo!() } + +#[tracing::instrument(ret, level = "debug")] +pub fn description<'r, 's>( + context: Context<'r, 's>, + input: &'s str, +) -> Res<&'s str, Vec>> { + let (remaining, _opening_bracket) = tag("[[")(input)?; + let parser_context = + context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { + class: ExitClass::Beta, + exit_matcher: &description_end, + })); + let (remaining, (children, _exit_contents)) = verify( + many_till( + parser_with_context!(regular_link_description_object_set)(&parser_context), + parser_with_context!(exit_matcher_parser)(&parser_context), + ), + |(children, _exit_contents)| !children.is_empty(), + )(remaining)?; + + Ok((remaining, children)) +} + +#[tracing::instrument(ret, level = "debug")] +fn description_end<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s str, &'s str> { + tag("]]")(input) +} From b4d44531868521b13d18403688248795aab1e786 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Sun, 23 Apr 2023 17:37:35 -0400 Subject: [PATCH 4/9] Just doing a simple match everything for path reg. --- src/parser/regular_link.rs | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/parser/regular_link.rs b/src/parser/regular_link.rs index 9b3084f..8793f3f 100644 --- a/src/parser/regular_link.rs +++ b/src/parser/regular_link.rs @@ -1,7 +1,14 @@ use nom::branch::alt; +use nom::bytes::complete::escaped; use nom::bytes::complete::tag; +use nom::bytes::complete::take_till1; +use nom::character::complete::line_ending; +use nom::character::complete::one_of; +use nom::character::complete::space0; +use nom::combinator::opt; use nom::combinator::verify; use nom::multi::many_till; +use nom::sequence::tuple; use super::parser_with_context::parser_with_context; use super::util::get_consumed; @@ -54,9 +61,15 @@ pub fn regular_link_with_description<'r, 's>( #[tracing::instrument(ret, level = "debug")] pub fn pathreg<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s str, &'s str> { - let (remaining, _opening_bracket) = tag("[[")(input)?; - // pathreg - todo!() + let (remaining, path) = escaped( + take_till1(|c| match c { + '\\' | ']' => true, + _ => false, + }), + '\\', + one_of(r#"]"#), + )(input)?; + Ok((remaining, path)) } #[tracing::instrument(ret, level = "debug")] From 87be28ed15d20a2e68fd3410fd1c1c9ea5969b84 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Mon, 24 Apr 2023 16:05:46 -0400 Subject: [PATCH 5/9] Fix matching of description in links. --- src/parser/regular_link.rs | 3 +-- toy_language.txt | 4 +++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/parser/regular_link.rs b/src/parser/regular_link.rs index 8793f3f..5432ac0 100644 --- a/src/parser/regular_link.rs +++ b/src/parser/regular_link.rs @@ -77,7 +77,6 @@ pub fn description<'r, 's>( context: Context<'r, 's>, input: &'s str, ) -> Res<&'s str, Vec>> { - let (remaining, _opening_bracket) = tag("[[")(input)?; let parser_context = context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode { class: ExitClass::Beta, @@ -89,7 +88,7 @@ pub fn description<'r, 's>( parser_with_context!(exit_matcher_parser)(&parser_context), ), |(children, _exit_contents)| !children.is_empty(), - )(remaining)?; + )(input)?; Ok((remaining, children)) } diff --git a/toy_language.txt b/toy_language.txt index d990b43..ad63ddb 100644 --- a/toy_language.txt +++ b/toy_language.txt @@ -1 +1,3 @@ -foo *bar baz * lorem* ipsum +[[https://fizz.buzz/]] + +[[https://fizz.buzz][super cool website]] From 28759edb3b70f780d3734cb0c2972e25b281a65e Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Mon, 24 Apr 2023 16:19:29 -0400 Subject: [PATCH 6/9] Remove unused imports. --- src/parser/regular_link.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/parser/regular_link.rs b/src/parser/regular_link.rs index 5432ac0..c0d94b8 100644 --- a/src/parser/regular_link.rs +++ b/src/parser/regular_link.rs @@ -2,13 +2,13 @@ use nom::branch::alt; use nom::bytes::complete::escaped; use nom::bytes::complete::tag; use nom::bytes::complete::take_till1; -use nom::character::complete::line_ending; + use nom::character::complete::one_of; -use nom::character::complete::space0; -use nom::combinator::opt; + + use nom::combinator::verify; use nom::multi::many_till; -use nom::sequence::tuple; + use super::parser_with_context::parser_with_context; use super::util::get_consumed; From b2b1e9272cd3c4bd4c4126c6a2d0528a554d756b Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Mon, 24 Apr 2023 16:19:48 -0400 Subject: [PATCH 7/9] Format. --- src/parser/regular_link.rs | 4 ---- src/parser/text_markup.rs | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/parser/regular_link.rs b/src/parser/regular_link.rs index c0d94b8..a43f509 100644 --- a/src/parser/regular_link.rs +++ b/src/parser/regular_link.rs @@ -2,14 +2,10 @@ use nom::branch::alt; use nom::bytes::complete::escaped; use nom::bytes::complete::tag; use nom::bytes::complete::take_till1; - use nom::character::complete::one_of; - - use nom::combinator::verify; use nom::multi::many_till; - use super::parser_with_context::parser_with_context; use super::util::get_consumed; use super::Context; diff --git a/src/parser/text_markup.rs b/src/parser/text_markup.rs index 1c36c51..18cb60b 100644 --- a/src/parser/text_markup.rs +++ b/src/parser/text_markup.rs @@ -25,6 +25,7 @@ use crate::parser::parser_with_context::parser_with_context; use crate::parser::util::exit_matcher_parser; use crate::parser::util::get_consumed; use crate::parser::util::get_one_before; +use crate::parser::util::preceded_by_whitespace; use crate::parser::Bold; use crate::parser::Code; use crate::parser::Italic; @@ -32,7 +33,6 @@ use crate::parser::Object; use crate::parser::StrikeThrough; use crate::parser::Underline; use crate::parser::Verbatim; -use crate::parser::util::preceded_by_whitespace; #[tracing::instrument(ret, level = "debug")] pub fn text_markup<'r, 's>(context: Context<'r, 's>, input: &'s str) -> Res<&'s str, Object<'s>> { From c6403423cfcdf384882a58b65a1223854dd96003 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Mon, 24 Apr 2023 16:25:05 -0400 Subject: [PATCH 8/9] Looks like link should consume trailing whitespace. --- build.rs | 2 -- toy_language.txt | 14 ++++++++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/build.rs b/build.rs index fe47ad4..bb99b66 100644 --- a/build.rs +++ b/build.rs @@ -78,9 +78,7 @@ fn is_expect_fail(name: &str) -> Option<&str> { "element_container_priority_footnote_definition_greater_block" => Some("Need to implement subscript."), "element_container_priority_greater_block_greater_block" => Some("Need to implement subscript."), "element_container_priority_section_greater_block" => Some("Need to implement subscript."), - "keyword_affiliated_keyword" => Some("Need to implement link."), "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."), - "text_markup_opening_and_closing" => Some("Need to implement bold and link."), _ => None, } } diff --git a/toy_language.txt b/toy_language.txt index ad63ddb..fc07a3b 100644 --- a/toy_language.txt +++ b/toy_language.txt @@ -1,3 +1,13 @@ -[[https://fizz.buzz/]] +prologue *goes here* I guess *bold +text* -[[https://fizz.buzz][super cool website]] +bold*wont* start *or stop*when there is text outside it + +I guess *regular + +text* + +[[foo][foo *bar]] baz* car + + +*nesting *bold entrances* and* exits From f9d83ee09dabf5366d659266060ff32f83eda949 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Mon, 24 Apr 2023 16:28:18 -0400 Subject: [PATCH 9/9] Consume trailing whitespace for links. --- src/parser/regular_link.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/parser/regular_link.rs b/src/parser/regular_link.rs index a43f509..321addd 100644 --- a/src/parser/regular_link.rs +++ b/src/parser/regular_link.rs @@ -3,6 +3,7 @@ use nom::bytes::complete::escaped; use nom::bytes::complete::tag; use nom::bytes::complete::take_till1; use nom::character::complete::one_of; +use nom::character::complete::space0; use nom::combinator::verify; use nom::multi::many_till; @@ -37,6 +38,7 @@ pub fn regular_link_without_description<'r, 's>( let (remaining, _opening_bracket) = tag("[[")(input)?; let (remaining, _path) = pathreg(context, remaining)?; let (remaining, _closing_bracket) = tag("]]")(remaining)?; + let (remaining, _trailing_whitespace) = space0(remaining)?; let source = get_consumed(input, remaining); Ok((remaining, RegularLink { source })) } @@ -51,6 +53,7 @@ pub fn regular_link_with_description<'r, 's>( let (remaining, _closing_bracket) = tag("][")(remaining)?; let (remaining, _description) = description(context, remaining)?; let (remaining, _closing_bracket) = tag("]]")(remaining)?; + let (remaining, _trailing_whitespace) = space0(remaining)?; let source = get_consumed(input, remaining); Ok((remaining, RegularLink { source })) }