diff --git a/examples/html-slugify.rs b/examples/html-slugify.rs
index 993a357..57972dd 100644
--- a/examples/html-slugify.rs
+++ b/examples/html-slugify.rs
@@ -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::();
- self.0.push_str(format!(
- "",
- slugify!(&title)
- ));
- for elem in headline.title() {
- self.element(elem, ctx);
- }
- self.0.push_str(format!(""));
- } else {
- // forwrad to default html export
- self.0.event(event, ctx);
- }
- }
-}
-
fn main() {
let args: Vec<_> = args().collect();
if args.len() < 2 {
eprintln!("Usage: {} ", 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::();
+ html_export.push_str(format!(
+ "",
+ slugify!(&title)
+ ));
+ for elem in headline.title() {
+ html_export.element(elem, ctx);
+ }
+ html_export.push_str(format!(""));
+ } 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());
}
}
diff --git a/src/export/mod.rs b/src/export/mod.rs
index b5e4401..74837cc 100644
--- a/src/export/mod.rs
+++ b/src/export/mod.rs
@@ -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};
diff --git a/src/export/traverse.rs b/src/export/traverse.rs
index ce87712..9afe01c 100644
--- a/src/export/traverse.rs
+++ b/src/export/traverse.rs
@@ -223,3 +223,64 @@ pub trait Traverser {
};
}
}
+
+pub struct FromFn(F);
+
+impl Traverser for FromFn {
+ fn event(&mut self, event: Event, _: &mut TraversalContext) {
+ (self.0)(event)
+ }
+}
+
+pub struct FromFnWithCtx(F);
+
+impl Traverser for FromFnWithCtx {
+ 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: F) -> FromFn {
+ 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: F) -> FromFnWithCtx {
+ FromFnWithCtx(f)
+}