From 19c62979f05b66aeacdf8b8b29eca08a99382252 Mon Sep 17 00:00:00 2001 From: PoiScript Date: Tue, 5 Dec 2023 17:32:05 +0800 Subject: [PATCH] feat: simpify Traverser trait --- examples/html-slugify.rs | 29 +- src/export/event.rs | 70 +++++ src/export/forward.rs | 224 --------------- src/export/html.rs | 583 ++++++++++++--------------------------- src/export/mod.rs | 3 +- src/export/traverse.rs | 407 ++++++++++++--------------- src/org.rs | 8 +- 7 files changed, 439 insertions(+), 885 deletions(-) create mode 100644 src/export/event.rs delete mode 100644 src/export/forward.rs diff --git a/examples/html-slugify.rs b/examples/html-slugify.rs index 996a263..993a357 100644 --- a/examples/html-slugify.rs +++ b/examples/html-slugify.rs @@ -3,10 +3,7 @@ //! ``` use orgize::{ - ast::Headline, - export::{HtmlExport, TraversalContext, Traverser}, - forward_handler, - rowan::WalkEvent, + export::{Container, Event, HtmlExport, TraversalContext, Traverser}, Org, }; use slugify::slugify; @@ -16,16 +13,9 @@ use std::env::args; #[derive(Default)] struct MyHtmlHandler(pub HtmlExport); -// AsMut trait is required for using forward_handler macros -impl AsMut for MyHtmlHandler { - fn as_mut(&mut self) -> &mut HtmlExport { - &mut self.0 - } -} - impl Traverser for MyHtmlHandler { - fn headline(&mut self, event: WalkEvent<&Headline>, ctx: &mut TraversalContext) { - if let WalkEvent::Enter(headline) = event { + 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!( @@ -36,18 +26,11 @@ impl Traverser for MyHtmlHandler { self.element(elem, ctx); } self.0.push_str(format!("")); + } else { + // forwrad to default html export + self.0.event(event, ctx); } } - - forward_handler! { - HtmlExport, - link text document paragraph section rule comment - inline_src inline_call code bold verbatim italic strike underline list list_item - special_block quote_block center_block verse_block comment_block example_block export_block - source_block babel_call clock cookie radio_target drawer dyn_block fn_def fn_ref macros - snippet timestamp target fixed_width org_table org_table_row org_table_cell latex_fragment - latex_environment entity line_break superscript subscript keyword property_drawer - } } fn main() { diff --git a/src/export/event.rs b/src/export/event.rs new file mode 100644 index 0000000..b525d61 --- /dev/null +++ b/src/export/event.rs @@ -0,0 +1,70 @@ +use crate::{ast::*, SyntaxToken}; + +#[non_exhaustive] +#[derive(Clone, PartialEq, Eq, Debug)] +pub enum Container { + Document(Document), + Section(Section), + Paragraph(Paragraph), + Headline(Headline), + + OrgTable(OrgTable), + OrgTableRow(OrgTableRow), + OrgTableCell(OrgTableCell), + TableEl(TableEl), + + List(List), + ListItem(ListItem), + Drawer(Drawer), + DynBlock(DynBlock), + + FnDef(FnDef), + Comment(Comment), + FixedWidth(FixedWidth), + SpecialBlock(SpecialBlock), + QuoteBlock(QuoteBlock), + CenterBlock(CenterBlock), + VerseBlock(VerseBlock), + CommentBlock(CommentBlock), + ExampleBlock(ExampleBlock), + ExportBlock(ExportBlock), + SourceBlock(SourceBlock), + + Link(Link), + RadioTarget(RadioTarget), + FnRef(FnRef), + Target(Target), + Bold(Bold), + Strike(Strike), + Italic(Italic), + Underline(Underline), + Verbatim(Verbatim), + Code(Code), + Superscript(Superscript), + Subscript(Subscript), + BabelCall(BabelCall), + PropertyDrawer(PropertyDrawer), + AffiliatedKeyword(AffiliatedKeyword), + Keyword(Keyword), +} + +#[non_exhaustive] +#[derive(Clone, PartialEq, Eq, Debug)] +pub enum Event { + Enter(Container), + Leave(Container), + + Text(SyntaxToken), + Macros(Macros), + Cookie(Cookie), + InlineCall(InlineCall), + InlineSrc(InlineSrc), + Clock(Clock), + LineBreak(LineBreak), + Snippet(Snippet), + Rule(Rule), + Timestamp(Timestamp), + LatexFragment(LatexFragment), + LatexEnvironment(LatexEnvironment), + Entity(Entity), +} diff --git a/src/export/forward.rs b/src/export/forward.rs deleted file mode 100644 index 2bd742a..0000000 --- a/src/export/forward.rs +++ /dev/null @@ -1,224 +0,0 @@ -/// Forward traverser method implement to other -/// -/// Used to "extend" some builtin traverser like `HtmlExport`. -/// -/// ```rust -/// use orgize::{ -/// ast::Headline, -/// export::{HtmlExport, TraversalContext, Traverser}, -/// forward_handler, -/// rowan::{ast::AstNode, WalkEvent}, -/// Org, -/// }; -/// use slugify::slugify; -/// use std::cmp::min; -/// -/// #[derive(Default)] -/// struct SlugifyTitleHandler(pub HtmlExport); -/// -/// // AsMut trait is required -/// impl AsMut for SlugifyTitleHandler { -/// fn as_mut(&mut self) -> &mut HtmlExport { -/// &mut self.0 -/// } -/// } -/// -/// impl Traverser for SlugifyTitleHandler { -/// fn headline(&mut self, event: WalkEvent<&Headline>, ctx: &mut TraversalContext) { -/// if let WalkEvent::Enter(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!("")); -/// } -/// } -/// -/// forward_handler! { -/// HtmlExport, -/// link text document paragraph section rule comment -/// inline_src inline_call code bold verbatim italic strike underline list list_item -/// special_block quote_block center_block verse_block comment_block example_block export_block -/// source_block babel_call clock cookie radio_target drawer dyn_block fn_def fn_ref macros -/// snippet timestamp target fixed_width org_table org_table_row org_table_cell latex_fragment -/// latex_environment entity line_break superscript subscript keyword property_drawer -/// } -/// } -/// -/// let mut handler = SlugifyTitleHandler::default(); -/// Org::parse("* hello world!").traverse(&mut handler); -/// assert_eq!(handler.0.finish(), r##"

hello world!

"##); -/// ``` -#[macro_export(local_inner_macros)] -macro_rules! forward_handler { - ($handler:ty, $($func:ident)*) => { - $( - forward_handler!(@method $handler, $func); - )* - }; - - (@method $handler:ty, text) => { - forward_handler!(@method $handler, text, $crate::SyntaxToken); - }; - (@method $handler:ty, document) => { - forward_handler!(@method $handler, document, WalkEvent<&$crate::ast::Document>); - }; - (@method $handler:ty, headline) => { - forward_handler!(@method $handler, headline, WalkEvent<&$crate::ast::Headline>); - }; - (@method $handler:ty, paragraph) => { - forward_handler!(@method $handler, paragraph, WalkEvent<&$crate::ast::Paragraph>); - }; - (@method $handler:ty, section) => { - forward_handler!(@method $handler, section, WalkEvent<&$crate::ast::Section>); - }; - (@method $handler:ty, rule) => { - forward_handler!(@method $handler, rule, WalkEvent<&$crate::ast::Rule>); - }; - (@method $handler:ty, comment) => { - forward_handler!(@method $handler, comment, WalkEvent<&$crate::ast::Comment>); - }; - (@method $handler:ty, inline_src) => { - forward_handler!(@method $handler, inline_src, WalkEvent<&$crate::ast::InlineSrc>); - }; - (@method $handler:ty, inline_call) => { - forward_handler!(@method $handler, inline_call, WalkEvent<&$crate::ast::InlineCall>); - }; - (@method $handler:ty, code) => { - forward_handler!(@method $handler, code, WalkEvent<&$crate::ast::Code>); - }; - (@method $handler:ty, bold) => { - forward_handler!(@method $handler, bold, WalkEvent<&$crate::ast::Bold>); - }; - (@method $handler:ty, verbatim) => { - forward_handler!(@method $handler, verbatim, WalkEvent<&$crate::ast::Verbatim>); - }; - (@method $handler:ty, italic) => { - forward_handler!(@method $handler, italic, WalkEvent<&$crate::ast::Italic>); - }; - (@method $handler:ty, strike) => { - forward_handler!(@method $handler, strike, WalkEvent<&$crate::ast::Strike>); - }; - (@method $handler:ty, underline) => { - forward_handler!(@method $handler, underline, WalkEvent<&$crate::ast::Underline>); - }; - (@method $handler:ty, list) => { - forward_handler!(@method $handler, list, WalkEvent<&$crate::ast::List>); - }; - (@method $handler:ty, list_item) => { - forward_handler!(@method $handler, list_item, WalkEvent<&$crate::ast::ListItem>); - }; - (@method $handler:ty, special_block) => { - forward_handler!(@method $handler, special_block, WalkEvent<&$crate::ast::SpecialBlock>); - }; - (@method $handler:ty, quote_block) => { - forward_handler!(@method $handler, quote_block, WalkEvent<&$crate::ast::QuoteBlock>); - }; - (@method $handler:ty, center_block) => { - forward_handler!(@method $handler, center_block, WalkEvent<&$crate::ast::CenterBlock>); - }; - (@method $handler:ty, verse_block) => { - forward_handler!(@method $handler, verse_block, WalkEvent<&$crate::ast::VerseBlock>); - }; - (@method $handler:ty, comment_block) => { - forward_handler!(@method $handler, comment_block, WalkEvent<&$crate::ast::CommentBlock>); - }; - (@method $handler:ty, example_block) => { - forward_handler!(@method $handler, example_block, WalkEvent<&$crate::ast::ExampleBlock>); - }; - (@method $handler:ty, export_block) => { - forward_handler!(@method $handler, export_block, WalkEvent<&$crate::ast::ExportBlock>); - }; - (@method $handler:ty, source_block) => { - forward_handler!(@method $handler, source_block, WalkEvent<&$crate::ast::SourceBlock>); - }; - (@method $handler:ty, babel_call) => { - forward_handler!(@method $handler, babel_call, WalkEvent<&$crate::ast::BabelCall>); - }; - (@method $handler:ty, clock) => { - forward_handler!(@method $handler, clock, WalkEvent<&$crate::ast::Clock>); - }; - (@method $handler:ty, cookie) => { - forward_handler!(@method $handler, cookie, WalkEvent<&$crate::ast::Cookie>); - }; - (@method $handler:ty, radio_target) => { - forward_handler!(@method $handler, radio_target, WalkEvent<&$crate::ast::RadioTarget>); - }; - (@method $handler:ty, drawer) => { - forward_handler!(@method $handler, drawer, WalkEvent<&$crate::ast::Drawer>); - }; - (@method $handler:ty, dyn_block) => { - forward_handler!(@method $handler, dyn_block, WalkEvent<&$crate::ast::DynBlock>); - }; - (@method $handler:ty, fn_def) => { - forward_handler!(@method $handler, fn_def, WalkEvent<&$crate::ast::FnDef>); - }; - (@method $handler:ty, fn_ref) => { - forward_handler!(@method $handler, fn_ref, WalkEvent<&$crate::ast::FnRef>); - }; - (@method $handler:ty, macros) => { - forward_handler!(@method $handler, macros, WalkEvent<&$crate::ast::Macros>); - }; - (@method $handler:ty, snippet) => { - forward_handler!(@method $handler, snippet, WalkEvent<&$crate::ast::Snippet>); - }; - (@method $handler:ty, timestamp) => { - forward_handler!(@method $handler, timestamp, WalkEvent<&$crate::ast::Timestamp>); - }; - (@method $handler:ty, target) => { - forward_handler!(@method $handler, target, WalkEvent<&$crate::ast::Target>); - }; - (@method $handler:ty, fixed_width) => { - forward_handler!(@method $handler, fixed_width, WalkEvent<&$crate::ast::FixedWidth>); - }; - (@method $handler:ty, org_table) => { - forward_handler!(@method $handler, org_table, WalkEvent<&$crate::ast::OrgTable>); - }; - (@method $handler:ty, org_table_row) => { - forward_handler!(@method $handler, org_table_row, WalkEvent<&$crate::ast::OrgTableRow>); - }; - (@method $handler:ty, org_table_cell) => { - forward_handler!(@method $handler, org_table_cell, WalkEvent<&$crate::ast::OrgTableCell>); - }; - (@method $handler:ty, link) => { - forward_handler!(@method $handler, link, WalkEvent<&$crate::ast::Link>); - }; - (@method $handler:ty, latex_fragment) => { - forward_handler!(@method $handler, latex_fragment, WalkEvent<&$crate::ast::LatexFragment>); - }; - (@method $handler:ty, latex_environment) => { - forward_handler!(@method $handler, latex_environment, WalkEvent<&$crate::ast::LatexEnvironment>); - }; - (@method $handler:ty, entity) => { - forward_handler!(@method $handler, entity, WalkEvent<&$crate::ast::Entity>); - }; - (@method $handler:ty, line_break) => { - forward_handler!(@method $handler, line_break, WalkEvent<&$crate::ast::LineBreak>); - }; - (@method $handler:ty, superscript) => { - forward_handler!(@method $handler, superscript, WalkEvent<&$crate::ast::Superscript>); - }; - (@method $handler:ty, subscript) => { - forward_handler!(@method $handler, subscript, WalkEvent<&$crate::ast::Subscript>); - }; - (@method $handler:ty, keyword) => { - forward_handler!(@method $handler, keyword, WalkEvent<&$crate::ast::Keyword>); - }; - (@method $handler:ty, property_drawer) => { - forward_handler!(@method $handler, property_drawer, WalkEvent<&$crate::ast::PropertyDrawer>); - }; - (@method $handler:ty, $x:ident) => { - std::compile_error!(std::concat!(std::stringify!($x), " is not a method")); - }; - - (@method $handler:ty, $name:ident, $type:ty) => { - fn $name(&mut self, item: $type, ctx: &mut $crate::export::TraversalContext) { - >::as_mut(self).$name(item, ctx) - } - }; -} diff --git a/src/export/html.rs b/src/export/html.rs index 5a44b70..9ec25e0 100644 --- a/src/export/html.rs +++ b/src/export/html.rs @@ -1,12 +1,11 @@ -use rowan::{NodeOrToken, WalkEvent}; +use rowan::NodeOrToken; use std::cmp::min; use std::fmt; use std::fmt::Write as _; +use super::event::{Container, Event}; use super::TraversalContext; use super::Traverser; -use crate::ast::*; -use crate::syntax::SyntaxToken; use crate::SyntaxKind; /// A wrapper for escaping sensitive characters in html. @@ -77,23 +76,70 @@ impl HtmlExport { } impl Traverser for HtmlExport { - #[tracing::instrument(skip(self, _ctx))] - fn text(&mut self, token: SyntaxToken, _ctx: &mut TraversalContext) { - self.output += &HtmlEscape(token.text()).to_string(); - } - - #[tracing::instrument(skip(self, _ctx))] - fn document(&mut self, event: WalkEvent<&Document>, _ctx: &mut TraversalContext) { - self.output += match event { - WalkEvent::Enter(_) => "
", - WalkEvent::Leave(_) => "
", - }; - } - - #[tracing::instrument(skip(self, _ctx))] - fn list(&mut self, event: WalkEvent<&List>, _ctx: &mut TraversalContext) { + fn event(&mut self, event: Event, ctx: &mut TraversalContext) { match event { - WalkEvent::Enter(list) => { + Event::Enter(Container::Document(_)) => self.output += "
", + Event::Leave(Container::Document(_)) => self.output += "
", + + Event::Enter(Container::Headline(headline)) => { + let level = min(headline.level(), 6); + let _ = write!(&mut self.output, ""); + for elem in headline.title() { + self.element(elem, ctx); + } + let _ = write!(&mut self.output, ""); + } + Event::Leave(Container::Headline(_)) => {} + + Event::Enter(Container::Paragraph(_)) => self.output += "

