From e12e89d401d35ec3269b34398c28e641a95c6123 Mon Sep 17 00:00:00 2001 From: PoiScript Date: Tue, 26 Mar 2024 17:17:25 +0800 Subject: [PATCH] feat: add from_fn and from_fn_with_ctx --- examples/html-slugify.rs | 49 +++++++++++++++----------------- src/export/mod.rs | 2 +- src/export/traverse.rs | 61 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 85 insertions(+), 27 deletions(-) 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) +}