16 Commits

Author SHA1 Message Date
Tom Alexander
678106bb65 Use tekton matrix for specifying all combinations of features for the build CI job.
All checks were successful
rust-test Build rust-test has succeeded
2023-08-25 03:56:08 -04:00
Tom Alexander
19432d91ab Get the emacs and org-mode versions when launching the compare script.
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-25 03:11:19 -04:00
Tom Alexander
16a107eebb Update org-mode version. 2023-08-25 02:56:28 -04:00
Tom Alexander
77348b560c Parameterize the emacs and org-mode versions in the dockerfiles.
All checks were successful
rustfmt Build rustfmt has succeeded
rust-build Build rust-build has succeeded
rust-test Build rust-test has succeeded
2023-08-25 02:03:35 -04:00
Tom Alexander
fc79507ef3 Merge branch 'plain_list_perf_investigation'
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-25 01:10:04 -04:00
Tom Alexander
9c1e6ccc97 Add a detect_element function.
All checks were successful
rust-test Build rust-test has succeeded
rust-build Build rust-build has succeeded
This is an optimization. When you have something like plain text which ends when it hits the next element, we only need to parse enough to detect that an element is about to occur. For elements like plain lists, this is as simple as parsing a line starting with optional whitespace and then a bullet, which avoids parsing the entire plain list tree. The benefit is most noticeable in deeply nested plain lists.
2023-08-25 01:07:53 -04:00
Tom Alexander
0dbc8f0925 Remove redundant exit matcher checks.
All checks were successful
rust-test Build rust-test has succeeded
rust-build Build rust-build has succeeded
2023-08-25 00:01:56 -04:00
Tom Alexander
02fe10fba3 Move objects to a lower exit class.
All checks were successful
rust-test Build rust-test has succeeded
rust-build Build rust-build has succeeded
Paragraph's exit matcher which detects elements was causing the plain list parser to exit after the first item was parsed which was causing significant amounts of re-parsing.
2023-08-24 23:34:23 -04:00
Tom Alexander
33d7ae03d1 Add a TODO.
All checks were successful
rust-test Build rust-test has succeeded
rust-build Build rust-build has succeeded
2023-08-24 21:35:34 -04:00
Tom Alexander
03faa7257f Move the indent level for plain list's exit matcher to const fn instead of grabbing from the context.
All checks were successful
rust-test Build rust-test has succeeded
rust-build Build rust-build has succeeded
This made a slight improvement to performance.
2023-08-24 20:50:24 -04:00
Tom Alexander
ae3510abd5 Do not cast lesser block name to lowercase at runtime.
This reduced the runtime of my problematic test case from 6.9 seconds to 6 seconds.
2023-08-24 20:10:43 -04:00
fluxcdbot
ad3f47864a CI: autofix rust code.
Some checks failed
rustfmt Build rustfmt has succeeded
rust-test Build rust-test has succeeded
rust-build Build rust-build has failed
2023-08-24 23:43:41 +00:00
Tom Alexander
533ef2a9a8 Merge branch 'wrapped_input'
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-24 19:40:55 -04:00
Tom Alexander
cf37bc4111 Remove unnecessary context from some util functions.
All checks were successful
rust-test Build rust-test has succeeded
rust-build Build rust-build has succeeded
2023-08-24 19:29:00 -04:00
Tom Alexander
e5224cda63 Removing dead code.
All checks were successful
rust-test Build rust-test has succeeded
rust-build Build rust-build has succeeded
2023-08-24 18:40:25 -04:00
Tom Alexander
64e3481660 Update get_consumed to use the new wrapped input type. 2023-08-24 18:33:40 -04:00
53 changed files with 396 additions and 343 deletions

View File

@@ -14,10 +14,6 @@ spec:
- name: path-to-dockerfile
description: The path to the Dockerfile
type: string
- name: command
type: array
description: Command to run.
default: []
tasks:
- name: report-pending
taskRef:
@@ -81,9 +77,19 @@ spec:
workspace: docker-credentials
runAfter:
- fetch-repository
- name: run-image-none
- name: build-organic
taskRef:
name: run-docker-image
matrix:
params:
- name: feature-compare
value:
- "true"
- "false"
- name: feature-tracing
value:
- "true"
- "false"
workspaces:
- name: source
workspace: git-source
@@ -93,77 +99,21 @@ spec:
- build-image
params:
- name: command
value: ["$(params.command[*])"]
value: ["/bin/sh", "-c"]
- name: args
value: ["--no-default-features"]
- name: docker-image
value: "$(params.image-name):$(tasks.fetch-repository.results.commit)"
- name: run-image-tracing
taskRef:
name: run-docker-image
workspaces:
- name: source
workspace: git-source
- name: cargo-cache
workspace: cargo-cache
runAfter:
- run-image-none
params:
- name: command
value: ["$(params.command[*])"]
- name: args
value: ["--no-default-features", "--features", "tracing"]
- name: docker-image
value: "$(params.image-name):$(tasks.fetch-repository.results.commit)"
- name: run-image-compare
taskRef:
name: run-docker-image
workspaces:
- name: source
workspace: git-source
- name: cargo-cache
workspace: cargo-cache
runAfter:
- run-image-tracing
params:
- name: command
value: ["$(params.command[*])"]
- name: args
value: ["--no-default-features", "--features", "compare"]
- name: docker-image
value: "$(params.image-name):$(tasks.fetch-repository.results.commit)"
- name: run-image-default
taskRef:
name: run-docker-image
workspaces:
- name: source
workspace: git-source
- name: cargo-cache
workspace: cargo-cache
runAfter:
- run-image-compare
params:
- name: command
value: ["$(params.command[*])"]
- name: args
value: []
- name: docker-image
value: "$(params.image-name):$(tasks.fetch-repository.results.commit)"
- name: run-image-all
taskRef:
name: run-docker-image
workspaces:
- name: source
workspace: git-source
- name: cargo-cache
workspace: cargo-cache
runAfter:
- run-image-default
params:
- name: command
value: ["$(params.command[*])"]
- name: args
value: ["--no-default-features", "--features", "tracing,compare"]
value:
- |
set -euo pipefail
IFS=$$'\n\t'
features=()
if [ $(params.feature-compare) = "true" ]; then features+=(compare); fi
if [ $(params.feature-tracing) = "true" ]; then features+=(tracing); fi
if [ $${#features[@]} -eq 0 ]; then
exec cargo build --no-default-features
else
featurelist=$$(IFS="," ; echo "$${features[*]}")
exec cargo build --no-default-features --features "$$featurelist"
fi
- name: docker-image
value: "$(params.image-name):$(tasks.fetch-repository.results.commit)"
finally:
@@ -256,5 +206,3 @@ spec:
value: docker/organic_build/
- name: path-to-dockerfile
value: docker/organic_build/Dockerfile
- name: command
value: [cargo, build]

View File

@@ -75,9 +75,6 @@ fn is_expect_fail(name: &str) -> Option<&str> {
"autogen_greater_element_drawer_drawer_with_headline_inside" => Some("Apparently lines with :end: become their own paragraph. This odd behavior needs to be investigated more."),
"autogen_element_container_priority_footnote_definition_dynamic_block" => Some("Apparently broken begin lines become their own paragraph."),
"autogen_lesser_element_paragraphs_paragraph_with_backslash_line_breaks" => Some("The text we're getting out of the parse tree is already processed to remove line breaks, so our comparison needs to take that into account."),
"autogen_greater_element_plain_list_trailing_whitespace_ownership_test_case_1" => Some("Seeing odd behavior about whitespace ownership."), // https://list.orgmode.org/9372527e-3852-419e-936a-7b4dd38cc847@app.fastmail.com/
"autogen_greater_element_plain_list_trailing_whitespace_ownership_test_case_3" => Some("Seeing odd behavior about whitespace ownership."), // https://list.orgmode.org/9372527e-3852-419e-936a-7b4dd38cc847@app.fastmail.com/
"autogen_greater_element_plain_list_trailing_whitespace_ownership_test_case_4" => Some("Seeing odd behavior about whitespace ownership."), // https://list.orgmode.org/9372527e-3852-419e-936a-7b4dd38cc847@app.fastmail.com/
_ => None,
}
}

View File

@@ -1,11 +1,10 @@
FROM alpine:3.17 AS build
RUN apk add --no-cache build-base musl-dev git autoconf make texinfo gnutls-dev ncurses-dev gawk
FROM build AS build-emacs
RUN git clone --depth 1 --branch emacs-29.1 https://git.savannah.gnu.org/git/emacs.git /root/emacs
ARG EMACS_VERSION=emacs-29.1
RUN git clone --depth 1 --branch $EMACS_VERSION https://git.savannah.gnu.org/git/emacs.git /root/emacs
WORKDIR /root/emacs
RUN mkdir /root/dist
RUN ./autogen.sh
@@ -15,9 +14,12 @@ RUN make DESTDIR="/root/dist" install
FROM build AS build-org-mode
ARG ORG_VERSION=7bdec435ff5d86220d13c431e799c5ed44a57da1
COPY --from=build-emacs /root/dist/ /
RUN mkdir /root/dist
RUN mkdir /root/org-mode && git -C /root/org-mode init --initial-branch=main && git -C /root/org-mode remote add origin https://git.savannah.gnu.org/git/emacs/org-mode.git && git -C /root/org-mode fetch origin 299193bf091a63474fc8036bd31de51800a2555a && git -C /root/org-mode checkout FETCH_HEAD
# Savannah does not allow fetching specific revisions, so we're going to have to put unnecessary load on their server by cloning main and then checking out the revision we want.
RUN git clone https://git.savannah.gnu.org/git/emacs/org-mode.git /root/org-mode && git -C /root/org-mode checkout $ORG_VERSION
# RUN mkdir /root/org-mode && git -C /root/org-mode init --initial-branch=main && git -C /root/org-mode remote add origin https://git.savannah.gnu.org/git/emacs/org-mode.git && git -C /root/org-mode fetch origin $ORG_VERSION && git -C /root/org-mode checkout FETCH_HEAD
WORKDIR /root/org-mode
RUN make compile
RUN make DESTDIR="/root/dist" install

0
foo Normal file
View File

View File

@@ -3,3 +3,5 @@ mod parse;
mod util;
pub use diff::compare_document;
pub use parse::emacs_parse_org_document;
pub use parse::get_emacs_version;
pub use parse::get_org_mode_version;

View File

@@ -49,3 +49,40 @@ where
}
output
}
pub fn get_emacs_version() -> Result<String, Box<dyn std::error::Error>> {
let elisp_script = r#"(progn
(message "%s" (version))
)"#;
let mut cmd = Command::new("emacs");
let proc = cmd
.arg("-q")
.arg("--no-site-file")
.arg("--no-splash")
.arg("--batch")
.arg("--eval")
.arg(elisp_script);
let out = proc.output()?;
out.status.exit_ok()?;
Ok(String::from_utf8(out.stderr)?)
}
pub fn get_org_mode_version() -> Result<String, Box<dyn std::error::Error>> {
let elisp_script = r#"(progn
(org-mode)
(message "%s" (org-version nil t nil))
)"#;
let mut cmd = Command::new("emacs");
let proc = cmd
.arg("-q")
.arg("--no-site-file")
.arg("--no-splash")
.arg("--batch")
.arg("--eval")
.arg(elisp_script);
let out = proc.output()?;
out.status.exit_ok()?;
Ok(String::from_utf8(out.stderr)?)
}

View File

@@ -42,6 +42,39 @@ pub fn assert_bounds<'s, S: Source<'s>>(
emacs: &'s Token<'s>,
rust: &'s S,
) -> Result<(), Box<dyn std::error::Error>> {
let standard_properties = get_standard_properties(emacs)?;
let (begin, end) = (
standard_properties
.begin
.ok_or("Token should have a begin.")?,
standard_properties
.end
.ok_or("Token should have a begin.")?,
);
let (rust_begin, rust_end) = get_offsets(source, rust);
if (rust_begin + 1) != begin || (rust_end + 1) != end {
Err(format!("Rust bounds ({rust_begin}, {rust_end}) do not match emacs bounds ({emacs_begin}, {emacs_end})", rust_begin = rust_begin + 1, rust_end = rust_end + 1, emacs_begin=begin, emacs_end=end))?;
}
Ok(())
}
struct StandardProperties {
begin: Option<usize>,
#[allow(dead_code)]
post_affiliated: Option<usize>,
#[allow(dead_code)]
contents_begin: Option<usize>,
#[allow(dead_code)]
contents_end: Option<usize>,
end: Option<usize>,
#[allow(dead_code)]
post_blank: Option<usize>,
}
fn get_standard_properties<'s>(
emacs: &'s Token<'s>,
) -> Result<StandardProperties, Box<dyn std::error::Error>> {
let children = emacs.as_list()?;
let attributes_child = children
.iter()
@@ -49,34 +82,60 @@ pub fn assert_bounds<'s, S: Source<'s>>(
.ok_or("Should have an attributes child.")?;
let attributes_map = attributes_child.as_map()?;
let standard_properties = attributes_map.get(":standard-properties");
let (begin, end) = if standard_properties.is_some() {
let std_props = standard_properties
Ok(if standard_properties.is_some() {
let mut std_props = standard_properties
.expect("if statement proves its Some")
.as_vector()?;
let begin = std_props
.get(0)
.ok_or("Missing first element in standard properties")?
.as_atom()?;
let end = std_props
.get(1)
.ok_or("Missing first element in standard properties")?
.as_atom()?;
(begin, end)
.as_vector()?
.into_iter();
let begin = maybe_token_to_usize(std_props.next())?;
let post_affiliated = maybe_token_to_usize(std_props.next())?;
let contents_begin = maybe_token_to_usize(std_props.next())?;
let contents_end = maybe_token_to_usize(std_props.next())?;
let end = maybe_token_to_usize(std_props.next())?;
let post_blank = maybe_token_to_usize(std_props.next())?;
StandardProperties {
begin,
post_affiliated,
contents_begin,
contents_end,
end,
post_blank,
}
} else {
let begin = attributes_map
.get(":begin")
.ok_or("Missing :begin attribute.")?
.as_atom()?;
let end = attributes_map
.get(":end")
.ok_or("Missing :end attribute.")?
.as_atom()?;
(begin, end)
};
let (rust_begin, rust_end) = get_offsets(source, rust);
if (rust_begin + 1).to_string() != begin || (rust_end + 1).to_string() != end {
Err(format!("Rust bounds ({rust_begin}, {rust_end}) do not match emacs bounds ({emacs_begin}, {emacs_end})", rust_begin = rust_begin + 1, rust_end = rust_end + 1, emacs_begin=begin, emacs_end=end))?;
}
Ok(())
let begin = maybe_token_to_usize(attributes_map.get(":begin").map(|token| *token))?;
let end = maybe_token_to_usize(attributes_map.get(":end").map(|token| *token))?;
let contents_begin =
maybe_token_to_usize(attributes_map.get(":contents-begin").map(|token| *token))?;
let contents_end =
maybe_token_to_usize(attributes_map.get(":contents-end").map(|token| *token))?;
let post_blank =
maybe_token_to_usize(attributes_map.get(":post-blank").map(|token| *token))?;
let post_affiliated =
maybe_token_to_usize(attributes_map.get(":post-affiliated").map(|token| *token))?;
StandardProperties {
begin,
post_affiliated,
contents_begin,
contents_end,
end,
post_blank,
}
})
}
fn maybe_token_to_usize(
token: Option<&Token<'_>>,
) -> Result<Option<usize>, Box<dyn std::error::Error>> {
Ok(token
.map(|token| token.as_atom())
.map_or(Ok(None), |r| r.map(Some))?
.map(|val| {
if val == "nil" {
None
} else {
Some(val.parse::<usize>())
}
})
.flatten() // Outer option is whether or not the param exists, inner option is whether or not it is nil
.map_or(Ok(None), |r| r.map(Some))?)
}

View File

@@ -7,6 +7,10 @@ mod compare;
pub use compare::compare_document;
#[cfg(feature = "compare")]
pub use compare::emacs_parse_org_document;
#[cfg(feature = "compare")]
pub use compare::get_emacs_version;
#[cfg(feature = "compare")]
pub use compare::get_org_mode_version;
mod error;
pub mod parser;

View File

@@ -7,6 +7,10 @@ use organic::compare_document;
#[cfg(feature = "compare")]
use organic::emacs_parse_org_document;
#[cfg(feature = "compare")]
use organic::get_emacs_version;
#[cfg(feature = "compare")]
use organic::get_org_mode_version;
#[cfg(feature = "compare")]
use organic::parser::sexp::sexp_with_padding;
#[cfg(feature = "tracing")]
@@ -49,10 +53,14 @@ fn read_stdin_to_string() -> Result<String, Box<dyn std::error::Error>> {
#[cfg(feature = "compare")]
fn run_compare<P: AsRef<str>>(org_contents: P) -> Result<(), Box<dyn std::error::Error>> {
let (remaining, rust_parsed) = document(org_contents.as_ref()).expect("Org Parse failure");
let emacs_version = get_emacs_version()?;
let org_mode_version = get_org_mode_version()?;
eprintln!("Using emacs version: {}", emacs_version.trim());
eprintln!("Using org-mode version: {}", org_mode_version.trim());
let (remaining, rust_parsed) = document(org_contents.as_ref()).map_err(|e| e.to_string())?;
let org_sexp = emacs_parse_org_document(org_contents.as_ref())?;
let (_remaining, parsed_sexp) =
sexp_with_padding(org_sexp.as_str()).expect("Sexp Parse failure");
sexp_with_padding(org_sexp.as_str()).map_err(|e| e.to_string())?;
println!("{}\n\n\n", org_contents.as_ref());
println!("{}", org_sexp);
@@ -74,8 +82,10 @@ fn run_compare<P: AsRef<str>>(org_contents: P) -> Result<(), Box<dyn std::error:
#[cfg(not(feature = "compare"))]
fn run_compare<P: AsRef<str>>(org_contents: P) -> Result<(), Box<dyn std::error::Error>> {
eprintln!("This program was built with compare disabled. Dumping the AST from rust.");
let (remaining, rust_parsed) = document(org_contents.as_ref()).expect("Org Parse failure");
eprintln!(
"This program was built with compare disabled. Only parsing with organic, not comparing."
);
let (remaining, rust_parsed) = document(org_contents.as_ref()).map_err(|e| e.to_string())?;
println!("{:#?}", rust_parsed);
Ok(())
}

View File

@@ -44,7 +44,7 @@ fn path_angle<'r, 's>(
) -> Res<OrgSource<'s>, OrgSource<'s>> {
let parser_context =
context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode {
class: ExitClass::Beta,
class: ExitClass::Gamma,
exit_matcher: &path_angle_end,
}));
@@ -56,7 +56,7 @@ fn path_angle<'r, 's>(
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn path_angle_end<'r, 's>(
context: Context<'r, 's>,
_context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
tag(">")(input)

View File

@@ -90,7 +90,7 @@ fn global_prefix<'r, 's>(
depth: 0,
}))
.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode {
class: ExitClass::Beta,
class: ExitClass::Gamma,
exit_matcher: &global_prefix_end,
}));
let (remaining, (children, _exit_contents)) = verify(
@@ -151,7 +151,7 @@ fn global_suffix<'r, 's>(
depth: 0,
}))
.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode {
class: ExitClass::Beta,
class: ExitClass::Gamma,
exit_matcher: &global_suffix_end,
}));
let (remaining, (children, _exit_contents)) = verify(

View File

@@ -76,7 +76,7 @@ fn key_prefix<'r, 's>(
depth: 0,
}))
.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode {
class: ExitClass::Beta,
class: ExitClass::Gamma,
exit_matcher: &key_prefix_end,
}));
let (remaining, (children, _exit_contents)) = verify(
@@ -101,7 +101,7 @@ fn key_suffix<'r, 's>(
depth: 0,
}))
.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode {
class: ExitClass::Beta,
class: ExitClass::Gamma,
exit_matcher: &key_suffix_end,
}));
let (remaining, (children, _exit_contents)) = verify(

View File

@@ -24,7 +24,7 @@ pub fn clock<'r, 's>(
context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, Clock<'s>> {
start_of_line(context, input)?;
start_of_line(input)?;
let (remaining, _leading_whitespace) = space0(input)?;
let (remaining, _clock) = tag_no_case("clock:")(remaining)?;
let (remaining, _gap_whitespace) = space1(remaining)?;
@@ -45,7 +45,7 @@ pub fn clock<'r, 's>(
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn inactive_timestamp_range_duration<'r, 's>(
context: Context<'r, 's>,
_context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
recognize(tuple((
@@ -67,7 +67,7 @@ fn inactive_timestamp_range_duration<'r, 's>(
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn inactive_timestamp<'r, 's>(
context: Context<'r, 's>,
_context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
recognize(tuple((

View File

@@ -52,10 +52,10 @@ pub fn comment<'r, 's>(
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn comment_line<'r, 's>(
context: Context<'r, 's>,
_context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
start_of_line(context, input)?;
start_of_line(input)?;
let (remaining, _indent) = space0(input)?;
let (remaining, (_hash, _leading_whitespace_and_content, _line_ending)) = tuple((
tag("#"),

View File

@@ -16,10 +16,10 @@ use crate::parser::DiarySexp;
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
pub fn diary_sexp<'r, 's>(
context: Context<'r, 's>,
_context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, DiarySexp<'s>> {
start_of_line(context, input)?;
start_of_line(input)?;
let (remaining, _leading_whitespace) = space0(input)?;
let (remaining, _clock) = tag("%%")(remaining)?;
let (remaining, _gap_whitespace) = space0(remaining)?;

View File

@@ -300,10 +300,9 @@ fn headline<'r, 's>(
exit_matcher: &headline_end,
}));
let standard_set_object_matcher = parser_with_context!(standard_set_object)(&parser_context);
let start_of_line_matcher = parser_with_context!(start_of_line)(&parser_context);
let (remaining, (_sol, star_count, ws, title, _line_ending)) = tuple((
start_of_line_matcher,
start_of_line,
many1_count(tag("*")),
space1,
many1(standard_set_object_matcher),

View File

@@ -41,7 +41,7 @@ pub fn drawer<'r, 's>(
"Cannot nest objects of the same element".into(),
))));
}
start_of_line(context, input)?;
start_of_line(input)?;
let (remaining, _leading_whitespace) = space0(input)?;
let (remaining, (_open_colon, drawer_name, _close_colon, _new_line)) = tuple((
tag(":"),
@@ -99,10 +99,10 @@ fn name<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn drawer_end<'r, 's>(
context: Context<'r, 's>,
_context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
start_of_line(context, input)?;
start_of_line(input)?;
recognize(tuple((
space0,
tag_no_case(":end:"),

View File

@@ -42,7 +42,7 @@ pub fn dynamic_block<'r, 's>(
"Cannot nest objects of the same element".into(),
))));
}
start_of_line(context, input)?;
start_of_line(input)?;
let (remaining, _leading_whitespace) = space0(input)?;
let (remaining, (_begin, name, parameters, _ws)) = tuple((
recognize(tuple((tag_no_case("#+begin:"), space1))),
@@ -107,10 +107,10 @@ fn parameters<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn dynamic_block_end<'r, 's>(
context: Context<'r, 's>,
_context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
start_of_line(context, input)?;
start_of_line(input)?;
let (remaining, source) = recognize(tuple((
space0,
tag_no_case("#+end:"),

View File

@@ -21,16 +21,19 @@ use super::lesser_block::src_block;
use super::lesser_block::verse_block;
use super::org_source::OrgSource;
use super::paragraph::paragraph;
use super::plain_list::detect_plain_list;
use super::plain_list::plain_list;
use super::source::SetSource;
use super::util::get_consumed;
use super::util::maybe_consume_trailing_whitespace_if_not_exiting;
use super::Context;
use crate::error::CustomError;
use crate::error::MyError;
use crate::error::Res;
use crate::parser::parser_with_context::parser_with_context;
use crate::parser::table::org_mode_table;
pub fn element(
pub const fn element(
can_be_paragraph: bool,
) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res<OrgSource<'s>, Element<'s>> {
move |context: Context, input: OrgSource<'_>| _element(context, input, can_be_paragraph)
@@ -108,3 +111,26 @@ fn _element<'r, 's>(
Ok((remaining, element))
}
pub const fn detect_element(
can_be_paragraph: bool,
) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res<OrgSource<'s>, ()> {
move |context: Context, input: OrgSource<'_>| _detect_element(context, input, can_be_paragraph)
}
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn _detect_element<'r, 's>(
context: Context<'r, 's>,
input: OrgSource<'s>,
can_be_paragraph: bool,
) -> Res<OrgSource<'s>, ()> {
if detect_plain_list(context, input).is_ok() {
return Ok((input, ()));
}
if _element(context, input, can_be_paragraph).is_ok() {
return Ok((input, ()));
}
return Err(nom::Err::Error(CustomError::MyError(MyError(
"No element detected.".into(),
))));
}

View File

@@ -39,7 +39,7 @@ pub fn entity<'r, 's>(
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn name<'r, 's>(
context: Context<'r, 's>,
_context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
// TODO: This should be defined by org-entities and optionally org-entities-user
@@ -50,7 +50,7 @@ fn name<'r, 's>(
}
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn entity_end<'r, 's>(context: Context<'r, 's>, input: OrgSource<'s>) -> Res<OrgSource<'s>, ()> {
fn entity_end<'r, 's>(_context: Context<'r, 's>, input: OrgSource<'s>) -> Res<OrgSource<'s>, ()> {
let (remaining, _) = alt((eof, recognize(satisfy(|c| !c.is_alphabetic()))))(input)?;
Ok((remaining, ()))

View File

@@ -8,6 +8,9 @@ pub enum ExitClass {
/// Elements who cede priority to alpha elements when matching.
Beta = 300,
/// Elements who cede priority to alpha and beta elements when matching.
Gamma = 4000,
}
impl std::fmt::Display for ExitClass {

View File

@@ -27,7 +27,7 @@ pub fn export_snippet<'r, 's>(
let (remaining, backend_name) = backend(context, remaining)?;
let parser_context =
context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode {
class: ExitClass::Beta,
class: ExitClass::Gamma,
exit_matcher: &export_snippet_end,
}));
let (remaining, backend_contents) = opt(tuple((
@@ -48,7 +48,7 @@ pub fn export_snippet<'r, 's>(
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn backend<'r, 's>(
context: Context<'r, 's>,
_context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
let (remaining, backend_name) =
@@ -71,7 +71,7 @@ fn contents<'r, 's>(
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn export_snippet_end<'r, 's>(
context: Context<'r, 's>,
_context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
tag("@@")(input)

View File

@@ -42,10 +42,10 @@ pub fn fixed_width_area<'r, 's>(
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn fixed_width_area_line<'r, 's>(
context: Context<'r, 's>,
_context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
start_of_line(context, input)?;
start_of_line(input)?;
let (remaining, _indent) = space0(input)?;
let (remaining, (_hash, _leading_whitespace_and_content, _line_ending)) = tuple((
tag(":"),

View File

@@ -39,7 +39,7 @@ pub fn footnote_definition<'r, 's>(
"Cannot nest objects of the same element".into(),
))));
}
start_of_line(context, input)?;
start_of_line(input)?;
// Cannot be indented.
let (remaining, (_lead_in, lbl, _lead_out, _ws)) =
tuple((tag_no_case("[fn:"), label, tag("]"), space0))(input)?;
@@ -80,7 +80,6 @@ fn footnote_definition_end<'r, 's>(
context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
let start_of_line_matcher = parser_with_context!(start_of_line)(context);
let allow_nesting_context =
context.with_additional_node(ContextElement::Context("allow nesting footnotes"));
let footnote_definition_matcher = parser_with_context!(footnote_definition)(
@@ -98,7 +97,7 @@ fn footnote_definition_end<'r, 's>(
footnote_definition_matcher,
))),
recognize(tuple((
start_of_line_matcher,
start_of_line,
verify(many1(blank_line), |lines: &Vec<OrgSource<'_>>| {
lines.len() >= 2
}),

View File

@@ -20,7 +20,6 @@ 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::FootnoteReference;
use crate::parser::Object;
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
pub fn footnote_reference<'r, 's>(
@@ -116,7 +115,7 @@ fn inline_footnote<'r, 's>(
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn footnote_reference_only<'r, 's>(
context: Context<'r, 's>,
_context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, FootnoteReference<'s>> {
let (remaining, _) = tag_no_case("[fn:")(input)?;
@@ -134,11 +133,6 @@ fn footnote_reference_only<'r, 's>(
))
}
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn definition<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, Vec<Object<'s>>> {
Ok((input, vec![]))
}
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn footnote_definition_end<'r, 's>(
context: Context<'r, 's>,

View File

@@ -37,7 +37,7 @@ pub fn greater_block<'r, 's>(
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, GreaterBlock<'s>> {
// TODO: Do I need to differentiate between different greater block types.
start_of_line(context, input)?;
start_of_line(input)?;
let (remaining, _leading_whitespace) = space0(input)?;
let (remaining, (_begin, name)) = tuple((
tag_no_case("#+begin_"),
@@ -125,7 +125,7 @@ fn greater_block_end<'r, 's>(
context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
start_of_line(context, input)?;
start_of_line(input)?;
let current_name: &str = get_context_greater_block_name(context).ok_or(nom::Err::Error(
CustomError::MyError(MyError("Not inside a greater block".into())),
))?;

View File

@@ -16,10 +16,10 @@ use crate::parser::HorizontalRule;
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
pub fn horizontal_rule<'r, 's>(
context: Context<'r, 's>,
_context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, HorizontalRule<'s>> {
start_of_line(context, input)?;
start_of_line(input)?;
let (remaining, rule) = recognize(tuple((
space0,
verify(many1_count(tag("-")), |dashes| *dashes >= 5),

View File

@@ -49,7 +49,7 @@ fn name<'r, 's>(
) -> Res<OrgSource<'s>, OrgSource<'s>> {
let parser_context =
context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode {
class: ExitClass::Beta,
class: ExitClass::Gamma,
exit_matcher: &name_end,
}));
let (remaining, name) = recognize(many_till(
@@ -61,7 +61,7 @@ fn name<'r, 's>(
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn name_end<'r, 's>(
context: Context<'r, 's>,
_context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
recognize(one_of("[("))(input)
@@ -80,7 +80,7 @@ fn header<'r, 's>(
depth: 0,
}))
.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode {
class: ExitClass::Beta,
class: ExitClass::Gamma,
exit_matcher: &header_end,
}));
@@ -131,7 +131,7 @@ fn argument<'r, 's>(
depth: 0,
}))
.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode {
class: ExitClass::Beta,
class: ExitClass::Gamma,
exit_matcher: &argument_end,
}));

View File

@@ -62,7 +62,7 @@ fn lang<'r, 's>(
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn lang_end<'r, 's>(
context: Context<'r, 's>,
_context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
recognize(one_of("[{"))(input)

View File

@@ -19,10 +19,10 @@ use crate::parser::Keyword;
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
pub fn keyword<'r, 's>(
context: Context<'r, 's>,
_context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, Keyword<'s>> {
start_of_line(context, input)?;
start_of_line(input)?;
// TODO: When key is a member of org-element-parsed-keywords, value can contain the standard set objects, excluding footnote references.
let (remaining, rule) = recognize(tuple((
space0,

View File

@@ -28,7 +28,7 @@ pub fn latex_environment<'r, 's>(
context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, LatexEnvironment<'s>> {
start_of_line(context, input)?;
start_of_line(input)?;
let (remaining, _leading_whitespace) = space0(input)?;
let (remaining, (_opening, name, _open_close_brace, _ws, _line_ending)) = tuple((
tag_no_case(r#"\begin{"#),
@@ -97,11 +97,11 @@ fn latex_environment_end(
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn _latex_environment_end<'r, 's, 'x>(
context: Context<'r, 's>,
_context: Context<'r, 's>,
input: OrgSource<'s>,
current_name_lower: &'x str,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
start_of_line(context, input)?;
start_of_line(input)?;
let (remaining, _leading_whitespace) = space0(input)?;
let (remaining, (_begin, _name, _close_brace, _ws, _line_ending)) = tuple((
tag_no_case(r#"\end{"#),

View File

@@ -61,7 +61,7 @@ fn raw_latex_fragment<'r, 's>(
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn name<'r, 's>(
context: Context<'r, 's>,
_context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
alpha1(input)
@@ -173,7 +173,7 @@ fn dollar_char_fragment<'r, 's>(
}
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
pub fn pre<'r, 's>(context: Context<'r, 's>, input: OrgSource<'s>) -> Res<OrgSource<'s>, ()> {
pub fn pre<'r, 's>(_context: Context<'r, 's>, input: OrgSource<'s>) -> Res<OrgSource<'s>, ()> {
let preceding_character = input.get_preceding_character();
if let Some('$') = preceding_character {
return Err(nom::Err::Error(CustomError::MyError(MyError(
@@ -184,7 +184,7 @@ pub fn pre<'r, 's>(context: Context<'r, 's>, input: OrgSource<'s>) -> Res<OrgSou
}
#[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>, ()> {
// TODO: What about eof? Test to find out.
// TODO: Figure out which punctuation characters should be included.
@@ -224,7 +224,7 @@ fn bordered_dollar_fragment<'r, 's>(
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
pub fn open_border<'r, 's>(
context: Context<'r, 's>,
_context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
recognize(verify(none_of(".,;$"), |c| !c.is_whitespace()))(input)
@@ -232,7 +232,7 @@ pub fn open_border<'r, 's>(
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
pub fn close_border<'r, 's>(
context: Context<'r, 's>,
_context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, ()> {
let preceding_character = input.get_preceding_character();

View File

@@ -124,7 +124,7 @@ pub fn example_block<'r, 's>(
context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, ExampleBlock<'s>> {
let (remaining, name) = lesser_block_begin("example")(context, input)?;
let (remaining, _name) = lesser_block_begin("example")(context, input)?;
let (remaining, parameters) = opt(tuple((space1, data)))(remaining)?;
let (remaining, _nl) = line_ending(remaining)?;
let lesser_block_end_specialized = lesser_block_end("example");
@@ -250,11 +250,11 @@ fn lesser_block_end(
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn _lesser_block_end<'r, 's, 'x>(
context: Context<'r, 's>,
_context: Context<'r, 's>,
input: OrgSource<'s>,
current_name_lower: &'x str,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
start_of_line(context, input)?;
start_of_line(input)?;
let (remaining, _leading_whitespace) = space0(input)?;
let (remaining, (_begin, _name, _ws)) = tuple((
tag_no_case("#+end_"),
@@ -265,22 +265,23 @@ fn _lesser_block_end<'r, 's, 'x>(
Ok((remaining, source))
}
fn lesser_block_begin(
current_name: &str,
/// Parser for the beginning of a lesser block
///
/// current_name MUST be lowercase. We do not do the conversion ourselves because it is not allowed in a const fn.
const fn lesser_block_begin(
current_name: &'static str,
) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
let current_name_lower = current_name.to_lowercase();
move |context: Context, input: OrgSource<'_>| {
_lesser_block_begin(context, input, current_name_lower.as_str())
}
// TODO: Since this is a const fn, is there ANY way to "generate" functions at compile time?
move |context: Context, input: OrgSource<'_>| _lesser_block_begin(context, input, current_name)
}
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn _lesser_block_begin<'r, 's, 'x>(
context: Context<'r, 's>,
_context: Context<'r, 's>,
input: OrgSource<'s>,
current_name_lower: &'x str,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
start_of_line(context, input)?;
start_of_line(input)?;
let (remaining, _leading_whitespace) = space0(input)?;
let (remaining, (_begin, name)) = tuple((
tag_no_case("#+begin_"),

View File

@@ -31,7 +31,7 @@ pub fn line_break<'r, 's>(
}
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn pre<'r, 's>(context: Context<'r, 's>, input: OrgSource<'s>) -> Res<OrgSource<'s>, ()> {
fn pre<'r, 's>(_context: Context<'r, 's>, input: OrgSource<'s>) -> Res<OrgSource<'s>, ()> {
let preceding_character = input.get_preceding_character();
match preceding_character {
// If None, we are at the start of the file

View File

@@ -1,6 +1,5 @@
use nom::branch::alt;
use nom::combinator::map;
use nom::combinator::not;
use super::org_source::OrgSource;
use super::parser_with_context::parser_with_context;
@@ -34,8 +33,6 @@ pub fn standard_set_object<'r, 's>(
context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, Object<'s>> {
not(|i| context.check_exit_matcher(i))(input)?;
alt((
map(parser_with_context!(timestamp)(context), Object::Timestamp),
map(parser_with_context!(subscript)(context), Object::Subscript),
@@ -93,8 +90,6 @@ pub fn minimal_set_object<'r, 's>(
context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, Object<'s>> {
not(|i| context.check_exit_matcher(i))(input)?;
alt((
map(parser_with_context!(subscript)(context), Object::Subscript),
map(
@@ -116,7 +111,6 @@ pub fn any_object_except_plain_text<'r, 's>(
context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, Object<'s>> {
// Used for exit matchers so this does not check exit matcher condition.
alt((
map(parser_with_context!(timestamp)(context), Object::Timestamp),
map(parser_with_context!(subscript)(context), Object::Subscript),

View File

@@ -42,7 +42,7 @@ pub fn org_macro<'r, 's>(
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn org_macro_name<'r, 's>(
context: Context<'r, 's>,
_context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
let (remaining, _) = verify(anychar, |c| c.is_alphabetic())(input)?;

View File

@@ -50,6 +50,12 @@ impl<'s> OrgSource<'s> {
pub fn is_at_start_of_line(&self) -> bool {
self.start == self.start_of_line
}
pub fn get_until(&self, other: OrgSource<'s>) -> OrgSource<'s> {
assert!(other.start >= self.start);
assert!(other.end <= self.end);
self.slice(..(other.start - self.start))
}
}
impl<'s> InputTake for OrgSource<'s> {
@@ -118,7 +124,6 @@ where
.map(|idx| self.start + idx + 1)
.unwrap_or(self.start_of_line);
// TODO: calculate updated values for WrappedInput
OrgSource {
full_source: self.full_source,
start: new_start,

View File

@@ -6,13 +6,13 @@ use nom::multi::many1;
use nom::multi::many_till;
use nom::sequence::tuple;
use super::element_parser::detect_element;
use super::lesser_element::Paragraph;
use super::org_source::OrgSource;
use super::util::blank_line;
use super::util::get_consumed;
use super::Context;
use crate::error::Res;
use crate::parser::element_parser::element;
use crate::parser::exiting::ExitClass;
use crate::parser::object_parser::standard_set_object;
use crate::parser::parser_context::ContextElement;
@@ -28,7 +28,7 @@ pub fn paragraph<'r, 's>(
) -> Res<OrgSource<'s>, Paragraph<'s>> {
let parser_context =
context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode {
class: ExitClass::Beta,
class: ExitClass::Gamma,
exit_matcher: &paragraph_end,
}));
let standard_set_object_matcher = parser_with_context!(standard_set_object)(&parser_context);
@@ -57,10 +57,9 @@ fn paragraph_end<'r, 's>(
context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
let non_paragraph_element_matcher = parser_with_context!(element(false))(context);
let start_of_line_matcher = parser_with_context!(start_of_line)(&context);
let non_paragraph_element_matcher = parser_with_context!(detect_element(false))(context);
alt((
recognize(tuple((start_of_line_matcher, many1(blank_line)))),
recognize(tuple((start_of_line, many1(blank_line)))),
recognize(non_paragraph_element_matcher),
eof,
))(input)

View File

@@ -62,7 +62,7 @@ impl<'r, 's> ContextTree<'r, 's> {
// exit_matcher: ChainBehavior::IgnoreParent(Some(&always_fail)),
// }));
let mut current_class_filter = ExitClass::Beta;
let mut current_class_filter = ExitClass::Gamma;
for current_node in self.iter() {
let context_element = current_node.get_data();
match context_element {
@@ -112,9 +112,6 @@ pub enum ContextElement<'r, 's> {
ExitMatcherNode(ExitMatcherNode<'r>),
Context(&'r str),
/// Stores the indentation level of the current list item.
ListItem(usize),
/// Stores the name of the greater block.
GreaterBlock(&'s str),

View File

@@ -45,7 +45,7 @@ pub fn plain_link<'r, 's>(
}
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn pre<'r, 's>(context: Context<'r, 's>, input: OrgSource<'s>) -> Res<OrgSource<'s>, ()> {
fn pre<'r, 's>(_context: Context<'r, 's>, input: OrgSource<'s>) -> Res<OrgSource<'s>, ()> {
let preceding_character = input.get_preceding_character();
match preceding_character {
// If None, we are at the start of the file which is fine
@@ -62,14 +62,14 @@ fn pre<'r, 's>(context: Context<'r, 's>, input: OrgSource<'s>) -> Res<OrgSource<
}
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn post<'r, 's>(context: Context<'r, 's>, input: OrgSource<'s>) -> Res<OrgSource<'s>, ()> {
fn post<'r, 's>(_context: Context<'r, 's>, input: OrgSource<'s>) -> Res<OrgSource<'s>, ()> {
let (remaining, _) = alt((eof, recognize(none_of(WORD_CONSTITUENT_CHARACTERS))))(input)?;
Ok((remaining, ()))
}
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
pub fn protocol<'r, 's>(
context: Context<'r, 's>,
_context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
// TODO: This should be defined by org-link-parameters
@@ -113,7 +113,7 @@ fn path_plain<'r, 's>(
// 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 =
context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode {
class: ExitClass::Beta,
class: ExitClass::Gamma,
exit_matcher: &path_plain_end,
}));
@@ -125,7 +125,7 @@ fn path_plain<'r, 's>(
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn path_plain_end<'r, 's>(
context: Context<'r, 's>,
_context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
recognize(one_of(" \t\r\n()[]<>"))(input)

View File

@@ -32,6 +32,27 @@ use crate::parser::util::get_consumed;
use crate::parser::util::maybe_consume_trailing_whitespace_if_not_exiting;
use crate::parser::util::start_of_line;
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
pub fn detect_plain_list<'r, 's>(
_context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, ()> {
// TODO: Add support for plain list items that do not have content on the first line.
if verify(
tuple((start_of_line, space0, bullet, space1)),
|(_start, indent, bull, _after_whitespace)| {
Into::<&str>::into(bull) != "*" || indent.len() > 0
},
)(input)
.is_ok()
{
return Ok((input, ()));
}
return Err(nom::Err::Error(CustomError::MyError(MyError(
"No element detected.".into(),
))));
}
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
pub fn plain_list<'r, 's>(
context: Context<'r, 's>,
@@ -90,9 +111,6 @@ pub fn plain_list<'r, 's>(
parser_with_context!(plain_list_item)(&final_item_context)(final_child_start)?;
children.push((final_child_start, reparsed_final_item));
let (remaining, _trailing_ws) =
maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?;
let source = get_consumed(input, remaining);
Ok((
remaining,
@@ -108,7 +126,7 @@ pub fn plain_list_item<'r, 's>(
context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, PlainListItem<'s>> {
start_of_line(context, input)?;
start_of_line(input)?;
let (remaining, leading_whitespace) = space0(input)?;
// It is fine that we get the indent level using the number of bytes rather than the number of characters because nom's space0 only matches space and tab (0x20 and 0x09)
let indent_level = leading_whitespace.len();
@@ -116,6 +134,7 @@ pub fn plain_list_item<'r, 's>(
Into::<&str>::into(bull) != "*" || indent_level > 0
})(remaining)?;
// TODO: This isn't taking into account items that immediately line break and then have contents
let maybe_contentless_item: Res<OrgSource<'_>, OrgSource<'_>> =
alt((eof, line_ending))(remaining);
match maybe_contentless_item {
@@ -135,12 +154,12 @@ pub fn plain_list_item<'r, 's>(
};
let (remaining, _ws) = space1(remaining)?;
let exit_matcher = plain_list_item_end(indent_level);
let parser_context = context
.with_additional_node(ContextElement::ConsumeTrailingWhitespace(true))
.with_additional_node(ContextElement::ListItem(indent_level))
.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode {
class: ExitClass::Beta,
exit_matcher: &plain_list_item_end,
exit_matcher: &exit_matcher,
}));
let (remaining, (children, _exit_contents)) = verify(
@@ -183,59 +202,66 @@ fn counter<'s>(i: OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn plain_list_end<'r, 's>(
context: Context<'r, 's>,
_context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
let start_of_line_matcher = parser_with_context!(start_of_line)(context);
recognize(tuple((
start_of_line_matcher,
start_of_line,
verify(many1(blank_line), |lines: &Vec<OrgSource<'_>>| {
lines.len() >= 2
}),
)))(input)
}
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn plain_list_item_end<'r, 's>(
const fn plain_list_item_end(
indent_level: usize,
) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
let line_indented_lte_matcher = line_indented_lte(indent_level);
move |context: Context, input: OrgSource<'_>| {
_plain_list_item_end(context, input, &line_indented_lte_matcher)
}
}
#[cfg_attr(
feature = "tracing",
tracing::instrument(ret, level = "debug", skip(line_indented_lte_matcher))
)]
fn _plain_list_item_end<'r, 's>(
context: Context<'r, 's>,
input: OrgSource<'s>,
line_indented_lte_matcher: impl for<'rr, 'ss> Fn(
Context<'rr, 'ss>,
OrgSource<'ss>,
) -> Res<OrgSource<'ss>, OrgSource<'ss>>,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
start_of_line(context, input)?;
start_of_line(input)?;
recognize(tuple((
opt(blank_line),
parser_with_context!(line_indented_lte)(context),
parser_with_context!(line_indented_lte_matcher)(context),
)))(input)
}
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn line_indented_lte<'r, 's>(
context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
let current_item_indent_level: &usize =
get_context_item_indent(context).ok_or(nom::Err::Error(CustomError::MyError(MyError(
"Not inside a plain list item".into(),
))))?;
const fn line_indented_lte(
indent_level: usize,
) -> impl for<'r, 's> Fn(Context<'r, 's>, OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
move |context: Context, input: OrgSource<'_>| _line_indented_lte(context, input, indent_level)
}
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn _line_indented_lte<'r, 's>(
_context: Context<'r, 's>,
input: OrgSource<'s>,
indent_level: usize,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
let matched = recognize(verify(
tuple((space0::<OrgSource<'_>, _>, non_whitespace_character)),
// It is fine that we get the indent level using the number of bytes rather than the number of characters because nom's space0 only matches space and tab (0x20 and 0x09)
|(_space0, _anychar)| _space0.len() <= *current_item_indent_level,
|(_space0, _anychar)| _space0.len() <= indent_level,
))(input)?;
Ok(matched)
}
fn get_context_item_indent<'r, 's>(context: Context<'r, 's>) -> Option<&'r usize> {
for thing in context.iter() {
match thing.get_data() {
ContextElement::ListItem(depth) => return Some(depth),
_ => {}
};
}
None
}
#[cfg(test)]
mod tests {
use super::*;

View File

@@ -18,10 +18,10 @@ use crate::parser::util::start_of_line;
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
pub fn planning<'r, 's>(
context: Context<'r, 's>,
_context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, Planning<'s>> {
start_of_line(context, input)?;
start_of_line(input)?;
let (remaining, _leading_whitespace) = space0(input)?;
let (remaining, _planning_parameters) = separated_list1(space1, planning_parameter)(remaining)?;
let (remaining, _trailing_ws) = tuple((space0, alt((line_ending, eof))))(remaining)?;

View File

@@ -44,7 +44,7 @@ pub fn property_drawer<'r, 's>(
remaining,
(_start_of_line, _leading_whitespace, _open_tag, _trailing_whitespace, _line_ending),
) = tuple((
parser_with_context!(start_of_line)(context),
start_of_line,
space0,
tag_no_case(":PROPERTIES:"),
space0,
@@ -80,11 +80,11 @@ pub fn property_drawer<'r, 's>(
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn property_drawer_end<'r, 's>(
context: Context<'r, 's>,
_context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
recognize(tuple((
parser_with_context!(start_of_line)(context),
start_of_line,
space0,
tag_no_case(":end:"),
space0,
@@ -99,7 +99,7 @@ fn node_property<'r, 's>(
) -> Res<OrgSource<'s>, NodeProperty<'s>> {
let (remaining, (_start_of_line, _leading_whitespace, _open_colon, _name, _close_colon)) =
tuple((
parser_with_context!(start_of_line)(context),
start_of_line,
space0,
tag(":"),
parser_with_context!(node_property_name)(context),
@@ -157,7 +157,7 @@ fn node_property_name<'r, 's>(
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn node_property_name_end<'r, 's>(
context: Context<'r, 's>,
_context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
alt((tag("+:"), tag(":")))(input)

View File

@@ -91,7 +91,7 @@ pub fn radio_target<'r, 's>(
let (remaining, _opening) = tag("<<<")(input)?;
let parser_context =
context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode {
class: ExitClass::Beta,
class: ExitClass::Gamma,
exit_matcher: &radio_target_end,
}));
@@ -117,7 +117,7 @@ pub fn radio_target<'r, 's>(
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn radio_target_end<'r, 's>(
context: Context<'r, 's>,
_context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
alt((tag("<"), tag(">"), line_ending))(input)

View File

@@ -71,7 +71,7 @@ pub fn regular_link_with_description<'r, 's>(
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
pub fn pathreg<'r, 's>(
context: Context<'r, 's>,
_context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
let (remaining, path) = escaped(
@@ -108,7 +108,7 @@ pub fn description<'r, 's>(
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn description_end<'r, 's>(
context: Context<'r, 's>,
_context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
tag("]]")(input)

View File

@@ -137,7 +137,9 @@ impl<'s> Token<'s> {
pub fn sexp_with_padding<'s>(input: &'s str) -> Res<&'s str, Token<'s>> {
let (remaining, _) = multispace0(input)?;
let remaining = OrgSource::new(remaining);
let (remaining, tkn) = token(remaining).map(|(rem, out)| (Into::<&str>::into(rem), out)).map_err(convert_error)?;
let (remaining, tkn) = token(remaining)
.map(|(rem, out)| (Into::<&str>::into(rem), out))
.map_err(convert_error)?;
let (remaining, _) = multispace0(remaining)?;
Ok((remaining, tkn))
}

View File

@@ -23,7 +23,7 @@ pub fn statistics_cookie<'r, 's>(
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
pub fn percent_statistics_cookie<'r, 's>(
context: Context<'r, 's>,
_context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, StatisticsCookie<'s>> {
let (remaining, source) =
@@ -39,7 +39,7 @@ pub fn percent_statistics_cookie<'r, 's>(
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
pub fn fraction_statistics_cookie<'r, 's>(
context: Context<'r, 's>,
_context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, StatisticsCookie<'s>> {
let (remaining, source) = recognize(tuple((

View File

@@ -67,7 +67,7 @@ pub fn superscript<'r, 's>(
}
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn pre<'r, 's>(context: Context<'r, 's>, input: OrgSource<'s>) -> Res<OrgSource<'s>, ()> {
fn pre<'r, 's>(_context: Context<'r, 's>, input: OrgSource<'s>) -> Res<OrgSource<'s>, ()> {
let preceding_character = input.get_preceding_character();
match preceding_character {
Some(c) if !c.is_whitespace() => {}
@@ -106,7 +106,7 @@ fn script_body<'r, 's>(
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn script_asterisk<'r, 's>(
context: Context<'r, 's>,
_context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
tag("*")(input)
@@ -128,7 +128,7 @@ fn script_alphanum<'r, 's>(
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn script_alphanum_character<'r, 's>(
context: Context<'r, 's>,
_context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
recognize(verify(anychar, |c| {
@@ -162,7 +162,7 @@ fn script_with_braces<'r, 's>(
},
))
.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode {
class: ExitClass::Beta,
class: ExitClass::Gamma,
exit_matcher: &script_with_braces_end,
}));

View File

@@ -36,7 +36,7 @@ pub fn org_mode_table<'r, 's>(
context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, Table<'s>> {
start_of_line(context, input)?;
start_of_line(input)?;
peek(tuple((space0, tag("|"))))(input)?;
let parser_context = context
@@ -67,10 +67,10 @@ pub fn org_mode_table<'r, 's>(
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn table_end<'r, 's>(
context: Context<'r, 's>,
_context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
start_of_line(context, input)?;
start_of_line(input)?;
recognize(tuple((space0, not(tag("|")))))(input)
}
@@ -87,10 +87,10 @@ pub fn org_mode_table_row<'r, 's>(
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
pub fn org_mode_table_row_rule<'r, 's>(
context: Context<'r, 's>,
_context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, TableRow<'s>> {
start_of_line(context, input)?;
start_of_line(input)?;
let (remaining, _) = tuple((space0, tag("|-"), is_not("\r\n"), line_ending))(input)?;
let source = get_consumed(input, remaining);
Ok((
@@ -107,7 +107,7 @@ pub fn org_mode_table_row_regular<'r, 's>(
context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, TableRow<'s>> {
start_of_line(context, input)?;
start_of_line(input)?;
let (remaining, _) = tuple((space0, tag("|")))(input)?;
let (remaining, children) =
many1(parser_with_context!(org_mode_table_cell)(context))(remaining)?;
@@ -157,7 +157,7 @@ pub fn org_mode_table_cell<'r, 's>(
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn org_mode_table_cell_end<'r, 's>(
context: Context<'r, 's>,
_context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
recognize(tuple((space0, alt((tag("|"), peek(line_ending))))))(input)

View File

@@ -62,7 +62,7 @@ pub fn target<'r, 's>(
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn target_end<'r, 's>(
context: Context<'r, 's>,
_context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
recognize(one_of("<>\n"))(input)

View File

@@ -179,7 +179,7 @@ fn _text_markup_object<'r, 's, 'x>(
let text_markup_end_specialized = text_markup_end(open.into());
let parser_context =
context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode {
class: ExitClass::Beta,
class: ExitClass::Gamma,
exit_matcher: &text_markup_end_specialized,
}));
@@ -229,7 +229,7 @@ fn _text_markup_string<'r, 's, 'x>(
let text_markup_end_specialized = text_markup_end(open.into());
let parser_context =
context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode {
class: ExitClass::Beta,
class: ExitClass::Gamma,
exit_matcher: &text_markup_end_specialized,
}));
@@ -259,7 +259,7 @@ fn _text_markup_string<'r, 's, 'x>(
}
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
pub fn pre<'r, 's>(context: Context<'r, 's>, input: OrgSource<'s>) -> Res<OrgSource<'s>, ()> {
pub fn pre<'r, 's>(_context: Context<'r, 's>, input: OrgSource<'s>) -> Res<OrgSource<'s>, ()> {
let preceding_character = input.get_preceding_character();
match preceding_character {
// If None, we are at the start of the file which is technically the beginning of a line.
@@ -276,7 +276,7 @@ pub fn pre<'r, 's>(context: Context<'r, 's>, input: OrgSource<'s>) -> Res<OrgSou
}
#[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)?;
Ok((remaining, ()))
}
@@ -296,7 +296,7 @@ fn _text_markup_end<'r, 's, 'x>(
input: OrgSource<'s>,
marker_symbol: &'x str,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
not(parser_with_context!(preceded_by_whitespace)(context))(input)?;
not(preceded_by_whitespace)(input)?;
let (remaining, _marker) = terminated(
tag(marker_symbol),
peek(parser_with_context!(post)(context)),
@@ -338,7 +338,7 @@ fn _rematch_text_markup_object<'r, 's, 'x>(
let text_markup_end_specialized = text_markup_end(open.into());
let parser_context =
context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode {
class: ExitClass::Beta,
class: ExitClass::Gamma,
exit_matcher: &text_markup_end_specialized,
}));

View File

@@ -67,7 +67,7 @@ fn sexp<'r, 's>(
) -> Res<OrgSource<'s>, OrgSource<'s>> {
let parser_context =
context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode {
class: ExitClass::Beta,
class: ExitClass::Gamma,
exit_matcher: &sexp_end,
}));
@@ -84,7 +84,7 @@ fn sexp<'r, 's>(
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn sexp_end<'r, 's>(
context: Context<'r, 's>,
_context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
alt((tag(")>"), recognize(one_of(">\n"))))(input)
@@ -99,7 +99,7 @@ fn active_timestamp<'r, 's>(
let (remaining, _date) = date(context, remaining)?;
let time_context =
context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode {
class: ExitClass::Beta,
class: ExitClass::Gamma,
exit_matcher: &active_time_rest_end,
}));
let (remaining, _time) =
@@ -132,7 +132,7 @@ fn inactive_timestamp<'r, 's>(
let (remaining, _date) = date(context, remaining)?;
let time_context =
context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode {
class: ExitClass::Beta,
class: ExitClass::Gamma,
exit_matcher: &inactive_time_rest_end,
}));
let (remaining, _time) =
@@ -186,12 +186,12 @@ fn active_time_range_timestamp<'r, 's>(
let (remaining, _date) = date(context, remaining)?;
let time_context =
context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode {
class: ExitClass::Beta,
class: ExitClass::Gamma,
exit_matcher: &active_time_rest_end,
}));
let first_time_context =
time_context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode {
class: ExitClass::Beta,
class: ExitClass::Gamma,
exit_matcher: &time_range_rest_end,
}));
let (remaining, _first_time) =
@@ -247,12 +247,12 @@ fn inactive_time_range_timestamp<'r, 's>(
let (remaining, _date) = date(context, remaining)?;
let time_context =
context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode {
class: ExitClass::Beta,
class: ExitClass::Gamma,
exit_matcher: &inactive_time_rest_end,
}));
let first_time_context =
time_context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode {
class: ExitClass::Beta,
class: ExitClass::Gamma,
exit_matcher: &time_range_rest_end,
}));
let (remaining, _first_time) =
@@ -303,7 +303,7 @@ fn dayname<'r, 's>(
) -> Res<OrgSource<'s>, OrgSource<'s>> {
let parser_context =
context.with_additional_node(ContextElement::ExitMatcherNode(ExitMatcherNode {
class: ExitClass::Beta,
class: ExitClass::Gamma,
exit_matcher: &dayname_end,
}));
@@ -320,7 +320,7 @@ fn dayname<'r, 's>(
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn dayname_end<'r, 's>(
context: Context<'r, 's>,
_context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
recognize(verify(anychar, |c| {
@@ -402,7 +402,7 @@ fn time_range_rest_end<'r, 's>(
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn repeater<'r, 's>(
context: Context<'r, 's>,
_context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
// + for cumulative type
@@ -418,7 +418,7 @@ fn repeater<'r, 's>(
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
fn warning_delay<'r, 's>(
context: Context<'r, 's>,
_context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
// - for all type

View File

@@ -1,7 +1,6 @@
use nom::branch::alt;
use nom::character::complete::anychar;
use nom::character::complete::line_ending;
use nom::character::complete::multispace0;
use nom::character::complete::none_of;
use nom::character::complete::space0;
use nom::combinator::eof;
@@ -49,26 +48,9 @@ pub fn immediate_in_section<'r, 's, 'x>(context: Context<'r, 's>, section_name:
false
}
/// Check if the child string slice is a slice of the parent string slice.
fn is_slice_of(parent: &str, child: &str) -> bool {
let parent_start = parent.as_ptr() as usize;
let parent_end = parent_start + parent.len();
let child_start = child.as_ptr() as usize;
let child_end = child_start + child.len();
child_start >= parent_start && child_end <= parent_end
}
/// Get a slice of the string that was consumed in a parser using the original input to the parser and the remaining input after the parser.
pub fn get_consumed<'s>(input: OrgSource<'s>, remaining: OrgSource<'s>) -> OrgSource<'s> {
// TODO: This should be replaced with new logic now that we are wrapping the input type.
let input = Into::<&str>::into(&input);
let remaining = Into::<&str>::into(&remaining);
assert!(is_slice_of(input, remaining));
let source = {
let offset = remaining.as_ptr() as usize - input.as_ptr() as usize;
&input[..offset]
};
source.into()
input.get_until(remaining)
}
/// A line containing only whitespace and then a line break
@@ -81,11 +63,8 @@ pub fn blank_line(input: OrgSource<'_>) -> Res<OrgSource<'_>, OrgSource<'_>> {
}
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
pub fn element_trailing_whitespace<'r, 's>(
context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
start_of_line(context, input)?;
pub fn element_trailing_whitespace<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
start_of_line(input)?;
alt((eof, recognize(many0(blank_line))))(input)
}
@@ -96,9 +75,7 @@ pub fn maybe_consume_trailing_whitespace_if_not_exiting<'r, 's>(
) -> Res<OrgSource<'s>, Option<OrgSource<'s>>> {
if context.should_consume_trailing_whitespace() && exit_matcher_parser(context, input).is_err()
{
Ok(opt(parser_with_context!(element_trailing_whitespace)(
context,
))(input)?)
Ok(opt(element_trailing_whitespace)(input)?)
} else {
Ok((input, None))
}
@@ -110,25 +87,15 @@ pub fn maybe_consume_trailing_whitespace<'r, 's>(
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, Option<OrgSource<'s>>> {
if context.should_consume_trailing_whitespace() {
Ok(opt(parser_with_context!(element_trailing_whitespace)(
context,
))(input)?)
Ok(opt(element_trailing_whitespace)(input)?)
} else {
Ok((input, None))
}
}
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
pub fn trailing_whitespace(input: OrgSource<'_>) -> Res<OrgSource<'_>, OrgSource<'_>> {
alt((eof, recognize(tuple((line_ending, many0(blank_line))))))(input)
}
/// Check that we are at the start of a line
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
pub fn start_of_line<'r, 's>(
context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, ()> {
pub fn start_of_line<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, ()> {
if input.is_at_start_of_line() {
Ok((input, ()))
} else {
@@ -140,10 +107,7 @@ pub fn start_of_line<'r, 's>(
/// Check that we are at the start of a line
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
pub fn preceded_by_whitespace<'r, 's>(
context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, ()> {
pub fn preceded_by_whitespace<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, ()> {
let preceding_character = input.get_preceding_character();
match preceding_character {
Some('\n') | Some('\r') | Some(' ') | Some('\t') => {}
@@ -174,21 +138,6 @@ pub fn exit_matcher_parser<'r, 's>(
peek(|i| context.check_exit_matcher(i))(input)
}
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
pub fn always_fail<'r, 's>(
_context: Context<'r, 's>,
input: OrgSource<'s>,
) -> Res<OrgSource<'s>, OrgSource<'s>> {
Err(nom::Err::Error(CustomError::MyError(MyError(
"Always fail".into(),
))))
}
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
pub fn whitespace_eof(input: OrgSource<'_>) -> Res<OrgSource<'_>, OrgSource<'_>> {
recognize(tuple((multispace0, eof)))(input)
}
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
pub fn text_until_exit<'r, 's>(
context: Context<'r, 's>,