feat: add from_fn and from_fn_with_ctx
This commit is contained in:
parent
42c47fa5b6
commit
e12e89d401
3 changed files with 85 additions and 27 deletions
|
|
@ -3,45 +3,42 @@
|
|||
//! ```
|
||||
|
||||
use orgize::{
|
||||
export::{Container, Event, HtmlExport, TraversalContext, Traverser},
|
||||
export::HtmlExport,
|
||||
export::{from_fn_with_ctx, Container, Event, Traverser},
|
||||
Org,
|
||||
};
|
||||
use slugify::slugify;
|
||||
use std::cmp::min;
|
||||
use std::env::args;
|
||||
|
||||
#[derive(Default)]
|
||||
struct MyHtmlHandler(pub HtmlExport);
|
||||
|
||||
impl Traverser for MyHtmlHandler {
|
||||
fn event(&mut self, event: Event, ctx: &mut TraversalContext) {
|
||||
if let Event::Enter(Container::Headline(headline)) = event {
|
||||
let level = min(headline.level(), 6);
|
||||
let title = headline.title().map(|e| e.to_string()).collect::<String>();
|
||||
self.0.push_str(format!(
|
||||
"<h{level}><a id=\"{0}\" href=\"#{0}\">",
|
||||
slugify!(&title)
|
||||
));
|
||||
for elem in headline.title() {
|
||||
self.element(elem, ctx);
|
||||
}
|
||||
self.0.push_str(format!("</a></h{level}>"));
|
||||
} else {
|
||||
// forwrad to default html export
|
||||
self.0.event(event, ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let args: Vec<_> = args().collect();
|
||||
|
||||
if args.len() < 2 {
|
||||
eprintln!("Usage: {} <org-mode-string>", args[0]);
|
||||
} else {
|
||||
let mut handler = MyHtmlHandler::default();
|
||||
let mut html_export = HtmlExport::default();
|
||||
|
||||
let mut handler = from_fn_with_ctx(|event, ctx| {
|
||||
if let Event::Enter(Container::Headline(headline)) = event {
|
||||
let level = min(headline.level(), 6);
|
||||
let title = headline.title().map(|e| e.to_string()).collect::<String>();
|
||||
html_export.push_str(format!(
|
||||
"<h{level}><a id=\"{0}\" href=\"#{0}\">",
|
||||
slugify!(&title)
|
||||
));
|
||||
for elem in headline.title() {
|
||||
html_export.element(elem, ctx);
|
||||
}
|
||||
html_export.push_str(format!("</a></h{level}>"));
|
||||
} else {
|
||||
// forward to default html export
|
||||
html_export.event(event, ctx);
|
||||
}
|
||||
});
|
||||
|
||||
Org::parse(&args[1]).traverse(&mut handler);
|
||||
|
||||
println!("{}", handler.0.finish());
|
||||
println!("{}", html_export.finish());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,4 +6,4 @@ mod traverse;
|
|||
|
||||
pub use event::{Container, Event};
|
||||
pub use html::{HtmlEscape, HtmlExport};
|
||||
pub use traverse::{TraversalContext, Traverser};
|
||||
pub use traverse::{from_fn, from_fn_with_ctx, FromFn, FromFnWithCtx, TraversalContext, Traverser};
|
||||
|
|
|
|||
|
|
@ -223,3 +223,64 @@ pub trait Traverser {
|
|||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FromFn<F: FnMut(Event)>(F);
|
||||
|
||||
impl<F: FnMut(Event)> Traverser for FromFn<F> {
|
||||
fn event(&mut self, event: Event, _: &mut TraversalContext) {
|
||||
(self.0)(event)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FromFnWithCtx<F: FnMut(Event, &mut TraversalContext)>(F);
|
||||
|
||||
impl<F: FnMut(Event, &mut TraversalContext)> Traverser for FromFnWithCtx<F> {
|
||||
fn event(&mut self, event: Event, ctx: &mut TraversalContext) {
|
||||
(self.0)(event, ctx)
|
||||
}
|
||||
}
|
||||
|
||||
/// A helper for creating traverser
|
||||
///
|
||||
/// ```rust
|
||||
/// use orgize::{
|
||||
/// export::{from_fn, Container, Event, Traverser},
|
||||
/// Org,
|
||||
/// };
|
||||
///
|
||||
/// let mut count = 0;
|
||||
/// let mut handler = from_fn(|event| {
|
||||
/// if matches!(event, Event::Enter(Container::Headline(_))) {
|
||||
/// count += 1;
|
||||
/// }
|
||||
/// });
|
||||
/// Org::parse("* 1\n** 2\n*** 3\n****4").traverse(&mut handler);
|
||||
/// assert_eq!(count, 3);
|
||||
/// ```
|
||||
pub fn from_fn<F: FnMut(Event)>(f: F) -> FromFn<F> {
|
||||
FromFn(f)
|
||||
}
|
||||
|
||||
/// A helper for creating traverser
|
||||
///
|
||||
/// ```rust
|
||||
/// use orgize::{
|
||||
/// export::{from_fn_with_ctx, Container, Event, Traverser},
|
||||
/// Org,
|
||||
/// };
|
||||
///
|
||||
/// let mut count = 0;
|
||||
/// let mut handler = from_fn_with_ctx(|event, ctx| {
|
||||
/// if let Event::Enter(Container::Headline(hdl)) = event {
|
||||
/// count += 1;
|
||||
/// if &hdl.title_raw() == "cow" {
|
||||
/// ctx.stop();
|
||||
/// }
|
||||
/// }
|
||||
/// });
|
||||
/// Org::parse("* 1\n* cow\n* 3").traverse(&mut handler);
|
||||
/// assert_eq!(count, 2);
|
||||
/// ```
|
||||
pub fn from_fn_with_ctx<F: FnMut(Event, &mut TraversalContext)>(f: F) -> FromFnWithCtx<F> {
|
||||
FromFnWithCtx(f)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue