feat(elements): planning element

This commit is contained in:
PoiScript 2019-06-27 13:20:21 +08:00
parent 74fd77dba2
commit 2cba072245
10 changed files with 341 additions and 256 deletions

View file

@ -9,7 +9,7 @@ use test::Bencher;
fn org_syntax(b: &mut Bencher) { fn org_syntax(b: &mut Bencher) {
// wget https://orgmode.org/worg/sources/dev/org-syntax.org // wget https://orgmode.org/worg/sources/dev/org-syntax.org
b.iter(|| { b.iter(|| {
Org::new(include_str!("org-syntax.org")).parse(); Org::parse(include_str!("org-syntax.org"));
}) })
} }
@ -17,7 +17,7 @@ fn org_syntax(b: &mut Bencher) {
fn doc(b: &mut Bencher) { fn doc(b: &mut Bencher) {
// wget https://orgmode.org/worg/sources/doc.org // wget https://orgmode.org/worg/sources/doc.org
b.iter(|| { b.iter(|| {
Org::new(include_str!("doc.org")).parse(); Org::parse(include_str!("doc.org"));
}) })
} }
@ -25,6 +25,6 @@ fn doc(b: &mut Bencher) {
fn org_faq(b: &mut Bencher) { fn org_faq(b: &mut Bencher) {
// wget https://orgmode.org/worg/sources/org-faq.org // wget https://orgmode.org/worg/sources/org-faq.org
b.iter(|| { b.iter(|| {
Org::new(include_str!("org-faq.org")).parse(); Org::parse(include_str!("org-faq.org"));
}) })
} }

View file

@ -60,11 +60,9 @@ fn main() -> Result<(), MyError> {
eprintln!("Usage: {} <org-file>", args[0]); eprintln!("Usage: {} <org-file>", args[0]);
} else { } else {
let contents = String::from_utf8(fs::read(&args[1])?)?; let contents = String::from_utf8(fs::read(&args[1])?)?;
let mut org = Org::new(&contents);
let mut writer = Vec::new();
org.parse(); let mut writer = Vec::new();
org.html(&mut writer, CustomHtmlHandler)?; Org::parse(&contents).html(&mut writer, CustomHtmlHandler)?;
println!("{}", String::from_utf8(writer)?); println!("{}", String::from_utf8(writer)?);
} }

View file

@ -11,9 +11,7 @@ fn main() -> Result<()> {
eprintln!("Usage: {} <org-file>", args[0]); eprintln!("Usage: {} <org-file>", args[0]);
} else { } else {
let contents = String::from_utf8(fs::read(&args[1])?).unwrap(); let contents = String::from_utf8(fs::read(&args[1])?).unwrap();
let mut org = Org::new(&contents); println!("{}", to_string(&Org::parse(&contents)).unwrap());
org.parse();
println!("{}", to_string(&org).unwrap());
} }
Ok(()) Ok(())
} }

View file

@ -3,7 +3,7 @@
use jetscii::ByteSubstring; use jetscii::ByteSubstring;
use memchr::{memchr, memchr2, memrchr}; use memchr::{memchr, memchr2, memrchr};
pub(crate) const DEFAULT_TODO_KEYWORDS: &[&str] = pub const DEFAULT_TODO_KEYWORDS: &[&str] =
&["TODO", "DONE", "NEXT", "WAITING", "LATER", "CANCELLED"]; &["TODO", "DONE", "NEXT", "WAITING", "LATER", "CANCELLED"];
#[cfg_attr(test, derive(PartialEq))] #[cfg_attr(test, derive(PartialEq))]

View file

@ -30,7 +30,7 @@ pub use self::{
dyn_block::DynBlock, dyn_block::DynBlock,
fn_def::FnDef, fn_def::FnDef,
fn_ref::FnRef, fn_ref::FnRef,
headline::Headline, headline::{Headline, DEFAULT_TODO_KEYWORDS},
inline_call::InlineCall, inline_call::InlineCall,
inline_src::InlineSrc, inline_src::InlineSrc,
keyword::{BabelCall, Keyword}, keyword::{BabelCall, Keyword},
@ -45,6 +45,8 @@ pub use self::{
timestamp::*, timestamp::*,
}; };
use indextree::NodeId;
#[derive(Debug)] #[derive(Debug)]
pub enum Element<'a> { pub enum Element<'a> {
Root, Root,
@ -91,6 +93,8 @@ pub enum Element<'a> {
Document { Document {
begin: usize, begin: usize,
end: usize, end: usize,
contents_begin: usize,
contents_end: usize,
}, },
DynBlock { DynBlock {
dyn_block: DynBlock<'a>, dyn_block: DynBlock<'a>,
@ -157,7 +161,13 @@ pub enum Element<'a> {
begin: usize, begin: usize,
end: usize, end: usize,
}, },
Planning(Planning<'a>), Planning {
deadline: Option<NodeId>,
scheduled: Option<NodeId>,
closed: Option<NodeId>,
begin: usize,
end: usize,
},
Snippet { Snippet {
begin: usize, begin: usize,
end: usize, end: usize,

View file

@ -6,16 +6,24 @@ use memchr::memchr;
#[derive(Debug)] #[derive(Debug)]
pub struct Planning<'a> { pub struct Planning<'a> {
/// the date when the task should be done /// the date when the task should be done
pub deadline: Option<Timestamp<'a>>, pub deadline: Option<&'a Timestamp<'a>>,
/// the date when you should start working on the task /// the date when you should start working on the task
pub scheduled: Option<Timestamp<'a>>, pub scheduled: Option<&'a Timestamp<'a>>,
/// the date when the task is closed /// the date when the task is closed
pub closed: Option<Timestamp<'a>>, pub closed: Option<&'a Timestamp<'a>>,
} }
impl Planning<'_> { impl Planning<'_> {
#[inline] #[inline]
pub(crate) fn parse(text: &str) -> Option<(Planning<'_>, usize)> { pub(crate) fn parse(
text: &str,
) -> Option<(
// TODO: timestamp position
Option<(Timestamp<'_>, usize, usize)>,
Option<(Timestamp<'_>, usize, usize)>,
Option<(Timestamp<'_>, usize, usize)>,
usize,
)> {
let (mut deadline, mut scheduled, mut closed) = (None, None, None); let (mut deadline, mut scheduled, mut closed) = (None, None, None);
let (mut tail, off) = memchr(b'\n', text.as_bytes()) let (mut tail, off) = memchr(b'\n', text.as_bytes())
.map(|i| (text[..i].trim(), i + 1)) .map(|i| (text[..i].trim(), i + 1))
@ -28,7 +36,7 @@ impl Planning<'_> {
($timestamp:expr) => { ($timestamp:expr) => {
if $timestamp.is_none() { if $timestamp.is_none() {
let (timestamp, off) = Timestamp::parse(next)?; let (timestamp, off) = Timestamp::parse(next)?;
$timestamp = Some(timestamp); $timestamp = Some((timestamp, 0, 0));
tail = &next[off..].trim_start(); tail = &next[off..].trim_start();
} else { } else {
return None; return None;
@ -47,14 +55,7 @@ impl Planning<'_> {
if deadline.is_none() && scheduled.is_none() && closed.is_none() { if deadline.is_none() && scheduled.is_none() && closed.is_none() {
None None
} else { } else {
Some(( Some((deadline, scheduled, closed, off))
Planning {
deadline,
scheduled,
closed,
},
off,
))
} }
} }
} }
@ -66,8 +67,9 @@ fn prase() {
assert_eq!( assert_eq!(
Planning::parse("SCHEDULED: <2019-04-08 Mon>\n"), Planning::parse("SCHEDULED: <2019-04-08 Mon>\n"),
Some(( Some((
Planning { None,
scheduled: Some(Timestamp::Active { Some((
Timestamp::Active {
start: Datetime { start: Datetime {
date: "2019-04-08", date: "2019-04-08",
time: None, time: None,
@ -75,10 +77,11 @@ fn prase() {
}, },
repeater: None, repeater: None,
delay: None delay: None
}), },
closed: None, 0,
deadline: None, 0
}, )),
None,
"SCHEDULED: <2019-04-08 Mon>\n".len() "SCHEDULED: <2019-04-08 Mon>\n".len()
)) ))
) )

View file

@ -32,7 +32,7 @@ pub enum Event<'a> {
Keyword(&'a Keyword<'a>), Keyword(&'a Keyword<'a>),
Link(&'a Link<'a>), Link(&'a Link<'a>),
Macros(&'a Macros<'a>), Macros(&'a Macros<'a>),
Planning(&'a Planning<'a>), Planning(Planning<'a>),
RadioTarget(&'a RadioTarget<'a>), RadioTarget(&'a RadioTarget<'a>),
Rule, Rule,
Snippet(&'a Snippet<'a>), Snippet(&'a Snippet<'a>),
@ -226,9 +226,36 @@ impl<'a> Iter<'a> {
self.state = State::Start; self.state = State::Start;
Some(Event::Macros(macros)) Some(Event::Macros(macros))
} }
Element::Planning(planning) => { Element::Planning {
deadline,
scheduled,
closed,
..
} => {
self.state = State::Start; self.state = State::Start;
Some(Event::Planning(planning)) Some(Event::Planning(Planning {
deadline: deadline.and_then(|id| {
if let Element::Timestamp { timestamp, .. } = &self.arena[id].data {
Some(timestamp)
} else {
None
}
}),
scheduled: scheduled.and_then(|id| {
if let Element::Timestamp { timestamp, .. } = &self.arena[id].data {
Some(timestamp)
} else {
None
}
}),
closed: closed.and_then(|id| {
if let Element::Timestamp { timestamp, .. } = &self.arena[id].data {
Some(timestamp)
} else {
None
}
}),
}))
} }
Element::RadioTarget { radio_target, .. } => { Element::RadioTarget { radio_target, .. } => {
self.state = State::Start; self.state = State::Start;
@ -364,9 +391,36 @@ impl<'a> Iter<'a> {
self.state = State::End; self.state = State::End;
Some(Event::Macros(macros)) Some(Event::Macros(macros))
} }
Element::Planning(planning) => { Element::Planning {
deadline,
scheduled,
closed,
..
} => {
self.state = State::End; self.state = State::End;
Some(Event::Planning(planning)) Some(Event::Planning(Planning {
deadline: deadline.and_then(|id| {
if let Element::Timestamp { timestamp, .. } = &self.arena[id].data {
Some(timestamp)
} else {
None
}
}),
scheduled: scheduled.and_then(|id| {
if let Element::Timestamp { timestamp, .. } = &self.arena[id].data {
Some(timestamp)
} else {
None
}
}),
closed: closed.and_then(|id| {
if let Element::Timestamp { timestamp, .. } = &self.arena[id].data {
Some(timestamp)
} else {
None
}
}),
}))
} }
Element::RadioTarget { radio_target, .. } => { Element::RadioTarget { radio_target, .. } => {
self.state = State::End; self.state = State::End;

View file

@ -1,12 +1,12 @@
use crate::elements::*;
use crate::export::{DefaultHtmlHandler, HtmlHandler};
use crate::iter::Iter;
use indextree::{Arena, NodeId}; use indextree::{Arena, NodeId};
use jetscii::bytes; use jetscii::bytes;
use memchr::{memchr, memchr_iter, memrchr_iter}; use memchr::{memchr, memchr_iter, memrchr_iter};
use std::io::{Error, Write}; use std::io::{Error, Write};
use crate::elements::*;
use crate::export::{DefaultHtmlHandler, HtmlHandler};
use crate::iter::Iter;
pub struct Org<'a> { pub struct Org<'a> {
pub(crate) arena: Arena<Element<'a>>, pub(crate) arena: Arena<Element<'a>>,
pub(crate) document: NodeId, pub(crate) document: NodeId,
@ -15,25 +15,26 @@ pub struct Org<'a> {
} }
impl<'a> Org<'a> { impl<'a> Org<'a> {
pub fn new(text: &'a str) -> Self { pub fn parse(text: &'a str) -> Self {
let mut arena = Arena::new(); let mut arena = Arena::new();
let root = arena.new_node(Element::Root); let root = arena.new_node(Element::Root);
let document = arena.new_node(Element::Document { let document = arena.new_node(Element::Document {
begin: 0, begin: 0,
end: text.len(), end: text.len(),
contents_begin: 0,
contents_end: text.len(),
}); });
root.append(document, &mut arena).unwrap(); root.append(document, &mut arena).unwrap();
Org { let mut org = Org {
arena, arena,
root, root,
document, document,
text, text,
} };
} org.parse_internal();
pub fn finish(&self) -> bool { org
self.arena[self.document].first_child().is_some()
} }
pub fn iter(&'a self) -> Iter<'a> { pub fn iter(&'a self) -> Iter<'a> {
@ -62,7 +63,7 @@ impl<'a> Org<'a> {
Keyword(e) => handler.keyword(&mut writer, e)?, Keyword(e) => handler.keyword(&mut writer, e)?,
Link(e) => handler.link(&mut writer, e)?, Link(e) => handler.link(&mut writer, e)?,
Macros(e) => handler.macros(&mut writer, e)?, Macros(e) => handler.macros(&mut writer, e)?,
Planning(e) => handler.planning(&mut writer, e)?, Planning(e) => handler.planning(&mut writer, &e)?,
RadioTarget(e) => handler.radio_target(&mut writer, e)?, RadioTarget(e) => handler.radio_target(&mut writer, e)?,
Snippet(e) => handler.snippet(&mut writer, e)?, Snippet(e) => handler.snippet(&mut writer, e)?,
Target(e) => handler.target(&mut writer, e)?, Target(e) => handler.target(&mut writer, e)?,
@ -82,15 +83,15 @@ impl<'a> Org<'a> {
self.html(wrtier, DefaultHtmlHandler) self.html(wrtier, DefaultHtmlHandler)
} }
pub fn parse(&mut self) { fn parse_internal(&mut self) {
if self.finish() {
return;
}
let mut node = self.document; let mut node = self.document;
loop { loop {
match self.arena[node].data { match self.arena[node].data {
Element::Document { begin, end, .. } Element::Document {
contents_begin: begin,
contents_end: end,
..
}
| Element::Headline { | Element::Headline {
contents_begin: begin, contents_begin: begin,
contents_end: end, contents_end: end,
@ -131,8 +132,51 @@ impl<'a> Org<'a> {
contents_begin, contents_begin,
contents_end, contents_end,
.. ..
} => {
let (mut deadline_node, mut scheduled_node, mut closed_node) =
(None, None, None);
if let Some((deadline, scheduled, closed, off)) =
Planning::parse(&self.text[contents_begin..contents_end])
{
if let Some((deadline, off, end)) = deadline {
let timestamp = Element::Timestamp {
timestamp: deadline,
begin: contents_begin + off,
end: contents_end + end,
};
deadline_node = Some(self.arena.new_node(timestamp));
}
if let Some((scheduled, off, end)) = scheduled {
let timestamp = Element::Timestamp {
timestamp: scheduled,
begin: contents_begin + off,
end: contents_end + end,
};
scheduled_node = Some(self.arena.new_node(timestamp));
}
if let Some((closed, off, end)) = closed {
let timestamp = Element::Timestamp {
timestamp: closed,
begin: contents_begin + off,
end: contents_end + end,
};
closed_node = Some(self.arena.new_node(timestamp));
}
let planning = Element::Planning {
deadline: deadline_node,
scheduled: scheduled_node,
closed: closed_node,
begin: contents_begin,
end: contents_begin + off,
};
let new_node = self.arena.new_node(planning);
node.append(new_node, &mut self.arena).unwrap();
self.parse_elements_children(contents_begin + off, contents_end, node);
} else {
self.parse_elements_children(contents_begin, contents_end, node);
}
} }
| Element::Block { Element::Block {
contents_begin, contents_begin,
contents_end, contents_end,
.. ..

View file

@ -25,19 +25,59 @@ struct ElementNode<'a> {
impl Serialize for ElementNode<'_> { impl Serialize for ElementNode<'_> {
#[allow(unused_variables)] #[allow(unused_variables)]
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let mut state; let node = &self.arena[self.node];
match &self.arena[self.node].data {
Element::Root => { macro_rules! ser {
state = serializer.serialize_struct("Element::Root", 2)?; ($state:ident, $begin:ident, $end:ident) => {
state.serialize_field("type", "root")?;
}
Element::Document { begin, end } => {
state = serializer.serialize_struct("Element::Document", 2)?;
state.serialize_field("type", "document")?;
if cfg!(feature = "extra-serde-info") { if cfg!(feature = "extra-serde-info") {
state.serialize_field("begin", begin)?; $state.serialize_field("begin", $begin)?;
state.serialize_field("end", end)?; $state.serialize_field("end", $end)?;
} }
};
($state:ident, $begin:ident, $end:ident, $contents_begin:ident, $contents_end:ident) => {
if cfg!(feature = "extra-serde-info") {
$state.serialize_field("begin", $begin)?;
$state.serialize_field("end", $end)?;
$state.serialize_field("contents_begin", $contents_begin)?;
$state.serialize_field("contents_end", $contents_end)?;
}
if let Some(first) = node.first_child() {
$state.serialize_field(
"children",
&ElementChildrenNode {
first,
arena: self.arena,
},
)?;
}
};
}
match &node.data {
Element::Root => {
let mut state = serializer.serialize_struct("Element::Root", 2)?;
state.serialize_field("type", "root")?;
if let Some(first) = node.first_child() {
state.serialize_field(
"children",
&ElementChildrenNode {
first,
arena: self.arena,
},
)?;
}
state.end()
}
Element::Document {
begin,
end,
contents_begin,
contents_end,
} => {
let mut state = serializer.serialize_struct("Element::Document", 2)?;
state.serialize_field("type", "document")?;
ser!(state, begin, end, contents_begin, contents_end);
state.end()
} }
Element::Block { Element::Block {
block, block,
@ -46,14 +86,10 @@ impl Serialize for ElementNode<'_> {
contents_begin, contents_begin,
contents_end, contents_end,
} => { } => {
state = serializer.serialize_struct("Element::Block", 2)?; let mut state = serializer.serialize_struct("Element::Block", 2)?;
state.serialize_field("type", "block")?; state.serialize_field("type", "block")?;
if cfg!(feature = "extra-serde-info") { ser!(state, begin, end, contents_begin, contents_end);
state.serialize_field("begin", begin)?; state.end()
state.serialize_field("end", end)?;
state.serialize_field("contents_begin", contents_begin)?;
state.serialize_field("contents_end", contents_end)?;
}
} }
Element::Section { Element::Section {
begin, begin,
@ -61,14 +97,10 @@ impl Serialize for ElementNode<'_> {
contents_begin, contents_begin,
contents_end, contents_end,
} => { } => {
state = serializer.serialize_struct("Element::Section", 2)?; let mut state = serializer.serialize_struct("Element::Section", 2)?;
state.serialize_field("type", "section")?; state.serialize_field("type", "section")?;
if cfg!(feature = "extra-serde-info") { ser!(state, begin, end, contents_begin, contents_end);
state.serialize_field("begin", begin)?; state.end()
state.serialize_field("end", end)?;
state.serialize_field("contents_begin", contents_begin)?;
state.serialize_field("contents_end", contents_end)?;
}
} }
Element::Drawer { Element::Drawer {
drawer, drawer,
@ -77,14 +109,10 @@ impl Serialize for ElementNode<'_> {
contents_begin, contents_begin,
contents_end, contents_end,
} => { } => {
state = serializer.serialize_struct("Element::Drawer", 2)?; let mut state = serializer.serialize_struct("Element::Drawer", 2)?;
state.serialize_field("type", "drawer")?; state.serialize_field("type", "drawer")?;
if cfg!(feature = "extra-serde-info") { ser!(state, begin, end, contents_begin, contents_end);
state.serialize_field("begin", begin)?; state.end()
state.serialize_field("end", end)?;
state.serialize_field("contents_begin", contents_begin)?;
state.serialize_field("contents_end", contents_end)?;
}
} }
Element::DynBlock { Element::DynBlock {
dyn_block, dyn_block,
@ -93,14 +121,10 @@ impl Serialize for ElementNode<'_> {
contents_begin, contents_begin,
contents_end, contents_end,
} => { } => {
state = serializer.serialize_struct("Element::DynBlock", 2)?; let mut state = serializer.serialize_struct("Element::DynBlock", 2)?;
state.serialize_field("type", "dynamic_block")?; state.serialize_field("type", "dynamic_block")?;
if cfg!(feature = "extra-serde-info") { ser!(state, begin, end, contents_begin, contents_end);
state.serialize_field("begin", begin)?; state.end()
state.serialize_field("end", end)?;
state.serialize_field("contents_begin", contents_begin)?;
state.serialize_field("contents_end", contents_end)?;
}
} }
Element::FnDef { Element::FnDef {
begin, begin,
@ -109,14 +133,10 @@ impl Serialize for ElementNode<'_> {
contents_end, contents_end,
fn_def, fn_def,
} => { } => {
state = serializer.serialize_struct("Element::FnDef", 2)?; let mut state = serializer.serialize_struct("Element::FnDef", 2)?;
state.serialize_field("type", "footnote_definition")?; state.serialize_field("type", "footnote_definition")?;
if cfg!(feature = "extra-serde-info") { ser!(state, begin, end, contents_begin, contents_end);
state.serialize_field("begin", begin)?; state.end()
state.serialize_field("end", end)?;
state.serialize_field("contents_begin", contents_begin)?;
state.serialize_field("contents_end", contents_end)?;
}
} }
Element::Headline { Element::Headline {
begin, begin,
@ -125,7 +145,7 @@ impl Serialize for ElementNode<'_> {
contents_end, contents_end,
headline, headline,
} => { } => {
state = serializer.serialize_struct("Element::Headline", 2)?; let mut state = serializer.serialize_struct("Element::Headline", 6)?;
state.serialize_field("type", "headline")?; state.serialize_field("type", "headline")?;
state.serialize_field("level", &headline.level)?; state.serialize_field("level", &headline.level)?;
state.serialize_field("title", &headline.title)?; state.serialize_field("title", &headline.title)?;
@ -138,12 +158,8 @@ impl Serialize for ElementNode<'_> {
if !headline.tags.is_empty() { if !headline.tags.is_empty() {
state.serialize_field("tags", &headline.tags)?; state.serialize_field("tags", &headline.tags)?;
} }
if cfg!(feature = "extra-serde-info") { ser!(state, begin, end, contents_begin, contents_end);
state.serialize_field("begin", begin)?; state.end()
state.serialize_field("end", end)?;
state.serialize_field("contents_begin", contents_begin)?;
state.serialize_field("contents_end", contents_end)?;
}
} }
Element::List { Element::List {
list, list,
@ -152,14 +168,10 @@ impl Serialize for ElementNode<'_> {
contents_begin, contents_begin,
contents_end, contents_end,
} => { } => {
state = serializer.serialize_struct("Element::List", 2)?; let mut state = serializer.serialize_struct("Element::List", 2)?;
state.serialize_field("type", "list")?; state.serialize_field("type", "list")?;
if cfg!(feature = "extra-serde-info") { ser!(state, begin, end, contents_begin, contents_end);
state.serialize_field("begin", begin)?; state.end()
state.serialize_field("end", end)?;
state.serialize_field("contents_begin", contents_begin)?;
state.serialize_field("contents_end", contents_end)?;
}
} }
Element::ListItem { Element::ListItem {
list_item, list_item,
@ -168,15 +180,11 @@ impl Serialize for ElementNode<'_> {
contents_begin, contents_begin,
contents_end, contents_end,
} => { } => {
state = serializer.serialize_struct("Element::ListItem", 2)?; let mut state = serializer.serialize_struct("Element::ListItem", 3)?;
state.serialize_field("type", "list_item")?; state.serialize_field("type", "list_item")?;
state.serialize_field("bullet", list_item.bullet)?; state.serialize_field("bullet", list_item.bullet)?;
if cfg!(feature = "extra-serde-info") { ser!(state, begin, end, contents_begin, contents_end);
state.serialize_field("begin", begin)?; state.end()
state.serialize_field("end", end)?;
state.serialize_field("contents_begin", contents_begin)?;
state.serialize_field("contents_end", contents_end)?;
}
} }
Element::Paragraph { Element::Paragraph {
begin, begin,
@ -184,152 +192,157 @@ impl Serialize for ElementNode<'_> {
contents_begin, contents_begin,
contents_end, contents_end,
} => { } => {
state = serializer.serialize_struct("Element::Paragraph", 2)?; let mut state = serializer.serialize_struct("Element::Paragraph", 2)?;
state.serialize_field("type", "paragraph")?; state.serialize_field("type", "paragraph")?;
if cfg!(feature = "extra-serde-info") { ser!(state, begin, end, contents_begin, contents_end);
state.serialize_field("begin", begin)?; state.end()
state.serialize_field("end", end)?;
state.serialize_field("contents_begin", contents_begin)?;
state.serialize_field("contents_end", contents_end)?;
}
} }
Element::Clock { clock, begin, end } => { Element::Clock { clock, begin, end } => {
state = serializer.serialize_struct("Element::Clock", 2)?; let mut state = serializer.serialize_struct("Element::Clock", 1)?;
state.serialize_field("type", "clock")?; state.serialize_field("type", "clock")?;
if cfg!(feature = "extra-serde-info") { ser!(state, begin, end);
state.serialize_field("begin", begin)?; state.end()
state.serialize_field("end", end)?;
}
} }
Element::BabelCall { call, begin, end } => { Element::BabelCall { call, begin, end } => {
state = serializer.serialize_struct("Element::BabelCall", 2)?; let mut state = serializer.serialize_struct("Element::BabelCall", 1)?;
state.serialize_field("type", "babel_call")?; state.serialize_field("type", "babel_call")?;
if cfg!(feature = "extra-serde-info") { ser!(state, begin, end);
state.serialize_field("begin", begin)?; state.end()
state.serialize_field("end", end)?;
}
} }
Element::Cookie { cookie, begin, end } => { Element::Cookie { cookie, begin, end } => {
state = serializer.serialize_struct("Element::Cookie", 2)?; let mut state = serializer.serialize_struct("Element::Cookie", 1)?;
state.serialize_field("type", "cookie")?; state.serialize_field("type", "cookie")?;
if cfg!(feature = "extra-serde-info") { ser!(state, begin, end);
state.serialize_field("begin", begin)?; state.end()
state.serialize_field("end", end)?;
}
} }
Element::FnRef { fn_ref, begin, end } => { Element::FnRef { fn_ref, begin, end } => {
state = serializer.serialize_struct("Element::FnRef", 2)?; let mut state = serializer.serialize_struct("Element::FnRef", 1)?;
state.serialize_field("type", "footnote_reference")?; state.serialize_field("type", "footnote_reference")?;
if cfg!(feature = "extra-serde-info") { ser!(state, begin, end);
state.serialize_field("begin", begin)?; state.end()
state.serialize_field("end", end)?;
}
} }
Element::InlineCall { Element::InlineCall {
inline_call, inline_call,
begin, begin,
end, end,
} => { } => {
state = serializer.serialize_struct("Element::InlineCall", 2)?; let mut state = serializer.serialize_struct("Element::InlineCall", 1)?;
state.serialize_field("type", "inline_call")?; state.serialize_field("type", "inline_call")?;
if cfg!(feature = "extra-serde-info") { ser!(state, begin, end);
state.serialize_field("begin", begin)?; state.end()
state.serialize_field("end", end)?;
}
} }
Element::InlineSrc { Element::InlineSrc {
inline_src, inline_src,
begin, begin,
end, end,
} => { } => {
state = serializer.serialize_struct("Element::InlineSrc", 2)?; let mut state = serializer.serialize_struct("Element::InlineSrc", 1)?;
state.serialize_field("type", "inlne_source_block")?; state.serialize_field("type", "inlne_source_block")?;
if cfg!(feature = "extra-serde-info") { ser!(state, begin, end);
state.serialize_field("begin", begin)?; state.end()
state.serialize_field("end", end)?;
}
} }
Element::Keyword { Element::Keyword {
keyword, keyword,
begin, begin,
end, end,
} => { } => {
state = serializer.serialize_struct("Element::Keyword", 2)?; let mut state = serializer.serialize_struct("Element::Keyword", 4)?;
state.serialize_field("type", "keyword")?; state.serialize_field("type", "keyword")?;
state.serialize_field("key", keyword.key)?; state.serialize_field("key", keyword.key)?;
if let Some(option) = keyword.option { if let Some(option) = keyword.option {
state.serialize_field("option", option)?; state.serialize_field("option", option)?;
} }
state.serialize_field("value", keyword.value)?; state.serialize_field("value", keyword.value)?;
if cfg!(feature = "extra-serde-info") { ser!(state, begin, end);
state.serialize_field("begin", begin)?; state.end()
state.serialize_field("end", end)?;
}
} }
Element::Link { link, begin, end } => { Element::Link { link, begin, end } => {
state = serializer.serialize_struct("Element::Link", 2)?; let mut state = serializer.serialize_struct("Element::Link", 3)?;
state.serialize_field("type", "link")?; state.serialize_field("type", "link")?;
state.serialize_field("path", link.path)?; state.serialize_field("path", link.path)?;
if let Some(desc) = link.desc { if let Some(desc) = link.desc {
state.serialize_field("desc", desc)?; state.serialize_field("desc", desc)?;
} }
if cfg!(feature = "extra-serde-info") { ser!(state, begin, end);
state.serialize_field("begin", begin)?; state.end()
state.serialize_field("end", end)?;
}
} }
Element::Macros { macros, begin, end } => { Element::Macros { macros, begin, end } => {
state = serializer.serialize_struct("Element::Macros", 2)?; let mut state = serializer.serialize_struct("Element::Macros", 1)?;
state.serialize_field("type", "macros")?; state.serialize_field("type", "macros")?;
if cfg!(feature = "extra-serde-info") { ser!(state, begin, end);
state.serialize_field("begin", begin)?; state.end()
state.serialize_field("end", end)?;
}
} }
Element::Planning(_) => { Element::Planning {
state = serializer.serialize_struct("Element::Planning", 2)?; deadline,
scheduled,
closed,
begin,
end,
} => {
let mut state = serializer.serialize_struct("Element::Planning", 4)?;
state.serialize_field("type", "planning")?; state.serialize_field("type", "planning")?;
if let Some(node) = deadline {
state.serialize_field(
"deadline",
&ElementNode {
node: *node,
arena: &self.arena,
},
)?;
}
if let Some(node) = closed {
state.serialize_field(
"closed",
&ElementNode {
node: *node,
arena: &self.arena,
},
)?;
}
if let Some(node) = scheduled {
state.serialize_field(
"scheduled",
&ElementNode {
node: *node,
arena: &self.arena,
},
)?;
}
ser!(state, begin, end);
state.end()
} }
Element::Snippet { Element::Snippet {
begin, begin,
end, end,
snippet, snippet,
} => { } => {
state = serializer.serialize_struct("Element::Snippet", 2)?; let mut state = serializer.serialize_struct("Element::Snippet", 2)?;
state.serialize_field("type", "snippet")?; state.serialize_field("type", "snippet")?;
if cfg!(feature = "extra-serde-info") { ser!(state, begin, end);
state.serialize_field("begin", begin)?; state.end()
state.serialize_field("end", end)?;
}
} }
Element::Text { value, begin, end } => { Element::Text { value, begin, end } => {
state = serializer.serialize_struct("Element::Text", 2)?; let mut state = serializer.serialize_struct("Element::Text", 2)?;
state.serialize_field("type", "text")?; state.serialize_field("type", "text")?;
state.serialize_field("value", value)?; state.serialize_field("value", value)?;
if cfg!(feature = "extra-serde-info") { ser!(state, begin, end);
state.serialize_field("begin", begin)?; state.end()
state.serialize_field("end", end)?;
}
} }
Element::Rule { begin, end } => { Element::Rule { begin, end } => {
state = serializer.serialize_struct("Element::Rule", 2)?; let mut state = serializer.serialize_struct("Element::Rule", 1)?;
state.serialize_field("type", "rule")?; state.serialize_field("type", "rule")?;
if cfg!(feature = "extra-serde-info") { ser!(state, begin, end);
state.serialize_field("begin", begin)?; state.end()
state.serialize_field("end", end)?;
}
} }
Element::Timestamp { Element::Timestamp {
begin, begin,
end, end,
timestamp, timestamp,
} => { } => {
state = serializer.serialize_struct("Element::Timestamp", 2)?; let mut state = serializer.serialize_struct("Element::Timestamp", 1)?;
state.serialize_field("type", "timestamp")?; state.serialize_field("type", "timestamp")?;
if cfg!(feature = "extra-serde-info") { ser!(state, begin, end);
state.serialize_field("begin", begin)?; state.end()
state.serialize_field("end", end)?;
}
} }
Element::Bold { Element::Bold {
begin, begin,
@ -337,14 +350,10 @@ impl Serialize for ElementNode<'_> {
contents_begin, contents_begin,
contents_end, contents_end,
} => { } => {
state = serializer.serialize_struct("Element::Bold", 2)?; let mut state = serializer.serialize_struct("Element::Bold", 2)?;
state.serialize_field("type", "bold")?; state.serialize_field("type", "bold")?;
if cfg!(feature = "extra-serde-info") { ser!(state, begin, end, contents_begin, contents_end);
state.serialize_field("begin", begin)?; state.end()
state.serialize_field("end", end)?;
state.serialize_field("contents_begin", contents_begin)?;
state.serialize_field("contents_end", contents_end)?;
}
} }
Element::Strike { Element::Strike {
begin, begin,
@ -352,14 +361,10 @@ impl Serialize for ElementNode<'_> {
contents_begin, contents_begin,
contents_end, contents_end,
} => { } => {
state = serializer.serialize_struct("Element::Strike", 2)?; let mut state = serializer.serialize_struct("Element::Strike", 2)?;
state.serialize_field("type", "strike")?; state.serialize_field("type", "strike")?;
if cfg!(feature = "extra-serde-info") { ser!(state, begin, end, contents_begin, contents_end);
state.serialize_field("begin", begin)?; state.end()
state.serialize_field("end", end)?;
state.serialize_field("contents_begin", contents_begin)?;
state.serialize_field("contents_end", contents_end)?;
}
} }
Element::Italic { Element::Italic {
begin, begin,
@ -367,14 +372,10 @@ impl Serialize for ElementNode<'_> {
contents_begin, contents_begin,
contents_end, contents_end,
} => { } => {
state = serializer.serialize_struct("Element::Italic", 2)?; let mut state = serializer.serialize_struct("Element::Italic", 2)?;
state.serialize_field("type", "italic")?; state.serialize_field("type", "italic")?;
if cfg!(feature = "extra-serde-info") { ser!(state, begin, end, contents_begin, contents_end);
state.serialize_field("begin", begin)?; state.end()
state.serialize_field("end", end)?;
state.serialize_field("contents_begin", contents_begin)?;
state.serialize_field("contents_end", contents_end)?;
}
} }
Element::Underline { Element::Underline {
begin, begin,
@ -382,64 +383,42 @@ impl Serialize for ElementNode<'_> {
contents_begin, contents_begin,
contents_end, contents_end,
} => { } => {
state = serializer.serialize_struct("Element::Underline", 2)?; let mut state = serializer.serialize_struct("Element::Underline", 2)?;
state.serialize_field("type", "underline")?; state.serialize_field("type", "underline")?;
if cfg!(feature = "extra-serde-info") { ser!(state, begin, end, contents_begin, contents_end);
state.serialize_field("begin", begin)?; state.end()
state.serialize_field("end", end)?;
state.serialize_field("contents_begin", contents_begin)?;
state.serialize_field("contents_end", contents_end)?;
}
} }
Element::Code { begin, end, value } => { Element::Code { begin, end, value } => {
state = serializer.serialize_struct("Element::Code", 2)?; let mut state = serializer.serialize_struct("Element::Code", 2)?;
state.serialize_field("type", "code")?; state.serialize_field("type", "code")?;
state.serialize_field("value", value)?; state.serialize_field("value", value)?;
if cfg!(feature = "extra-serde-info") { ser!(state, begin, end);
state.serialize_field("begin", begin)?; state.end()
state.serialize_field("end", end)?;
}
} }
Element::Verbatim { begin, end, value } => { Element::Verbatim { begin, end, value } => {
state = serializer.serialize_struct("Element::Verbatim", 2)?; let mut state = serializer.serialize_struct("Element::Verbatim", 2)?;
state.serialize_field("type", "verbatim")?; state.serialize_field("type", "verbatim")?;
state.serialize_field("value", value)?; state.serialize_field("value", value)?;
if cfg!(feature = "extra-serde-info") { ser!(state, begin, end);
state.serialize_field("begin", begin)?; state.end()
state.serialize_field("end", end)?;
}
} }
Element::RadioTarget { Element::RadioTarget {
radio_target, radio_target,
begin, begin,
end, end,
} => { } => {
state = serializer.serialize_struct("Element::RadioTarget", 2)?; let mut state = serializer.serialize_struct("Element::RadioTarget", 1)?;
state.serialize_field("type", "radio_target")?; state.serialize_field("type", "radio_target")?;
if cfg!(feature = "extra-serde-info") { ser!(state, begin, end);
state.serialize_field("begin", begin)?; state.end()
state.serialize_field("end", end)?;
}
} }
Element::Target { target, begin, end } => { Element::Target { target, begin, end } => {
state = serializer.serialize_struct("Element::Target", 2)?; let mut state = serializer.serialize_struct("Element::Target", 1)?;
state.serialize_field("type", "target")?; state.serialize_field("type", "target")?;
if cfg!(feature = "extra-serde-info") { ser!(state, begin, end);
state.serialize_field("begin", begin)?; state.end()
state.serialize_field("end", end)?;
}
} }
} }
if let Some(first) = self.arena[self.node].first_child() {
state.serialize_field(
"children",
&ElementChildrenNode {
first,
arena: self.arena,
},
)?;
}
state.end()
} }
} }

View file

@ -6,8 +6,7 @@ macro_rules! test_suite {
#[test] #[test]
fn $name() { fn $name() {
let mut writer = Vec::new(); let mut writer = Vec::new();
let mut org = Org::new($content); let org = Org::parse($content);
org.parse();
org.html_default(&mut writer).unwrap(); org.html_default(&mut writer).unwrap();
let string = String::from_utf8(writer).unwrap(); let string = String::from_utf8(writer).unwrap();
assert_eq!(string, $expected); assert_eq!(string, $expected);