feat(export): export Org struct as org
This commit is contained in:
parent
53d8f9dc90
commit
73380b26bc
|
@ -1,4 +1,4 @@
|
|||
//! Org-mode elements module
|
||||
//! Org-mode elements
|
||||
|
||||
mod block;
|
||||
mod clock;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
//! Export `Org` struct to various formats.
|
||||
|
||||
pub mod html;
|
||||
// pub mod org;
|
||||
pub mod org;
|
||||
|
||||
pub use html::{DefaultHtmlHandler, HtmlHandler};
|
||||
// pub use org::{DefaultOrgHandler, OrgHandler};
|
||||
pub use org::{DefaultOrgHandler, OrgHandler};
|
||||
|
|
219
src/export/org.rs
Normal file
219
src/export/org.rs
Normal file
|
@ -0,0 +1,219 @@
|
|||
use crate::elements::Element;
|
||||
use std::io::{Error, Write};
|
||||
|
||||
pub trait OrgHandler<E: From<Error>> {
|
||||
fn start<W: Write>(&mut self, mut w: W, element: &Element) -> Result<(), E> {
|
||||
use Element::*;
|
||||
|
||||
match element {
|
||||
// container elements
|
||||
Block(block) => {
|
||||
write!(&mut w, "#+BEGIN_{}", block.name)?;
|
||||
if let Some(parameters) = block.args {
|
||||
write!(&mut w, " {}", parameters)?;
|
||||
}
|
||||
writeln!(&mut w)?;
|
||||
}
|
||||
Bold => write!(w, "*")?,
|
||||
Document => (),
|
||||
DynBlock(dyn_block) => {
|
||||
write!(&mut w, "#+BEGIN: {}", dyn_block.block_name)?;
|
||||
if let Some(parameters) = dyn_block.arguments {
|
||||
write!(&mut w, " {}", parameters)?;
|
||||
}
|
||||
writeln!(&mut w)?;
|
||||
}
|
||||
Headline => (),
|
||||
List(_list) => (),
|
||||
Italic => write!(w, "/")?,
|
||||
ListItem(list_item) => write!(w, "{}", list_item.bullet)?,
|
||||
Paragraph => (),
|
||||
Section => (),
|
||||
Strike => write!(w, "+")?,
|
||||
Underline => write!(w, "_")?,
|
||||
Drawer(drawer) => writeln!(w, ":{}:", drawer.name)?,
|
||||
// non-container elements
|
||||
BabelCall(_babel_call) => (),
|
||||
InlineSrc(inline_src) => {
|
||||
write!(&mut w, "src_{}", inline_src.lang)?;
|
||||
if let Some(options) = inline_src.options {
|
||||
write!(&mut w, "[{}]", options)?;
|
||||
}
|
||||
write!(&mut w, "{{{}}}", inline_src.body)?;
|
||||
}
|
||||
Code { value } => write!(w, "~{}~", value)?,
|
||||
FnRef(fn_ref) => {
|
||||
write!(&mut w, "[fn:")?;
|
||||
if let Some(label) = fn_ref.label {
|
||||
write!(&mut w, "{}", label)?;
|
||||
}
|
||||
if let Some(definition) = fn_ref.definition {
|
||||
write!(&mut w, ":{}", definition)?;
|
||||
}
|
||||
write!(&mut w, "]")?;
|
||||
}
|
||||
InlineCall(inline_call) => {
|
||||
write!(&mut w, "call_{}", inline_call.name)?;
|
||||
if let Some(header) = inline_call.inside_header {
|
||||
write!(&mut w, "[{}]", header)?;
|
||||
}
|
||||
write!(&mut w, "({})", inline_call.arguments)?;
|
||||
if let Some(header) = inline_call.end_header {
|
||||
write!(&mut w, "[{}]", header)?;
|
||||
}
|
||||
}
|
||||
Link(link) => {
|
||||
write!(&mut w, "[[{}]", link.path)?;
|
||||
if let Some(desc) = link.desc {
|
||||
write!(&mut w, "[{}]", desc)?;
|
||||
}
|
||||
write!(&mut w, "]")?;
|
||||
}
|
||||
Macros(_macros) => (),
|
||||
Planning(_planning) => (),
|
||||
RadioTarget(_radio_target) => (),
|
||||
Snippet(snippet) => write!(w, "@@{}:{}@@", snippet.name, snippet.value)?,
|
||||
Target(_target) => (),
|
||||
Text { value } => write!(w, "{}", value)?,
|
||||
Timestamp(timestamp) => {
|
||||
use crate::elements::{Date, Time, Timestamp::*};
|
||||
|
||||
fn write_date<W: Write>(mut w: W, date: &Date) -> Result<(), Error> {
|
||||
write!(
|
||||
w,
|
||||
"{}-{}-{} {}",
|
||||
date.year, date.month, date.day, date.dayname
|
||||
)
|
||||
}
|
||||
|
||||
fn write_time<W: Write>(mut w: W, time: &Option<Time>) -> Result<(), Error> {
|
||||
if let Some(time) = time {
|
||||
write!(w, " {}:{}", time.hour, time.minute)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
match timestamp {
|
||||
Active {
|
||||
start_date,
|
||||
start_time,
|
||||
..
|
||||
} => {
|
||||
write!(&mut w, "<")?;
|
||||
write_date(&mut w, start_date)?;
|
||||
write_time(&mut w, start_time)?;
|
||||
write!(&mut w, ">")?;
|
||||
}
|
||||
Inactive {
|
||||
start_date,
|
||||
start_time,
|
||||
..
|
||||
} => {
|
||||
write!(&mut w, "[")?;
|
||||
write_date(&mut w, start_date)?;
|
||||
write_time(&mut w, start_time)?;
|
||||
write!(&mut w, "]")?;
|
||||
}
|
||||
ActiveRange {
|
||||
start_date,
|
||||
start_time,
|
||||
end_date,
|
||||
end_time,
|
||||
..
|
||||
} => {
|
||||
write!(&mut w, "<")?;
|
||||
write_date(&mut w, start_date)?;
|
||||
write_time(&mut w, start_time)?;
|
||||
write!(&mut w, ">--<")?;
|
||||
write_date(&mut w, end_date)?;
|
||||
write_time(&mut w, end_time)?;
|
||||
write!(&mut w, ">")?;
|
||||
}
|
||||
InactiveRange {
|
||||
start_date,
|
||||
start_time,
|
||||
end_date,
|
||||
end_time,
|
||||
..
|
||||
} => {
|
||||
write!(&mut w, "[")?;
|
||||
write_date(&mut w, start_date)?;
|
||||
write_time(&mut w, start_time)?;
|
||||
write!(&mut w, "]--[")?;
|
||||
write_date(&mut w, end_date)?;
|
||||
write_time(&mut w, end_time)?;
|
||||
write!(&mut w, "]")?;
|
||||
}
|
||||
Diary(value) => write!(w, "<%%({})>", value)?,
|
||||
}
|
||||
}
|
||||
Verbatim { value } => write!(w, "={}=", value)?,
|
||||
FnDef(_fn_def) => (),
|
||||
Clock(_clock) => (),
|
||||
Comment { value } => write!(w, "{}", value)?,
|
||||
FixedWidth { value } => write!(w, "{}", value)?,
|
||||
Keyword(keyword) => {
|
||||
write!(&mut w, "#+{}", keyword.key)?;
|
||||
if let Some(optional) = keyword.optional {
|
||||
write!(&mut w, "[{}]", optional)?;
|
||||
}
|
||||
writeln!(&mut w, ": {}", keyword.value)?;
|
||||
}
|
||||
Rule => writeln!(w, "-----")?,
|
||||
Cookie(_cookie) => (),
|
||||
Title(title) => {
|
||||
for _ in 0..title.level {
|
||||
write!(&mut w, "*")?;
|
||||
}
|
||||
if let Some(keyword) = title.keyword {
|
||||
write!(&mut w, " {}", keyword)?;
|
||||
}
|
||||
if let Some(priority) = title.priority {
|
||||
write!(&mut w, " [#{}]", priority)?;
|
||||
}
|
||||
write!(&mut w, " ")?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn end<W: Write>(&mut self, mut w: W, element: &Element) -> Result<(), E> {
|
||||
use Element::*;
|
||||
|
||||
match element {
|
||||
// container elements
|
||||
Block(block) => writeln!(w, "#+END_{}", block.name)?,
|
||||
Bold => write!(w, "*")?,
|
||||
Document => (),
|
||||
DynBlock(_dyn_block) => writeln!(w, "#+END:")?,
|
||||
Headline => (),
|
||||
List(_list) => (),
|
||||
Italic => write!(w, "/")?,
|
||||
ListItem(_) => (),
|
||||
Paragraph => write!(w, "\n\n")?,
|
||||
Section => (),
|
||||
Strike => write!(w, "+")?,
|
||||
Underline => write!(w, "_")?,
|
||||
Drawer(_) => writeln!(w, ":END:")?,
|
||||
Title(title) => {
|
||||
if !title.tags.is_empty() {
|
||||
write!(&mut w, " :")?;
|
||||
}
|
||||
for tag in &title.tags {
|
||||
write!(&mut w, "{}:", tag)?;
|
||||
}
|
||||
writeln!(&mut w)?;
|
||||
}
|
||||
// non-container elements
|
||||
_ => debug_assert!(!element.is_container()),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DefaultOrgHandler;
|
||||
|
||||
impl OrgHandler<Error> for DefaultOrgHandler {}
|
|
@ -88,7 +88,7 @@
|
|||
//! use std::io::{Error as IOError, Write};
|
||||
//! use std::string::FromUtf8Error;
|
||||
//!
|
||||
//! use orgize::export::{html::Escape, DefaultHtmlHandler, HtmlHandler};
|
||||
//! use orgize::export::{DefaultHtmlHandler, HtmlHandler};
|
||||
//! use orgize::{Element, Org};
|
||||
//! use slugify::slugify;
|
||||
//!
|
||||
|
|
20
src/org.rs
20
src/org.rs
|
@ -146,6 +146,26 @@ impl<'a> Org<'a> {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn org<W: Write>(&self, wrtier: W) -> Result<(), Error> {
|
||||
self.org_with_handler(wrtier, DefaultOrgHandler)
|
||||
}
|
||||
|
||||
pub fn org_with_handler<W, H, E>(&self, mut writer: W, mut handler: H) -> Result<(), E>
|
||||
where
|
||||
W: Write,
|
||||
E: From<Error>,
|
||||
H: OrgHandler<E>,
|
||||
{
|
||||
for event in self.iter() {
|
||||
match event {
|
||||
Event::Start(element) => handler.start(&mut writer, element)?,
|
||||
Event::End(element) => handler.end(&mut writer, element)?,
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn is_headline(text: &str) -> Option<usize> {
|
||||
|
|
Loading…
Reference in a new issue