", + Event::Leave(Container::Paragraph(_)) => self.output += "

", + + Event::Enter(Container::Section(_)) => self.output += "
", + Event::Leave(Container::Section(_)) => self.output += "
", + + Event::Enter(Container::Italic(_)) => self.output += "", + Event::Leave(Container::Italic(_)) => self.output += "", + + Event::Enter(Container::Bold(_)) => self.output += "", + Event::Leave(Container::Bold(_)) => self.output += "", + + Event::Enter(Container::Strike(_)) => self.output += "", + Event::Leave(Container::Strike(_)) => self.output += "", + + Event::Enter(Container::Underline(_)) => self.output += "", + Event::Leave(Container::Underline(_)) => self.output += "", + + Event::Enter(Container::Verbatim(_)) => self.output += "", + Event::Leave(Container::Verbatim(_)) => self.output += "", + + Event::Enter(Container::Code(_)) => self.output += "", + Event::Leave(Container::Code(_)) => self.output += "", + + Event::Enter(Container::QuoteBlock(_)) => self.output += "
", + Event::Leave(Container::QuoteBlock(_)) => self.output += "
", + + Event::Enter(Container::VerseBlock(_)) => self.output += "

", + Event::Leave(Container::VerseBlock(_)) => self.output += "

", + + Event::Enter(Container::ExampleBlock(_)) => self.output += "
",
+            Event::Leave(Container::ExampleBlock(_)) => self.output += "
", + + Event::Enter(Container::CenterBlock(_)) => self.output += "
", + Event::Leave(Container::CenterBlock(_)) => self.output += "
", + + Event::Enter(Container::CommentBlock(_)) => self.output += "", + + Event::Enter(Container::Comment(_)) => self.output += "", + + Event::Enter(Container::Subscript(_)) => self.output += "", + Event::Leave(Container::Subscript(_)) => self.output += "", + + Event::Enter(Container::Superscript(_)) => self.output += "", + Event::Leave(Container::Superscript(_)) => self.output += "", + + Event::Enter(Container::List(list)) => { self.output += if list.is_ordered() { self.in_descriptive_list.push(false); "
    " @@ -105,7 +151,7 @@ impl Traverser for HtmlExport { "
      " }; } - WalkEvent::Leave(list) => { + Event::Leave(Container::List(list)) => { self.output += if list.is_ordered() { "
" } else if let Some(true) = self.in_descriptive_list.last() { @@ -115,123 +161,92 @@ impl Traverser for HtmlExport { }; self.in_descriptive_list.pop(); } - }; - } - - #[tracing::instrument(skip(self, ctx))] - fn list_item(&mut self, event: WalkEvent<&ListItem>, ctx: &mut TraversalContext) { - if self.in_descriptive_list.last().copied().unwrap_or_default() { - match event { - WalkEvent::Enter(item) => { + Event::Enter(Container::ListItem(list_item)) => { + if let Some(&true) = self.in_descriptive_list.last() { self.output += "
"; - for elem in item.tag() { + for elem in list_item.tag() { self.element(elem, ctx); } self.output += "
"; + } else { + self.output += "
  • "; + } + } + Event::Leave(Container::ListItem(_)) => { + if let Some(&true) = self.in_descriptive_list.last() { + self.output += "
  • "; + } else { + self.output += ""; } - WalkEvent::Leave(_) => self.output += "", - }; - } else { - match event { - WalkEvent::Enter(_) => self.output += "
  • ", - WalkEvent::Leave(_) => self.output += "
  • ", - }; - } - } - - #[tracing::instrument(skip(self, _ctx))] - fn paragraph(&mut self, event: WalkEvent<&Paragraph>, _ctx: &mut TraversalContext) { - self.output += match event { - WalkEvent::Enter(_) => "

    ", - WalkEvent::Leave(_) => "

    ", - }; - } - - #[tracing::instrument(skip(self, _ctx))] - fn section(&mut self, event: WalkEvent<&Section>, _ctx: &mut TraversalContext) { - self.output += match event { - WalkEvent::Enter(_) => "
    ", - WalkEvent::Leave(_) => "
    ", - }; - } - - #[tracing::instrument(skip(self, _ctx))] - fn fixed_width(&mut self, event: WalkEvent<&FixedWidth>, _ctx: &mut TraversalContext) { - if let WalkEvent::Enter(_f) = event { - // self.output += f.text(); - }; - } - - #[tracing::instrument(skip(self, ctx))] - fn snippet(&mut self, event: WalkEvent<&Snippet>, ctx: &mut TraversalContext) { - if let WalkEvent::Enter(snippet) = event { - if snippet.backend().eq_ignore_ascii_case("html") { - self.output += &snippet.value(); } - return ctx.skip(); - }; - } - #[tracing::instrument(skip(self, _ctx))] - fn italic(&mut self, event: WalkEvent<&Italic>, _ctx: &mut TraversalContext) { - self.output += match event { - WalkEvent::Enter(_) => "", - WalkEvent::Leave(_) => "", - }; - } + Event::Enter(Container::OrgTable(table)) => { + self.output += ""; + self.table_row = if table.has_header() { + TableRow::HeaderRule + } else { + TableRow::BodyRule + } + } + Event::Leave(Container::OrgTable(_)) => { + match self.table_row { + TableRow::Body => self.output += "", + TableRow::Header => self.output += "", + _ => {} + } + self.output += "
    "; + } + Event::Enter(Container::OrgTableRow(row)) => { + if row.is_rule() { + match self.table_row { + TableRow::Body => { + self.output += ""; + self.table_row = TableRow::BodyRule; + } + TableRow::Header => { + self.output += ""; + self.table_row = TableRow::BodyRule; + } + _ => {} + } + ctx.skip(); + } else { + match self.table_row { + TableRow::HeaderRule => { + self.table_row = TableRow::Header; + self.output += ""; + } + TableRow::BodyRule => { + self.table_row = TableRow::Body; + self.output += ""; + } + _ => {} + } + self.output += ""; + } + } + Event::Leave(Container::OrgTableRow(row)) => { + if row.is_rule() { + match self.table_row { + TableRow::Body => { + self.output += ""; + self.table_row = TableRow::BodyRule; + } + TableRow::Header => { + self.output += ""; + self.table_row = TableRow::BodyRule; + } + _ => {} + } + ctx.skip(); + } else { + self.output += ""; + } + } + Event::Enter(Container::OrgTableCell(_)) => self.output += "", + Event::Leave(Container::OrgTableCell(_)) => self.output += "", - #[tracing::instrument(skip(self, _ctx))] - fn bold(&mut self, event: WalkEvent<&Bold>, _ctx: &mut TraversalContext) { - self.output += match event { - WalkEvent::Enter(_) => "", - WalkEvent::Leave(_) => "", - }; - } - - #[tracing::instrument(skip(self, _ctx))] - fn strike(&mut self, event: WalkEvent<&Strike>, _ctx: &mut TraversalContext) { - self.output += match event { - WalkEvent::Enter(_) => "", - WalkEvent::Leave(_) => "", - }; - } - - #[tracing::instrument(skip(self, _ctx))] - fn underline(&mut self, event: WalkEvent<&Underline>, _ctx: &mut TraversalContext) { - self.output += match event { - WalkEvent::Enter(_) => "", - WalkEvent::Leave(_) => "", - }; - } - - #[tracing::instrument(skip(self, _ctx))] - fn verbatim(&mut self, event: WalkEvent<&Verbatim>, _ctx: &mut TraversalContext) { - self.output += match event { - WalkEvent::Enter(_) => "", - WalkEvent::Leave(_) => "", - }; - } - - #[tracing::instrument(skip(self, _ctx))] - fn code(&mut self, event: WalkEvent<&Code>, _ctx: &mut TraversalContext) { - self.output += match event { - WalkEvent::Enter(_) => "", - WalkEvent::Leave(_) => "", - }; - } - - #[tracing::instrument(skip(self, ctx))] - fn rule(&mut self, event: WalkEvent<&Rule>, ctx: &mut TraversalContext) { - if let WalkEvent::Enter(_) = event { - self.output += "
    " - }; - ctx.skip() - } - - #[tracing::instrument(skip(self, ctx))] - fn link(&mut self, event: WalkEvent<&Link>, ctx: &mut TraversalContext) { - match event { - WalkEvent::Enter(link) => { + Event::Enter(Container::Link(link)) => { let path = link.path(); if link.is_image() { @@ -243,299 +258,51 @@ impl Traverser for HtmlExport { if !link.has_description() { let _ = write!(&mut self.output, "{}", HtmlEscape(&path)); - return ctx.skip(); + ctx.skip(); } } - WalkEvent::Leave(_) => { - self.output += ""; + Event::Leave(Container::Link(_)) => self.output += "", + + Event::Text(text) => { + let _ = write!(&mut self.output, "{}", HtmlEscape(text.text())); } - } - } - #[tracing::instrument(skip(self, _ctx))] - fn quote_block(&mut self, event: WalkEvent<&QuoteBlock>, _ctx: &mut TraversalContext) { - self.output += match event { - WalkEvent::Enter(_) => "
    ", - WalkEvent::Leave(_) => "
    ", - }; - } + Event::LineBreak(_) => self.output += "
    ", - #[tracing::instrument(skip(self, _ctx))] - fn verse_block(&mut self, event: WalkEvent<&VerseBlock>, _ctx: &mut TraversalContext) { - self.output += match event { - WalkEvent::Enter(_) => "

    ", - WalkEvent::Leave(_) => "

    ", - }; - } - - #[tracing::instrument(skip(self, _ctx))] - fn example_block(&mut self, event: WalkEvent<&ExampleBlock>, _ctx: &mut TraversalContext) { - self.output += match event { - WalkEvent::Enter(_) => "
    ",
    -            WalkEvent::Leave(_) => "
    ", - }; - } - - #[tracing::instrument(skip(self, _ctx))] - fn center_block(&mut self, event: WalkEvent<&CenterBlock>, _ctx: &mut TraversalContext) { - self.output += match event { - WalkEvent::Enter(_) => "
    ", - WalkEvent::Leave(_) => "
    ", - }; - } - - #[tracing::instrument(skip(self, _ctx))] - fn org_table(&mut self, event: WalkEvent<&OrgTable>, _ctx: &mut TraversalContext) { - match event { - WalkEvent::Enter(table) => { - self.output += ""; - self.table_row = if table.has_header() { - TableRow::HeaderRule - } else { - TableRow::BodyRule + Event::Snippet(snippet) => { + if snippet.backend().eq_ignore_ascii_case("html") { + self.output += &snippet.value(); } } - WalkEvent::Leave(_) => { - match self.table_row { - TableRow::Body => self.output += "", - TableRow::Header => self.output += "", - _ => {} - } - self.output += "
    "; - } - } - } - #[tracing::instrument(skip(self, ctx))] - fn org_table_row(&mut self, event: WalkEvent<&OrgTableRow>, ctx: &mut TraversalContext) { - if match event { - WalkEvent::Enter(n) | WalkEvent::Leave(n) => n.is_rule(), - } { - match self.table_row { - TableRow::Body => { - self.output += ""; - self.table_row = TableRow::BodyRule; - } - TableRow::Header => { - self.output += ""; - self.table_row = TableRow::BodyRule; - } - _ => {} - } - return ctx.skip(); - } + Event::Rule(_) => self.output += "
    ", - match event { - WalkEvent::Enter(_) => { - match self.table_row { - TableRow::HeaderRule => { - self.table_row = TableRow::Header; - self.output += ""; + Event::Timestamp(timestamp) => { + self.output += r#""#; + for e in timestamp.syntax.children_with_tokens() { + match e { + NodeOrToken::Token(t) if t.kind() == SyntaxKind::MINUS2 => { + self.output += "–"; + } + NodeOrToken::Token(t) => { + self.output += t.text(); + } + _ => {} } - TableRow::BodyRule => { - self.table_row = TableRow::Body; - self.output += ""; - } - _ => {} } - self.output += ""; + self.output += r#""#; } - WalkEvent::Leave(_) => { - self.output += ""; + + Event::LatexFragment(latex) => { + let _ = write!(&mut self.output, "{}", &latex.syntax); } - } - } - - #[tracing::instrument(skip(self, _ctx))] - fn org_table_cell(&mut self, event: WalkEvent<&OrgTableCell>, _ctx: &mut TraversalContext) { - self.output += match event { - WalkEvent::Enter(_) => "", - WalkEvent::Leave(_) => "", - }; - } - - #[tracing::instrument(skip(self, _ctx))] - fn comment(&mut self, event: WalkEvent<&Comment>, _ctx: &mut TraversalContext) { - self.output += match event { - WalkEvent::Enter(_) => "", - }; - } - - #[tracing::instrument(skip(self, _ctx))] - fn comment_block(&mut self, event: WalkEvent<&CommentBlock>, _ctx: &mut TraversalContext) { - self.output += match event { - WalkEvent::Enter(_) => "", - }; - } - - #[tracing::instrument(skip(self, ctx))] - fn headline(&mut self, event: WalkEvent<&Headline>, ctx: &mut TraversalContext) { - if let WalkEvent::Enter(headline) = event { - let level = min(headline.level(), 6); - let _ = write!(&mut self.output, ""); - for elem in headline.title() { - self.element(elem, ctx); + Event::LatexEnvironment(latex) => { + let _ = write!(&mut self.output, "{}", &latex.syntax); } - let _ = write!(&mut self.output, ""); + + Event::Entity(entity) => self.output += entity.html(), + + _ => {} } } - - #[tracing::instrument(skip(self, ctx))] - fn inline_src(&mut self, _event: WalkEvent<&InlineSrc>, ctx: &mut TraversalContext) { - ctx.skip(); - } - - #[tracing::instrument(skip(self, ctx))] - fn inline_call(&mut self, _event: WalkEvent<&InlineCall>, ctx: &mut TraversalContext) { - ctx.skip(); - } - - #[tracing::instrument(skip(self, ctx))] - fn special_block(&mut self, _event: WalkEvent<&SpecialBlock>, ctx: &mut TraversalContext) { - ctx.skip(); - } - - #[tracing::instrument(skip(self, ctx))] - fn export_block(&mut self, _event: WalkEvent<&ExportBlock>, ctx: &mut TraversalContext) { - ctx.skip(); - } - - #[tracing::instrument(skip(self, ctx))] - fn source_block(&mut self, _event: WalkEvent<&SourceBlock>, ctx: &mut TraversalContext) { - ctx.skip(); - } - - #[tracing::instrument(skip(self, ctx))] - fn babel_call(&mut self, _event: WalkEvent<&BabelCall>, ctx: &mut TraversalContext) { - ctx.skip(); - } - - #[tracing::instrument(skip(self, ctx))] - fn clock(&mut self, _event: WalkEvent<&Clock>, ctx: &mut TraversalContext) { - ctx.skip(); - } - - #[tracing::instrument(skip(self, ctx))] - fn cookie(&mut self, _event: WalkEvent<&Cookie>, ctx: &mut TraversalContext) { - ctx.skip(); - } - - #[tracing::instrument(skip(self, ctx))] - fn radio_target(&mut self, _event: WalkEvent<&RadioTarget>, ctx: &mut TraversalContext) { - ctx.skip(); - } - - #[tracing::instrument(skip(self, ctx))] - fn drawer(&mut self, _event: WalkEvent<&Drawer>, ctx: &mut TraversalContext) { - ctx.skip(); - } - - #[tracing::instrument(skip(self, ctx))] - fn dyn_block(&mut self, _event: WalkEvent<&DynBlock>, ctx: &mut TraversalContext) { - ctx.skip(); - } - - #[tracing::instrument(skip(self, ctx))] - fn fn_def(&mut self, _event: WalkEvent<&FnDef>, ctx: &mut TraversalContext) { - ctx.skip(); - } - - #[tracing::instrument(skip(self, ctx))] - fn fn_ref(&mut self, _event: WalkEvent<&FnRef>, ctx: &mut TraversalContext) { - ctx.skip(); - } - - #[tracing::instrument(skip(self, ctx))] - fn macros(&mut self, _event: WalkEvent<&Macros>, ctx: &mut TraversalContext) { - ctx.skip(); - } - - #[tracing::instrument(skip(self, ctx))] - fn timestamp(&mut self, event: WalkEvent<&Timestamp>, ctx: &mut TraversalContext) { - if let WalkEvent::Enter(t) = event { - self.output += r#""#; - for e in t.syntax.children_with_tokens() { - match e { - NodeOrToken::Token(t) if t.kind() == SyntaxKind::MINUS2 => { - self.output += "–"; - } - NodeOrToken::Token(t) => { - self.output += t.text(); - } - _ => {} - } - } - self.output += r#""#; - ctx.skip(); - } - } - - #[tracing::instrument(skip(self, ctx))] - fn target(&mut self, _event: WalkEvent<&Target>, ctx: &mut TraversalContext) { - ctx.skip(); - } - - #[tracing::instrument(skip(self, ctx))] - fn latex_fragment(&mut self, event: WalkEvent<&LatexFragment>, ctx: &mut TraversalContext) { - if let WalkEvent::Enter(l) = event { - self.output += &l.syntax.to_string(); - ctx.skip(); - } - } - - #[tracing::instrument(skip(self, ctx))] - fn latex_environment( - &mut self, - event: WalkEvent<&LatexEnvironment>, - ctx: &mut TraversalContext, - ) { - if let WalkEvent::Enter(l) = event { - self.output += &l.syntax.to_string(); - ctx.skip(); - } - } - - #[tracing::instrument(skip(self, ctx))] - fn entity(&mut self, event: WalkEvent<&Entity>, ctx: &mut TraversalContext) { - if let WalkEvent::Enter(e) = event { - self.output += e.html(); - ctx.skip(); - } - } - - #[tracing::instrument(skip(self, ctx))] - fn line_break(&mut self, event: WalkEvent<&LineBreak>, ctx: &mut TraversalContext) { - if let WalkEvent::Enter(_) = event { - self.output += "
    "; - ctx.skip(); - } - } - - #[tracing::instrument(skip(self, _ctx))] - fn subscript(&mut self, event: WalkEvent<&Subscript>, _ctx: &mut TraversalContext) { - match event { - WalkEvent::Enter(_) => self.output += "", - WalkEvent::Leave(_) => self.output += "", - } - } - - #[tracing::instrument(skip(self, _ctx))] - fn superscript(&mut self, event: WalkEvent<&Superscript>, _ctx: &mut TraversalContext) { - match event { - WalkEvent::Enter(_) => self.output += "", - WalkEvent::Leave(_) => self.output += "", - } - } - - #[tracing::instrument(skip(self, ctx))] - fn keyword(&mut self, _event: WalkEvent<&Keyword>, ctx: &mut TraversalContext) { - ctx.skip(); - } - - #[tracing::instrument(skip(self, ctx))] - fn property_drawer(&mut self, _event: WalkEvent<&PropertyDrawer>, ctx: &mut TraversalContext) { - ctx.skip() - } } diff --git a/src/export/mod.rs b/src/export/mod.rs index 3d3f0bd..b5e4401 100644 --- a/src/export/mod.rs +++ b/src/export/mod.rs @@ -1,8 +1,9 @@ //! Export `Org` struct to various formats. -mod forward; +mod event; mod html; mod traverse; +pub use event::{Container, Event}; pub use html::{HtmlEscape, HtmlExport}; pub use traverse::{TraversalContext, Traverser}; diff --git a/src/export/traverse.rs b/src/export/traverse.rs index 4c1464a..42e2c24 100644 --- a/src/export/traverse.rs +++ b/src/export/traverse.rs @@ -1,8 +1,10 @@ use crate::ast::*; -use crate::syntax::{SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken}; -use rowan::{ast::AstNode, WalkEvent}; +use crate::syntax::{SyntaxElement, SyntaxKind}; +use rowan::ast::AstNode; use SyntaxKind::*; +use super::event::{Container, Event}; + #[derive(Default, Debug, PartialEq, Eq, Clone, Copy)] enum TraversalControl { Up, @@ -12,26 +14,6 @@ enum TraversalControl { Continue, } -macro_rules! take_control { - ($ctrl:expr) => { - match $ctrl.control { - TraversalControl::Stop => { - $ctrl.control = TraversalControl::Stop; - return; - } - TraversalControl::Up => { - $ctrl.control = TraversalControl::Skip; - return; - } - TraversalControl::Skip => { - $ctrl.control = TraversalControl::Continue; - return; - } - TraversalControl::Continue => {} - } - }; -} - #[derive(Default)] pub struct TraversalContext { control: TraversalControl, @@ -56,216 +38,187 @@ impl TraversalContext { } } -/// Enumerates org syntax tree +/// A trait for enumerating org syntax tree /// -/// Traverser enumerates org syntax tree and calls handle method on each -/// enumerated node and token. +/// ### `TraversalContext` /// -/// Each handle method can returns a `TraversalControl` to control the traversal. +/// `TraversalContext` can be used to control the traversal. +/// +/// For example, `ctx.skip()` will skips the traversal for current +/// element and its descendants and improve the traversal performance. +/// +/// ```rust +/// use orgize::{ +/// export::{Container, Event, HtmlExport, TraversalContext, Traverser}, +/// Org, +/// }; +/// use slugify::slugify; +/// +/// #[derive(Default)] +/// struct Toc(HtmlExport); +/// +/// impl Traverser for Toc { +/// fn event(&mut self, event: Event, ctx: &mut TraversalContext) { +/// match event { +/// Event::Enter(Container::Headline(headline)) => { +/// 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(""); +/// if headline.headlines().count() > 0 { +/// self.0.push_str("
      "); +/// } +/// } +/// Event::Leave(Container::Headline(headline)) => { +/// if headline.headlines().count() > 0 { +/// self.0.push_str("
    "); +/// } +/// } +/// Event::Enter(Container::Section(_)) | Event::Leave(Container::Section(_)) => ctx.skip(), +/// Event::Enter(Container::Document(_)) | Event::Leave(Container::Document(_)) => {} +/// _ => self.0.event(event, ctx), +/// } +/// } +/// } +/// +/// let org = Org::parse(r#" +/// * heading 1 +/// section 1 +/// ** heading 1.1 +/// ** heading 1.2 +/// * heading 2 +/// section 2 +/// * heading 3 +/// **** heading 3.1"#); +/// let mut toc = Toc::default(); +/// org.traverse(&mut toc); +/// assert_eq!(toc.0.finish(), "\ +/// heading 1\ +/// \ +/// heading 2\ +/// heading 3\ +/// "); +/// ``` pub trait Traverser { + /// Handles traversal event + fn event(&mut self, event: Event, ctx: &mut TraversalContext); + fn element(&mut self, element: SyntaxElement, ctx: &mut TraversalContext) { + macro_rules! take_control { + () => { + match ctx.control { + TraversalControl::Stop => { + ctx.control = TraversalControl::Stop; + return; + } + TraversalControl::Up => { + ctx.control = TraversalControl::Skip; + return; + } + TraversalControl::Skip => { + ctx.control = TraversalControl::Continue; + return; + } + TraversalControl::Continue => {} + } + }; + } + match element { - SyntaxElement::Node(node) => self.node(node, ctx), - SyntaxElement::Token(token) => self.token(token, ctx), + SyntaxElement::Node(node) => { + macro_rules! walk { + ($ast:ident) => {{ + debug_assert!($ast::can_cast(node.kind())); + let node = $ast { syntax: node }; + self.event(Event::Enter(Container::$ast(node.clone())), ctx); + take_control!(); + for child in node.syntax.children_with_tokens() { + self.element(child, ctx); + take_control!(); + } + self.event(Event::Leave(Container::$ast(node.clone())), ctx); + take_control!(); + }}; + (@$ast:ident) => {{ + debug_assert!($ast::can_cast(node.kind())); + let node = $ast { syntax: node }; + self.event(Event::$ast(node), ctx); + take_control!(); + }}; + } + + match node.kind() { + DOCUMENT => walk!(Document), + HEADLINE => walk!(Headline), + SECTION => walk!(Section), + PARAGRAPH => walk!(Paragraph), + BOLD => walk!(Bold), + ITALIC => walk!(Italic), + STRIKE => walk!(Strike), + UNDERLINE => walk!(Underline), + LIST => walk!(List), + LIST_ITEM => walk!(ListItem), + CODE => walk!(Code), + INLINE_CALL => walk!(@InlineCall), + INLINE_SRC => walk!(@InlineSrc), + RULE => walk!(@Rule), + VERBATIM => walk!(Verbatim), + SPECIAL_BLOCK => walk!(SpecialBlock), + QUOTE_BLOCK => walk!(QuoteBlock), + CENTER_BLOCK => walk!(CenterBlock), + VERSE_BLOCK => walk!(VerseBlock), + COMMENT_BLOCK => walk!(CommentBlock), + EXAMPLE_BLOCK => walk!(ExampleBlock), + EXPORT_BLOCK => walk!(ExportBlock), + SOURCE_BLOCK => walk!(SourceBlock), + BABEL_CALL => walk!(BabelCall), + CLOCK => walk!(@Clock), + COOKIE => walk!(@Cookie), + RADIO_TARGET => walk!(RadioTarget), + DRAWER => walk!(Drawer), + DYN_BLOCK => walk!(DynBlock), + FN_DEF => walk!(FnDef), + FN_REF => walk!(FnRef), + MACROS => walk!(@Macros), + SNIPPET => walk!(@Snippet), + TIMESTAMP_ACTIVE | TIMESTAMP_INACTIVE | TIMESTAMP_DIARY => walk!(@Timestamp), + TARGET => walk!(Target), + COMMENT => walk!(Comment), + FIXED_WIDTH => walk!(FixedWidth), + ORG_TABLE => walk!(OrgTable), + ORG_TABLE_RULE_ROW | ORG_TABLE_STANDARD_ROW => walk!(OrgTableRow), + ORG_TABLE_CELL => walk!(OrgTableCell), + LINK => walk!(Link), + LATEX_FRAGMENT => walk!(@LatexFragment), + LATEX_ENVIRONMENT => walk!(@LatexEnvironment), + ENTITY => walk!(@Entity), + LINE_BREAK => walk!(@LineBreak), + SUPERSCRIPT => walk!(Superscript), + SUBSCRIPT => walk!(Subscript), + KEYWORD => walk!(Keyword), + PROPERTY_DRAWER => walk!(PropertyDrawer), + BLOCK_CONTENT | LIST_ITEM_CONTENT => { + for child in node.children_with_tokens() { + self.element(child, ctx); + take_control!(); + } + } + + kind => debug_assert!( + !kind.is_element() && !kind.is_object(), + "{:?} is not handled", + kind + ), + } + } + SyntaxElement::Token(token) => { + if token.kind() == TEXT { + self.event(Event::Text(token), ctx); + take_control!(); + } + } }; } - - /// Called when visiting any node - fn node(&mut self, node: SyntaxNode, ctx: &mut TraversalContext) { - macro_rules! traverse_children { - ($node:expr) => {{ - for child in $node.children_with_tokens() { - self.element(child, ctx); - take_control!(ctx); - } - }}; - } - - macro_rules! traverse { - ($node:ident, $method:ident) => {{ - debug_assert!($node::can_cast(node.kind())); - let node = $node { syntax: node }; - self.$method(WalkEvent::Enter(&node), ctx); - take_control!(ctx); - traverse_children!(&node.syntax); - self.$method(WalkEvent::Leave(&node), ctx); - take_control!(ctx); - }}; - } - - match node.kind() { - DOCUMENT => traverse!(Document, document), - HEADLINE => traverse!(Headline, headline), - SECTION => traverse!(Section, section), - PARAGRAPH => traverse!(Paragraph, paragraph), - BOLD => traverse!(Bold, bold), - ITALIC => traverse!(Italic, italic), - STRIKE => traverse!(Strike, strike), - UNDERLINE => traverse!(Underline, underline), - LIST => traverse!(List, list), - LIST_ITEM => traverse!(ListItem, list_item), - CODE => traverse!(Code, code), - INLINE_CALL => traverse!(InlineCall, inline_call), - INLINE_SRC => traverse!(InlineSrc, inline_src), - RULE => traverse!(Rule, rule), - VERBATIM => traverse!(Verbatim, verbatim), - SPECIAL_BLOCK => traverse!(SpecialBlock, special_block), - QUOTE_BLOCK => traverse!(QuoteBlock, quote_block), - CENTER_BLOCK => traverse!(CenterBlock, center_block), - VERSE_BLOCK => traverse!(VerseBlock, verse_block), - COMMENT_BLOCK => traverse!(CommentBlock, comment_block), - EXAMPLE_BLOCK => traverse!(ExampleBlock, example_block), - EXPORT_BLOCK => traverse!(ExportBlock, export_block), - SOURCE_BLOCK => traverse!(SourceBlock, source_block), - BABEL_CALL => traverse!(BabelCall, babel_call), - CLOCK => traverse!(Clock, clock), - COOKIE => traverse!(Cookie, cookie), - RADIO_TARGET => traverse!(RadioTarget, radio_target), - DRAWER => traverse!(Drawer, drawer), - DYN_BLOCK => traverse!(DynBlock, dyn_block), - FN_DEF => traverse!(FnDef, fn_def), - FN_REF => traverse!(FnRef, fn_ref), - MACROS => traverse!(Macros, macros), - SNIPPET => traverse!(Snippet, snippet), - TIMESTAMP_ACTIVE | TIMESTAMP_INACTIVE | TIMESTAMP_DIARY => { - traverse!(Timestamp, timestamp) - } - TARGET => traverse!(Target, target), - COMMENT => traverse!(Comment, comment), - FIXED_WIDTH => traverse!(FixedWidth, fixed_width), - ORG_TABLE => traverse!(OrgTable, org_table), - ORG_TABLE_RULE_ROW | ORG_TABLE_STANDARD_ROW => traverse!(OrgTableRow, org_table_row), - ORG_TABLE_CELL => traverse!(OrgTableCell, org_table_cell), - LINK => traverse!(Link, link), - LATEX_FRAGMENT => traverse!(LatexFragment, latex_fragment), - LATEX_ENVIRONMENT => traverse!(LatexEnvironment, latex_environment), - ENTITY => traverse!(Entity, entity), - LINE_BREAK => traverse!(LineBreak, line_break), - SUPERSCRIPT => traverse!(Superscript, superscript), - SUBSCRIPT => traverse!(Subscript, subscript), - KEYWORD => traverse!(Keyword, keyword), - PROPERTY_DRAWER => traverse!(PropertyDrawer, property_drawer), - - BLOCK_CONTENT | LIST_ITEM_CONTENT => traverse_children!(node), - - kind => debug_assert!( - !kind.is_element() && !kind.is_object(), - "{:?} is not handled", - kind - ), - } - } - - /// Called when visiting any token - fn token(&mut self, token: SyntaxToken, ctx: &mut TraversalContext) { - if token.kind() == TEXT { - self.text(token, ctx); - } - take_control!(ctx); - } - - /// Called when visiting `Text` token - fn text(&mut self, token: SyntaxToken, ctx: &mut TraversalContext); - /// Called when entering or leaving `Document` node - fn document(&mut self, event: WalkEvent<&Document>, ctx: &mut TraversalContext); - /// Called when entering or leaving `Headline` node - fn headline(&mut self, event: WalkEvent<&Headline>, ctx: &mut TraversalContext); - /// Called when entering or leaving `Paragraph` node - fn paragraph(&mut self, event: WalkEvent<&Paragraph>, ctx: &mut TraversalContext); - /// Called when entering or leaving `Section` node - fn section(&mut self, event: WalkEvent<&Section>, ctx: &mut TraversalContext); - /// Called when entering or leaving `Rule` node - fn rule(&mut self, event: WalkEvent<&Rule>, ctx: &mut TraversalContext); - /// Called when entering or leaving `Comment` node - fn comment(&mut self, event: WalkEvent<&Comment>, ctx: &mut TraversalContext); - /// Called when entering or leaving `InlineSrc` node - fn inline_src(&mut self, event: WalkEvent<&InlineSrc>, ctx: &mut TraversalContext); - /// Called when entering or leaving `InlineCall` node - fn inline_call(&mut self, event: WalkEvent<&InlineCall>, ctx: &mut TraversalContext); - /// Called when entering or leaving `Code` node - fn code(&mut self, event: WalkEvent<&Code>, ctx: &mut TraversalContext); - /// Called when entering or leaving `Bold` node - fn bold(&mut self, event: WalkEvent<&Bold>, ctx: &mut TraversalContext); - /// Called when entering or leaving `Verbatim` node - fn verbatim(&mut self, event: WalkEvent<&Verbatim>, ctx: &mut TraversalContext); - /// Called when entering or leaving `Italic` node - fn italic(&mut self, event: WalkEvent<&Italic>, ctx: &mut TraversalContext); - /// Called when entering or leaving `Strike` node - fn strike(&mut self, event: WalkEvent<&Strike>, ctx: &mut TraversalContext); - /// Called when entering or leaving `Underline` node - fn underline(&mut self, event: WalkEvent<&Underline>, ctx: &mut TraversalContext); - /// Called when entering or leaving `List` node - fn list(&mut self, event: WalkEvent<&List>, ctx: &mut TraversalContext); - /// Called when entering or leaving `ListItem` node - fn list_item(&mut self, event: WalkEvent<&ListItem>, ctx: &mut TraversalContext); - /// Called when entering or leaving `SpecialBlock` node - fn special_block(&mut self, event: WalkEvent<&SpecialBlock>, ctx: &mut TraversalContext); - /// Called when entering or leaving `QuoteBlock` node - fn quote_block(&mut self, event: WalkEvent<&QuoteBlock>, ctx: &mut TraversalContext); - /// Called when entering or leaving `CenterBlock` node - fn center_block(&mut self, event: WalkEvent<&CenterBlock>, ctx: &mut TraversalContext); - /// Called when entering or leaving `VerseBlock` node - fn verse_block(&mut self, event: WalkEvent<&VerseBlock>, ctx: &mut TraversalContext); - /// Called when entering or leaving `CommentBlock` node - fn comment_block(&mut self, event: WalkEvent<&CommentBlock>, ctx: &mut TraversalContext); - /// Called when entering or leaving `ExampleBlock` node - fn example_block(&mut self, event: WalkEvent<&ExampleBlock>, ctx: &mut TraversalContext); - /// Called when entering or leaving `ExportBlock` node - fn export_block(&mut self, event: WalkEvent<&ExportBlock>, ctx: &mut TraversalContext); - /// Called when entering or leaving `SourceBlock` node - fn source_block(&mut self, event: WalkEvent<&SourceBlock>, ctx: &mut TraversalContext); - /// Called when entering or leaving `BabelCall` node - fn babel_call(&mut self, event: WalkEvent<&BabelCall>, ctx: &mut TraversalContext); - /// Called when entering or leaving `Clock` node - fn clock(&mut self, event: WalkEvent<&Clock>, ctx: &mut TraversalContext); - /// Called when entering or leaving `Cookie` node - fn cookie(&mut self, event: WalkEvent<&Cookie>, ctx: &mut TraversalContext); - /// Called when entering or leaving `RadioTarget` node - fn radio_target(&mut self, event: WalkEvent<&RadioTarget>, ctx: &mut TraversalContext); - /// Called when entering or leaving `Drawer` node - fn drawer(&mut self, event: WalkEvent<&Drawer>, ctx: &mut TraversalContext); - /// Called when entering or leaving `DynBlock` node - fn dyn_block(&mut self, event: WalkEvent<&DynBlock>, ctx: &mut TraversalContext); - /// Called when entering or leaving `FnDef` node - fn fn_def(&mut self, event: WalkEvent<&FnDef>, ctx: &mut TraversalContext); - /// Called when entering or leaving `FnRef` node - fn fn_ref(&mut self, event: WalkEvent<&FnRef>, ctx: &mut TraversalContext); - /// Called when entering or leaving `Macros` node - fn macros(&mut self, event: WalkEvent<&Macros>, ctx: &mut TraversalContext); - /// Called when entering or leaving `Snippet` node - fn snippet(&mut self, event: WalkEvent<&Snippet>, ctx: &mut TraversalContext); - /// Called when entering or leaving `Timestamp` node - fn timestamp(&mut self, event: WalkEvent<&Timestamp>, ctx: &mut TraversalContext); - /// Called when entering or leaving `Target` node - fn target(&mut self, event: WalkEvent<&Target>, ctx: &mut TraversalContext); - /// Called when entering or leaving `FixedWidth` node - fn fixed_width(&mut self, event: WalkEvent<&FixedWidth>, ctx: &mut TraversalContext); - /// Called when entering or leaving `OrgTable` node - fn org_table(&mut self, event: WalkEvent<&OrgTable>, ctx: &mut TraversalContext); - /// Called when entering or leaving `OrgTableRow` node - fn org_table_row(&mut self, event: WalkEvent<&OrgTableRow>, ctx: &mut TraversalContext); - /// Called when entering or leaving `OrgTableCell` node - fn org_table_cell(&mut self, event: WalkEvent<&OrgTableCell>, ctx: &mut TraversalContext); - /// Called when entering or leaving `Link` node - fn link(&mut self, event: WalkEvent<&Link>, ctx: &mut TraversalContext); - /// Called when entering or leaving `LatexFragment` node - fn latex_fragment(&mut self, event: WalkEvent<&LatexFragment>, ctx: &mut TraversalContext); - /// Called when entering or leaving `LatexEnvironment` node - fn latex_environment( - &mut self, - event: WalkEvent<&LatexEnvironment>, - ctx: &mut TraversalContext, - ); - /// Called when entering or leaving `Entity` node - fn entity(&mut self, event: WalkEvent<&Entity>, ctx: &mut TraversalContext); - /// Called when entering or leaving `LineBreak` node - fn line_break(&mut self, event: WalkEvent<&LineBreak>, ctx: &mut TraversalContext); - /// Called when entering or leaving `Superscript` node - fn superscript(&mut self, event: WalkEvent<&Superscript>, ctx: &mut TraversalContext); - /// Called when entering or leaving `Subscript` node - fn subscript(&mut self, event: WalkEvent<&Subscript>, ctx: &mut TraversalContext); - /// Called when entering or leaving `Keyword` node - fn keyword(&mut self, event: WalkEvent<&Keyword>, ctx: &mut TraversalContext); - /// Called when entering or leaving `PropertyDrawer` node - fn property_drawer(&mut self, event: WalkEvent<&PropertyDrawer>, ctx: &mut TraversalContext); } diff --git a/src/org.rs b/src/org.rs index dfd088e..1a3a144 100644 --- a/src/org.rs +++ b/src/org.rs @@ -5,6 +5,7 @@ use crate::ast::Document; use crate::config::ParseConfig; use crate::export::{HtmlExport, TraversalContext, Traverser}; use crate::syntax::{OrgLanguage, SyntaxNode}; +use crate::SyntaxElement; #[derive(Debug)] pub struct Org { @@ -46,9 +47,12 @@ impl Org { } /// Walk through org element tree using given traverser - pub fn traverse(&self, h: &mut T) { + pub fn traverse(&self, t: &mut T) { let mut ctx = TraversalContext::default(); - h.node(SyntaxNode::new_root(self.green.clone()), &mut ctx); + t.element( + SyntaxElement::Node(SyntaxNode::new_root(self.green.clone())), + &mut ctx, + ); } /// Returns the first node in org element tree in depth first order