refactor: remove HeadlineTitle, ListItemTag, ListItemContent

This commit is contained in:
PoiScript 2023-11-18 22:37:47 +08:00
parent d81c1a2966
commit 12bee6fb6b
No known key found for this signature in database
GPG key ID: 22C2B1249D99985E
8 changed files with 240 additions and 346 deletions

View file

@ -25,7 +25,6 @@ const nodes = [
struct: "Headline",
kind: ["HEADLINE"],
first_child: [
["title", "HeadlineTitle"],
["section", "Section"],
["planning", "Planning"],
],
@ -74,7 +73,6 @@ const nodes = [
{
struct: "ListItem",
kind: ["LIST_ITEM"],
first_child: [["content", "ListItemContent"]],
},
{
struct: "Drawer",

View file

@ -157,9 +157,6 @@ impl Headline {
pub fn keyword(&self) -> Option<SyntaxToken> {
support::token(&self.syntax, HEADLINE_KEYWORD)
}
pub fn title(&self) -> Option<HeadlineTitle> {
support::child(&self.syntax)
}
pub fn section(&self) -> Option<Section> {
support::child(&self.syntax)
}
@ -449,115 +446,6 @@ impl ListItem {
pub fn end(&self) -> u32 {
self.syntax.text_range().end().into()
}
pub fn indent(&self) -> Option<SyntaxToken> {
support::token(&self.syntax, LIST_ITEM_INDENT)
}
pub fn bullet(&self) -> Option<SyntaxToken> {
support::token(&self.syntax, LIST_ITEM_BULLET)
}
pub fn content(&self) -> Option<ListItemContent> {
support::child(&self.syntax)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ListItemIndent {
pub(crate) syntax: SyntaxNode,
}
impl AstNode for ListItemIndent {
type Language = OrgLanguage;
fn can_cast(kind: SyntaxKind) -> bool {
kind == LIST_ITEM_INDENT
}
fn cast(node: SyntaxNode) -> Option<ListItemIndent> {
Self::can_cast(node.kind()).then(|| ListItemIndent { syntax: node })
}
fn syntax(&self) -> &SyntaxNode {
&self.syntax
}
}
impl ListItemIndent {
pub fn begin(&self) -> u32 {
self.syntax.text_range().start().into()
}
pub fn end(&self) -> u32 {
self.syntax.text_range().end().into()
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ListItemTag {
pub(crate) syntax: SyntaxNode,
}
impl AstNode for ListItemTag {
type Language = OrgLanguage;
fn can_cast(kind: SyntaxKind) -> bool {
kind == LIST_ITEM_TAG
}
fn cast(node: SyntaxNode) -> Option<ListItemTag> {
Self::can_cast(node.kind()).then(|| ListItemTag { syntax: node })
}
fn syntax(&self) -> &SyntaxNode {
&self.syntax
}
}
impl ListItemTag {
pub fn begin(&self) -> u32 {
self.syntax.text_range().start().into()
}
pub fn end(&self) -> u32 {
self.syntax.text_range().end().into()
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ListItemBullet {
pub(crate) syntax: SyntaxNode,
}
impl AstNode for ListItemBullet {
type Language = OrgLanguage;
fn can_cast(kind: SyntaxKind) -> bool {
kind == LIST_ITEM_BULLET
}
fn cast(node: SyntaxNode) -> Option<ListItemBullet> {
Self::can_cast(node.kind()).then(|| ListItemBullet { syntax: node })
}
fn syntax(&self) -> &SyntaxNode {
&self.syntax
}
}
impl ListItemBullet {
pub fn begin(&self) -> u32 {
self.syntax.text_range().start().into()
}
pub fn end(&self) -> u32 {
self.syntax.text_range().end().into()
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ListItemContent {
pub(crate) syntax: SyntaxNode,
}
impl AstNode for ListItemContent {
type Language = OrgLanguage;
fn can_cast(kind: SyntaxKind) -> bool {
kind == LIST_ITEM_CONTENT
}
fn cast(node: SyntaxNode) -> Option<ListItemContent> {
Self::can_cast(node.kind()).then(|| ListItemContent { syntax: node })
}
fn syntax(&self) -> &SyntaxNode {
&self.syntax
}
}
impl ListItemContent {
pub fn begin(&self) -> u32 {
self.syntax.text_range().start().into()
}
pub fn end(&self) -> u32 {
self.syntax.text_range().end().into()
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@ -1452,31 +1340,6 @@ impl FnRef {
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct LatexEnvironment {
pub(crate) syntax: SyntaxNode,
}
impl AstNode for LatexEnvironment {
type Language = OrgLanguage;
fn can_cast(kind: SyntaxKind) -> bool {
kind == LATEX_ENVIRONMENT
}
fn cast(node: SyntaxNode) -> Option<LatexEnvironment> {
Self::can_cast(node.kind()).then(|| LatexEnvironment { syntax: node })
}
fn syntax(&self) -> &SyntaxNode {
&self.syntax
}
}
impl LatexEnvironment {
pub fn begin(&self) -> u32 {
self.syntax.text_range().start().into()
}
pub fn end(&self) -> u32 {
self.syntax.text_range().end().into()
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Macros {
pub(crate) syntax: SyntaxNode,

View file

@ -1,4 +1,7 @@
use crate::syntax::{SyntaxKind, SyntaxToken};
use crate::{
syntax::{SyntaxKind, SyntaxToken},
SyntaxElement,
};
use super::{filter_token, Headline, Timestamp};
@ -24,6 +27,21 @@ impl Headline {
})
}
/// ```rust
/// use orgize::{Org, ast::Headline};
///
/// let hdl = Org::parse("*** abc *abc* /abc/ :tag:").first_node::<Headline>().unwrap();
/// let title = hdl.title().map(|n| n.to_string()).collect::<String>();
/// assert_eq!(title, "abc *abc* /abc/ ");
/// ```
pub fn title(&self) -> impl Iterator<Item = SyntaxElement> {
self.syntax
.children()
.find(|n| n.kind() == SyntaxKind::HEADLINE_TITLE)
.into_iter()
.flat_map(|n| n.children_with_tokens())
}
/// Return `true` if this headline contains a COMMENT keyword
///
/// ```rust
@ -38,12 +56,16 @@ impl Headline {
/// ```
pub fn is_commented(&self) -> bool {
self.title()
.and_then(|title| title.syntax.first_token())
.map(|title| {
let text = title.text();
title.kind() == SyntaxKind::TEXT
&& text.starts_with("COMMENT")
&& (text.len() == 7 || text[7..].starts_with(char::is_whitespace))
.next()
.map(|first| {
if let Some(t) = first.as_token() {
let text = t.text();
t.kind() == SyntaxKind::TEXT
&& text.starts_with("COMMENT")
&& (text.len() == 7 || text[7..].starts_with(char::is_whitespace))
} else {
false
}
})
.unwrap_or_default()
}

View file

@ -1,55 +1,7 @@
use super::{filter_token, List};
use super::{filter_token, List, ListItem};
use crate::{syntax::SyntaxKind, SyntaxElement, SyntaxToken};
impl List {
pub fn indent(&self) -> usize {
self.syntax
.children_with_tokens()
.find_map(filter_token(SyntaxKind::LIST_ITEM_INDENT))
.map(|t| t.text().len())
.unwrap_or_else(|| {
debug_assert!(false, "list must contains indent token");
0
})
}
pub fn bullet(&self) -> Option<SyntaxToken> {
self.syntax
.children_with_tokens()
.find_map(filter_token(SyntaxKind::LIST_ITEM_BULLET))
}
pub fn checkbox(&self) -> Option<SyntaxToken> {
self.syntax
.children()
.find(|n| n.kind() == SyntaxKind::LIST_ITEM_CHECK_BOX)
.and_then(|n| {
n.children_with_tokens()
.find_map(filter_token(SyntaxKind::TEXT))
})
}
pub fn counter(&self) -> Option<SyntaxToken> {
self.syntax
.children()
.find(|n| n.kind() == SyntaxKind::LIST_ITEM_COUNTER)
.and_then(|n| {
n.children_with_tokens()
.find_map(filter_token(SyntaxKind::TEXT))
})
}
pub fn tag(&self) -> impl Iterator<Item = SyntaxElement> {
self.syntax
.children()
.find(|n| n.kind() == SyntaxKind::LIST_ITEM_TAG)
.into_iter()
.flat_map(|n| {
n.children_with_tokens()
.filter(|n| n.kind() != SyntaxKind::COLON2)
})
}
/// Returns `true` if this list is an ordered link
///
/// ```rust
@ -93,3 +45,87 @@ impl List {
.unwrap_or_default()
}
}
impl ListItem {
/// ```rust
/// use orgize::{Org, ast::ListItem};
///
/// let item = Org::parse("- 1").first_node::<ListItem>().unwrap();
/// assert_eq!(item.indent(), 0);
/// let item = Org::parse(" \t * 2").first_node::<ListItem>().unwrap();
/// assert_eq!(item.indent(), 3);
/// ```
pub fn indent(&self) -> usize {
self.syntax
.children_with_tokens()
.find_map(filter_token(SyntaxKind::LIST_ITEM_INDENT))
.map(|t| t.text().len())
.unwrap_or_else(|| {
debug_assert!(false, "list must contains indent token");
0
})
}
/// ```rust
/// use orgize::{Org, ast::ListItem};
///
/// let item = Org::parse("- some tag").first_node::<ListItem>().unwrap();
/// assert_eq!(item.bullet().unwrap().text(), "- ");
/// let item = Org::parse("2. [X] item 2").first_node::<ListItem>().unwrap();
/// assert_eq!(item.bullet().unwrap().text(), "2. ");
/// ```
pub fn bullet(&self) -> Option<SyntaxToken> {
self.syntax
.children_with_tokens()
.find_map(filter_token(SyntaxKind::LIST_ITEM_BULLET))
}
/// ```rust
/// use orgize::{Org, ast::ListItem};
///
/// let item = Org::parse("- [-] item 1").first_node::<ListItem>().unwrap();
/// assert_eq!(item.checkbox().unwrap().text(), "-");
/// let item = Org::parse("2. [X] item 2").first_node::<ListItem>().unwrap();
/// assert_eq!(item.checkbox().unwrap().text(), "X");
/// let item = Org::parse("3) [ ] item 3").first_node::<ListItem>().unwrap();
/// assert_eq!(item.checkbox().unwrap().text(), " ");
/// ```
pub fn checkbox(&self) -> Option<SyntaxToken> {
self.syntax
.children()
.find(|n| n.kind() == SyntaxKind::LIST_ITEM_CHECK_BOX)
.and_then(|n| {
n.children_with_tokens()
.find_map(filter_token(SyntaxKind::TEXT))
})
}
pub fn counter(&self) -> Option<SyntaxToken> {
self.syntax
.children()
.find(|n| n.kind() == SyntaxKind::LIST_ITEM_COUNTER)
.and_then(|n| {
n.children_with_tokens()
.find_map(filter_token(SyntaxKind::TEXT))
})
}
/// ```rust
/// use orgize::{Org, ast::ListItem};
///
/// let item = Org::parse("+ this is *TAG* :: item1").first_node::<ListItem>().unwrap();
/// let tag = item.tag().map(|n| n.to_string()).collect::<String>();
/// assert_eq!(tag, "this is *TAG* ");
/// ```
pub fn tag(&self) -> impl Iterator<Item = SyntaxElement> {
self.syntax
.children()
.find(|n| n.kind() == SyntaxKind::LIST_ITEM_TAG)
.into_iter()
.flat_map(|n| {
n.children_with_tokens().filter(|n| {
n.kind() != SyntaxKind::WHITESPACE && n.kind() != SyntaxKind::COLON2
})
})
}
}

View file

@ -1,14 +1,13 @@
/// Forward handler method implement to other handler
/// Forward traverser method implement to other
///
/// This macros is commonly used if you want to extend
/// some builtin handlers like HtmlExport.
/// Used to "extend" some builtin traverser like `HtmlExport`.
///
/// ```rust
/// use orgize::{
/// ast::HeadlineTitle,
/// ast::Headline,
/// export::{HtmlExport, TraversalContext, Traverser},
/// forward_handler,
/// rowan::{ast::AstNode, WalkEvent},
/// rowan::{ast::AstNode, WalkEvent, NodeOrToken},
/// Org,
/// };
/// use slugify::slugify;
@ -25,27 +24,31 @@
/// }
///
/// impl Traverser for SlugifyTitleHandler {
/// fn headline_title(&mut self, event: WalkEvent<&HeadlineTitle>, _ctx: &mut TraversalContext) {
/// match event {
/// WalkEvent::Enter(title) => {
/// let level = title.headline().map(|h| min(h.level(), 6)).unwrap_or(1);
/// let raw = title.syntax().to_string();
/// self.0.push_str(format!("<h{level}><a id=\"{0}\" href=\"#{0}\">", slugify!(&raw)));
/// }
/// WalkEvent::Leave(title) => {
/// let level = title.headline().map(|h| min(h.level(), 6)).unwrap_or(1);
/// self.0.push_str(format!("</a></h{level}>"));
/// 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::<String>();
/// self.0.push_str(format!(
/// "<h{level}><a id=\"{0}\" href=\"#{0}\">",
/// slugify!(&title)
/// ));
/// for elem in headline.title() {
/// match elem {
/// NodeOrToken::Node(node) => self.node(node, ctx),
/// NodeOrToken::Token(token) => self.token(token, ctx),
/// }
/// }
/// self.0.push_str(format!("</a></h{level}>"));
/// }
/// }
///
/// forward_handler! {
/// HtmlExport,
/// link text document headline paragraph section rule comment
/// inline_src inline_call code bold verbatim italic strike underline list list_item list_item_tag
/// 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 list_item_content
/// snippet timestamp target fixed_width org_table org_table_row org_table_cell
/// }
/// }
///
@ -62,146 +65,137 @@ macro_rules! forward_handler {
};
(@method $handler:ty, text) => {
forward_handler!(@method $handler, text, ::orgize::SyntaxToken);
forward_handler!(@method $handler, text, $crate::SyntaxToken);
};
(@method $handler:ty, document) => {
forward_handler!(@method $handler, document, WalkEvent<&::orgize::ast::Document>);
forward_handler!(@method $handler, document, WalkEvent<&$crate::ast::Document>);
};
(@method $handler:ty, headline) => {
forward_handler!(@method $handler, headline, WalkEvent<&::orgize::ast::Headline>);
forward_handler!(@method $handler, headline, WalkEvent<&$crate::ast::Headline>);
};
(@method $handler:ty, paragraph) => {
forward_handler!(@method $handler, paragraph, WalkEvent<&::orgize::ast::Paragraph>);
forward_handler!(@method $handler, paragraph, WalkEvent<&$crate::ast::Paragraph>);
};
(@method $handler:ty, section) => {
forward_handler!(@method $handler, section, WalkEvent<&::orgize::ast::Section>);
forward_handler!(@method $handler, section, WalkEvent<&$crate::ast::Section>);
};
(@method $handler:ty, rule) => {
forward_handler!(@method $handler, rule, WalkEvent<&::orgize::ast::Rule>);
forward_handler!(@method $handler, rule, WalkEvent<&$crate::ast::Rule>);
};
(@method $handler:ty, comment) => {
forward_handler!(@method $handler, comment, WalkEvent<&::orgize::ast::Comment>);
forward_handler!(@method $handler, comment, WalkEvent<&$crate::ast::Comment>);
};
(@method $handler:ty, inline_src) => {
forward_handler!(@method $handler, inline_src, WalkEvent<&::orgize::ast::InlineSrc>);
forward_handler!(@method $handler, inline_src, WalkEvent<&$crate::ast::InlineSrc>);
};
(@method $handler:ty, inline_call) => {
forward_handler!(@method $handler, inline_call, WalkEvent<&::orgize::ast::InlineCall>);
forward_handler!(@method $handler, inline_call, WalkEvent<&$crate::ast::InlineCall>);
};
(@method $handler:ty, code) => {
forward_handler!(@method $handler, code, WalkEvent<&::orgize::ast::Code>);
forward_handler!(@method $handler, code, WalkEvent<&$crate::ast::Code>);
};
(@method $handler:ty, bold) => {
forward_handler!(@method $handler, bold, WalkEvent<&::orgize::ast::Bold>);
forward_handler!(@method $handler, bold, WalkEvent<&$crate::ast::Bold>);
};
(@method $handler:ty, verbatim) => {
forward_handler!(@method $handler, verbatim, WalkEvent<&::orgize::ast::Verbatim>);
forward_handler!(@method $handler, verbatim, WalkEvent<&$crate::ast::Verbatim>);
};
(@method $handler:ty, italic) => {
forward_handler!(@method $handler, italic, WalkEvent<&::orgize::ast::Italic>);
forward_handler!(@method $handler, italic, WalkEvent<&$crate::ast::Italic>);
};
(@method $handler:ty, strike) => {
forward_handler!(@method $handler, strike, WalkEvent<&::orgize::ast::Strike>);
forward_handler!(@method $handler, strike, WalkEvent<&$crate::ast::Strike>);
};
(@method $handler:ty, underline) => {
forward_handler!(@method $handler, underline, WalkEvent<&::orgize::ast::Underline>);
forward_handler!(@method $handler, underline, WalkEvent<&$crate::ast::Underline>);
};
(@method $handler:ty, list) => {
forward_handler!(@method $handler, list, WalkEvent<&::orgize::ast::List>);
forward_handler!(@method $handler, list, WalkEvent<&$crate::ast::List>);
};
(@method $handler:ty, list_item) => {
forward_handler!(@method $handler, list_item, WalkEvent<&::orgize::ast::ListItem>);
};
(@method $handler:ty, list_item_tag) => {
forward_handler!(@method $handler, list_item_tag, WalkEvent<&::orgize::ast::ListItemTag>);
};
(@method $handler:ty, list_item_content) => {
forward_handler!(@method $handler, list_item_content, WalkEvent<&::orgize::ast::ListItemContent>);
forward_handler!(@method $handler, list_item, WalkEvent<&$crate::ast::ListItem>);
};
(@method $handler:ty, special_block) => {
forward_handler!(@method $handler, special_block, WalkEvent<&::orgize::ast::SpecialBlock>);
forward_handler!(@method $handler, special_block, WalkEvent<&$crate::ast::SpecialBlock>);
};
(@method $handler:ty, quote_block) => {
forward_handler!(@method $handler, quote_block, WalkEvent<&::orgize::ast::QuoteBlock>);
forward_handler!(@method $handler, quote_block, WalkEvent<&$crate::ast::QuoteBlock>);
};
(@method $handler:ty, center_block) => {
forward_handler!(@method $handler, center_block, WalkEvent<&::orgize::ast::CenterBlock>);
forward_handler!(@method $handler, center_block, WalkEvent<&$crate::ast::CenterBlock>);
};
(@method $handler:ty, verse_block) => {
forward_handler!(@method $handler, verse_block, WalkEvent<&::orgize::ast::VerseBlock>);
forward_handler!(@method $handler, verse_block, WalkEvent<&$crate::ast::VerseBlock>);
};
(@method $handler:ty, comment_block) => {
forward_handler!(@method $handler, comment_block, WalkEvent<&::orgize::ast::CommentBlock>);
forward_handler!(@method $handler, comment_block, WalkEvent<&$crate::ast::CommentBlock>);
};
(@method $handler:ty, example_block) => {
forward_handler!(@method $handler, example_block, WalkEvent<&::orgize::ast::ExampleBlock>);
forward_handler!(@method $handler, example_block, WalkEvent<&$crate::ast::ExampleBlock>);
};
(@method $handler:ty, export_block) => {
forward_handler!(@method $handler, export_block, WalkEvent<&::orgize::ast::ExportBlock>);
forward_handler!(@method $handler, export_block, WalkEvent<&$crate::ast::ExportBlock>);
};
(@method $handler:ty, source_block) => {
forward_handler!(@method $handler, source_block, WalkEvent<&::orgize::ast::SourceBlock>);
forward_handler!(@method $handler, source_block, WalkEvent<&$crate::ast::SourceBlock>);
};
(@method $handler:ty, babel_call) => {
forward_handler!(@method $handler, babel_call, WalkEvent<&::orgize::ast::BabelCall>);
forward_handler!(@method $handler, babel_call, WalkEvent<&$crate::ast::BabelCall>);
};
(@method $handler:ty, clock) => {
forward_handler!(@method $handler, clock, WalkEvent<&::orgize::ast::Clock>);
forward_handler!(@method $handler, clock, WalkEvent<&$crate::ast::Clock>);
};
(@method $handler:ty, cookie) => {
forward_handler!(@method $handler, cookie, WalkEvent<&::orgize::ast::Cookie>);
forward_handler!(@method $handler, cookie, WalkEvent<&$crate::ast::Cookie>);
};
(@method $handler:ty, radio_target) => {
forward_handler!(@method $handler, radio_target, WalkEvent<&::orgize::ast::RadioTarget>);
forward_handler!(@method $handler, radio_target, WalkEvent<&$crate::ast::RadioTarget>);
};
(@method $handler:ty, drawer) => {
forward_handler!(@method $handler, drawer, WalkEvent<&::orgize::ast::Drawer>);
forward_handler!(@method $handler, drawer, WalkEvent<&$crate::ast::Drawer>);
};
(@method $handler:ty, dyn_block) => {
forward_handler!(@method $handler, dyn_block, WalkEvent<&::orgize::ast::DynBlock>);
forward_handler!(@method $handler, dyn_block, WalkEvent<&$crate::ast::DynBlock>);
};
(@method $handler:ty, fn_def) => {
forward_handler!(@method $handler, fn_def, WalkEvent<&::orgize::ast::FnDef>);
forward_handler!(@method $handler, fn_def, WalkEvent<&$crate::ast::FnDef>);
};
(@method $handler:ty, fn_ref) => {
forward_handler!(@method $handler, fn_ref, WalkEvent<&::orgize::ast::FnRef>);
forward_handler!(@method $handler, fn_ref, WalkEvent<&$crate::ast::FnRef>);
};
(@method $handler:ty, macros) => {
forward_handler!(@method $handler, macros, WalkEvent<&::orgize::ast::Macros>);
forward_handler!(@method $handler, macros, WalkEvent<&$crate::ast::Macros>);
};
(@method $handler:ty, snippet) => {
forward_handler!(@method $handler, snippet, WalkEvent<&::orgize::ast::Snippet>);
forward_handler!(@method $handler, snippet, WalkEvent<&$crate::ast::Snippet>);
};
(@method $handler:ty, timestamp) => {
forward_handler!(@method $handler, timestamp, WalkEvent<&::orgize::ast::Timestamp>);
forward_handler!(@method $handler, timestamp, WalkEvent<&$crate::ast::Timestamp>);
};
(@method $handler:ty, target) => {
forward_handler!(@method $handler, target, WalkEvent<&::orgize::ast::Target>);
forward_handler!(@method $handler, target, WalkEvent<&$crate::ast::Target>);
};
(@method $handler:ty, fixed_width) => {
forward_handler!(@method $handler, fixed_width, WalkEvent<&::orgize::ast::FixedWidth>);
};
(@method $handler:ty, headline_title) => {
forward_handler!(@method $handler, headline_title, WalkEvent<&::orgize::ast::HeadlineTitle>);
forward_handler!(@method $handler, fixed_width, WalkEvent<&$crate::ast::FixedWidth>);
};
(@method $handler:ty, org_table) => {
forward_handler!(@method $handler, org_table, WalkEvent<&::orgize::ast::OrgTable>);
forward_handler!(@method $handler, org_table, WalkEvent<&$crate::ast::OrgTable>);
};
(@method $handler:ty, org_table_row) => {
forward_handler!(@method $handler, org_table_row, WalkEvent<&::orgize::ast::OrgTableRow>);
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<&::orgize::ast::OrgTableCell>);
forward_handler!(@method $handler, org_table_cell, WalkEvent<&$crate::ast::OrgTableCell>);
};
(@method $handler:ty, link) => {
forward_handler!(@method $handler, link, WalkEvent<&::orgize::ast::Link>);
forward_handler!(@method $handler, link, WalkEvent<&$crate::ast::Link>);
};
(@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 ::orgize::export::TraversalContext) {
fn $name(&mut self, item: $type, ctx: &mut $crate::export::TraversalContext) {
<Self as AsMut<$handler>>::as_mut(self).$name(item, ctx)
}
};

View file

@ -1,4 +1,4 @@
use rowan::WalkEvent;
use rowan::{NodeOrToken, WalkEvent};
use std::cmp::min;
use std::fmt;
@ -116,36 +116,26 @@ impl Traverser for HtmlExport {
};
}
#[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() {
self.output += match event {
WalkEvent::Enter(_) => "<li>",
WalkEvent::Leave(_) => "</li>",
};
}
}
#[tracing::instrument(skip(self, _ctx))]
fn list_item_content(
&mut self,
event: WalkEvent<&ListItemContent>,
_ctx: &mut TraversalContext,
) {
#[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() {
self.output += match event {
WalkEvent::Enter(_) => "<dd>",
WalkEvent::Leave(_) => "</dd>",
match event {
WalkEvent::Enter(item) => {
self.output += "<dt>";
for elem in item.tag() {
match elem {
NodeOrToken::Node(n) => self.node(n, ctx),
NodeOrToken::Token(t) => self.token(t, ctx),
}
}
self.output += "</dt><dd>";
}
WalkEvent::Leave(_) => self.output += "</dd>",
};
}
}
#[tracing::instrument(skip(self, _ctx))]
fn list_item_tag(&mut self, event: WalkEvent<&ListItemTag>, _ctx: &mut TraversalContext) {
if self.in_descriptive_list.last().copied().unwrap_or_default() {
self.output += match event {
WalkEvent::Enter(_) => "<dt>",
WalkEvent::Leave(_) => "</dt>",
} else {
match event {
WalkEvent::Enter(_) => self.output += "<li>",
WalkEvent::Leave(_) => self.output += "</li>",
};
}
}
@ -185,20 +175,6 @@ impl Traverser for HtmlExport {
};
}
#[tracing::instrument(skip(self, _ctx))]
fn headline_title(&mut self, event: WalkEvent<&HeadlineTitle>, _ctx: &mut TraversalContext) {
self.output += &match event {
WalkEvent::Enter(title) => {
let level = title.headline().map(|h| min(h.level(), 6)).unwrap_or(1);
format!("<h{level}>")
}
WalkEvent::Leave(title) => {
let level = title.headline().map(|h| min(h.level(), 6)).unwrap_or(1);
format!("</h{level}>")
}
};
}
#[tracing::instrument(skip(self, _ctx))]
fn italic(&mut self, event: WalkEvent<&Italic>, _ctx: &mut TraversalContext) {
self.output += match event {
@ -403,8 +379,20 @@ impl Traverser for HtmlExport {
};
}
#[tracing::instrument(skip(self, _ctx))]
fn headline(&mut self, _event: WalkEvent<&Headline>, _ctx: &mut TraversalContext) {}
#[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);
self.output += &format!("<h{level}>");
for elem in headline.title() {
match elem {
NodeOrToken::Node(node) => self.node(node, ctx),
NodeOrToken::Token(token) => self.token(token, ctx),
}
}
self.output += &format!("</h{level}>");
}
}
#[tracing::instrument(skip(self, _ctx))]
fn inline_src(&mut self, _event: WalkEvent<&InlineSrc>, _ctx: &mut TraversalContext) {}

View file

@ -63,15 +63,19 @@ impl TraversalContext {
///
/// Each handle method can returns a `TraversalControl` to control the traversal.
pub trait Traverser {
fn element(&mut self, element: SyntaxElement, ctx: &mut TraversalContext) {
match element {
SyntaxElement::Node(node) => self.node(node, ctx),
SyntaxElement::Token(token) => self.token(token, ctx),
};
}
/// 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() {
match child {
SyntaxElement::Node(node) => self.node(node, ctx),
SyntaxElement::Token(token) => self.token(token, ctx),
};
self.element(child, ctx);
take_control!(ctx);
}
}};
@ -100,8 +104,6 @@ pub trait Traverser {
UNDERLINE => traverse!(Underline, underline),
LIST => traverse!(List, list),
LIST_ITEM => traverse!(ListItem, list_item),
LIST_ITEM_CONTENT => traverse!(ListItemContent, list_item_content),
LIST_ITEM_TAG => traverse!(ListItemTag, list_item_tag),
CODE => traverse!(Code, code),
INLINE_CALL => traverse!(InlineCall, inline_call),
INLINE_SRC => traverse!(InlineSrc, inline_src),
@ -131,13 +133,12 @@ pub trait Traverser {
TARGET => traverse!(Target, target),
COMMENT => traverse!(Comment, comment),
FIXED_WIDTH => traverse!(FixedWidth, fixed_width),
HEADLINE_TITLE => traverse!(HeadlineTitle, headline_title),
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),
BLOCK_CONTENT => traverse_children!(node),
BLOCK_CONTENT | LIST_ITEM_CONTENT => traverse_children!(node),
_ => {}
}
@ -185,14 +186,6 @@ pub trait Traverser {
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 `ListItemTag` node
fn list_item_tag(&mut self, _event: WalkEvent<&ListItemTag>, _ctx: &mut TraversalContext);
/// Called when entering or leaving `ListItemContent` node
fn list_item_content(
&mut self,
_event: WalkEvent<&ListItemContent>,
_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
@ -235,8 +228,6 @@ pub trait Traverser {
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 `HeadlineTitle` node
fn headline_title(&mut self, _event: WalkEvent<&HeadlineTitle>, _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