refactor: cleanup parse functions
This commit is contained in:
parent
d9fb9aadcb
commit
2128e86b81
24 changed files with 507 additions and 656 deletions
|
|
@ -3,7 +3,6 @@ use std::borrow::Cow;
|
|||
use nom::{
|
||||
bytes::complete::tag_no_case,
|
||||
character::complete::{alpha1, space0},
|
||||
error::ParseError,
|
||||
sequence::preceded,
|
||||
IResult,
|
||||
};
|
||||
|
|
@ -11,136 +10,6 @@ use nom::{
|
|||
use crate::elements::Element;
|
||||
use crate::parse::combinators::{blank_lines_count, line, lines_till};
|
||||
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(test, derive(PartialEq))]
|
||||
pub(crate) struct RawBlock<'a> {
|
||||
pub name: &'a str,
|
||||
pub arguments: &'a str,
|
||||
|
||||
pub pre_blank: usize,
|
||||
pub contents: &'a str,
|
||||
pub contents_without_blank_lines: &'a str,
|
||||
|
||||
pub post_blank: usize,
|
||||
}
|
||||
|
||||
impl<'a> RawBlock<'a> {
|
||||
pub fn parse(input: &'a str) -> Option<(&str, RawBlock)> {
|
||||
Self::parse_internal::<()>(input).ok()
|
||||
}
|
||||
|
||||
fn parse_internal<E>(input: &'a str) -> IResult<&str, RawBlock, E>
|
||||
where
|
||||
E: ParseError<&'a str>,
|
||||
{
|
||||
let (input, _) = space0(input)?;
|
||||
let (input, name) = preceded(tag_no_case("#+BEGIN_"), alpha1)(input)?;
|
||||
let (input, arguments) = line(input)?;
|
||||
let end_line = format!("#+END_{}", name);
|
||||
let (input, contents) =
|
||||
lines_till(|line| line.trim().eq_ignore_ascii_case(&end_line))(input)?;
|
||||
let (contents_without_blank_lines, pre_blank) = blank_lines_count(contents)?;
|
||||
let (input, post_blank) = blank_lines_count(input)?;
|
||||
|
||||
Ok((
|
||||
input,
|
||||
RawBlock {
|
||||
name,
|
||||
contents,
|
||||
arguments: arguments.trim(),
|
||||
pre_blank,
|
||||
contents_without_blank_lines,
|
||||
post_blank,
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
pub fn into_element(self) -> (Element<'a>, &'a str) {
|
||||
let RawBlock {
|
||||
name,
|
||||
contents,
|
||||
arguments,
|
||||
pre_blank,
|
||||
contents_without_blank_lines,
|
||||
post_blank,
|
||||
} = self;
|
||||
|
||||
let arguments: Option<Cow<'a, str>> = if arguments.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(arguments.into())
|
||||
};
|
||||
|
||||
let element = match &*name.to_uppercase() {
|
||||
"CENTER" => CenterBlock {
|
||||
parameters: arguments,
|
||||
pre_blank,
|
||||
post_blank,
|
||||
}
|
||||
.into(),
|
||||
"QUOTE" => QuoteBlock {
|
||||
parameters: arguments,
|
||||
pre_blank,
|
||||
post_blank,
|
||||
}
|
||||
.into(),
|
||||
"VERSE" => VerseBlock {
|
||||
parameters: arguments,
|
||||
pre_blank,
|
||||
post_blank,
|
||||
}
|
||||
.into(),
|
||||
"COMMENT" => CommentBlock {
|
||||
data: arguments,
|
||||
contents: contents.into(),
|
||||
post_blank,
|
||||
}
|
||||
.into(),
|
||||
"EXAMPLE" => ExampleBlock {
|
||||
data: arguments,
|
||||
contents: contents.into(),
|
||||
post_blank,
|
||||
}
|
||||
.into(),
|
||||
"EXPORT" => ExportBlock {
|
||||
data: arguments.unwrap_or_default(),
|
||||
contents: contents.into(),
|
||||
post_blank,
|
||||
}
|
||||
.into(),
|
||||
"SRC" => {
|
||||
let (language, arguments) = match &arguments {
|
||||
Some(Cow::Borrowed(args)) => {
|
||||
let (language, arguments) =
|
||||
args.split_at(args.find(' ').unwrap_or_else(|| args.len()));
|
||||
(language.into(), arguments.into())
|
||||
}
|
||||
None => (Cow::Borrowed(""), Cow::Borrowed("")),
|
||||
_ => unreachable!(
|
||||
"`parse_block_element` returns `Some(Cow::Borrowed)` or `None`"
|
||||
),
|
||||
};
|
||||
SourceBlock {
|
||||
arguments,
|
||||
language,
|
||||
contents: contents.into(),
|
||||
post_blank,
|
||||
}
|
||||
.into()
|
||||
}
|
||||
_ => SpecialBlock {
|
||||
parameters: arguments,
|
||||
name: name.into(),
|
||||
pre_blank,
|
||||
post_blank,
|
||||
}
|
||||
.into(),
|
||||
};
|
||||
|
||||
(element, contents_without_blank_lines)
|
||||
}
|
||||
}
|
||||
|
||||
/// Special Block Element
|
||||
#[derive(Debug, Clone)]
|
||||
#[cfg_attr(test, derive(PartialEq))]
|
||||
|
|
@ -351,16 +220,140 @@ impl SourceBlock<'_> {
|
|||
// TODO: fn retain_labels() -> bool { }
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(test, derive(PartialEq))]
|
||||
pub(crate) struct RawBlock<'a> {
|
||||
pub name: &'a str,
|
||||
pub arguments: &'a str,
|
||||
|
||||
pub pre_blank: usize,
|
||||
pub contents: &'a str,
|
||||
pub contents_without_blank_lines: &'a str,
|
||||
|
||||
pub post_blank: usize,
|
||||
}
|
||||
|
||||
impl<'a> RawBlock<'a> {
|
||||
pub fn parse(input: &str) -> Option<(&str, RawBlock)> {
|
||||
parse_internal(input).ok()
|
||||
}
|
||||
|
||||
pub fn into_element(self) -> (Element<'a>, &'a str) {
|
||||
let RawBlock {
|
||||
name,
|
||||
contents,
|
||||
arguments,
|
||||
pre_blank,
|
||||
contents_without_blank_lines,
|
||||
post_blank,
|
||||
} = self;
|
||||
|
||||
let arguments: Option<Cow<'a, str>> = if arguments.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(arguments.into())
|
||||
};
|
||||
|
||||
let element = match &*name.to_uppercase() {
|
||||
"CENTER" => CenterBlock {
|
||||
parameters: arguments,
|
||||
pre_blank,
|
||||
post_blank,
|
||||
}
|
||||
.into(),
|
||||
"QUOTE" => QuoteBlock {
|
||||
parameters: arguments,
|
||||
pre_blank,
|
||||
post_blank,
|
||||
}
|
||||
.into(),
|
||||
"VERSE" => VerseBlock {
|
||||
parameters: arguments,
|
||||
pre_blank,
|
||||
post_blank,
|
||||
}
|
||||
.into(),
|
||||
"COMMENT" => CommentBlock {
|
||||
data: arguments,
|
||||
contents: contents.into(),
|
||||
post_blank,
|
||||
}
|
||||
.into(),
|
||||
"EXAMPLE" => ExampleBlock {
|
||||
data: arguments,
|
||||
contents: contents.into(),
|
||||
post_blank,
|
||||
}
|
||||
.into(),
|
||||
"EXPORT" => ExportBlock {
|
||||
data: arguments.unwrap_or_default(),
|
||||
contents: contents.into(),
|
||||
post_blank,
|
||||
}
|
||||
.into(),
|
||||
"SRC" => {
|
||||
let (language, arguments) = match &arguments {
|
||||
Some(Cow::Borrowed(args)) => {
|
||||
let (language, arguments) =
|
||||
args.split_at(args.find(' ').unwrap_or_else(|| args.len()));
|
||||
(language.into(), arguments.into())
|
||||
}
|
||||
None => (Cow::Borrowed(""), Cow::Borrowed("")),
|
||||
_ => unreachable!(
|
||||
"`parse_block_element` returns `Some(Cow::Borrowed)` or `None`"
|
||||
),
|
||||
};
|
||||
SourceBlock {
|
||||
arguments,
|
||||
language,
|
||||
contents: contents.into(),
|
||||
post_blank,
|
||||
}
|
||||
.into()
|
||||
}
|
||||
_ => SpecialBlock {
|
||||
parameters: arguments,
|
||||
name: name.into(),
|
||||
pre_blank,
|
||||
post_blank,
|
||||
}
|
||||
.into(),
|
||||
};
|
||||
|
||||
(element, contents_without_blank_lines)
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_internal(input: &str) -> IResult<&str, RawBlock, ()> {
|
||||
let (input, _) = space0(input)?;
|
||||
let (input, name) = preceded(tag_no_case("#+BEGIN_"), alpha1)(input)?;
|
||||
let (input, arguments) = line(input)?;
|
||||
let end_line = format!("#+END_{}", name);
|
||||
let (input, contents) = lines_till(|line| line.trim().eq_ignore_ascii_case(&end_line))(input)?;
|
||||
let (contents_without_blank_lines, pre_blank) = blank_lines_count(contents)?;
|
||||
let (input, post_blank) = blank_lines_count(input)?;
|
||||
|
||||
Ok((
|
||||
input,
|
||||
RawBlock {
|
||||
name,
|
||||
contents,
|
||||
arguments: arguments.trim(),
|
||||
pre_blank,
|
||||
contents_without_blank_lines,
|
||||
post_blank,
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse() {
|
||||
use nom::error::VerboseError;
|
||||
|
||||
assert_eq!(
|
||||
RawBlock::parse_internal::<VerboseError<&str>>(
|
||||
RawBlock::parse(
|
||||
r#"#+BEGIN_SRC
|
||||
#+END_SRC"#
|
||||
),
|
||||
Ok((
|
||||
Some((
|
||||
"",
|
||||
RawBlock {
|
||||
contents: "",
|
||||
|
|
@ -374,11 +367,11 @@ fn parse() {
|
|||
);
|
||||
|
||||
assert_eq!(
|
||||
RawBlock::parse_internal::<VerboseError<&str>>(
|
||||
RawBlock::parse(
|
||||
r#"#+begin_src
|
||||
#+end_src"#
|
||||
),
|
||||
Ok((
|
||||
Some((
|
||||
"",
|
||||
RawBlock {
|
||||
contents: "",
|
||||
|
|
@ -392,14 +385,14 @@ fn parse() {
|
|||
);
|
||||
|
||||
assert_eq!(
|
||||
RawBlock::parse_internal::<VerboseError<&str>>(
|
||||
RawBlock::parse(
|
||||
r#"#+BEGIN_SRC javascript
|
||||
console.log('Hello World!');
|
||||
#+END_SRC
|
||||
|
||||
"#
|
||||
),
|
||||
Ok((
|
||||
Some((
|
||||
"",
|
||||
RawBlock {
|
||||
contents: "console.log('Hello World!');\n",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue