feat: simplify public api
This commit is contained in:
parent
394c013fd2
commit
e924359df6
10 changed files with 586 additions and 356 deletions
|
|
@ -27,8 +27,7 @@ impl Traverser for MyHtmlHandler {
|
|||
fn headline_title(&mut self, event: WalkEvent<&HeadlineTitle>, _ctx: &mut TraversalContext) {
|
||||
match event {
|
||||
WalkEvent::Enter(title) => {
|
||||
let level = title.headline().and_then(|h| h.level()).unwrap_or(1);
|
||||
let level = min(level, 6);
|
||||
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}\">",
|
||||
|
|
@ -36,8 +35,7 @@ impl Traverser for MyHtmlHandler {
|
|||
));
|
||||
}
|
||||
WalkEvent::Leave(title) => {
|
||||
let level = title.headline().and_then(|h| h.level()).unwrap_or(1);
|
||||
let level = min(level, 6);
|
||||
let level = title.headline().map(|h| min(h.level(), 6)).unwrap_or(1);
|
||||
self.0.push_str(format!("</a></h{level}>"));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,43 +27,17 @@ const nodes = [
|
|||
first_child: [
|
||||
["title", "HeadlineTitle"],
|
||||
["section", "Section"],
|
||||
["tags", "HeadlineTags"],
|
||||
["planning", "Planning"],
|
||||
["priority", "HeadlinePriority"],
|
||||
],
|
||||
children: [["headlines", "Headline"]],
|
||||
token: [
|
||||
["stars", "HEADLINE_STARS"],
|
||||
["keyword", "HEADLINE_KEYWORD"],
|
||||
],
|
||||
token: [["keyword", "HEADLINE_KEYWORD"]],
|
||||
post_blank: true,
|
||||
},
|
||||
{
|
||||
struct: "HeadlineStars",
|
||||
kind: ["HEADLINE_STARS"],
|
||||
parent: [["headline", "Headline"]],
|
||||
},
|
||||
{
|
||||
struct: "HeadlineTitle",
|
||||
kind: ["HEADLINE_TITLE"],
|
||||
parent: [["headline", "Headline"]],
|
||||
},
|
||||
{
|
||||
struct: "HeadlineKeyword",
|
||||
kind: ["HEADLINE_KEYWORD"],
|
||||
parent: [["headline", "Headline"]],
|
||||
},
|
||||
{
|
||||
struct: "HeadlinePriority",
|
||||
kind: ["HEADLINE_PRIORITY"],
|
||||
parent: [["headline", "Headline"]],
|
||||
token: [["text", "TEXT"]],
|
||||
},
|
||||
{
|
||||
struct: "HeadlineTags",
|
||||
kind: ["HEADLINE_TAGS"],
|
||||
parent: [["headline", "Headline"]],
|
||||
},
|
||||
{
|
||||
struct: "PropertyDrawer",
|
||||
kind: ["PROPERTY_DRAWER"],
|
||||
|
|
@ -76,23 +50,6 @@ const nodes = [
|
|||
{
|
||||
struct: "Planning",
|
||||
kind: ["PLANNING"],
|
||||
last_child: [
|
||||
["deadline", "PlanningDeadline"],
|
||||
["scheduled", "PlanningScheduled"],
|
||||
["closed", "PlanningClosed"],
|
||||
],
|
||||
},
|
||||
{
|
||||
struct: "PlanningDeadline",
|
||||
kind: ["PLANNING_DEADLINE"],
|
||||
},
|
||||
{
|
||||
struct: "PlanningScheduled",
|
||||
kind: ["PLANNING_SCHEDULED"],
|
||||
},
|
||||
{
|
||||
struct: "PlanningClosed",
|
||||
kind: ["PLANNING_CLOSED"],
|
||||
},
|
||||
{
|
||||
struct: "OrgTable",
|
||||
|
|
@ -118,26 +75,6 @@ const nodes = [
|
|||
struct: "ListItem",
|
||||
kind: ["LIST_ITEM"],
|
||||
first_child: [["content", "ListItemContent"]],
|
||||
token: [
|
||||
["indent", "LIST_ITEM_INDENT"],
|
||||
["bullet", "LIST_ITEM_BULLET"],
|
||||
],
|
||||
},
|
||||
{
|
||||
struct: "ListItemIndent",
|
||||
kind: ["LIST_ITEM_INDENT"],
|
||||
},
|
||||
{
|
||||
struct: "ListItemTag",
|
||||
kind: ["LIST_ITEM_TAG"],
|
||||
},
|
||||
{
|
||||
struct: "ListItemBullet",
|
||||
kind: ["LIST_ITEM_BULLET"],
|
||||
},
|
||||
{
|
||||
struct: "ListItemContent",
|
||||
kind: ["LIST_ITEM_CONTENT"],
|
||||
},
|
||||
{
|
||||
struct: "Drawer",
|
||||
|
|
@ -357,7 +294,14 @@ impl AstNode for ${node.struct} {
|
|||
}> { Self::can_cast(node.kind()).then(|| ${node.struct} { syntax: node }) }
|
||||
fn syntax(&self) -> &SyntaxNode { &self.syntax }
|
||||
}
|
||||
impl ${node.struct} {\n`;
|
||||
impl ${node.struct} {
|
||||
pub fn begin(&self) -> u32 {
|
||||
self.syntax.text_range().start().into()
|
||||
}
|
||||
pub fn end(&self) -> u32 {
|
||||
self.syntax.text_range().end().into()
|
||||
}
|
||||
`;
|
||||
for (const [method, kind] of node.token || []) {
|
||||
content += ` pub fn ${method}(&self) -> Option<SyntaxToken> { support::token(&self.syntax, ${kind}) }\n`;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,12 @@ impl AstNode for Document {
|
|||
}
|
||||
}
|
||||
impl Document {
|
||||
pub fn begin(&self) -> u32 {
|
||||
self.syntax.text_range().start().into()
|
||||
}
|
||||
pub fn end(&self) -> u32 {
|
||||
self.syntax.text_range().end().into()
|
||||
}
|
||||
pub fn section(&self) -> Option<Section> {
|
||||
support::child(&self.syntax)
|
||||
}
|
||||
|
|
@ -66,6 +72,12 @@ impl AstNode for Section {
|
|||
}
|
||||
}
|
||||
impl Section {
|
||||
pub fn begin(&self) -> u32 {
|
||||
self.syntax.text_range().start().into()
|
||||
}
|
||||
pub fn end(&self) -> u32 {
|
||||
self.syntax.text_range().end().into()
|
||||
}
|
||||
pub fn post_blank(&self) -> usize {
|
||||
super::blank_lines(&self.syntax)
|
||||
}
|
||||
|
|
@ -88,6 +100,12 @@ impl AstNode for Paragraph {
|
|||
}
|
||||
}
|
||||
impl Paragraph {
|
||||
pub fn begin(&self) -> u32 {
|
||||
self.syntax.text_range().start().into()
|
||||
}
|
||||
pub fn end(&self) -> u32 {
|
||||
self.syntax.text_range().end().into()
|
||||
}
|
||||
pub fn post_blank(&self) -> usize {
|
||||
super::blank_lines(&self.syntax)
|
||||
}
|
||||
|
|
@ -130,8 +148,11 @@ impl AstNode for Headline {
|
|||
}
|
||||
}
|
||||
impl Headline {
|
||||
pub fn stars(&self) -> Option<SyntaxToken> {
|
||||
support::token(&self.syntax, HEADLINE_STARS)
|
||||
pub fn begin(&self) -> u32 {
|
||||
self.syntax.text_range().start().into()
|
||||
}
|
||||
pub fn end(&self) -> u32 {
|
||||
self.syntax.text_range().end().into()
|
||||
}
|
||||
pub fn keyword(&self) -> Option<SyntaxToken> {
|
||||
support::token(&self.syntax, HEADLINE_KEYWORD)
|
||||
|
|
@ -142,15 +163,9 @@ impl Headline {
|
|||
pub fn section(&self) -> Option<Section> {
|
||||
support::child(&self.syntax)
|
||||
}
|
||||
pub fn tags(&self) -> Option<HeadlineTags> {
|
||||
support::child(&self.syntax)
|
||||
}
|
||||
pub fn planning(&self) -> Option<Planning> {
|
||||
support::child(&self.syntax)
|
||||
}
|
||||
pub fn priority(&self) -> Option<HeadlinePriority> {
|
||||
support::child(&self.syntax)
|
||||
}
|
||||
pub fn headlines(&self) -> AstChildren<Headline> {
|
||||
support::children(&self.syntax)
|
||||
}
|
||||
|
|
@ -159,28 +174,6 @@ impl Headline {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct HeadlineStars {
|
||||
pub(crate) syntax: SyntaxNode,
|
||||
}
|
||||
impl AstNode for HeadlineStars {
|
||||
type Language = OrgLanguage;
|
||||
fn can_cast(kind: SyntaxKind) -> bool {
|
||||
kind == HEADLINE_STARS
|
||||
}
|
||||
fn cast(node: SyntaxNode) -> Option<HeadlineStars> {
|
||||
Self::can_cast(node.kind()).then(|| HeadlineStars { syntax: node })
|
||||
}
|
||||
fn syntax(&self) -> &SyntaxNode {
|
||||
&self.syntax
|
||||
}
|
||||
}
|
||||
impl HeadlineStars {
|
||||
pub fn headline(&self) -> Option<Headline> {
|
||||
self.syntax.parent().and_then(Headline::cast)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct HeadlineTitle {
|
||||
pub(crate) syntax: SyntaxNode,
|
||||
|
|
@ -198,75 +191,12 @@ impl AstNode for HeadlineTitle {
|
|||
}
|
||||
}
|
||||
impl HeadlineTitle {
|
||||
pub fn headline(&self) -> Option<Headline> {
|
||||
self.syntax.parent().and_then(Headline::cast)
|
||||
pub fn begin(&self) -> u32 {
|
||||
self.syntax.text_range().start().into()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct HeadlineKeyword {
|
||||
pub(crate) syntax: SyntaxNode,
|
||||
}
|
||||
impl AstNode for HeadlineKeyword {
|
||||
type Language = OrgLanguage;
|
||||
fn can_cast(kind: SyntaxKind) -> bool {
|
||||
kind == HEADLINE_KEYWORD
|
||||
pub fn end(&self) -> u32 {
|
||||
self.syntax.text_range().end().into()
|
||||
}
|
||||
fn cast(node: SyntaxNode) -> Option<HeadlineKeyword> {
|
||||
Self::can_cast(node.kind()).then(|| HeadlineKeyword { syntax: node })
|
||||
}
|
||||
fn syntax(&self) -> &SyntaxNode {
|
||||
&self.syntax
|
||||
}
|
||||
}
|
||||
impl HeadlineKeyword {
|
||||
pub fn headline(&self) -> Option<Headline> {
|
||||
self.syntax.parent().and_then(Headline::cast)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct HeadlinePriority {
|
||||
pub(crate) syntax: SyntaxNode,
|
||||
}
|
||||
impl AstNode for HeadlinePriority {
|
||||
type Language = OrgLanguage;
|
||||
fn can_cast(kind: SyntaxKind) -> bool {
|
||||
kind == HEADLINE_PRIORITY
|
||||
}
|
||||
fn cast(node: SyntaxNode) -> Option<HeadlinePriority> {
|
||||
Self::can_cast(node.kind()).then(|| HeadlinePriority { syntax: node })
|
||||
}
|
||||
fn syntax(&self) -> &SyntaxNode {
|
||||
&self.syntax
|
||||
}
|
||||
}
|
||||
impl HeadlinePriority {
|
||||
pub fn text(&self) -> Option<SyntaxToken> {
|
||||
support::token(&self.syntax, TEXT)
|
||||
}
|
||||
pub fn headline(&self) -> Option<Headline> {
|
||||
self.syntax.parent().and_then(Headline::cast)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct HeadlineTags {
|
||||
pub(crate) syntax: SyntaxNode,
|
||||
}
|
||||
impl AstNode for HeadlineTags {
|
||||
type Language = OrgLanguage;
|
||||
fn can_cast(kind: SyntaxKind) -> bool {
|
||||
kind == HEADLINE_TAGS
|
||||
}
|
||||
fn cast(node: SyntaxNode) -> Option<HeadlineTags> {
|
||||
Self::can_cast(node.kind()).then(|| HeadlineTags { syntax: node })
|
||||
}
|
||||
fn syntax(&self) -> &SyntaxNode {
|
||||
&self.syntax
|
||||
}
|
||||
}
|
||||
impl HeadlineTags {
|
||||
pub fn headline(&self) -> Option<Headline> {
|
||||
self.syntax.parent().and_then(Headline::cast)
|
||||
}
|
||||
|
|
@ -289,6 +219,12 @@ impl AstNode for PropertyDrawer {
|
|||
}
|
||||
}
|
||||
impl PropertyDrawer {
|
||||
pub fn begin(&self) -> u32 {
|
||||
self.syntax.text_range().start().into()
|
||||
}
|
||||
pub fn end(&self) -> u32 {
|
||||
self.syntax.text_range().end().into()
|
||||
}
|
||||
pub fn node_properties(&self) -> AstChildren<NodeProperty> {
|
||||
support::children(&self.syntax)
|
||||
}
|
||||
|
|
@ -310,7 +246,14 @@ impl AstNode for NodeProperty {
|
|||
&self.syntax
|
||||
}
|
||||
}
|
||||
impl NodeProperty {}
|
||||
impl NodeProperty {
|
||||
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 Planning {
|
||||
|
|
@ -329,71 +272,14 @@ impl AstNode for Planning {
|
|||
}
|
||||
}
|
||||
impl Planning {
|
||||
pub fn deadline(&self) -> Option<PlanningDeadline> {
|
||||
super::last_child(&self.syntax)
|
||||
pub fn begin(&self) -> u32 {
|
||||
self.syntax.text_range().start().into()
|
||||
}
|
||||
pub fn scheduled(&self) -> Option<PlanningScheduled> {
|
||||
super::last_child(&self.syntax)
|
||||
}
|
||||
pub fn closed(&self) -> Option<PlanningClosed> {
|
||||
super::last_child(&self.syntax)
|
||||
pub fn end(&self) -> u32 {
|
||||
self.syntax.text_range().end().into()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct PlanningDeadline {
|
||||
pub(crate) syntax: SyntaxNode,
|
||||
}
|
||||
impl AstNode for PlanningDeadline {
|
||||
type Language = OrgLanguage;
|
||||
fn can_cast(kind: SyntaxKind) -> bool {
|
||||
kind == PLANNING_DEADLINE
|
||||
}
|
||||
fn cast(node: SyntaxNode) -> Option<PlanningDeadline> {
|
||||
Self::can_cast(node.kind()).then(|| PlanningDeadline { syntax: node })
|
||||
}
|
||||
fn syntax(&self) -> &SyntaxNode {
|
||||
&self.syntax
|
||||
}
|
||||
}
|
||||
impl PlanningDeadline {}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct PlanningScheduled {
|
||||
pub(crate) syntax: SyntaxNode,
|
||||
}
|
||||
impl AstNode for PlanningScheduled {
|
||||
type Language = OrgLanguage;
|
||||
fn can_cast(kind: SyntaxKind) -> bool {
|
||||
kind == PLANNING_SCHEDULED
|
||||
}
|
||||
fn cast(node: SyntaxNode) -> Option<PlanningScheduled> {
|
||||
Self::can_cast(node.kind()).then(|| PlanningScheduled { syntax: node })
|
||||
}
|
||||
fn syntax(&self) -> &SyntaxNode {
|
||||
&self.syntax
|
||||
}
|
||||
}
|
||||
impl PlanningScheduled {}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct PlanningClosed {
|
||||
pub(crate) syntax: SyntaxNode,
|
||||
}
|
||||
impl AstNode for PlanningClosed {
|
||||
type Language = OrgLanguage;
|
||||
fn can_cast(kind: SyntaxKind) -> bool {
|
||||
kind == PLANNING_CLOSED
|
||||
}
|
||||
fn cast(node: SyntaxNode) -> Option<PlanningClosed> {
|
||||
Self::can_cast(node.kind()).then(|| PlanningClosed { syntax: node })
|
||||
}
|
||||
fn syntax(&self) -> &SyntaxNode {
|
||||
&self.syntax
|
||||
}
|
||||
}
|
||||
impl PlanningClosed {}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct OrgTable {
|
||||
pub(crate) syntax: SyntaxNode,
|
||||
|
|
@ -411,6 +297,12 @@ impl AstNode for OrgTable {
|
|||
}
|
||||
}
|
||||
impl OrgTable {
|
||||
pub fn begin(&self) -> u32 {
|
||||
self.syntax.text_range().start().into()
|
||||
}
|
||||
pub fn end(&self) -> u32 {
|
||||
self.syntax.text_range().end().into()
|
||||
}
|
||||
pub fn post_blank(&self) -> usize {
|
||||
super::blank_lines(&self.syntax)
|
||||
}
|
||||
|
|
@ -452,7 +344,14 @@ impl AstNode for OrgTableRow {
|
|||
&self.syntax
|
||||
}
|
||||
}
|
||||
impl OrgTableRow {}
|
||||
impl OrgTableRow {
|
||||
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 OrgTableCell {
|
||||
|
|
@ -470,7 +369,14 @@ impl AstNode for OrgTableCell {
|
|||
&self.syntax
|
||||
}
|
||||
}
|
||||
impl OrgTableCell {}
|
||||
impl OrgTableCell {
|
||||
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 List {
|
||||
|
|
@ -489,6 +395,12 @@ impl AstNode for List {
|
|||
}
|
||||
}
|
||||
impl List {
|
||||
pub fn begin(&self) -> u32 {
|
||||
self.syntax.text_range().start().into()
|
||||
}
|
||||
pub fn end(&self) -> u32 {
|
||||
self.syntax.text_range().end().into()
|
||||
}
|
||||
pub fn items(&self) -> AstChildren<ListItem> {
|
||||
support::children(&self.syntax)
|
||||
}
|
||||
|
|
@ -531,6 +443,12 @@ impl AstNode for ListItem {
|
|||
}
|
||||
}
|
||||
impl ListItem {
|
||||
pub fn begin(&self) -> u32 {
|
||||
self.syntax.text_range().start().into()
|
||||
}
|
||||
pub fn end(&self) -> u32 {
|
||||
self.syntax.text_range().end().into()
|
||||
}
|
||||
pub fn indent(&self) -> Option<SyntaxToken> {
|
||||
support::token(&self.syntax, LIST_ITEM_INDENT)
|
||||
}
|
||||
|
|
@ -558,7 +476,14 @@ impl AstNode for ListItemIndent {
|
|||
&self.syntax
|
||||
}
|
||||
}
|
||||
impl ListItemIndent {}
|
||||
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 {
|
||||
|
|
@ -576,7 +501,14 @@ impl AstNode for ListItemTag {
|
|||
&self.syntax
|
||||
}
|
||||
}
|
||||
impl ListItemTag {}
|
||||
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 {
|
||||
|
|
@ -594,7 +526,14 @@ impl AstNode for ListItemBullet {
|
|||
&self.syntax
|
||||
}
|
||||
}
|
||||
impl ListItemBullet {}
|
||||
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 {
|
||||
|
|
@ -612,7 +551,14 @@ impl AstNode for ListItemContent {
|
|||
&self.syntax
|
||||
}
|
||||
}
|
||||
impl ListItemContent {}
|
||||
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)]
|
||||
pub struct Drawer {
|
||||
|
|
@ -630,7 +576,14 @@ impl AstNode for Drawer {
|
|||
&self.syntax
|
||||
}
|
||||
}
|
||||
impl Drawer {}
|
||||
impl Drawer {
|
||||
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 DynBlock {
|
||||
|
|
@ -649,6 +602,12 @@ impl AstNode for DynBlock {
|
|||
}
|
||||
}
|
||||
impl DynBlock {
|
||||
pub fn begin(&self) -> u32 {
|
||||
self.syntax.text_range().start().into()
|
||||
}
|
||||
pub fn end(&self) -> u32 {
|
||||
self.syntax.text_range().end().into()
|
||||
}
|
||||
pub fn caption(&self) -> Option<AffiliatedKeyword> {
|
||||
affiliated_keyword(&self.syntax, |k| k == "CAPTION")
|
||||
}
|
||||
|
|
@ -687,7 +646,14 @@ impl AstNode for Keyword {
|
|||
&self.syntax
|
||||
}
|
||||
}
|
||||
impl Keyword {}
|
||||
impl Keyword {
|
||||
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 BabelCall {
|
||||
|
|
@ -705,7 +671,14 @@ impl AstNode for BabelCall {
|
|||
&self.syntax
|
||||
}
|
||||
}
|
||||
impl BabelCall {}
|
||||
impl BabelCall {
|
||||
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 AffiliatedKeyword {
|
||||
|
|
@ -723,7 +696,14 @@ impl AstNode for AffiliatedKeyword {
|
|||
&self.syntax
|
||||
}
|
||||
}
|
||||
impl AffiliatedKeyword {}
|
||||
impl AffiliatedKeyword {
|
||||
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 TableEl {
|
||||
|
|
@ -742,6 +722,12 @@ impl AstNode for TableEl {
|
|||
}
|
||||
}
|
||||
impl TableEl {
|
||||
pub fn begin(&self) -> u32 {
|
||||
self.syntax.text_range().start().into()
|
||||
}
|
||||
pub fn end(&self) -> u32 {
|
||||
self.syntax.text_range().end().into()
|
||||
}
|
||||
pub fn post_blank(&self) -> usize {
|
||||
super::blank_lines(&self.syntax)
|
||||
}
|
||||
|
|
@ -764,6 +750,12 @@ impl AstNode for Clock {
|
|||
}
|
||||
}
|
||||
impl Clock {
|
||||
pub fn begin(&self) -> u32 {
|
||||
self.syntax.text_range().start().into()
|
||||
}
|
||||
pub fn end(&self) -> u32 {
|
||||
self.syntax.text_range().end().into()
|
||||
}
|
||||
pub fn post_blank(&self) -> usize {
|
||||
super::blank_lines(&self.syntax)
|
||||
}
|
||||
|
|
@ -786,6 +778,12 @@ impl AstNode for FnDef {
|
|||
}
|
||||
}
|
||||
impl FnDef {
|
||||
pub fn begin(&self) -> u32 {
|
||||
self.syntax.text_range().start().into()
|
||||
}
|
||||
pub fn end(&self) -> u32 {
|
||||
self.syntax.text_range().end().into()
|
||||
}
|
||||
pub fn post_blank(&self) -> usize {
|
||||
super::blank_lines(&self.syntax)
|
||||
}
|
||||
|
|
@ -828,6 +826,12 @@ impl AstNode for Comment {
|
|||
}
|
||||
}
|
||||
impl Comment {
|
||||
pub fn begin(&self) -> u32 {
|
||||
self.syntax.text_range().start().into()
|
||||
}
|
||||
pub fn end(&self) -> u32 {
|
||||
self.syntax.text_range().end().into()
|
||||
}
|
||||
pub fn text(&self) -> Option<SyntaxToken> {
|
||||
support::token(&self.syntax, TEXT)
|
||||
}
|
||||
|
|
@ -873,6 +877,12 @@ impl AstNode for Rule {
|
|||
}
|
||||
}
|
||||
impl Rule {
|
||||
pub fn begin(&self) -> u32 {
|
||||
self.syntax.text_range().start().into()
|
||||
}
|
||||
pub fn end(&self) -> u32 {
|
||||
self.syntax.text_range().end().into()
|
||||
}
|
||||
pub fn post_blank(&self) -> usize {
|
||||
super::blank_lines(&self.syntax)
|
||||
}
|
||||
|
|
@ -895,6 +905,12 @@ impl AstNode for FixedWidth {
|
|||
}
|
||||
}
|
||||
impl FixedWidth {
|
||||
pub fn begin(&self) -> u32 {
|
||||
self.syntax.text_range().start().into()
|
||||
}
|
||||
pub fn end(&self) -> u32 {
|
||||
self.syntax.text_range().end().into()
|
||||
}
|
||||
pub fn text(&self) -> Option<SyntaxToken> {
|
||||
support::token(&self.syntax, TEXT)
|
||||
}
|
||||
|
|
@ -940,6 +956,12 @@ impl AstNode for SpecialBlock {
|
|||
}
|
||||
}
|
||||
impl SpecialBlock {
|
||||
pub fn begin(&self) -> u32 {
|
||||
self.syntax.text_range().start().into()
|
||||
}
|
||||
pub fn end(&self) -> u32 {
|
||||
self.syntax.text_range().end().into()
|
||||
}
|
||||
pub fn caption(&self) -> Option<AffiliatedKeyword> {
|
||||
affiliated_keyword(&self.syntax, |k| k == "CAPTION")
|
||||
}
|
||||
|
|
@ -979,6 +1001,12 @@ impl AstNode for QuoteBlock {
|
|||
}
|
||||
}
|
||||
impl QuoteBlock {
|
||||
pub fn begin(&self) -> u32 {
|
||||
self.syntax.text_range().start().into()
|
||||
}
|
||||
pub fn end(&self) -> u32 {
|
||||
self.syntax.text_range().end().into()
|
||||
}
|
||||
pub fn caption(&self) -> Option<AffiliatedKeyword> {
|
||||
affiliated_keyword(&self.syntax, |k| k == "CAPTION")
|
||||
}
|
||||
|
|
@ -1018,6 +1046,12 @@ impl AstNode for CenterBlock {
|
|||
}
|
||||
}
|
||||
impl CenterBlock {
|
||||
pub fn begin(&self) -> u32 {
|
||||
self.syntax.text_range().start().into()
|
||||
}
|
||||
pub fn end(&self) -> u32 {
|
||||
self.syntax.text_range().end().into()
|
||||
}
|
||||
pub fn caption(&self) -> Option<AffiliatedKeyword> {
|
||||
affiliated_keyword(&self.syntax, |k| k == "CAPTION")
|
||||
}
|
||||
|
|
@ -1057,6 +1091,12 @@ impl AstNode for VerseBlock {
|
|||
}
|
||||
}
|
||||
impl VerseBlock {
|
||||
pub fn begin(&self) -> u32 {
|
||||
self.syntax.text_range().start().into()
|
||||
}
|
||||
pub fn end(&self) -> u32 {
|
||||
self.syntax.text_range().end().into()
|
||||
}
|
||||
pub fn caption(&self) -> Option<AffiliatedKeyword> {
|
||||
affiliated_keyword(&self.syntax, |k| k == "CAPTION")
|
||||
}
|
||||
|
|
@ -1096,6 +1136,12 @@ impl AstNode for CommentBlock {
|
|||
}
|
||||
}
|
||||
impl CommentBlock {
|
||||
pub fn begin(&self) -> u32 {
|
||||
self.syntax.text_range().start().into()
|
||||
}
|
||||
pub fn end(&self) -> u32 {
|
||||
self.syntax.text_range().end().into()
|
||||
}
|
||||
pub fn caption(&self) -> Option<AffiliatedKeyword> {
|
||||
affiliated_keyword(&self.syntax, |k| k == "CAPTION")
|
||||
}
|
||||
|
|
@ -1135,6 +1181,12 @@ impl AstNode for ExampleBlock {
|
|||
}
|
||||
}
|
||||
impl ExampleBlock {
|
||||
pub fn begin(&self) -> u32 {
|
||||
self.syntax.text_range().start().into()
|
||||
}
|
||||
pub fn end(&self) -> u32 {
|
||||
self.syntax.text_range().end().into()
|
||||
}
|
||||
pub fn caption(&self) -> Option<AffiliatedKeyword> {
|
||||
affiliated_keyword(&self.syntax, |k| k == "CAPTION")
|
||||
}
|
||||
|
|
@ -1174,6 +1226,12 @@ impl AstNode for ExportBlock {
|
|||
}
|
||||
}
|
||||
impl ExportBlock {
|
||||
pub fn begin(&self) -> u32 {
|
||||
self.syntax.text_range().start().into()
|
||||
}
|
||||
pub fn end(&self) -> u32 {
|
||||
self.syntax.text_range().end().into()
|
||||
}
|
||||
pub fn caption(&self) -> Option<AffiliatedKeyword> {
|
||||
affiliated_keyword(&self.syntax, |k| k == "CAPTION")
|
||||
}
|
||||
|
|
@ -1213,6 +1271,12 @@ impl AstNode for SourceBlock {
|
|||
}
|
||||
}
|
||||
impl SourceBlock {
|
||||
pub fn begin(&self) -> u32 {
|
||||
self.syntax.text_range().start().into()
|
||||
}
|
||||
pub fn end(&self) -> u32 {
|
||||
self.syntax.text_range().end().into()
|
||||
}
|
||||
pub fn caption(&self) -> Option<AffiliatedKeyword> {
|
||||
affiliated_keyword(&self.syntax, |k| k == "CAPTION")
|
||||
}
|
||||
|
|
@ -1251,7 +1315,14 @@ impl AstNode for InlineCall {
|
|||
&self.syntax
|
||||
}
|
||||
}
|
||||
impl InlineCall {}
|
||||
impl InlineCall {
|
||||
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 InlineSrc {
|
||||
|
|
@ -1269,7 +1340,14 @@ impl AstNode for InlineSrc {
|
|||
&self.syntax
|
||||
}
|
||||
}
|
||||
impl InlineSrc {}
|
||||
impl InlineSrc {
|
||||
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 Link {
|
||||
|
|
@ -1288,6 +1366,12 @@ impl AstNode for Link {
|
|||
}
|
||||
}
|
||||
impl Link {
|
||||
pub fn begin(&self) -> u32 {
|
||||
self.syntax.text_range().start().into()
|
||||
}
|
||||
pub fn end(&self) -> u32 {
|
||||
self.syntax.text_range().end().into()
|
||||
}
|
||||
pub fn path(&self) -> Option<SyntaxToken> {
|
||||
support::token(&self.syntax, LINK_PATH)
|
||||
}
|
||||
|
|
@ -1309,7 +1393,14 @@ impl AstNode for Cookie {
|
|||
&self.syntax
|
||||
}
|
||||
}
|
||||
impl Cookie {}
|
||||
impl Cookie {
|
||||
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 RadioTarget {
|
||||
|
|
@ -1327,7 +1418,14 @@ impl AstNode for RadioTarget {
|
|||
&self.syntax
|
||||
}
|
||||
}
|
||||
impl RadioTarget {}
|
||||
impl RadioTarget {
|
||||
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 FnRef {
|
||||
|
|
@ -1345,7 +1443,14 @@ impl AstNode for FnRef {
|
|||
&self.syntax
|
||||
}
|
||||
}
|
||||
impl FnRef {}
|
||||
impl FnRef {
|
||||
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 LatexEnvironment {
|
||||
|
|
@ -1363,7 +1468,14 @@ impl AstNode for LatexEnvironment {
|
|||
&self.syntax
|
||||
}
|
||||
}
|
||||
impl LatexEnvironment {}
|
||||
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 {
|
||||
|
|
@ -1381,7 +1493,14 @@ impl AstNode for Macros {
|
|||
&self.syntax
|
||||
}
|
||||
}
|
||||
impl Macros {}
|
||||
impl Macros {
|
||||
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 MacrosArgument {
|
||||
|
|
@ -1399,7 +1518,14 @@ impl AstNode for MacrosArgument {
|
|||
&self.syntax
|
||||
}
|
||||
}
|
||||
impl MacrosArgument {}
|
||||
impl MacrosArgument {
|
||||
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 Snippet {
|
||||
|
|
@ -1418,6 +1544,12 @@ impl AstNode for Snippet {
|
|||
}
|
||||
}
|
||||
impl Snippet {
|
||||
pub fn begin(&self) -> u32 {
|
||||
self.syntax.text_range().start().into()
|
||||
}
|
||||
pub fn end(&self) -> u32 {
|
||||
self.syntax.text_range().end().into()
|
||||
}
|
||||
pub fn name(&self) -> Option<SyntaxToken> {
|
||||
support::token(&self.syntax, TEXT)
|
||||
}
|
||||
|
|
@ -1439,7 +1571,14 @@ impl AstNode for Target {
|
|||
&self.syntax
|
||||
}
|
||||
}
|
||||
impl Target {}
|
||||
impl Target {
|
||||
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 Bold {
|
||||
|
|
@ -1457,7 +1596,14 @@ impl AstNode for Bold {
|
|||
&self.syntax
|
||||
}
|
||||
}
|
||||
impl Bold {}
|
||||
impl Bold {
|
||||
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 Strike {
|
||||
|
|
@ -1475,7 +1621,14 @@ impl AstNode for Strike {
|
|||
&self.syntax
|
||||
}
|
||||
}
|
||||
impl Strike {}
|
||||
impl Strike {
|
||||
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 Italic {
|
||||
|
|
@ -1493,7 +1646,14 @@ impl AstNode for Italic {
|
|||
&self.syntax
|
||||
}
|
||||
}
|
||||
impl Italic {}
|
||||
impl Italic {
|
||||
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 Underline {
|
||||
|
|
@ -1511,7 +1671,14 @@ impl AstNode for Underline {
|
|||
&self.syntax
|
||||
}
|
||||
}
|
||||
impl Underline {}
|
||||
impl Underline {
|
||||
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 Verbatim {
|
||||
|
|
@ -1529,7 +1696,14 @@ impl AstNode for Verbatim {
|
|||
&self.syntax
|
||||
}
|
||||
}
|
||||
impl Verbatim {}
|
||||
impl Verbatim {
|
||||
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 Code {
|
||||
|
|
@ -1548,6 +1722,12 @@ impl AstNode for Code {
|
|||
}
|
||||
}
|
||||
impl Code {
|
||||
pub fn begin(&self) -> u32 {
|
||||
self.syntax.text_range().start().into()
|
||||
}
|
||||
pub fn end(&self) -> u32 {
|
||||
self.syntax.text_range().end().into()
|
||||
}
|
||||
pub fn text(&self) -> Option<SyntaxToken> {
|
||||
support::token(&self.syntax, TEXT)
|
||||
}
|
||||
|
|
@ -1570,6 +1750,12 @@ impl AstNode for Timestamp {
|
|||
}
|
||||
}
|
||||
impl Timestamp {
|
||||
pub fn begin(&self) -> u32 {
|
||||
self.syntax.text_range().start().into()
|
||||
}
|
||||
pub fn end(&self) -> u32 {
|
||||
self.syntax.text_range().end().into()
|
||||
}
|
||||
pub fn year_start(&self) -> Option<SyntaxToken> {
|
||||
support::token(&self.syntax, TIMESTAMP_YEAR)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
use rowan::ast::support;
|
||||
use crate::syntax::{SyntaxKind, SyntaxToken};
|
||||
|
||||
use crate::syntax::{SyntaxElement, SyntaxKind, SyntaxToken};
|
||||
|
||||
use super::{filter_token, Headline, HeadlinePriority, HeadlineTags, Timestamp};
|
||||
use super::{filter_token, Headline, Timestamp};
|
||||
|
||||
impl Headline {
|
||||
/// Return level of this headline
|
||||
|
|
@ -11,12 +9,19 @@ impl Headline {
|
|||
/// use orgize::{Org, ast::Headline};
|
||||
///
|
||||
/// let hdl = Org::parse("* ").first_node::<Headline>().unwrap();
|
||||
/// assert_eq!(hdl.level(), Some(1));
|
||||
/// assert_eq!(hdl.level(), 1);
|
||||
/// let hdl = Org::parse("****** hello").first_node::<Headline>().unwrap();
|
||||
/// assert_eq!(hdl.level(), Some(6));
|
||||
/// assert_eq!(hdl.level(), 6);
|
||||
/// ```
|
||||
pub fn level(&self) -> Option<usize> {
|
||||
self.stars().map(|stars| stars.text().len())
|
||||
pub fn level(&self) -> usize {
|
||||
self.syntax
|
||||
.children_with_tokens()
|
||||
.find_map(filter_token(SyntaxKind::HEADLINE_STARS))
|
||||
.map(|stars| stars.text().len())
|
||||
.unwrap_or_else(|| {
|
||||
debug_assert!(false, "headline must contains starts token");
|
||||
0
|
||||
})
|
||||
}
|
||||
|
||||
/// Return `true` if this headline contains a COMMENT keyword
|
||||
|
|
@ -54,34 +59,67 @@ impl Headline {
|
|||
/// assert!(!hdl.is_archived());
|
||||
/// ```
|
||||
pub fn is_archived(&self) -> bool {
|
||||
self.tags()
|
||||
.map(|tags| {
|
||||
tags.syntax
|
||||
.children_with_tokens()
|
||||
.any(|elem| matches!(elem, SyntaxElement::Token(t) if t.text() == "ARCHIVE"))
|
||||
})
|
||||
.unwrap_or_default()
|
||||
self.tags().any(|t| t.text() == "ARCHIVE")
|
||||
}
|
||||
|
||||
/// Returns this headline's closed timestamp, or `None` if not set.
|
||||
pub fn closed(&self) -> Option<Timestamp> {
|
||||
self.planning()
|
||||
.and_then(|planning| planning.closed())
|
||||
.and_then(|node| support::child::<Timestamp>(&node.syntax))
|
||||
self.planning().and_then(|planning| planning.closed())
|
||||
}
|
||||
|
||||
/// Returns this headline's scheduled timestamp, or `None` if not set.
|
||||
pub fn scheduled(&self) -> Option<Timestamp> {
|
||||
self.planning()
|
||||
.and_then(|planning| planning.scheduled())
|
||||
.and_then(|node| support::child::<Timestamp>(&node.syntax))
|
||||
self.planning().and_then(|planning| planning.scheduled())
|
||||
}
|
||||
|
||||
/// Returns this headline's deadline timestamp, or `None` if not set.
|
||||
pub fn deadline(&self) -> Option<Timestamp> {
|
||||
self.planning()
|
||||
.and_then(|planning| planning.deadline())
|
||||
.and_then(|node| support::child::<Timestamp>(&node.syntax))
|
||||
self.planning().and_then(|planning| planning.deadline())
|
||||
}
|
||||
|
||||
/// Returns an iterator of text token in this tags
|
||||
///
|
||||
/// ```rust
|
||||
/// use orgize::{Org, ast::Headline};
|
||||
///
|
||||
/// let tags_vec = |input: &str| {
|
||||
/// let hdl = Org::parse(input).first_node::<Headline>().unwrap();
|
||||
/// let tags: Vec<_> = hdl.tags().map(|t| t.to_string()).collect();
|
||||
/// tags
|
||||
/// };
|
||||
///
|
||||
/// assert_eq!(tags_vec("* :tag:"), vec!["tag".to_string()]);
|
||||
/// assert_eq!(tags_vec("* [#A] :::::a2%:"), vec!["a2%".to_string()]);
|
||||
/// assert_eq!(tags_vec("* TODO :tag: :a2%:"), vec!["tag".to_string(), "a2%".to_string()]);
|
||||
/// assert_eq!(tags_vec("* title :tag:a2%:"), vec!["tag".to_string(), "a2%".to_string()]);
|
||||
/// ```
|
||||
pub fn tags(&self) -> impl Iterator<Item = SyntaxToken> {
|
||||
self.syntax
|
||||
.children()
|
||||
.find(|n| n.kind() == SyntaxKind::HEADLINE_TAGS)
|
||||
.into_iter()
|
||||
.flat_map(|t| t.children_with_tokens())
|
||||
.filter_map(filter_token(SyntaxKind::TEXT))
|
||||
}
|
||||
|
||||
/// Returns priority text
|
||||
///
|
||||
/// ```rust
|
||||
/// use orgize::{Org, ast::Headline};
|
||||
///
|
||||
/// let hdl = Org::parse("* [#A]").first_node::<Headline>().unwrap();
|
||||
/// assert_eq!(hdl.priority().unwrap().text(), "A");
|
||||
/// let hdl = Org::parse("* [#破]").first_node::<Headline>().unwrap();
|
||||
/// assert_eq!(hdl.priority().unwrap().text(), "破");
|
||||
/// ```
|
||||
pub fn priority(&self) -> Option<SyntaxToken> {
|
||||
self.syntax
|
||||
.children()
|
||||
.find(|n| n.kind() == SyntaxKind::HEADLINE_PRIORITY)
|
||||
.and_then(|n| {
|
||||
n.children_with_tokens()
|
||||
.find_map(filter_token(SyntaxKind::TEXT))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -316,43 +354,3 @@ impl Headline {
|
|||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
impl HeadlineTags {
|
||||
/// Returns an iterator of text token in this tags
|
||||
///
|
||||
/// ```rust
|
||||
/// use orgize::{Org, ast::HeadlineTags};
|
||||
///
|
||||
/// let tags_vec = |input: &str| {
|
||||
/// let tags = Org::parse(input).first_node::<HeadlineTags>().unwrap();
|
||||
/// let tags: Vec<_> = tags.iter().map(|t| t.to_string()).collect();
|
||||
/// tags
|
||||
/// };
|
||||
///
|
||||
/// assert_eq!(tags_vec("* :tag:"), vec!["tag".to_string()]);
|
||||
/// assert_eq!(tags_vec("* [#A] :::::a2%:"), vec!["a2%".to_string()]);
|
||||
/// assert_eq!(tags_vec("* TODO :tag: :a2%:"), vec!["tag".to_string(), "a2%".to_string()]);
|
||||
/// assert_eq!(tags_vec("* title :tag:a2%:"), vec!["tag".to_string(), "a2%".to_string()]);
|
||||
/// ```
|
||||
pub fn iter(&self) -> impl Iterator<Item = SyntaxToken> {
|
||||
self.syntax
|
||||
.children_with_tokens()
|
||||
.filter_map(filter_token(SyntaxKind::TEXT))
|
||||
}
|
||||
}
|
||||
|
||||
impl HeadlinePriority {
|
||||
/// Returns priority text
|
||||
///
|
||||
/// ```rust
|
||||
/// use orgize::{Org, ast::HeadlinePriority};
|
||||
///
|
||||
/// let priority = Org::parse("* [#A]").first_node::<HeadlinePriority>().unwrap();
|
||||
/// assert_eq!(priority.text_string().unwrap(), "A".to_string());
|
||||
/// let priority = Org::parse("* [#破]").first_node::<HeadlinePriority>().unwrap();
|
||||
/// assert_eq!(priority.text_string().unwrap(), "破".to_string());
|
||||
/// ```
|
||||
pub fn text_string(&self) -> Option<String> {
|
||||
self.text().map(|tk| tk.to_string())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,55 @@
|
|||
use super::List;
|
||||
use crate::syntax::SyntaxKind;
|
||||
use super::{filter_token, List};
|
||||
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
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ mod headline;
|
|||
mod inline_call;
|
||||
mod link;
|
||||
mod list;
|
||||
mod planning;
|
||||
mod snippet;
|
||||
mod table;
|
||||
mod timestamp;
|
||||
|
|
|
|||
67
src/ast/planning.rs
Normal file
67
src/ast/planning.rs
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
use rowan::ast::AstNode;
|
||||
|
||||
use super::{Planning, Timestamp};
|
||||
use crate::syntax::SyntaxKind;
|
||||
|
||||
impl Planning {
|
||||
/// Returns deadline timestamp
|
||||
///
|
||||
///
|
||||
/// ```rust
|
||||
/// use orgize::{ast::Planning, Org};
|
||||
///
|
||||
/// let s = Org::parse("* a\nDEADLINE: <2019-04-08 Mon>")
|
||||
/// .first_node::<Planning>()
|
||||
/// .unwrap()
|
||||
/// .deadline()
|
||||
/// .unwrap();
|
||||
/// assert_eq!(s.day_start().unwrap().text(), "08");
|
||||
/// ```
|
||||
pub fn deadline(&self) -> Option<Timestamp> {
|
||||
self.syntax
|
||||
.children()
|
||||
.filter(|n| n.kind() == SyntaxKind::PLANNING_DEADLINE)
|
||||
.last()
|
||||
.and_then(|n| n.children().find_map(Timestamp::cast))
|
||||
}
|
||||
|
||||
/// Returns scheduled timestamp
|
||||
///
|
||||
/// ```rust
|
||||
/// use orgize::{ast::Planning, Org};
|
||||
///
|
||||
/// let s = Org::parse("* a\nSCHEDULED: <2019-04-08 Mon>")
|
||||
/// .first_node::<Planning>()
|
||||
/// .unwrap()
|
||||
/// .scheduled()
|
||||
/// .unwrap();
|
||||
/// assert_eq!(s.year_start().unwrap().text(), "2019");
|
||||
/// ```
|
||||
pub fn scheduled(&self) -> Option<Timestamp> {
|
||||
self.syntax
|
||||
.children()
|
||||
.filter(|n| n.kind() == SyntaxKind::PLANNING_SCHEDULED)
|
||||
.last()
|
||||
.and_then(|n| n.children().find_map(Timestamp::cast))
|
||||
}
|
||||
|
||||
/// Returns closed timestamp
|
||||
///
|
||||
/// ```rust
|
||||
/// use orgize::{ast::Planning, Org};
|
||||
///
|
||||
/// let s = Org::parse("* a\nCLOSED: <2019-04-08 Mon>")
|
||||
/// .first_node::<Planning>()
|
||||
/// .unwrap()
|
||||
/// .closed()
|
||||
/// .unwrap();
|
||||
/// assert_eq!(s.month_start().unwrap().text(), "04");
|
||||
/// ```
|
||||
pub fn closed(&self) -> Option<Timestamp> {
|
||||
self.syntax
|
||||
.children()
|
||||
.filter(|n| n.kind() == SyntaxKind::PLANNING_CLOSED)
|
||||
.last()
|
||||
.and_then(|n| n.children().find_map(Timestamp::cast))
|
||||
}
|
||||
}
|
||||
|
|
@ -28,14 +28,12 @@
|
|||
/// fn headline_title(&mut self, event: WalkEvent<&HeadlineTitle>, _ctx: &mut TraversalContext) {
|
||||
/// match event {
|
||||
/// WalkEvent::Enter(title) => {
|
||||
/// let level = title.headline().and_then(|h| h.level()).unwrap_or(1);
|
||||
/// let level = min(level, 6);
|
||||
/// 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().and_then(|h| h.level()).unwrap_or(1);
|
||||
/// let level = min(level, 6);
|
||||
/// let level = title.headline().map(|h| min(h.level(), 6)).unwrap_or(1);
|
||||
/// self.0.push_str(format!("</a></h{level}>"));
|
||||
/// }
|
||||
/// }
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use rowan::WalkEvent;
|
||||
use std::cmp::min;
|
||||
use std::fmt;
|
||||
|
||||
use super::TraversalContext;
|
||||
|
|
@ -188,19 +189,11 @@ impl Traverser for HtmlExport {
|
|||
fn headline_title(&mut self, event: WalkEvent<&HeadlineTitle>, _ctx: &mut TraversalContext) {
|
||||
self.output += &match event {
|
||||
WalkEvent::Enter(title) => {
|
||||
let level = title
|
||||
.headline()
|
||||
.and_then(|hdl| hdl.level())
|
||||
.map(|lvl| std::cmp::min(lvl, 6))
|
||||
.unwrap_or(1);
|
||||
let level = title.headline().map(|h| min(h.level(), 6)).unwrap_or(1);
|
||||
format!("<h{level}>")
|
||||
}
|
||||
WalkEvent::Leave(title) => {
|
||||
let level = title
|
||||
.headline()
|
||||
.and_then(|hdl| hdl.level())
|
||||
.map(|lvl| std::cmp::min(lvl, 6))
|
||||
.unwrap_or(1);
|
||||
let level = title.headline().map(|h| min(h.level(), 6)).unwrap_or(1);
|
||||
format!("</h{level}>")
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -273,8 +273,8 @@ fn parse() {
|
|||
);
|
||||
|
||||
let hdl = to_headline("* TODO foo\nbar\n** baz\n");
|
||||
assert_eq!(hdl.level(), Some(1));
|
||||
assert_eq!(hdl.keyword().as_ref().map(|x| x.text()), Some("TODO"));
|
||||
assert_eq!(hdl.level(), 1);
|
||||
assert_eq!(hdl.keyword().unwrap().text(), "TODO");
|
||||
insta::assert_debug_snapshot!(
|
||||
hdl.syntax,
|
||||
@r###"
|
||||
|
|
@ -299,11 +299,8 @@ fn parse() {
|
|||
);
|
||||
|
||||
let hdl = to_headline("** [#A] foo\n* baz");
|
||||
assert_eq!(hdl.level(), Some(2));
|
||||
assert_eq!(
|
||||
hdl.priority().unwrap().text_string().unwrap(),
|
||||
"A".to_string()
|
||||
);
|
||||
assert_eq!(hdl.level(), 2);
|
||||
assert_eq!(hdl.priority().unwrap().text(), "A");
|
||||
insta::assert_debug_snapshot!(
|
||||
hdl.syntax,
|
||||
@r###"
|
||||
|
|
@ -329,41 +326,41 @@ fn issue_15_16() {
|
|||
|
||||
let to_headline = to_ast::<Headline>(headline_node);
|
||||
|
||||
assert!(to_headline("* a ::").tags().is_none());
|
||||
assert!(to_headline("* a : :").tags().is_none());
|
||||
assert!(to_headline("* a :(:").tags().is_none());
|
||||
assert!(to_headline("* a :a: :").tags().is_none());
|
||||
assert!(to_headline("* a :a :").tags().is_none());
|
||||
assert!(to_headline("* a a:").tags().is_none());
|
||||
assert!(to_headline("* a :a").tags().is_none());
|
||||
assert!(to_headline("* a ::").tags().count() == 0);
|
||||
assert!(to_headline("* a : :").tags().count() == 0);
|
||||
assert!(to_headline("* a :(:").tags().count() == 0);
|
||||
assert!(to_headline("* a :a: :").tags().count() == 0);
|
||||
assert!(to_headline("* a :a :").tags().count() == 0);
|
||||
assert!(to_headline("* a a:").tags().count() == 0);
|
||||
assert!(to_headline("* a :a").tags().count() == 0);
|
||||
|
||||
let tags = to_headline("* a \t:_:").tags().unwrap();
|
||||
let tags = to_headline("* a \t:_:").tags();
|
||||
assert_eq!(
|
||||
vec!["_".to_string()],
|
||||
tags.iter().map(|x| x.to_string()).collect::<Vec<_>>(),
|
||||
tags.map(|x| x.to_string()).collect::<Vec<_>>(),
|
||||
);
|
||||
|
||||
let tags = to_headline("* a \t :@:").tags().unwrap();
|
||||
let tags = to_headline("* a \t :@:").tags();
|
||||
assert_eq!(
|
||||
vec!["@".to_string()],
|
||||
tags.iter().map(|x| x.to_string()).collect::<Vec<_>>(),
|
||||
tags.map(|x| x.to_string()).collect::<Vec<_>>(),
|
||||
);
|
||||
|
||||
let tags = to_headline("* a :#:").tags().unwrap();
|
||||
let tags = to_headline("* a :#:").tags();
|
||||
assert_eq!(
|
||||
vec!["#".to_string()],
|
||||
tags.iter().map(|x| x.to_string()).collect::<Vec<_>>(),
|
||||
tags.map(|x| x.to_string()).collect::<Vec<_>>(),
|
||||
);
|
||||
|
||||
let tags = to_headline("* a\t :%:").tags().unwrap();
|
||||
let tags = to_headline("* a\t :%:").tags();
|
||||
assert_eq!(
|
||||
vec!["%".to_string()],
|
||||
tags.iter().map(|x| x.to_string()).collect::<Vec<_>>(),
|
||||
tags.map(|x| x.to_string()).collect::<Vec<_>>(),
|
||||
);
|
||||
|
||||
let tags = to_headline("* a :余: :破:").tags().unwrap();
|
||||
let tags = to_headline("* a :余: :破:").tags();
|
||||
assert_eq!(
|
||||
vec!["余".to_string(), "破".to_string()],
|
||||
tags.iter().map(|x| x.to_string()).collect::<Vec<_>>(),
|
||||
tags.map(|x| x.to_string()).collect::<Vec<_>>(),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue