refactor(org): store content in separate Vec
This commit is contained in:
parent
50f6b9f52a
commit
3e82172dfe
14 changed files with 520 additions and 573 deletions
|
|
@ -9,13 +9,11 @@ pub struct Block<'a> {
|
|||
pub name: &'a str,
|
||||
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
|
||||
pub args: Option<&'a str>,
|
||||
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
|
||||
pub contents: &'a str,
|
||||
}
|
||||
|
||||
impl Block<'_> {
|
||||
#[inline]
|
||||
pub(crate) fn parse(text: &str) -> Option<(&str, Element<'_>)> {
|
||||
pub(crate) fn parse(text: &str) -> Option<(&str, Element<'_>, &str)> {
|
||||
debug_assert!(text.starts_with("#+"));
|
||||
|
||||
if text.len() <= 8 || text[2..8].to_uppercase() != "BEGIN_" {
|
||||
|
|
@ -40,11 +38,8 @@ impl Block<'_> {
|
|||
if text[pos..i].trim().eq_ignore_ascii_case(&end) {
|
||||
return Some((
|
||||
&text[i + 1..],
|
||||
Element::Block(Block {
|
||||
name,
|
||||
args,
|
||||
contents: &text[off..pos],
|
||||
}),
|
||||
Element::Block(Block { name, args }),
|
||||
&text[off..pos],
|
||||
));
|
||||
}
|
||||
|
||||
|
|
@ -52,14 +47,7 @@ impl Block<'_> {
|
|||
}
|
||||
|
||||
if text[pos..].trim().eq_ignore_ascii_case(&end) {
|
||||
Some((
|
||||
"",
|
||||
Element::Block(Block {
|
||||
name,
|
||||
args,
|
||||
contents: &text[off..pos],
|
||||
}),
|
||||
))
|
||||
Some(("", Element::Block(Block { name, args }), &text[off..pos]))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
@ -75,8 +63,8 @@ fn parse() {
|
|||
Element::Block(Block {
|
||||
name: "SRC",
|
||||
args: None,
|
||||
contents: ""
|
||||
}),
|
||||
""
|
||||
))
|
||||
);
|
||||
assert_eq!(
|
||||
|
|
@ -86,8 +74,8 @@ fn parse() {
|
|||
Element::Block(Block {
|
||||
name: "SRC",
|
||||
args: Some("javascript"),
|
||||
contents: "console.log('Hello World!');\n"
|
||||
}),
|
||||
"console.log('Hello World!');\n"
|
||||
))
|
||||
);
|
||||
// TODO: more testing
|
||||
|
|
|
|||
|
|
@ -7,13 +7,11 @@ use crate::elements::Element;
|
|||
#[derive(Debug)]
|
||||
pub struct Drawer<'a> {
|
||||
pub name: &'a str,
|
||||
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
|
||||
pub contents: &'a str,
|
||||
}
|
||||
|
||||
impl Drawer<'_> {
|
||||
#[inline]
|
||||
pub(crate) fn parse(text: &str) -> Option<(&str, Element<'_>)> {
|
||||
pub(crate) fn parse(text: &str) -> Option<(&str, Element<'_>, &str)> {
|
||||
debug_assert!(text.starts_with(':'));
|
||||
|
||||
let mut lines = memchr_iter(b'\n', text.as_bytes());
|
||||
|
|
@ -36,8 +34,8 @@ impl Drawer<'_> {
|
|||
&text[i + 1..],
|
||||
Element::Drawer(Drawer {
|
||||
name: &name[0..name.len() - 1],
|
||||
contents: &text[off..pos],
|
||||
}),
|
||||
&text[off..pos],
|
||||
));
|
||||
}
|
||||
pos = i + 1;
|
||||
|
|
@ -48,8 +46,8 @@ impl Drawer<'_> {
|
|||
"",
|
||||
Element::Drawer(Drawer {
|
||||
name: &name[0..name.len() - 1],
|
||||
contents: &text[off..pos],
|
||||
}),
|
||||
&text[off..pos],
|
||||
))
|
||||
} else {
|
||||
None
|
||||
|
|
@ -63,10 +61,8 @@ fn parse() {
|
|||
Drawer::parse(":PROPERTIES:\n :CUSTOM_ID: id\n :END:"),
|
||||
Some((
|
||||
"",
|
||||
Element::Drawer(Drawer {
|
||||
name: "PROPERTIES",
|
||||
contents: " :CUSTOM_ID: id\n"
|
||||
})
|
||||
Element::Drawer(Drawer { name: "PROPERTIES" }),
|
||||
" :CUSTOM_ID: id\n"
|
||||
))
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,14 +9,11 @@ pub struct DynBlock<'a> {
|
|||
pub block_name: &'a str,
|
||||
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
|
||||
pub arguments: Option<&'a str>,
|
||||
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
|
||||
pub contents: &'a str,
|
||||
}
|
||||
|
||||
impl DynBlock<'_> {
|
||||
#[inline]
|
||||
// return (dyn_block, contents-begin, contents-end, end)
|
||||
pub(crate) fn parse(text: &str) -> Option<(&str, Element<'_>)> {
|
||||
pub(crate) fn parse(text: &str) -> Option<(&str, Element<'_>, &str)> {
|
||||
debug_assert!(text.starts_with("#+"));
|
||||
|
||||
if text.len() <= "#+BEGIN: ".len() || !text[2..9].eq_ignore_ascii_case("BEGIN: ") {
|
||||
|
|
@ -50,8 +47,8 @@ impl DynBlock<'_> {
|
|||
Element::DynBlock(DynBlock {
|
||||
block_name: name,
|
||||
arguments: para,
|
||||
contents: &text[off..pos],
|
||||
}),
|
||||
&text[off..pos],
|
||||
));
|
||||
}
|
||||
|
||||
|
|
@ -64,8 +61,8 @@ impl DynBlock<'_> {
|
|||
Element::DynBlock(DynBlock {
|
||||
block_name: name,
|
||||
arguments: para,
|
||||
contents: &text[off..pos],
|
||||
}),
|
||||
&text[off..pos],
|
||||
))
|
||||
} else {
|
||||
None
|
||||
|
|
@ -83,8 +80,8 @@ fn parse() {
|
|||
Element::DynBlock(DynBlock {
|
||||
block_name: "clocktable",
|
||||
arguments: Some(":scope file"),
|
||||
contents: "CONTENTS\n"
|
||||
},)
|
||||
}),
|
||||
"CONTENTS\n"
|
||||
))
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,39 +1,32 @@
|
|||
use memchr::memchr;
|
||||
use nom::{
|
||||
bytes::complete::{tag, take_while1},
|
||||
IResult,
|
||||
};
|
||||
|
||||
#[cfg_attr(test, derive(PartialEq))]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
|
||||
#[derive(Debug)]
|
||||
pub struct FnDef<'a> {
|
||||
pub label: &'a str,
|
||||
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
|
||||
pub contents: &'a str,
|
||||
}
|
||||
|
||||
fn parse_label(input: &str) -> IResult<&str, &str> {
|
||||
let (input, _) = tag("[fn:")(input)?;
|
||||
let (input, label) =
|
||||
take_while1(|c: char| c.is_ascii_alphanumeric() || c == '-' || c == '_')(input)?;
|
||||
let (input, _) = tag("]")(input)?;
|
||||
Ok((input, label))
|
||||
}
|
||||
|
||||
impl FnDef<'_> {
|
||||
#[inline]
|
||||
pub(crate) fn parse(text: &str) -> Option<(&str, FnDef<'_>)> {
|
||||
if text.starts_with("[fn:") {
|
||||
let (label, off) = memchr(b']', text.as_bytes())
|
||||
.filter(|&i| {
|
||||
i != 4
|
||||
&& text.as_bytes()["[fn:".len()..i]
|
||||
.iter()
|
||||
.all(|&c| c.is_ascii_alphanumeric() || c == b'-' || c == b'_')
|
||||
})
|
||||
.map(|i| (&text["[fn:".len()..i], i + 1))?;
|
||||
pub(crate) fn parse(text: &str) -> Option<(&str, FnDef<'_>, &str)> {
|
||||
let (tail, label) = parse_label(text).ok()?;
|
||||
|
||||
let end = memchr(b'\n', text.as_bytes()).unwrap_or_else(|| text.len());
|
||||
let end = memchr(b'\n', tail.as_bytes()).unwrap_or_else(|| tail.len());
|
||||
|
||||
Some((
|
||||
&text[end..],
|
||||
FnDef {
|
||||
label,
|
||||
contents: &text[off..end],
|
||||
},
|
||||
))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
Some((&tail[end..], FnDef { label }, &tail[0..end]))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -41,43 +34,19 @@ impl FnDef<'_> {
|
|||
fn parse() {
|
||||
assert_eq!(
|
||||
FnDef::parse("[fn:1] https://orgmode.org"),
|
||||
Some((
|
||||
"",
|
||||
FnDef {
|
||||
label: "1",
|
||||
contents: " https://orgmode.org"
|
||||
},
|
||||
))
|
||||
Some(("", FnDef { label: "1" }, " https://orgmode.org"))
|
||||
);
|
||||
assert_eq!(
|
||||
FnDef::parse("[fn:word_1] https://orgmode.org"),
|
||||
Some((
|
||||
"",
|
||||
FnDef {
|
||||
label: "word_1",
|
||||
contents: " https://orgmode.org"
|
||||
},
|
||||
))
|
||||
Some(("", FnDef { label: "word_1" }, " https://orgmode.org"))
|
||||
);
|
||||
assert_eq!(
|
||||
FnDef::parse("[fn:WORD-1] https://orgmode.org"),
|
||||
Some((
|
||||
"",
|
||||
FnDef {
|
||||
label: "WORD-1",
|
||||
contents: " https://orgmode.org"
|
||||
},
|
||||
))
|
||||
Some(("", FnDef { label: "WORD-1" }, " https://orgmode.org"))
|
||||
);
|
||||
assert_eq!(
|
||||
FnDef::parse("[fn:WORD]"),
|
||||
Some((
|
||||
"",
|
||||
FnDef {
|
||||
label: "WORD",
|
||||
contents: ""
|
||||
},
|
||||
))
|
||||
Some(("", FnDef { label: "WORD" }, ""))
|
||||
);
|
||||
assert_eq!(FnDef::parse("[fn:] https://orgmode.org"), None);
|
||||
assert_eq!(FnDef::parse("[fn:wor d] https://orgmode.org"), None);
|
||||
|
|
|
|||
|
|
@ -22,12 +22,13 @@ pub struct Headline<'a> {
|
|||
/// headline keyword
|
||||
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
|
||||
pub keyword: Option<&'a str>,
|
||||
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
|
||||
pub contents: &'a str,
|
||||
}
|
||||
|
||||
impl Headline<'_> {
|
||||
pub(crate) fn parse<'a>(text: &'a str, config: &ParseConfig<'_>) -> (&'a str, Headline<'a>) {
|
||||
pub(crate) fn parse<'a>(
|
||||
text: &'a str,
|
||||
config: &ParseConfig<'_>,
|
||||
) -> (&'a str, Headline<'a>, &'a str) {
|
||||
let level = memchr2(b'\n', b' ', text.as_bytes()).unwrap_or_else(|| text.len());
|
||||
|
||||
debug_assert!(level > 0);
|
||||
|
|
@ -55,8 +56,8 @@ impl Headline<'_> {
|
|||
priority: None,
|
||||
title: "",
|
||||
tags: Vec::new(),
|
||||
contents: &text[off..end],
|
||||
},
|
||||
&text[off..end],
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -108,8 +109,8 @@ impl Headline<'_> {
|
|||
priority,
|
||||
title,
|
||||
tags: tags.split(':').filter(|s| !s.is_empty()).collect(),
|
||||
contents: &text[off..end],
|
||||
},
|
||||
&text[off..end],
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -165,8 +166,8 @@ fn parse() {
|
|||
keyword: Some("DONE"),
|
||||
title: "COMMENT Title",
|
||||
tags: vec!["tag", "a2%"],
|
||||
contents: ""
|
||||
},
|
||||
""
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
|
|
@ -179,8 +180,8 @@ fn parse() {
|
|||
tags: vec!["tag", "a2%"],
|
||||
title: "ToDO [#A] COMMENT Title",
|
||||
keyword: None,
|
||||
contents: ""
|
||||
},
|
||||
""
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
|
|
@ -193,8 +194,8 @@ fn parse() {
|
|||
tags: vec!["tag", "a2%"],
|
||||
title: "T0DO [#A] COMMENT Title",
|
||||
keyword: None,
|
||||
contents: ""
|
||||
},
|
||||
""
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
|
|
@ -207,8 +208,8 @@ fn parse() {
|
|||
tags: vec!["tag", "a2%"],
|
||||
title: "[#1] COMMENT Title",
|
||||
keyword: Some("DONE"),
|
||||
contents: "",
|
||||
},
|
||||
""
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
|
|
@ -221,8 +222,8 @@ fn parse() {
|
|||
tags: vec!["tag", "a2%"],
|
||||
title: "[#a] COMMENT Title",
|
||||
keyword: Some("DONE"),
|
||||
contents: "",
|
||||
},
|
||||
""
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
|
|
@ -235,8 +236,8 @@ fn parse() {
|
|||
tags: Vec::new(),
|
||||
title: "COMMENT Title :tag:a2%",
|
||||
keyword: Some("DONE"),
|
||||
contents: ""
|
||||
},
|
||||
""
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
|
|
@ -249,8 +250,8 @@ fn parse() {
|
|||
tags: Vec::new(),
|
||||
title: "COMMENT Title tag:a2%:",
|
||||
keyword: Some("DONE"),
|
||||
contents: ""
|
||||
},
|
||||
""
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
|
|
@ -263,8 +264,8 @@ fn parse() {
|
|||
tags: Vec::new(),
|
||||
title: "COMMENT Title tag:a2%:",
|
||||
keyword: None,
|
||||
contents: ""
|
||||
},
|
||||
""
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
@ -287,8 +288,8 @@ fn parse_todo_keywords() {
|
|||
keyword: None,
|
||||
title: "DONE [#A] COMMENT Title",
|
||||
tags: vec!["tag", "a2%"],
|
||||
contents: ""
|
||||
},
|
||||
""
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
|
|
@ -307,8 +308,8 @@ fn parse_todo_keywords() {
|
|||
keyword: Some("TASK"),
|
||||
title: "COMMENT Title",
|
||||
tags: vec!["tag", "a2%"],
|
||||
contents: ""
|
||||
},
|
||||
""
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,16 +4,14 @@ use std::iter::once;
|
|||
#[cfg_attr(test, derive(PartialEq))]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
|
||||
#[derive(Debug)]
|
||||
pub struct List<'a> {
|
||||
pub struct List {
|
||||
pub indent: usize,
|
||||
pub ordered: bool,
|
||||
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
|
||||
pub contents: &'a str,
|
||||
}
|
||||
|
||||
impl List<'_> {
|
||||
impl List {
|
||||
#[inline]
|
||||
pub(crate) fn parse(text: &str) -> Option<(&str, List<'_>)> {
|
||||
pub(crate) fn parse(text: &str) -> Option<(&str, List, &str)> {
|
||||
let (indent, tail) = text
|
||||
.find(|c| c != ' ')
|
||||
.map(|off| (off, &text[off..]))
|
||||
|
|
@ -33,14 +31,7 @@ impl List<'_> {
|
|||
if line_indent < indent
|
||||
|| (line_indent == indent && is_item(&line[line_indent..]).is_none())
|
||||
{
|
||||
Some((
|
||||
&text[pos..],
|
||||
List {
|
||||
indent,
|
||||
ordered,
|
||||
contents: &text[0..pos],
|
||||
},
|
||||
))
|
||||
Some((&text[pos..], List { indent, ordered }, &text[0..pos]))
|
||||
} else {
|
||||
pos = i;
|
||||
continue;
|
||||
|
|
@ -52,48 +43,20 @@ impl List<'_> {
|
|||
if line_indent < indent
|
||||
|| (line_indent == indent && is_item(&line[line_indent..]).is_none())
|
||||
{
|
||||
Some((
|
||||
&text[pos..],
|
||||
List {
|
||||
indent,
|
||||
ordered,
|
||||
contents: &text[0..pos],
|
||||
},
|
||||
))
|
||||
Some((&text[pos..], List { indent, ordered }, &text[0..pos]))
|
||||
} else {
|
||||
pos = next_i;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
Some((
|
||||
&text[next_i..],
|
||||
List {
|
||||
indent,
|
||||
ordered,
|
||||
contents: &text[0..pos],
|
||||
},
|
||||
))
|
||||
Some((&text[next_i..], List { indent, ordered }, &text[0..pos]))
|
||||
}
|
||||
} else {
|
||||
Some((
|
||||
&text[i..],
|
||||
List {
|
||||
indent,
|
||||
ordered,
|
||||
contents: &text[0..pos],
|
||||
},
|
||||
))
|
||||
Some((&text[i..], List { indent, ordered }, &text[0..pos]))
|
||||
};
|
||||
}
|
||||
|
||||
Some((
|
||||
&text[pos..],
|
||||
List {
|
||||
indent,
|
||||
ordered,
|
||||
contents: &text[0..pos],
|
||||
},
|
||||
))
|
||||
Some((&text[pos..], List { indent, ordered }, &text[0..pos]))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -102,12 +65,11 @@ impl List<'_> {
|
|||
#[derive(Debug)]
|
||||
pub struct ListItem<'a> {
|
||||
pub bullet: &'a str,
|
||||
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
|
||||
pub contents: &'a str,
|
||||
}
|
||||
|
||||
impl ListItem<'_> {
|
||||
pub(crate) fn parse(text: &str, indent: usize) -> (&str, ListItem<'_>) {
|
||||
#[inline]
|
||||
pub(crate) fn parse(text: &str, indent: usize) -> (&str, ListItem<'_>, &str) {
|
||||
debug_assert!(&text[0..indent].trim().is_empty());
|
||||
let off = &text[indent..].find(' ').unwrap() + 1 + indent;
|
||||
|
||||
|
|
@ -125,8 +87,8 @@ impl ListItem<'_> {
|
|||
&text[pos..],
|
||||
ListItem {
|
||||
bullet: &text[indent..off],
|
||||
contents: &text[off..pos],
|
||||
},
|
||||
&text[off..pos],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -137,8 +99,8 @@ impl ListItem<'_> {
|
|||
"",
|
||||
ListItem {
|
||||
bullet: &text[indent..off],
|
||||
contents: &text[off..],
|
||||
},
|
||||
&text[off..],
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -197,8 +159,8 @@ fn list_parse() {
|
|||
List {
|
||||
indent: 0,
|
||||
ordered: false,
|
||||
contents: "+ item1\n+ item2"
|
||||
},
|
||||
"+ item1\n+ item2"
|
||||
))
|
||||
);
|
||||
assert_eq!(
|
||||
|
|
@ -208,8 +170,8 @@ fn list_parse() {
|
|||
List {
|
||||
indent: 0,
|
||||
ordered: false,
|
||||
contents: "* item1\n \n* item2"
|
||||
},
|
||||
"* item1\n \n* item2"
|
||||
))
|
||||
);
|
||||
assert_eq!(
|
||||
|
|
@ -219,8 +181,8 @@ fn list_parse() {
|
|||
List {
|
||||
indent: 0,
|
||||
ordered: false,
|
||||
contents: "* item1\n"
|
||||
},
|
||||
"* item1\n"
|
||||
))
|
||||
);
|
||||
assert_eq!(
|
||||
|
|
@ -230,8 +192,8 @@ fn list_parse() {
|
|||
List {
|
||||
indent: 0,
|
||||
ordered: false,
|
||||
contents: "* item1\n"
|
||||
},
|
||||
"* item1\n"
|
||||
))
|
||||
);
|
||||
assert_eq!(
|
||||
|
|
@ -241,8 +203,8 @@ fn list_parse() {
|
|||
List {
|
||||
indent: 0,
|
||||
ordered: false,
|
||||
contents: "+ item1\n + item2\n"
|
||||
},
|
||||
"+ item1\n + item2\n"
|
||||
))
|
||||
);
|
||||
assert_eq!(
|
||||
|
|
@ -252,8 +214,8 @@ fn list_parse() {
|
|||
List {
|
||||
indent: 0,
|
||||
ordered: false,
|
||||
contents: "+ item1\n \n + item2\n \n+ item 3"
|
||||
},
|
||||
"+ item1\n \n + item2\n \n+ item 3"
|
||||
))
|
||||
);
|
||||
assert_eq!(
|
||||
|
|
@ -263,8 +225,8 @@ fn list_parse() {
|
|||
List {
|
||||
indent: 2,
|
||||
ordered: false,
|
||||
contents: " + item1\n \n + item2"
|
||||
},
|
||||
" + item1\n \n + item2"
|
||||
))
|
||||
);
|
||||
assert_eq!(
|
||||
|
|
@ -274,8 +236,8 @@ fn list_parse() {
|
|||
List {
|
||||
indent: 0,
|
||||
ordered: false,
|
||||
contents: "+ 1\n\n - 2\n\n - 3\n\n+ 4"
|
||||
},
|
||||
"+ 1\n\n - 2\n\n - 3\n\n+ 4"
|
||||
))
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ fn parse() {
|
|||
Element::Macros(Macros {
|
||||
name: "poem",
|
||||
arguments: Some("red,blue")
|
||||
},)
|
||||
})
|
||||
))
|
||||
);
|
||||
assert_eq!(
|
||||
|
|
@ -54,7 +54,7 @@ fn parse() {
|
|||
Element::Macros(Macros {
|
||||
name: "poem",
|
||||
arguments: Some(")")
|
||||
},)
|
||||
})
|
||||
))
|
||||
);
|
||||
assert_eq!(
|
||||
|
|
@ -64,7 +64,7 @@ fn parse() {
|
|||
Element::Macros(Macros {
|
||||
name: "author",
|
||||
arguments: None
|
||||
},)
|
||||
})
|
||||
))
|
||||
);
|
||||
assert!(Macros::parse("{{{0uthor}}}").is_err());
|
||||
|
|
|
|||
|
|
@ -56,23 +56,16 @@ pub use self::{
|
|||
#[derive(Debug)]
|
||||
#[cfg_attr(test, derive(PartialEq))]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
|
||||
#[cfg_attr(feature = "serde", serde(tag = "type"))]
|
||||
#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
|
||||
#[cfg_attr(feature = "serde", serde(tag = "type", rename_all = "snake_case"))]
|
||||
pub enum Element<'a> {
|
||||
Block(Block<'a>),
|
||||
BabelCall(BabelCall<'a>),
|
||||
Section {
|
||||
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
|
||||
contents: &'a str,
|
||||
},
|
||||
Section,
|
||||
Clock(Clock<'a>),
|
||||
Cookie(Cookie<'a>),
|
||||
RadioTarget(RadioTarget<'a>),
|
||||
RadioTarget(RadioTarget),
|
||||
Drawer(Drawer<'a>),
|
||||
Document {
|
||||
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
|
||||
contents: &'a str,
|
||||
},
|
||||
Document,
|
||||
DynBlock(DynBlock<'a>),
|
||||
FnDef(FnDef<'a>),
|
||||
FnRef(FnRef<'a>),
|
||||
|
|
@ -81,49 +74,24 @@ pub enum Element<'a> {
|
|||
InlineSrc(InlineSrc<'a>),
|
||||
Keyword(Keyword<'a>),
|
||||
Link(Link<'a>),
|
||||
List(List<'a>),
|
||||
List(List),
|
||||
ListItem(ListItem<'a>),
|
||||
Macros(Macros<'a>),
|
||||
Planning(Planning<'a>),
|
||||
Snippet(Snippet<'a>),
|
||||
Text {
|
||||
value: &'a str,
|
||||
},
|
||||
Paragraph {
|
||||
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
|
||||
contents: &'a str,
|
||||
},
|
||||
Text { value: &'a str },
|
||||
Paragraph,
|
||||
Rule,
|
||||
Timestamp(Timestamp<'a>),
|
||||
Target(Target<'a>),
|
||||
Bold {
|
||||
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
|
||||
contents: &'a str,
|
||||
},
|
||||
Strike {
|
||||
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
|
||||
contents: &'a str,
|
||||
},
|
||||
Italic {
|
||||
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
|
||||
contents: &'a str,
|
||||
},
|
||||
Underline {
|
||||
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
|
||||
contents: &'a str,
|
||||
},
|
||||
Verbatim {
|
||||
value: &'a str,
|
||||
},
|
||||
Code {
|
||||
value: &'a str,
|
||||
},
|
||||
Comment {
|
||||
value: &'a str,
|
||||
},
|
||||
FixedWidth {
|
||||
value: &'a str,
|
||||
},
|
||||
Bold,
|
||||
Strike,
|
||||
Italic,
|
||||
Underline,
|
||||
Verbatim { value: &'a str },
|
||||
Code { value: &'a str },
|
||||
Comment { value: &'a str },
|
||||
FixedWidth { value: &'a str },
|
||||
}
|
||||
|
||||
macro_rules! impl_from {
|
||||
|
|
@ -140,7 +108,6 @@ impl_from!(Block);
|
|||
impl_from!(BabelCall);
|
||||
impl_from!(Clock);
|
||||
impl_from!(Cookie);
|
||||
impl_from!(RadioTarget);
|
||||
impl_from!(Drawer);
|
||||
impl_from!(DynBlock);
|
||||
impl_from!(FnDef);
|
||||
|
|
@ -150,7 +117,6 @@ impl_from!(InlineCall);
|
|||
impl_from!(InlineSrc);
|
||||
impl_from!(Keyword);
|
||||
impl_from!(Link);
|
||||
impl_from!(List);
|
||||
impl_from!(ListItem);
|
||||
impl_from!(Macros);
|
||||
impl_from!(Planning);
|
||||
|
|
|
|||
|
|
@ -10,14 +10,11 @@ use crate::elements::Element;
|
|||
#[cfg_attr(test, derive(PartialEq))]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
|
||||
#[derive(Debug)]
|
||||
pub struct RadioTarget<'a> {
|
||||
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
|
||||
contents: &'a str,
|
||||
}
|
||||
pub struct RadioTarget;
|
||||
|
||||
impl RadioTarget<'_> {
|
||||
impl RadioTarget {
|
||||
#[inline]
|
||||
pub(crate) fn parse(input: &str) -> IResult<&str, Element<'_>> {
|
||||
pub(crate) fn parse(input: &str) -> IResult<&str, (Element, &str)> {
|
||||
let (input, _) = tag("<<<")(input)?;
|
||||
let (input, contents) = verify(
|
||||
take_while(|c: char| c != '<' && c != '\n' && c != '>'),
|
||||
|
|
@ -25,7 +22,7 @@ impl RadioTarget<'_> {
|
|||
)(input)?;
|
||||
let (input, _) = tag(">>>")(input)?;
|
||||
|
||||
Ok((input, Element::RadioTarget(RadioTarget { contents })))
|
||||
Ok((input, (Element::RadioTarget(RadioTarget), contents)))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -33,16 +30,11 @@ impl RadioTarget<'_> {
|
|||
fn parse() {
|
||||
assert_eq!(
|
||||
RadioTarget::parse("<<<target>>>"),
|
||||
Ok(("", Element::RadioTarget(RadioTarget { contents: "target" })))
|
||||
Ok(("", (Element::RadioTarget(RadioTarget), "target")))
|
||||
);
|
||||
assert_eq!(
|
||||
RadioTarget::parse("<<<tar get>>>"),
|
||||
Ok((
|
||||
"",
|
||||
Element::RadioTarget(RadioTarget {
|
||||
contents: "tar get"
|
||||
},)
|
||||
))
|
||||
Ok(("", (Element::RadioTarget(RadioTarget), "tar get")))
|
||||
);
|
||||
assert!(RadioTarget::parse("<<<target >>>").is_err());
|
||||
assert!(RadioTarget::parse("<<< target>>>").is_err());
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue