Compare commits
55 Commits
2a003b85fd
...
v0.1.9
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e673aa862e | ||
|
|
3b6659c5fd | ||
|
|
68a3f8b87e | ||
|
|
b1244de1dc | ||
|
|
e5a402ee1b | ||
|
|
d4a2ad4a7f | ||
|
|
3d1b2713ed | ||
|
|
60bec4695b | ||
|
|
d992947ff1 | ||
|
|
76fb24d1d1 | ||
|
|
b56318fbe4 | ||
|
|
8169499de3 | ||
|
|
29d9e76545 | ||
|
|
4d356b855e | ||
|
|
ae66d1bd89 | ||
|
|
c551938904 | ||
|
|
0fb80e3fee | ||
|
|
590e7fba0e | ||
|
|
4a72747dc9 | ||
|
|
2352636672 | ||
|
|
36217f5704 | ||
|
|
0654b676f7 | ||
|
|
a80d171e4d | ||
|
|
2e1a946ac9 | ||
|
|
01c2f1bf66 | ||
|
|
be483110ef | ||
|
|
94401dcf00 | ||
|
|
2b5df83956 | ||
|
|
d53b9e1e1f | ||
|
|
5c929ffc13 | ||
|
|
bc3224be7a | ||
|
|
54c66fb4d6 | ||
|
|
6a8ae9d838 | ||
|
|
512432c5f0 | ||
|
|
890cd3e4fd | ||
|
|
9846cde2f0 | ||
|
|
dec3242e72 | ||
|
|
a8a34e2d9c | ||
|
|
c55fae86f8 | ||
|
|
e7ec23af3d | ||
|
|
10ae36a419 | ||
|
|
ecdfd7087f | ||
|
|
3ed9b552e2 | ||
|
|
d04c8c832c | ||
|
|
9575ef30ac | ||
|
|
06ecf41663 | ||
|
|
10d03fd432 | ||
|
|
a62c3fc522 | ||
|
|
25f664e69e | ||
|
|
52e0d305aa | ||
|
|
418c5c1ce8 | ||
|
|
ecd523fa8f | ||
|
|
c0555dec0b | ||
|
|
1b788f3f21 | ||
|
|
b3382c66cd |
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "organic"
|
name = "organic"
|
||||||
version = "0.1.8"
|
version = "0.1.9"
|
||||||
authors = ["Tom Alexander <tom@fizz.buzz>"]
|
authors = ["Tom Alexander <tom@fizz.buzz>"]
|
||||||
description = "An org-mode parser."
|
description = "An org-mode parser."
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
#+begin_defun foo bar baz
|
||||||
|
lorem
|
||||||
|
#+end_defun
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
# Comment
|
# Comment
|
||||||
|
#
|
||||||
# indented line
|
# indented line
|
||||||
# At the top of the file
|
# At the top of the file
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
# All the marks for repeater and warning delay
|
||||||
|
[1970-01-01 Thu 8:15-13:15foo +1h -2h]
|
||||||
|
[1970-01-01 Thu 8:15-13:15foo ++1d -2d]
|
||||||
|
[1970-01-01 Thu 8:15-13:15foo .+1w -2w]
|
||||||
|
[1970-01-01 Thu 8:15-13:15foo +1m --2m]
|
||||||
|
[1970-01-01 Thu 8:15-13:15foo ++1y --2y]
|
||||||
|
[1970-01-01 Thu 8:15-13:15foo .+1d --2h]
|
||||||
@@ -2,13 +2,17 @@
|
|||||||
<%%(foo bar baz)>
|
<%%(foo bar baz)>
|
||||||
# active
|
# active
|
||||||
<1970-01-01 Thu 8:15rest +1w -1d>
|
<1970-01-01 Thu 8:15rest +1w -1d>
|
||||||
|
# Any value for "REST" in the first timestamp makes this a regular timestamp rather than a time range.
|
||||||
|
<1970-01-01 Thu 8:15rest-13:15otherrest +1w -1d>
|
||||||
# inactive
|
# inactive
|
||||||
[1970-01-01 Thu 8:15rest +1w -1d]
|
[1970-01-01 Thu 8:15rest +1w -1d]
|
||||||
|
# Any value for "REST" in the first timestamp makes this a regular timestamp rather than a time range.
|
||||||
|
[1970-01-01 Thu 8:15rest-13:15otherrest +1w -1d]
|
||||||
# active date range
|
# active date range
|
||||||
<1970-01-01 Thu 8:15rest +1w -1d>--<1970-01-01 Thu 8:15rest +1w -1d>
|
<1970-01-01 Thu 8:15rest +1w -1d>--<1970-01-01 Thu 8:15rest +1w -1d>
|
||||||
# active time range
|
# active time range
|
||||||
<1970-01-01 Thu 8:15rest-13:15otherrest +1w -1d>
|
<1970-01-01 Thu 8:15-13:15otherrest +1w -1d>
|
||||||
# inactive date range
|
# inactive date range
|
||||||
[1970-01-01 Thu 8:15rest +1w -1d]--[1970-01-01 Thu 8:15rest +1w -1d]
|
[1970-01-01 Thu 8:15rest +1w -1d]--[1970-01-01 Thu 8:15rest +1w -1d]
|
||||||
# inactive time range
|
# inactive time range
|
||||||
[1970-01-01 Thu 8:15rest-13:15otherrest +1w -1d]
|
[1970-01-01 Thu 8:15-13:15otherrest +1w -1d]
|
||||||
|
|||||||
2
org_mode_samples/object/timestamp/timeless_rest.org
Normal file
2
org_mode_samples/object/timestamp/timeless_rest.org
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
# This should be a malformed timestamp according to the current org-mode documentation but it is accepted anyway (with no repeater).
|
||||||
|
<1970-01-01 Thu ++y>
|
||||||
1526
src/compare/diff.rs
1526
src/compare/diff.rs
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,10 @@
|
|||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
use crate::types::AngleLink;
|
use crate::types::AngleLink;
|
||||||
|
use crate::types::AstNode;
|
||||||
use crate::types::BabelCall;
|
use crate::types::BabelCall;
|
||||||
use crate::types::Bold;
|
use crate::types::Bold;
|
||||||
|
use crate::types::CenterBlock;
|
||||||
use crate::types::Citation;
|
use crate::types::Citation;
|
||||||
use crate::types::CitationReference;
|
use crate::types::CitationReference;
|
||||||
use crate::types::Clock;
|
use crate::types::Clock;
|
||||||
@@ -21,7 +23,6 @@ use crate::types::ExportSnippet;
|
|||||||
use crate::types::FixedWidthArea;
|
use crate::types::FixedWidthArea;
|
||||||
use crate::types::FootnoteDefinition;
|
use crate::types::FootnoteDefinition;
|
||||||
use crate::types::FootnoteReference;
|
use crate::types::FootnoteReference;
|
||||||
use crate::types::GreaterBlock;
|
|
||||||
use crate::types::Heading;
|
use crate::types::Heading;
|
||||||
use crate::types::HorizontalRule;
|
use crate::types::HorizontalRule;
|
||||||
use crate::types::InlineBabelCall;
|
use crate::types::InlineBabelCall;
|
||||||
@@ -41,10 +42,12 @@ use crate::types::PlainListItem;
|
|||||||
use crate::types::PlainText;
|
use crate::types::PlainText;
|
||||||
use crate::types::Planning;
|
use crate::types::Planning;
|
||||||
use crate::types::PropertyDrawer;
|
use crate::types::PropertyDrawer;
|
||||||
|
use crate::types::QuoteBlock;
|
||||||
use crate::types::RadioLink;
|
use crate::types::RadioLink;
|
||||||
use crate::types::RadioTarget;
|
use crate::types::RadioTarget;
|
||||||
use crate::types::RegularLink;
|
use crate::types::RegularLink;
|
||||||
use crate::types::Section;
|
use crate::types::Section;
|
||||||
|
use crate::types::SpecialBlock;
|
||||||
use crate::types::SrcBlock;
|
use crate::types::SrcBlock;
|
||||||
use crate::types::StatisticsCookie;
|
use crate::types::StatisticsCookie;
|
||||||
use crate::types::StrikeThrough;
|
use crate::types::StrikeThrough;
|
||||||
@@ -60,25 +63,92 @@ use crate::types::Verbatim;
|
|||||||
use crate::types::VerseBlock;
|
use crate::types::VerseBlock;
|
||||||
|
|
||||||
pub(crate) trait ElispFact<'s> {
|
pub(crate) trait ElispFact<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str>;
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) trait GetElispFact<'s> {
|
pub(crate) trait GetElispFact<'s> {
|
||||||
fn get_elisp_fact(&'s self) -> &'s dyn ElispFact<'s>;
|
fn get_elisp_fact<'b>(&'b self) -> &'b dyn ElispFact<'s>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s, I: ElispFact<'s>> GetElispFact<'s> for I {
|
impl<'s, I: ElispFact<'s>> GetElispFact<'s> for I {
|
||||||
fn get_elisp_fact(&'s self) -> &'s dyn ElispFact<'s> {
|
fn get_elisp_fact<'b>(&'b self) -> &'b dyn ElispFact<'s> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'r, 's> GetElispFact<'s> for AstNode<'r, 's> {
|
||||||
|
fn get_elisp_fact<'b>(&'b self) -> &'b dyn ElispFact<'s> {
|
||||||
|
match self {
|
||||||
|
AstNode::Document(inner) => *inner,
|
||||||
|
AstNode::Heading(inner) => *inner,
|
||||||
|
AstNode::Section(inner) => *inner,
|
||||||
|
AstNode::Paragraph(inner) => *inner,
|
||||||
|
AstNode::PlainList(inner) => *inner,
|
||||||
|
AstNode::PlainListItem(inner) => *inner,
|
||||||
|
AstNode::CenterBlock(inner) => *inner,
|
||||||
|
AstNode::QuoteBlock(inner) => *inner,
|
||||||
|
AstNode::SpecialBlock(inner) => *inner,
|
||||||
|
AstNode::DynamicBlock(inner) => *inner,
|
||||||
|
AstNode::FootnoteDefinition(inner) => *inner,
|
||||||
|
AstNode::Comment(inner) => *inner,
|
||||||
|
AstNode::Drawer(inner) => *inner,
|
||||||
|
AstNode::PropertyDrawer(inner) => *inner,
|
||||||
|
AstNode::NodeProperty(inner) => *inner,
|
||||||
|
AstNode::Table(inner) => *inner,
|
||||||
|
AstNode::TableRow(inner) => *inner,
|
||||||
|
AstNode::VerseBlock(inner) => *inner,
|
||||||
|
AstNode::CommentBlock(inner) => *inner,
|
||||||
|
AstNode::ExampleBlock(inner) => *inner,
|
||||||
|
AstNode::ExportBlock(inner) => *inner,
|
||||||
|
AstNode::SrcBlock(inner) => *inner,
|
||||||
|
AstNode::Clock(inner) => *inner,
|
||||||
|
AstNode::DiarySexp(inner) => *inner,
|
||||||
|
AstNode::Planning(inner) => *inner,
|
||||||
|
AstNode::FixedWidthArea(inner) => *inner,
|
||||||
|
AstNode::HorizontalRule(inner) => *inner,
|
||||||
|
AstNode::Keyword(inner) => *inner,
|
||||||
|
AstNode::BabelCall(inner) => *inner,
|
||||||
|
AstNode::LatexEnvironment(inner) => *inner,
|
||||||
|
AstNode::Bold(inner) => *inner,
|
||||||
|
AstNode::Italic(inner) => *inner,
|
||||||
|
AstNode::Underline(inner) => *inner,
|
||||||
|
AstNode::StrikeThrough(inner) => *inner,
|
||||||
|
AstNode::Code(inner) => *inner,
|
||||||
|
AstNode::Verbatim(inner) => *inner,
|
||||||
|
AstNode::PlainText(inner) => *inner,
|
||||||
|
AstNode::RegularLink(inner) => *inner,
|
||||||
|
AstNode::RadioLink(inner) => *inner,
|
||||||
|
AstNode::RadioTarget(inner) => *inner,
|
||||||
|
AstNode::PlainLink(inner) => *inner,
|
||||||
|
AstNode::AngleLink(inner) => *inner,
|
||||||
|
AstNode::OrgMacro(inner) => *inner,
|
||||||
|
AstNode::Entity(inner) => *inner,
|
||||||
|
AstNode::LatexFragment(inner) => *inner,
|
||||||
|
AstNode::ExportSnippet(inner) => *inner,
|
||||||
|
AstNode::FootnoteReference(inner) => *inner,
|
||||||
|
AstNode::Citation(inner) => *inner,
|
||||||
|
AstNode::CitationReference(inner) => *inner,
|
||||||
|
AstNode::InlineBabelCall(inner) => *inner,
|
||||||
|
AstNode::InlineSourceBlock(inner) => *inner,
|
||||||
|
AstNode::LineBreak(inner) => *inner,
|
||||||
|
AstNode::Target(inner) => *inner,
|
||||||
|
AstNode::StatisticsCookie(inner) => *inner,
|
||||||
|
AstNode::Subscript(inner) => *inner,
|
||||||
|
AstNode::Superscript(inner) => *inner,
|
||||||
|
AstNode::TableCell(inner) => *inner,
|
||||||
|
AstNode::Timestamp(inner) => *inner,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'s> GetElispFact<'s> for Element<'s> {
|
impl<'s> GetElispFact<'s> for Element<'s> {
|
||||||
fn get_elisp_fact(&'s self) -> &'s dyn ElispFact<'s> {
|
fn get_elisp_fact<'b>(&'b self) -> &'b dyn ElispFact<'s> {
|
||||||
match self {
|
match self {
|
||||||
Element::Paragraph(inner) => inner,
|
Element::Paragraph(inner) => inner,
|
||||||
Element::PlainList(inner) => inner,
|
Element::PlainList(inner) => inner,
|
||||||
Element::GreaterBlock(inner) => inner,
|
Element::CenterBlock(inner) => inner,
|
||||||
|
Element::QuoteBlock(inner) => inner,
|
||||||
|
Element::SpecialBlock(inner) => inner,
|
||||||
Element::DynamicBlock(inner) => inner,
|
Element::DynamicBlock(inner) => inner,
|
||||||
Element::FootnoteDefinition(inner) => inner,
|
Element::FootnoteDefinition(inner) => inner,
|
||||||
Element::Comment(inner) => inner,
|
Element::Comment(inner) => inner,
|
||||||
@@ -103,7 +173,7 @@ impl<'s> GetElispFact<'s> for Element<'s> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> GetElispFact<'s> for Object<'s> {
|
impl<'s> GetElispFact<'s> for Object<'s> {
|
||||||
fn get_elisp_fact(&'s self) -> &'s dyn ElispFact<'s> {
|
fn get_elisp_fact<'b>(&'b self) -> &'b dyn ElispFact<'s> {
|
||||||
match self {
|
match self {
|
||||||
Object::Bold(inner) => inner,
|
Object::Bold(inner) => inner,
|
||||||
Object::Italic(inner) => inner,
|
Object::Italic(inner) => inner,
|
||||||
@@ -137,337 +207,345 @@ impl<'s> GetElispFact<'s> for Object<'s> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for Document<'s> {
|
impl<'s> ElispFact<'s> for Document<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"org-data".into()
|
"org-data".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for Section<'s> {
|
impl<'s> ElispFact<'s> for Section<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"section".into()
|
"section".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for Heading<'s> {
|
impl<'s> ElispFact<'s> for Heading<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"headline".into()
|
"headline".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for PlainList<'s> {
|
impl<'s> ElispFact<'s> for PlainList<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"plain-list".into()
|
"plain-list".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for PlainListItem<'s> {
|
impl<'s> ElispFact<'s> for PlainListItem<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"item".into()
|
"item".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for GreaterBlock<'s> {
|
impl<'s> ElispFact<'s> for CenterBlock<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
match self.name.to_lowercase().as_str() {
|
"center-block".into()
|
||||||
"center" => "center-block".into(),
|
}
|
||||||
"quote" => "quote-block".into(),
|
}
|
||||||
_ => "special-block".into(),
|
|
||||||
}
|
impl<'s> ElispFact<'s> for QuoteBlock<'s> {
|
||||||
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
|
"quote-block".into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'s> ElispFact<'s> for SpecialBlock<'s> {
|
||||||
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
|
"special-block".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for DynamicBlock<'s> {
|
impl<'s> ElispFact<'s> for DynamicBlock<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"dynamic-block".into()
|
"dynamic-block".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for FootnoteDefinition<'s> {
|
impl<'s> ElispFact<'s> for FootnoteDefinition<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"footnote-definition".into()
|
"footnote-definition".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for Drawer<'s> {
|
impl<'s> ElispFact<'s> for Drawer<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"drawer".into()
|
"drawer".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for PropertyDrawer<'s> {
|
impl<'s> ElispFact<'s> for PropertyDrawer<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"property-drawer".into()
|
"property-drawer".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for NodeProperty<'s> {
|
impl<'s> ElispFact<'s> for NodeProperty<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"node-property".into()
|
"node-property".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for Table<'s> {
|
impl<'s> ElispFact<'s> for Table<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"table".into()
|
"table".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for TableRow<'s> {
|
impl<'s> ElispFact<'s> for TableRow<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"table-row".into()
|
"table-row".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for Paragraph<'s> {
|
impl<'s> ElispFact<'s> for Paragraph<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"paragraph".into()
|
"paragraph".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for TableCell<'s> {
|
impl<'s> ElispFact<'s> for TableCell<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"table-cell".into()
|
"table-cell".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for Comment<'s> {
|
impl<'s> ElispFact<'s> for Comment<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"comment".into()
|
"comment".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for VerseBlock<'s> {
|
impl<'s> ElispFact<'s> for VerseBlock<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"verse-block".into()
|
"verse-block".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<'s> ElispFact<'s> for CommentBlock<'s> {
|
impl<'s> ElispFact<'s> for CommentBlock<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"comment-block".into()
|
"comment-block".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<'s> ElispFact<'s> for ExampleBlock<'s> {
|
impl<'s> ElispFact<'s> for ExampleBlock<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"example-block".into()
|
"example-block".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<'s> ElispFact<'s> for ExportBlock<'s> {
|
impl<'s> ElispFact<'s> for ExportBlock<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"export-block".into()
|
"export-block".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<'s> ElispFact<'s> for SrcBlock<'s> {
|
impl<'s> ElispFact<'s> for SrcBlock<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"src-block".into()
|
"src-block".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for Clock<'s> {
|
impl<'s> ElispFact<'s> for Clock<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"clock".into()
|
"clock".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for DiarySexp<'s> {
|
impl<'s> ElispFact<'s> for DiarySexp<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"diary-sexp".into()
|
"diary-sexp".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for Planning<'s> {
|
impl<'s> ElispFact<'s> for Planning<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"planning".into()
|
"planning".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for FixedWidthArea<'s> {
|
impl<'s> ElispFact<'s> for FixedWidthArea<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"fixed-width".into()
|
"fixed-width".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for HorizontalRule<'s> {
|
impl<'s> ElispFact<'s> for HorizontalRule<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"horizontal-rule".into()
|
"horizontal-rule".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for Keyword<'s> {
|
impl<'s> ElispFact<'s> for Keyword<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"keyword".into()
|
"keyword".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for BabelCall<'s> {
|
impl<'s> ElispFact<'s> for BabelCall<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"babel-call".into()
|
"babel-call".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for LatexEnvironment<'s> {
|
impl<'s> ElispFact<'s> for LatexEnvironment<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"latex-environment".into()
|
"latex-environment".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for Bold<'s> {
|
impl<'s> ElispFact<'s> for Bold<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"bold".into()
|
"bold".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for Italic<'s> {
|
impl<'s> ElispFact<'s> for Italic<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"italic".into()
|
"italic".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for Underline<'s> {
|
impl<'s> ElispFact<'s> for Underline<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"underline".into()
|
"underline".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for StrikeThrough<'s> {
|
impl<'s> ElispFact<'s> for StrikeThrough<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"strike-through".into()
|
"strike-through".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for Code<'s> {
|
impl<'s> ElispFact<'s> for Code<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"code".into()
|
"code".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for Verbatim<'s> {
|
impl<'s> ElispFact<'s> for Verbatim<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"verbatim".into()
|
"verbatim".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for RegularLink<'s> {
|
impl<'s> ElispFact<'s> for RegularLink<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"link".into()
|
"link".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for RadioLink<'s> {
|
impl<'s> ElispFact<'s> for RadioLink<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"link".into()
|
"link".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for RadioTarget<'s> {
|
impl<'s> ElispFact<'s> for RadioTarget<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"radio-target".into()
|
"radio-target".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for PlainLink<'s> {
|
impl<'s> ElispFact<'s> for PlainLink<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"link".into()
|
"link".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for AngleLink<'s> {
|
impl<'s> ElispFact<'s> for AngleLink<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"link".into()
|
"link".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for OrgMacro<'s> {
|
impl<'s> ElispFact<'s> for OrgMacro<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"macro".into()
|
"macro".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for Entity<'s> {
|
impl<'s> ElispFact<'s> for Entity<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"entity".into()
|
"entity".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for LatexFragment<'s> {
|
impl<'s> ElispFact<'s> for LatexFragment<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"latex-fragment".into()
|
"latex-fragment".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for ExportSnippet<'s> {
|
impl<'s> ElispFact<'s> for ExportSnippet<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"export-snippet".into()
|
"export-snippet".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for FootnoteReference<'s> {
|
impl<'s> ElispFact<'s> for FootnoteReference<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"footnote-reference".into()
|
"footnote-reference".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for Citation<'s> {
|
impl<'s> ElispFact<'s> for Citation<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"citation".into()
|
"citation".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for CitationReference<'s> {
|
impl<'s> ElispFact<'s> for CitationReference<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"citation-reference".into()
|
"citation-reference".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for InlineBabelCall<'s> {
|
impl<'s> ElispFact<'s> for InlineBabelCall<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"inline-babel-call".into()
|
"inline-babel-call".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for InlineSourceBlock<'s> {
|
impl<'s> ElispFact<'s> for InlineSourceBlock<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"inline-src-block".into()
|
"inline-src-block".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for LineBreak<'s> {
|
impl<'s> ElispFact<'s> for LineBreak<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"line-break".into()
|
"line-break".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for Target<'s> {
|
impl<'s> ElispFact<'s> for Target<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"target".into()
|
"target".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for StatisticsCookie<'s> {
|
impl<'s> ElispFact<'s> for StatisticsCookie<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"statistics-cookie".into()
|
"statistics-cookie".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for Subscript<'s> {
|
impl<'s> ElispFact<'s> for Subscript<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"subscript".into()
|
"subscript".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for Superscript<'s> {
|
impl<'s> ElispFact<'s> for Superscript<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"superscript".into()
|
"superscript".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for Timestamp<'s> {
|
impl<'s> ElispFact<'s> for Timestamp<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
"timestamp".into()
|
"timestamp".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> ElispFact<'s> for PlainText<'s> {
|
impl<'s> ElispFact<'s> for PlainText<'s> {
|
||||||
fn get_elisp_name(&'s self) -> Cow<'s, str> {
|
fn get_elisp_name<'b>(&'b self) -> Cow<'s, str> {
|
||||||
// plain text from upstream emacs does not actually have a name but this is included here to make rendering the status diff easier.
|
// plain text from upstream emacs does not actually have a name but this is included here to make rendering the status diff easier.
|
||||||
"plain-text".into()
|
"plain-text".into()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
use super::elisp_fact::GetElispFact;
|
use super::elisp_fact::GetElispFact;
|
||||||
use super::sexp::Token;
|
use super::sexp::Token;
|
||||||
use crate::compare::sexp::unquote;
|
use crate::compare::sexp::unquote;
|
||||||
@@ -16,9 +18,9 @@ fn is_slice_of(parent: &str, child: &str) -> bool {
|
|||||||
/// Get the byte offset into source that the rust object exists at.
|
/// Get the byte offset into source that the rust object exists at.
|
||||||
///
|
///
|
||||||
/// These offsets are zero-based unlike the elisp ones.
|
/// These offsets are zero-based unlike the elisp ones.
|
||||||
fn get_rust_byte_offsets<'s, S: StandardProperties<'s> + ?Sized>(
|
fn get_rust_byte_offsets<'b, 's, S: StandardProperties<'s> + ?Sized>(
|
||||||
original_document: &'s str,
|
original_document: &'s str,
|
||||||
rust_ast_node: &'s S,
|
rust_ast_node: &'b S,
|
||||||
) -> (usize, usize) {
|
) -> (usize, usize) {
|
||||||
let rust_object_source = rust_ast_node.get_source();
|
let rust_object_source = rust_ast_node.get_source();
|
||||||
debug_assert!(is_slice_of(original_document, rust_object_source));
|
debug_assert!(is_slice_of(original_document, rust_object_source));
|
||||||
@@ -28,20 +30,21 @@ fn get_rust_byte_offsets<'s, S: StandardProperties<'s> + ?Sized>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn compare_standard_properties<
|
pub(crate) fn compare_standard_properties<
|
||||||
|
'b,
|
||||||
's,
|
's,
|
||||||
S: GetStandardProperties<'s> + GetElispFact<'s> + ?Sized,
|
S: GetStandardProperties<'s> + GetElispFact<'s> + ?Sized,
|
||||||
>(
|
>(
|
||||||
original_document: &'s str,
|
original_document: &'s str,
|
||||||
emacs: &'s Token<'s>,
|
emacs: &'b Token<'s>,
|
||||||
rust: &'s S,
|
rust: &'b S,
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
assert_name(emacs, rust.get_elisp_fact().get_elisp_name())?;
|
assert_name(emacs, rust.get_elisp_fact().get_elisp_name())?;
|
||||||
assert_bounds(original_document, emacs, rust.get_standard_properties())?;
|
assert_bounds(original_document, emacs, rust.get_standard_properties())?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn assert_name<'s, S: AsRef<str>>(
|
pub(crate) fn assert_name<'b, 's, S: AsRef<str>>(
|
||||||
emacs: &'s Token<'s>,
|
emacs: &'b Token<'s>,
|
||||||
name: S,
|
name: S,
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let name = name.as_ref();
|
let name = name.as_ref();
|
||||||
@@ -63,10 +66,10 @@ pub(crate) fn assert_name<'s, S: AsRef<str>>(
|
|||||||
/// Assert that the character ranges defined by upstream org-mode's :standard-properties match the slices in Organic's StandardProperties.
|
/// Assert that the character ranges defined by upstream org-mode's :standard-properties match the slices in Organic's StandardProperties.
|
||||||
///
|
///
|
||||||
/// This does **not** handle plain text because plain text is a special case.
|
/// This does **not** handle plain text because plain text is a special case.
|
||||||
pub(crate) fn assert_bounds<'s, S: StandardProperties<'s> + ?Sized>(
|
pub(crate) fn assert_bounds<'b, 's, S: StandardProperties<'s> + ?Sized>(
|
||||||
original_document: &'s str,
|
original_document: &'s str,
|
||||||
emacs: &'s Token<'s>,
|
emacs: &'b Token<'s>,
|
||||||
rust: &'s S,
|
rust: &'b S,
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let standard_properties = get_emacs_standard_properties(emacs)?; // 1-based
|
let standard_properties = get_emacs_standard_properties(emacs)?; // 1-based
|
||||||
let (begin, end) = (
|
let (begin, end) = (
|
||||||
@@ -99,8 +102,8 @@ struct EmacsStandardProperties {
|
|||||||
post_blank: Option<usize>,
|
post_blank: Option<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_emacs_standard_properties<'s>(
|
fn get_emacs_standard_properties<'b, 's>(
|
||||||
emacs: &'s Token<'s>,
|
emacs: &'b Token<'s>,
|
||||||
) -> Result<EmacsStandardProperties, Box<dyn std::error::Error>> {
|
) -> Result<EmacsStandardProperties, Box<dyn std::error::Error>> {
|
||||||
let children = emacs.as_list()?;
|
let children = emacs.as_list()?;
|
||||||
let attributes_child = children
|
let attributes_child = children
|
||||||
@@ -169,34 +172,30 @@ fn maybe_token_to_usize(
|
|||||||
|
|
||||||
/// Get a named property from the emacs token.
|
/// Get a named property from the emacs token.
|
||||||
///
|
///
|
||||||
/// Returns Ok(None) if value is nil.
|
/// Returns Ok(None) if value is nil or absent.
|
||||||
///
|
pub(crate) fn get_property<'b, 's, 'x>(
|
||||||
/// Returns error if the attribute is not specified on the token at all.
|
emacs: &'b Token<'s>,
|
||||||
pub(crate) fn get_property<'s, 'x>(
|
|
||||||
emacs: &'s Token<'s>,
|
|
||||||
key: &'x str,
|
key: &'x str,
|
||||||
) -> Result<Option<&'s Token<'s>>, Box<dyn std::error::Error>> {
|
) -> Result<Option<&'b Token<'s>>, Box<dyn std::error::Error>> {
|
||||||
let children = emacs.as_list()?;
|
let children = emacs.as_list()?;
|
||||||
let attributes_child = children
|
let attributes_child = children
|
||||||
.iter()
|
.iter()
|
||||||
.nth(1)
|
.nth(1)
|
||||||
.ok_or("Should have an attributes child.")?;
|
.ok_or("Should have an attributes child.")?;
|
||||||
let attributes_map = attributes_child.as_map()?;
|
let attributes_map = attributes_child.as_map()?;
|
||||||
let prop = attributes_map
|
let prop = attributes_map.get(key).map(|token| *token);
|
||||||
.get(key)
|
match prop.map(|token| token.as_atom()) {
|
||||||
.ok_or(format!("Missing {} attribute.", key))?;
|
Some(Ok("nil")) => return Ok(None),
|
||||||
match prop.as_atom() {
|
|
||||||
Ok("nil") => return Ok(None),
|
|
||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
Ok(Some(*prop))
|
Ok(prop)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a named property containing an unquoted atom from the emacs token.
|
/// Get a named property containing an unquoted atom from the emacs token.
|
||||||
///
|
///
|
||||||
/// Returns None if key is not found.
|
/// Returns None if key is not found.
|
||||||
pub(crate) fn get_property_unquoted_atom<'s, 'x>(
|
pub(crate) fn get_property_unquoted_atom<'b, 's, 'x>(
|
||||||
emacs: &'s Token<'s>,
|
emacs: &'b Token<'s>,
|
||||||
key: &'x str,
|
key: &'x str,
|
||||||
) -> Result<Option<&'s str>, Box<dyn std::error::Error>> {
|
) -> Result<Option<&'s str>, Box<dyn std::error::Error>> {
|
||||||
Ok(get_property(emacs, key)?
|
Ok(get_property(emacs, key)?
|
||||||
@@ -207,8 +206,8 @@ pub(crate) fn get_property_unquoted_atom<'s, 'x>(
|
|||||||
/// Get a named property containing an quoted string from the emacs token.
|
/// Get a named property containing an quoted string from the emacs token.
|
||||||
///
|
///
|
||||||
/// Returns None if key is not found.
|
/// Returns None if key is not found.
|
||||||
pub(crate) fn get_property_quoted_string<'s, 'x>(
|
pub(crate) fn get_property_quoted_string<'b, 's, 'x>(
|
||||||
emacs: &'s Token<'s>,
|
emacs: &'b Token<'s>,
|
||||||
key: &'x str,
|
key: &'x str,
|
||||||
) -> Result<Option<String>, Box<dyn std::error::Error>> {
|
) -> Result<Option<String>, Box<dyn std::error::Error>> {
|
||||||
Ok(get_property(emacs, key)?
|
Ok(get_property(emacs, key)?
|
||||||
@@ -223,8 +222,8 @@ pub(crate) fn get_property_quoted_string<'s, 'x>(
|
|||||||
/// This uses the elisp convention of nil == false, non-nil == true.
|
/// This uses the elisp convention of nil == false, non-nil == true.
|
||||||
///
|
///
|
||||||
/// Returns false if key is not found.
|
/// Returns false if key is not found.
|
||||||
pub(crate) fn get_property_boolean<'s, 'x>(
|
pub(crate) fn get_property_boolean<'b, 's, 'x>(
|
||||||
emacs: &'s Token<'s>,
|
emacs: &'b Token<'s>,
|
||||||
key: &'x str,
|
key: &'x str,
|
||||||
) -> Result<bool, Box<dyn std::error::Error>> {
|
) -> Result<bool, Box<dyn std::error::Error>> {
|
||||||
Ok(get_property(emacs, key)?
|
Ok(get_property(emacs, key)?
|
||||||
@@ -233,3 +232,23 @@ pub(crate) fn get_property_boolean<'s, 'x>(
|
|||||||
.unwrap_or("nil")
|
.unwrap_or("nil")
|
||||||
!= "nil")
|
!= "nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get a named property containing an unquoted numeric value.
|
||||||
|
///
|
||||||
|
/// Returns None if key is not found.
|
||||||
|
pub(crate) fn get_property_numeric<'b, 's, 'x, N: FromStr>(
|
||||||
|
emacs: &'b Token<'s>,
|
||||||
|
key: &'x str,
|
||||||
|
) -> Result<Option<N>, Box<dyn std::error::Error + 's>>
|
||||||
|
where
|
||||||
|
<N as FromStr>::Err: std::error::Error,
|
||||||
|
<N as FromStr>::Err: 's,
|
||||||
|
{
|
||||||
|
let unparsed_string = get_property(emacs, key)?
|
||||||
|
.map(Token::as_atom)
|
||||||
|
.map_or(Ok(None), |r| r.map(Some))?;
|
||||||
|
let parsed_number = unparsed_string
|
||||||
|
.map(|val| val.parse::<N>())
|
||||||
|
.map_or(Ok(None), |r| r.map(Some))?;
|
||||||
|
Ok(parsed_number)
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ pub enum CustomError<I> {
|
|||||||
MyError(MyError<&'static str>),
|
MyError(MyError<&'static str>),
|
||||||
Nom(I, ErrorKind),
|
Nom(I, ErrorKind),
|
||||||
IO(std::io::Error),
|
IO(std::io::Error),
|
||||||
|
BoxedError(Box<dyn std::error::Error>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -36,3 +37,9 @@ impl<I> From<&'static str> for CustomError<I> {
|
|||||||
CustomError::MyError(MyError(value))
|
CustomError::MyError(MyError(value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<I> From<Box<dyn std::error::Error>> for CustomError<I> {
|
||||||
|
fn from(value: Box<dyn std::error::Error>) -> Self {
|
||||||
|
CustomError::BoxedError(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
use super::ast_node::AstNode;
|
|
||||||
use super::ast_node_iter::AstNodeIter;
|
use super::ast_node_iter::AstNodeIter;
|
||||||
|
use crate::types::AstNode;
|
||||||
|
|
||||||
pub struct AllAstNodeIter<'r, 's> {
|
pub struct AllAstNodeIter<'r, 's> {
|
||||||
root: Option<AstNode<'r, 's>>,
|
root: Option<AstNode<'r, 's>>,
|
||||||
@@ -24,7 +24,9 @@ impl<'r, 's> Iterator for AllAstNodeIter<'r, 's> {
|
|||||||
AstNodeIter::Paragraph(ref mut i) => i.next(),
|
AstNodeIter::Paragraph(ref mut i) => i.next(),
|
||||||
AstNodeIter::PlainList(ref mut i) => i.next(),
|
AstNodeIter::PlainList(ref mut i) => i.next(),
|
||||||
AstNodeIter::PlainListItem(ref mut i) => i.next(),
|
AstNodeIter::PlainListItem(ref mut i) => i.next(),
|
||||||
AstNodeIter::GreaterBlock(ref mut i) => i.next(),
|
AstNodeIter::CenterBlock(ref mut i) => i.next(),
|
||||||
|
AstNodeIter::QuoteBlock(ref mut i) => i.next(),
|
||||||
|
AstNodeIter::SpecialBlock(ref mut i) => i.next(),
|
||||||
AstNodeIter::DynamicBlock(ref mut i) => i.next(),
|
AstNodeIter::DynamicBlock(ref mut i) => i.next(),
|
||||||
AstNodeIter::FootnoteDefinition(ref mut i) => i.next(),
|
AstNodeIter::FootnoteDefinition(ref mut i) => i.next(),
|
||||||
AstNodeIter::Comment(ref mut i) => i.next(),
|
AstNodeIter::Comment(ref mut i) => i.next(),
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use super::ast_node::AstNode;
|
|
||||||
use super::macros::children_iter;
|
use super::macros::children_iter;
|
||||||
use super::macros::empty_iter;
|
use super::macros::empty_iter;
|
||||||
use super::macros::multi_field_iter;
|
use super::macros::multi_field_iter;
|
||||||
use crate::types::AngleLink;
|
use crate::types::AngleLink;
|
||||||
|
use crate::types::AstNode;
|
||||||
use crate::types::BabelCall;
|
use crate::types::BabelCall;
|
||||||
use crate::types::Bold;
|
use crate::types::Bold;
|
||||||
|
use crate::types::CenterBlock;
|
||||||
use crate::types::Citation;
|
use crate::types::Citation;
|
||||||
use crate::types::CitationReference;
|
use crate::types::CitationReference;
|
||||||
use crate::types::Clock;
|
use crate::types::Clock;
|
||||||
@@ -26,7 +27,6 @@ use crate::types::ExportSnippet;
|
|||||||
use crate::types::FixedWidthArea;
|
use crate::types::FixedWidthArea;
|
||||||
use crate::types::FootnoteDefinition;
|
use crate::types::FootnoteDefinition;
|
||||||
use crate::types::FootnoteReference;
|
use crate::types::FootnoteReference;
|
||||||
use crate::types::GreaterBlock;
|
|
||||||
use crate::types::Heading;
|
use crate::types::Heading;
|
||||||
use crate::types::HorizontalRule;
|
use crate::types::HorizontalRule;
|
||||||
use crate::types::InlineBabelCall;
|
use crate::types::InlineBabelCall;
|
||||||
@@ -46,10 +46,12 @@ use crate::types::PlainListItem;
|
|||||||
use crate::types::PlainText;
|
use crate::types::PlainText;
|
||||||
use crate::types::Planning;
|
use crate::types::Planning;
|
||||||
use crate::types::PropertyDrawer;
|
use crate::types::PropertyDrawer;
|
||||||
|
use crate::types::QuoteBlock;
|
||||||
use crate::types::RadioLink;
|
use crate::types::RadioLink;
|
||||||
use crate::types::RadioTarget;
|
use crate::types::RadioTarget;
|
||||||
use crate::types::RegularLink;
|
use crate::types::RegularLink;
|
||||||
use crate::types::Section;
|
use crate::types::Section;
|
||||||
|
use crate::types::SpecialBlock;
|
||||||
use crate::types::SrcBlock;
|
use crate::types::SrcBlock;
|
||||||
use crate::types::StatisticsCookie;
|
use crate::types::StatisticsCookie;
|
||||||
use crate::types::StrikeThrough;
|
use crate::types::StrikeThrough;
|
||||||
@@ -78,7 +80,9 @@ pub(crate) enum AstNodeIter<'r, 's> {
|
|||||||
Paragraph(ParagraphIter<'r, 's>),
|
Paragraph(ParagraphIter<'r, 's>),
|
||||||
PlainList(PlainListIter<'r, 's>),
|
PlainList(PlainListIter<'r, 's>),
|
||||||
PlainListItem(PlainListItemIter<'r, 's>),
|
PlainListItem(PlainListItemIter<'r, 's>),
|
||||||
GreaterBlock(GreaterBlockIter<'r, 's>),
|
CenterBlock(CenterBlockIter<'r, 's>),
|
||||||
|
QuoteBlock(QuoteBlockIter<'r, 's>),
|
||||||
|
SpecialBlock(SpecialBlockIter<'r, 's>),
|
||||||
DynamicBlock(DynamicBlockIter<'r, 's>),
|
DynamicBlock(DynamicBlockIter<'r, 's>),
|
||||||
FootnoteDefinition(FootnoteDefinitionIter<'r, 's>),
|
FootnoteDefinition(FootnoteDefinitionIter<'r, 's>),
|
||||||
Comment(CommentIter<'r, 's>),
|
Comment(CommentIter<'r, 's>),
|
||||||
@@ -140,7 +144,9 @@ impl<'r, 's> AstNodeIter<'r, 's> {
|
|||||||
AstNode::Paragraph(inner) => AstNodeIter::Paragraph(inner.into_iter()),
|
AstNode::Paragraph(inner) => AstNodeIter::Paragraph(inner.into_iter()),
|
||||||
AstNode::PlainList(inner) => AstNodeIter::PlainList(inner.into_iter()),
|
AstNode::PlainList(inner) => AstNodeIter::PlainList(inner.into_iter()),
|
||||||
AstNode::PlainListItem(inner) => AstNodeIter::PlainListItem(inner.into_iter()),
|
AstNode::PlainListItem(inner) => AstNodeIter::PlainListItem(inner.into_iter()),
|
||||||
AstNode::GreaterBlock(inner) => AstNodeIter::GreaterBlock(inner.into_iter()),
|
AstNode::CenterBlock(inner) => AstNodeIter::CenterBlock(inner.into_iter()),
|
||||||
|
AstNode::QuoteBlock(inner) => AstNodeIter::QuoteBlock(inner.into_iter()),
|
||||||
|
AstNode::SpecialBlock(inner) => AstNodeIter::SpecialBlock(inner.into_iter()),
|
||||||
AstNode::DynamicBlock(inner) => AstNodeIter::DynamicBlock(inner.into_iter()),
|
AstNode::DynamicBlock(inner) => AstNodeIter::DynamicBlock(inner.into_iter()),
|
||||||
AstNode::FootnoteDefinition(inner) => {
|
AstNode::FootnoteDefinition(inner) => {
|
||||||
AstNodeIter::FootnoteDefinition(inner.into_iter())
|
AstNodeIter::FootnoteDefinition(inner.into_iter())
|
||||||
@@ -232,8 +238,18 @@ multi_field_iter!(
|
|||||||
std::slice::Iter<'r, Element<'s>>
|
std::slice::Iter<'r, Element<'s>>
|
||||||
);
|
);
|
||||||
children_iter!(
|
children_iter!(
|
||||||
GreaterBlock<'s>,
|
CenterBlock<'s>,
|
||||||
GreaterBlockIter,
|
CenterBlockIter,
|
||||||
|
std::slice::Iter<'r, Element<'s>>
|
||||||
|
);
|
||||||
|
children_iter!(
|
||||||
|
QuoteBlock<'s>,
|
||||||
|
QuoteBlockIter,
|
||||||
|
std::slice::Iter<'r, Element<'s>>
|
||||||
|
);
|
||||||
|
children_iter!(
|
||||||
|
SpecialBlock<'s>,
|
||||||
|
SpecialBlockIter,
|
||||||
std::slice::Iter<'r, Element<'s>>
|
std::slice::Iter<'r, Element<'s>>
|
||||||
);
|
);
|
||||||
children_iter!(
|
children_iter!(
|
||||||
|
|||||||
@@ -1,16 +1,3 @@
|
|||||||
/// Write the implementation of From<> to convert a borrow of the type to an AstNode
|
|
||||||
macro_rules! to_ast_node {
|
|
||||||
($inp:ty, $enum:expr) => {
|
|
||||||
impl<'r, 's> From<$inp> for AstNode<'r, 's> {
|
|
||||||
fn from(value: $inp) -> Self {
|
|
||||||
$enum(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) use to_ast_node;
|
|
||||||
|
|
||||||
/// Create iterators for ast nodes where it only has to iterate over children
|
/// Create iterators for ast nodes where it only has to iterate over children
|
||||||
macro_rules! children_iter {
|
macro_rules! children_iter {
|
||||||
($astnodetype:ty, $itertype:ident, $innertype:ty) => {
|
($astnodetype:ty, $itertype:ident, $innertype:ty) => {
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
mod all_ast_node_iter;
|
mod all_ast_node_iter;
|
||||||
mod ast_node;
|
|
||||||
mod ast_node_iter;
|
mod ast_node_iter;
|
||||||
mod macros;
|
mod macros;
|
||||||
pub(crate) use ast_node::AstNode;
|
|
||||||
|
|||||||
@@ -1,18 +1,19 @@
|
|||||||
use nom::branch::alt;
|
use nom::branch::alt;
|
||||||
use nom::bytes::complete::is_not;
|
|
||||||
use nom::bytes::complete::tag;
|
use nom::bytes::complete::tag;
|
||||||
|
use nom::character::complete::anychar;
|
||||||
use nom::character::complete::line_ending;
|
use nom::character::complete::line_ending;
|
||||||
use nom::character::complete::space0;
|
use nom::character::complete::space0;
|
||||||
use nom::character::complete::space1;
|
|
||||||
use nom::combinator::eof;
|
use nom::combinator::eof;
|
||||||
use nom::combinator::not;
|
use nom::combinator::not;
|
||||||
use nom::combinator::opt;
|
use nom::combinator::recognize;
|
||||||
use nom::multi::many0;
|
use nom::multi::many0;
|
||||||
|
use nom::multi::many_till;
|
||||||
use nom::sequence::preceded;
|
use nom::sequence::preceded;
|
||||||
use nom::sequence::tuple;
|
use nom::sequence::tuple;
|
||||||
|
|
||||||
use super::org_source::OrgSource;
|
use super::org_source::OrgSource;
|
||||||
use super::util::get_consumed;
|
use super::util::get_consumed;
|
||||||
|
use super::util::org_line_ending;
|
||||||
use crate::context::parser_with_context;
|
use crate::context::parser_with_context;
|
||||||
use crate::context::ContextElement;
|
use crate::context::ContextElement;
|
||||||
use crate::context::RefContext;
|
use crate::context::RefContext;
|
||||||
@@ -38,15 +39,29 @@ pub(crate) fn comment<'b, 'g, 'r, 's>(
|
|||||||
let parser_context = context.with_additional_node(&parser_context);
|
let parser_context = context.with_additional_node(&parser_context);
|
||||||
let comment_line_matcher = parser_with_context!(comment_line)(&parser_context);
|
let comment_line_matcher = parser_with_context!(comment_line)(&parser_context);
|
||||||
let exit_matcher = parser_with_context!(exit_matcher_parser)(&parser_context);
|
let exit_matcher = parser_with_context!(exit_matcher_parser)(&parser_context);
|
||||||
let (remaining, _first_line) = comment_line_matcher(input)?;
|
let (remaining, first_line) = comment_line_matcher(input)?;
|
||||||
let (remaining, _remaining_lines) =
|
let (remaining, mut remaining_lines) =
|
||||||
many0(preceded(not(exit_matcher), comment_line_matcher))(remaining)?;
|
many0(preceded(not(exit_matcher), comment_line_matcher))(remaining)?;
|
||||||
|
|
||||||
let source = get_consumed(input, remaining);
|
let source = get_consumed(input, remaining);
|
||||||
|
let mut value = Vec::with_capacity(remaining_lines.len() + 1);
|
||||||
|
let last_line = remaining_lines.pop();
|
||||||
|
if let Some(last_line) = last_line {
|
||||||
|
value.push(Into::<&str>::into(first_line));
|
||||||
|
value.extend(remaining_lines.into_iter().map(Into::<&str>::into));
|
||||||
|
let last_line = Into::<&str>::into(last_line);
|
||||||
|
// Trim the line ending from the final line.
|
||||||
|
value.push(&last_line[..(last_line.len() - 1)])
|
||||||
|
} else {
|
||||||
|
// Trim the line ending from the only line.
|
||||||
|
let only_line = Into::<&str>::into(first_line);
|
||||||
|
value.push(&only_line[..(only_line.len() - 1)])
|
||||||
|
}
|
||||||
Ok((
|
Ok((
|
||||||
remaining,
|
remaining,
|
||||||
Comment {
|
Comment {
|
||||||
source: source.into(),
|
source: source.into(),
|
||||||
|
value,
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@@ -57,14 +72,13 @@ fn comment_line<'b, 'g, 'r, 's>(
|
|||||||
input: OrgSource<'s>,
|
input: OrgSource<'s>,
|
||||||
) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
||||||
start_of_line(input)?;
|
start_of_line(input)?;
|
||||||
let (remaining, _indent) = space0(input)?;
|
let (remaining, _) = tuple((space0, tag("#")))(input)?;
|
||||||
let (remaining, (_hash, _leading_whitespace_and_content, _line_ending)) = tuple((
|
if let Ok((remaining, line_break)) = org_line_ending(remaining) {
|
||||||
tag("#"),
|
return Ok((remaining, line_break));
|
||||||
opt(tuple((space1, is_not("\r\n")))),
|
}
|
||||||
alt((line_ending, eof)),
|
let (remaining, _) = tag(" ")(remaining)?;
|
||||||
))(remaining)?;
|
let (remaining, value) = recognize(many_till(anychar, org_line_ending))(remaining)?;
|
||||||
let source = get_consumed(input, remaining);
|
Ok((remaining, value))
|
||||||
Ok((remaining, source))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||||
|
|||||||
@@ -20,9 +20,9 @@ use crate::context::RefContext;
|
|||||||
use crate::error::CustomError;
|
use crate::error::CustomError;
|
||||||
use crate::error::MyError;
|
use crate::error::MyError;
|
||||||
use crate::error::Res;
|
use crate::error::Res;
|
||||||
use crate::iter::AstNode;
|
|
||||||
use crate::parser::org_source::convert_error;
|
use crate::parser::org_source::convert_error;
|
||||||
use crate::parser::util::blank_line;
|
use crate::parser::util::blank_line;
|
||||||
|
use crate::types::AstNode;
|
||||||
use crate::types::Document;
|
use crate::types::Document;
|
||||||
use crate::types::Object;
|
use crate::types::Object;
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ use nom::branch::alt;
|
|||||||
use nom::bytes::complete::is_not;
|
use nom::bytes::complete::is_not;
|
||||||
use nom::bytes::complete::tag;
|
use nom::bytes::complete::tag;
|
||||||
use nom::bytes::complete::tag_no_case;
|
use nom::bytes::complete::tag_no_case;
|
||||||
|
use nom::character::complete::anychar;
|
||||||
use nom::character::complete::line_ending;
|
use nom::character::complete::line_ending;
|
||||||
use nom::character::complete::space0;
|
use nom::character::complete::space0;
|
||||||
use nom::character::complete::space1;
|
use nom::character::complete::space1;
|
||||||
@@ -9,6 +10,7 @@ use nom::combinator::consumed;
|
|||||||
use nom::combinator::eof;
|
use nom::combinator::eof;
|
||||||
use nom::combinator::not;
|
use nom::combinator::not;
|
||||||
use nom::combinator::opt;
|
use nom::combinator::opt;
|
||||||
|
use nom::combinator::peek;
|
||||||
use nom::combinator::recognize;
|
use nom::combinator::recognize;
|
||||||
use nom::multi::many0;
|
use nom::multi::many0;
|
||||||
use nom::multi::many_till;
|
use nom::multi::many_till;
|
||||||
@@ -47,10 +49,11 @@ pub(crate) fn dynamic_block<'b, 'g, 'r, 's>(
|
|||||||
}
|
}
|
||||||
start_of_line(input)?;
|
start_of_line(input)?;
|
||||||
let (remaining, _leading_whitespace) = space0(input)?;
|
let (remaining, _leading_whitespace) = space0(input)?;
|
||||||
let (remaining, (_begin, name, parameters, _ws)) = tuple((
|
let (remaining, (_, name, parameters, _, _)) = tuple((
|
||||||
recognize(tuple((tag_no_case("#+begin:"), space1))),
|
recognize(tuple((tag_no_case("#+begin:"), space1))),
|
||||||
name,
|
name,
|
||||||
opt(tuple((space1, parameters))),
|
opt(tuple((space1, parameters))),
|
||||||
|
space0,
|
||||||
line_ending,
|
line_ending,
|
||||||
))(remaining)?;
|
))(remaining)?;
|
||||||
let contexts = [
|
let contexts = [
|
||||||
@@ -108,7 +111,7 @@ fn name<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
|||||||
|
|
||||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||||
fn parameters<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
fn parameters<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
||||||
is_not("\r\n")(input)
|
recognize(many_till(anychar, peek(tuple((space0, line_ending)))))(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ fn _element<'b, 'g, 'r, 's>(
|
|||||||
let (remaining, mut affiliated_keywords) = many0(affiliated_keyword_matcher)(input)?;
|
let (remaining, mut affiliated_keywords) = many0(affiliated_keyword_matcher)(input)?;
|
||||||
let (remaining, mut element) = match alt((
|
let (remaining, mut element) = match alt((
|
||||||
map(plain_list_matcher, Element::PlainList),
|
map(plain_list_matcher, Element::PlainList),
|
||||||
map(greater_block_matcher, Element::GreaterBlock),
|
greater_block_matcher,
|
||||||
map(dynamic_block_matcher, Element::DynamicBlock),
|
map(dynamic_block_matcher, Element::DynamicBlock),
|
||||||
map(footnote_definition_matcher, Element::FootnoteDefinition),
|
map(footnote_definition_matcher, Element::FootnoteDefinition),
|
||||||
map(comment_matcher, Element::Comment),
|
map(comment_matcher, Element::Comment),
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
use nom::branch::alt;
|
use nom::branch::alt;
|
||||||
use nom::bytes::complete::is_not;
|
use nom::bytes::complete::is_not;
|
||||||
use nom::bytes::complete::tag_no_case;
|
use nom::bytes::complete::tag_no_case;
|
||||||
|
use nom::character::complete::anychar;
|
||||||
use nom::character::complete::line_ending;
|
use nom::character::complete::line_ending;
|
||||||
use nom::character::complete::space0;
|
use nom::character::complete::space0;
|
||||||
use nom::character::complete::space1;
|
use nom::character::complete::space1;
|
||||||
@@ -8,6 +9,8 @@ use nom::combinator::consumed;
|
|||||||
use nom::combinator::eof;
|
use nom::combinator::eof;
|
||||||
use nom::combinator::not;
|
use nom::combinator::not;
|
||||||
use nom::combinator::opt;
|
use nom::combinator::opt;
|
||||||
|
use nom::combinator::peek;
|
||||||
|
use nom::combinator::recognize;
|
||||||
use nom::combinator::verify;
|
use nom::combinator::verify;
|
||||||
use nom::multi::many0;
|
use nom::multi::many0;
|
||||||
use nom::multi::many_till;
|
use nom::multi::many_till;
|
||||||
@@ -30,17 +33,18 @@ use crate::parser::util::blank_line;
|
|||||||
use crate::parser::util::exit_matcher_parser;
|
use crate::parser::util::exit_matcher_parser;
|
||||||
use crate::parser::util::get_consumed;
|
use crate::parser::util::get_consumed;
|
||||||
use crate::parser::util::start_of_line;
|
use crate::parser::util::start_of_line;
|
||||||
|
use crate::types::CenterBlock;
|
||||||
use crate::types::Element;
|
use crate::types::Element;
|
||||||
use crate::types::GreaterBlock;
|
|
||||||
use crate::types::Paragraph;
|
use crate::types::Paragraph;
|
||||||
|
use crate::types::QuoteBlock;
|
||||||
use crate::types::SetSource;
|
use crate::types::SetSource;
|
||||||
|
use crate::types::SpecialBlock;
|
||||||
|
|
||||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||||
pub(crate) fn greater_block<'b, 'g, 'r, 's>(
|
pub(crate) fn greater_block<'b, 'g, 'r, 's>(
|
||||||
context: RefContext<'b, 'g, 'r, 's>,
|
context: RefContext<'b, 'g, 'r, 's>,
|
||||||
input: OrgSource<'s>,
|
input: OrgSource<'s>,
|
||||||
) -> Res<OrgSource<'s>, GreaterBlock<'s>> {
|
) -> Res<OrgSource<'s>, Element<'s>> {
|
||||||
// TODO: Do I need to differentiate between different greater block types.
|
|
||||||
start_of_line(input)?;
|
start_of_line(input)?;
|
||||||
let (remaining, _leading_whitespace) = space0(input)?;
|
let (remaining, _leading_whitespace) = space0(input)?;
|
||||||
let (remaining, (_begin, name)) = tuple((
|
let (remaining, (_begin, name)) = tuple((
|
||||||
@@ -52,22 +56,97 @@ pub(crate) fn greater_block<'b, 'g, 'r, 's>(
|
|||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
))(remaining)?;
|
))(remaining)?;
|
||||||
let context_name = match Into::<&str>::into(name).to_lowercase().as_str() {
|
let name = Into::<&str>::into(name);
|
||||||
"center" => "center block".to_owned(),
|
let (remaining, element) = match name.to_lowercase().as_str() {
|
||||||
"quote" => "quote block".to_owned(),
|
"center" => center_block(context, remaining, input)?,
|
||||||
name @ _ => format!("special block {}", name),
|
"quote" => quote_block(context, remaining, input)?,
|
||||||
|
_ => special_block(name)(context, remaining, input)?,
|
||||||
};
|
};
|
||||||
if in_section(context, context_name.as_str()) {
|
Ok((remaining, element))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||||
|
fn center_block<'b, 'g, 'r, 's>(
|
||||||
|
context: RefContext<'b, 'g, 'r, 's>,
|
||||||
|
input: OrgSource<'s>,
|
||||||
|
original_input: OrgSource<'s>,
|
||||||
|
) -> Res<OrgSource<'s>, Element<'s>> {
|
||||||
|
let (remaining, (source, children)) =
|
||||||
|
greater_block_body(context, input, original_input, "center", "center block")?;
|
||||||
|
Ok((
|
||||||
|
remaining,
|
||||||
|
Element::CenterBlock(CenterBlock { source, children }),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||||
|
fn quote_block<'b, 'g, 'r, 's>(
|
||||||
|
context: RefContext<'b, 'g, 'r, 's>,
|
||||||
|
input: OrgSource<'s>,
|
||||||
|
original_input: OrgSource<'s>,
|
||||||
|
) -> Res<OrgSource<'s>, Element<'s>> {
|
||||||
|
let (remaining, (source, children)) =
|
||||||
|
greater_block_body(context, input, original_input, "quote", "quote block")?;
|
||||||
|
Ok((
|
||||||
|
remaining,
|
||||||
|
Element::QuoteBlock(QuoteBlock { source, children }),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn special_block<'s>(
|
||||||
|
name: &'s str,
|
||||||
|
) -> impl for<'b, 'g, 'r> Fn(
|
||||||
|
RefContext<'b, 'g, 'r, 's>,
|
||||||
|
OrgSource<'s>,
|
||||||
|
OrgSource<'s>,
|
||||||
|
) -> Res<OrgSource<'s>, Element<'s>>
|
||||||
|
+ 's {
|
||||||
|
let context_name = format!("special block {}", name);
|
||||||
|
move |context, input, original_input| {
|
||||||
|
_special_block(context, input, original_input, name, context_name.as_str())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||||
|
fn _special_block<'c, 'b, 'g, 'r, 's>(
|
||||||
|
context: RefContext<'b, 'g, 'r, 's>,
|
||||||
|
input: OrgSource<'s>,
|
||||||
|
original_input: OrgSource<'s>,
|
||||||
|
name: &'s str,
|
||||||
|
context_name: &'c str,
|
||||||
|
) -> Res<OrgSource<'s>, Element<'s>> {
|
||||||
|
let (remaining, parameters) = opt(tuple((space1, parameters)))(input)?;
|
||||||
|
let (remaining, (source, children)) =
|
||||||
|
greater_block_body(context, remaining, original_input, name, context_name)?;
|
||||||
|
Ok((
|
||||||
|
remaining,
|
||||||
|
Element::SpecialBlock(SpecialBlock {
|
||||||
|
source,
|
||||||
|
children,
|
||||||
|
name,
|
||||||
|
parameters: parameters.map(|(_, parameters)| Into::<&str>::into(parameters)),
|
||||||
|
}),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||||
|
fn greater_block_body<'c, 'b, 'g, 'r, 's>(
|
||||||
|
context: RefContext<'b, 'g, 'r, 's>,
|
||||||
|
input: OrgSource<'s>,
|
||||||
|
original_input: OrgSource<'s>,
|
||||||
|
name: &'c str,
|
||||||
|
context_name: &'c str,
|
||||||
|
) -> Res<OrgSource<'s>, (&'s str, Vec<Element<'s>>)> {
|
||||||
|
if in_section(context, context_name) {
|
||||||
return Err(nom::Err::Error(CustomError::MyError(MyError(
|
return Err(nom::Err::Error(CustomError::MyError(MyError(
|
||||||
"Cannot nest objects of the same element".into(),
|
"Cannot nest objects of the same element".into(),
|
||||||
))));
|
))));
|
||||||
}
|
}
|
||||||
let exit_with_name = greater_block_end(name.into());
|
let exit_with_name = greater_block_end(name);
|
||||||
let (remaining, parameters) = opt(tuple((space1, parameters)))(remaining)?;
|
let (remaining, _nl) = tuple((space0, line_ending))(input)?;
|
||||||
let (remaining, _nl) = line_ending(remaining)?;
|
|
||||||
let contexts = [
|
let contexts = [
|
||||||
ContextElement::ConsumeTrailingWhitespace(true),
|
ContextElement::ConsumeTrailingWhitespace(true),
|
||||||
ContextElement::Context(context_name.as_str()),
|
ContextElement::Context(context_name),
|
||||||
ContextElement::ExitMatcherNode(ExitMatcherNode {
|
ContextElement::ExitMatcherNode(ExitMatcherNode {
|
||||||
class: ExitClass::Alpha,
|
class: ExitClass::Alpha,
|
||||||
exit_matcher: &exit_with_name,
|
exit_matcher: &exit_with_name,
|
||||||
@@ -76,11 +155,6 @@ pub(crate) fn greater_block<'b, 'g, 'r, 's>(
|
|||||||
let parser_context = context.with_additional_node(&contexts[0]);
|
let parser_context = context.with_additional_node(&contexts[0]);
|
||||||
let parser_context = parser_context.with_additional_node(&contexts[1]);
|
let parser_context = parser_context.with_additional_node(&contexts[1]);
|
||||||
let parser_context = parser_context.with_additional_node(&contexts[2]);
|
let parser_context = parser_context.with_additional_node(&contexts[2]);
|
||||||
let parameters = match parameters {
|
|
||||||
Some((_ws, parameters)) => Some(parameters),
|
|
||||||
None => None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let element_matcher = parser_with_context!(element(true))(&parser_context);
|
let element_matcher = parser_with_context!(element(true))(&parser_context);
|
||||||
let exit_matcher = parser_with_context!(exit_matcher_parser)(&parser_context);
|
let exit_matcher = parser_with_context!(exit_matcher_parser)(&parser_context);
|
||||||
not(exit_matcher)(remaining)?;
|
not(exit_matcher)(remaining)?;
|
||||||
@@ -104,16 +178,8 @@ pub(crate) fn greater_block<'b, 'g, 'r, 's>(
|
|||||||
|
|
||||||
// Not checking if parent exit matcher is causing exit because the greater_block_end matcher asserts we matched a full greater block
|
// Not checking if parent exit matcher is causing exit because the greater_block_end matcher asserts we matched a full greater block
|
||||||
|
|
||||||
let source = get_consumed(input, remaining);
|
let source = get_consumed(original_input, remaining);
|
||||||
Ok((
|
Ok((remaining, (Into::<&str>::into(source), children)))
|
||||||
remaining,
|
|
||||||
GreaterBlock {
|
|
||||||
source: source.into(),
|
|
||||||
name: name.into(),
|
|
||||||
parameters: parameters.map(|val| Into::<&str>::into(val)),
|
|
||||||
children,
|
|
||||||
},
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||||
@@ -123,7 +189,7 @@ fn name<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
|||||||
|
|
||||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||||
fn parameters<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
fn parameters<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
||||||
is_not("\r\n")(input)
|
recognize(many_till(anychar, peek(tuple((space0, line_ending)))))(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn greater_block_end<'c>(name: &'c str) -> impl ContextMatcher + 'c {
|
fn greater_block_end<'c>(name: &'c str) -> impl ContextMatcher + 'c {
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ use crate::error::Res;
|
|||||||
use crate::parser::object_parser::standard_set_object;
|
use crate::parser::object_parser::standard_set_object;
|
||||||
use crate::parser::util::blank_line;
|
use crate::parser::util::blank_line;
|
||||||
use crate::types::DocumentElement;
|
use crate::types::DocumentElement;
|
||||||
|
use crate::types::Element;
|
||||||
use crate::types::Heading;
|
use crate::types::Heading;
|
||||||
use crate::types::HeadlineLevel;
|
use crate::types::HeadlineLevel;
|
||||||
use crate::types::Object;
|
use crate::types::Object;
|
||||||
@@ -55,6 +56,9 @@ fn _heading<'b, 'g, 'r, 's>(
|
|||||||
input: OrgSource<'s>,
|
input: OrgSource<'s>,
|
||||||
parent_star_count: HeadlineLevel,
|
parent_star_count: HeadlineLevel,
|
||||||
) -> Res<OrgSource<'s>, Heading<'s>> {
|
) -> Res<OrgSource<'s>, Heading<'s>> {
|
||||||
|
let mut scheduled = None;
|
||||||
|
let mut deadline = None;
|
||||||
|
let mut closed = None;
|
||||||
not(|i| context.check_exit_matcher(i))(input)?;
|
not(|i| context.check_exit_matcher(i))(input)?;
|
||||||
let (remaining, pre_headline) = headline(context, input, parent_star_count)?;
|
let (remaining, pre_headline) = headline(context, input, parent_star_count)?;
|
||||||
let section_matcher = parser_with_context!(section)(context);
|
let section_matcher = parser_with_context!(section)(context);
|
||||||
@@ -65,6 +69,14 @@ fn _heading<'b, 'g, 'r, 's>(
|
|||||||
let (remaining, mut children) =
|
let (remaining, mut children) =
|
||||||
many0(map(heading_matcher, DocumentElement::Heading))(remaining)?;
|
many0(map(heading_matcher, DocumentElement::Heading))(remaining)?;
|
||||||
if let Some(section) = maybe_section {
|
if let Some(section) = maybe_section {
|
||||||
|
// If the section has a planning then the timestamp values are copied to the heading.
|
||||||
|
if let DocumentElement::Section(inner_section) = §ion {
|
||||||
|
if let Some(Element::Planning(planning)) = inner_section.children.first() {
|
||||||
|
scheduled = planning.scheduled.clone();
|
||||||
|
deadline = planning.deadline.clone();
|
||||||
|
closed = planning.closed.clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
children.insert(0, section);
|
children.insert(0, section);
|
||||||
}
|
}
|
||||||
let remaining = if children.is_empty() {
|
let remaining = if children.is_empty() {
|
||||||
@@ -94,6 +106,9 @@ fn _heading<'b, 'g, 'r, 's>(
|
|||||||
is_comment: pre_headline.comment.is_some(),
|
is_comment: pre_headline.comment.is_some(),
|
||||||
is_archived,
|
is_archived,
|
||||||
is_footnote_section: pre_headline.is_footnote_section,
|
is_footnote_section: pre_headline.is_footnote_section,
|
||||||
|
scheduled,
|
||||||
|
deadline,
|
||||||
|
closed,
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@@ -107,6 +122,7 @@ pub(crate) fn detect_headline<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, ()
|
|||||||
/// Fields from a not-yet-fully-parsed Headline.
|
/// Fields from a not-yet-fully-parsed Headline.
|
||||||
///
|
///
|
||||||
/// This struct exists to give names to the fields of a partially-parsed Headline to avoid returning a large tuple of nameless fields.
|
/// This struct exists to give names to the fields of a partially-parsed Headline to avoid returning a large tuple of nameless fields.
|
||||||
|
#[derive(Debug)]
|
||||||
struct PreHeadline<'s> {
|
struct PreHeadline<'s> {
|
||||||
headline_level: HeadlineLevel,
|
headline_level: HeadlineLevel,
|
||||||
star_count: HeadlineLevel,
|
star_count: HeadlineLevel,
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ use super::OrgSource;
|
|||||||
use crate::context::HeadlineLevelFilter;
|
use crate::context::HeadlineLevelFilter;
|
||||||
use crate::error::CustomError;
|
use crate::error::CustomError;
|
||||||
use crate::error::Res;
|
use crate::error::Res;
|
||||||
use crate::iter::AstNode;
|
|
||||||
use crate::settings::GlobalSettings;
|
use crate::settings::GlobalSettings;
|
||||||
|
use crate::types::AstNode;
|
||||||
use crate::types::Document;
|
use crate::types::Document;
|
||||||
use crate::types::Keyword;
|
use crate::types::Keyword;
|
||||||
|
|
||||||
|
|||||||
@@ -388,6 +388,7 @@ impl<'s> From<CustomError<OrgSource<'s>>> for CustomError<&'s str> {
|
|||||||
CustomError::MyError(err) => CustomError::MyError(err.into()),
|
CustomError::MyError(err) => CustomError::MyError(err.into()),
|
||||||
CustomError::Nom(input, error_kind) => CustomError::Nom(input.into(), error_kind),
|
CustomError::Nom(input, error_kind) => CustomError::Nom(input.into(), error_kind),
|
||||||
CustomError::IO(err) => CustomError::IO(err),
|
CustomError::IO(err) => CustomError::IO(err),
|
||||||
|
CustomError::BoxedError(err) => CustomError::BoxedError(err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ use nom::bytes::complete::tag;
|
|||||||
use nom::bytes::complete::tag_no_case;
|
use nom::bytes::complete::tag_no_case;
|
||||||
use nom::character::complete::space0;
|
use nom::character::complete::space0;
|
||||||
use nom::character::complete::space1;
|
use nom::character::complete::space1;
|
||||||
|
use nom::combinator::map;
|
||||||
use nom::multi::many1;
|
use nom::multi::many1;
|
||||||
use nom::sequence::tuple;
|
use nom::sequence::tuple;
|
||||||
|
|
||||||
@@ -16,6 +17,7 @@ use crate::error::Res;
|
|||||||
use crate::parser::util::get_consumed;
|
use crate::parser::util::get_consumed;
|
||||||
use crate::parser::util::start_of_line;
|
use crate::parser::util::start_of_line;
|
||||||
use crate::types::Planning;
|
use crate::types::Planning;
|
||||||
|
use crate::types::Timestamp;
|
||||||
|
|
||||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||||
pub(crate) fn planning<'b, 'g, 'r, 's>(
|
pub(crate) fn planning<'b, 'g, 'r, 's>(
|
||||||
@@ -24,7 +26,7 @@ pub(crate) fn planning<'b, 'g, 'r, 's>(
|
|||||||
) -> Res<OrgSource<'s>, Planning<'s>> {
|
) -> Res<OrgSource<'s>, Planning<'s>> {
|
||||||
start_of_line(input)?;
|
start_of_line(input)?;
|
||||||
let (remaining, _leading_whitespace) = space0(input)?;
|
let (remaining, _leading_whitespace) = space0(input)?;
|
||||||
let (remaining, _planning_parameters) =
|
let (remaining, planning_parameters) =
|
||||||
many1(parser_with_context!(planning_parameter)(context))(remaining)?;
|
many1(parser_with_context!(planning_parameter)(context))(remaining)?;
|
||||||
let (remaining, _trailing_ws) = tuple((space0, org_line_ending))(remaining)?;
|
let (remaining, _trailing_ws) = tuple((space0, org_line_ending))(remaining)?;
|
||||||
|
|
||||||
@@ -32,26 +34,55 @@ pub(crate) fn planning<'b, 'g, 'r, 's>(
|
|||||||
maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?;
|
maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?;
|
||||||
let source = get_consumed(input, remaining);
|
let source = get_consumed(input, remaining);
|
||||||
|
|
||||||
|
let mut scheduled = None;
|
||||||
|
let mut deadline = None;
|
||||||
|
let mut closed = None;
|
||||||
|
|
||||||
|
for (timestamp_type, timestamp) in planning_parameters.into_iter() {
|
||||||
|
match timestamp_type {
|
||||||
|
PlanningTimestampType::Scheduled => {
|
||||||
|
scheduled = Some(timestamp);
|
||||||
|
}
|
||||||
|
PlanningTimestampType::Deadline => {
|
||||||
|
deadline = Some(timestamp);
|
||||||
|
}
|
||||||
|
PlanningTimestampType::Closed => {
|
||||||
|
closed = Some(timestamp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
remaining,
|
remaining,
|
||||||
Planning {
|
Planning {
|
||||||
source: source.into(),
|
source: source.into(),
|
||||||
|
scheduled,
|
||||||
|
deadline,
|
||||||
|
closed,
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum PlanningTimestampType {
|
||||||
|
Scheduled,
|
||||||
|
Deadline,
|
||||||
|
Closed,
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||||
fn planning_parameter<'b, 'g, 'r, 's>(
|
fn planning_parameter<'b, 'g, 'r, 's>(
|
||||||
context: RefContext<'b, 'g, 'r, 's>,
|
context: RefContext<'b, 'g, 'r, 's>,
|
||||||
input: OrgSource<'s>,
|
input: OrgSource<'s>,
|
||||||
) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
) -> Res<OrgSource<'s>, (PlanningTimestampType, Timestamp<'s>)> {
|
||||||
let (remaining, _planning_type) = alt((
|
let (remaining, planning_type) = alt((
|
||||||
tag_no_case("DEADLINE"),
|
map(tag_no_case("DEADLINE"), |_| PlanningTimestampType::Deadline),
|
||||||
tag_no_case("SCHEDULED"),
|
map(tag_no_case("SCHEDULED"), |_| {
|
||||||
tag_no_case("CLOSED"),
|
PlanningTimestampType::Scheduled
|
||||||
|
}),
|
||||||
|
map(tag_no_case("CLOSED"), |_| PlanningTimestampType::Closed),
|
||||||
))(input)?;
|
))(input)?;
|
||||||
let (remaining, _gap) = tuple((tag(":"), space1))(remaining)?;
|
let (remaining, _gap) = tuple((tag(":"), space1))(remaining)?;
|
||||||
let (remaining, _timestamp) = timestamp(context, remaining)?;
|
let (remaining, timestamp) = timestamp(context, remaining)?;
|
||||||
let source = get_consumed(input, remaining);
|
Ok((remaining, (planning_type, timestamp)))
|
||||||
Ok((remaining, source))
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ fn node_property<'b, 'g, 'r, 's>(
|
|||||||
context: RefContext<'b, 'g, 'r, 's>,
|
context: RefContext<'b, 'g, 'r, 's>,
|
||||||
input: OrgSource<'s>,
|
input: OrgSource<'s>,
|
||||||
) -> Res<OrgSource<'s>, NodeProperty<'s>> {
|
) -> Res<OrgSource<'s>, NodeProperty<'s>> {
|
||||||
let (remaining, (_start_of_line, _leading_whitespace, _open_colon, _name, _close_colon)) =
|
let (remaining, (_start_of_line, _leading_whitespace, _open_colon, name, _close_colon)) =
|
||||||
tuple((
|
tuple((
|
||||||
start_of_line,
|
start_of_line,
|
||||||
space0,
|
space0,
|
||||||
@@ -120,6 +120,7 @@ fn node_property<'b, 'g, 'r, 's>(
|
|||||||
remaining,
|
remaining,
|
||||||
NodeProperty {
|
NodeProperty {
|
||||||
source: source.into(),
|
source: source.into(),
|
||||||
|
name: Into::<&str>::into(name),
|
||||||
value: None,
|
value: None,
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
@@ -132,6 +133,7 @@ fn node_property<'b, 'g, 'r, 's>(
|
|||||||
remaining,
|
remaining,
|
||||||
NodeProperty {
|
NodeProperty {
|
||||||
source: source.into(),
|
source: source.into(),
|
||||||
|
name: Into::<&str>::into(name),
|
||||||
value: Some(value.into()),
|
value: Some(value.into()),
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ use nom::bytes::complete::is_not;
|
|||||||
use nom::bytes::complete::tag;
|
use nom::bytes::complete::tag;
|
||||||
use nom::character::complete::line_ending;
|
use nom::character::complete::line_ending;
|
||||||
use nom::character::complete::space0;
|
use nom::character::complete::space0;
|
||||||
use nom::combinator::eof;
|
|
||||||
use nom::combinator::not;
|
use nom::combinator::not;
|
||||||
|
use nom::combinator::opt;
|
||||||
use nom::combinator::peek;
|
use nom::combinator::peek;
|
||||||
use nom::combinator::recognize;
|
use nom::combinator::recognize;
|
||||||
use nom::combinator::verify;
|
use nom::combinator::verify;
|
||||||
@@ -17,6 +17,7 @@ use super::keyword::table_formula_keyword;
|
|||||||
use super::object_parser::table_cell_set_object;
|
use super::object_parser::table_cell_set_object;
|
||||||
use super::org_source::OrgSource;
|
use super::org_source::OrgSource;
|
||||||
use super::util::exit_matcher_parser;
|
use super::util::exit_matcher_parser;
|
||||||
|
use super::util::org_line_ending;
|
||||||
use crate::context::parser_with_context;
|
use crate::context::parser_with_context;
|
||||||
use crate::context::ContextElement;
|
use crate::context::ContextElement;
|
||||||
use crate::context::ExitClass;
|
use crate::context::ExitClass;
|
||||||
@@ -105,7 +106,7 @@ fn org_mode_table_row_rule<'b, 'g, 'r, 's>(
|
|||||||
input: OrgSource<'s>,
|
input: OrgSource<'s>,
|
||||||
) -> Res<OrgSource<'s>, TableRow<'s>> {
|
) -> Res<OrgSource<'s>, TableRow<'s>> {
|
||||||
start_of_line(input)?;
|
start_of_line(input)?;
|
||||||
let (remaining, _) = tuple((space0, tag("|-"), is_not("\r\n"), line_ending))(input)?;
|
let (remaining, _) = tuple((space0, tag("|-"), opt(is_not("\r\n")), org_line_ending))(input)?;
|
||||||
let source = get_consumed(input, remaining);
|
let source = get_consumed(input, remaining);
|
||||||
Ok((
|
Ok((
|
||||||
remaining,
|
remaining,
|
||||||
@@ -125,7 +126,7 @@ fn org_mode_table_row_regular<'b, 'g, 'r, 's>(
|
|||||||
let (remaining, _) = tuple((space0, tag("|")))(input)?;
|
let (remaining, _) = tuple((space0, tag("|")))(input)?;
|
||||||
let (remaining, children) =
|
let (remaining, children) =
|
||||||
many1(parser_with_context!(org_mode_table_cell)(context))(remaining)?;
|
many1(parser_with_context!(org_mode_table_cell)(context))(remaining)?;
|
||||||
let (remaining, _tail) = recognize(tuple((space0, alt((line_ending, eof)))))(remaining)?;
|
let (remaining, _tail) = recognize(tuple((space0, org_line_ending)))(remaining)?;
|
||||||
let source = get_consumed(input, remaining);
|
let source = get_consumed(input, remaining);
|
||||||
Ok((
|
Ok((
|
||||||
remaining,
|
remaining,
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
use nom::branch::alt;
|
use nom::branch::alt;
|
||||||
use nom::bytes::complete::tag;
|
use nom::bytes::complete::tag;
|
||||||
use nom::character::complete::anychar;
|
use nom::character::complete::anychar;
|
||||||
use nom::character::complete::digit0;
|
|
||||||
use nom::character::complete::digit1;
|
use nom::character::complete::digit1;
|
||||||
use nom::character::complete::one_of;
|
use nom::character::complete::one_of;
|
||||||
use nom::character::complete::space1;
|
use nom::character::complete::space1;
|
||||||
|
use nom::combinator::map;
|
||||||
use nom::combinator::opt;
|
use nom::combinator::opt;
|
||||||
use nom::combinator::recognize;
|
use nom::combinator::recognize;
|
||||||
use nom::combinator::verify;
|
use nom::combinator::verify;
|
||||||
@@ -21,7 +21,21 @@ use crate::context::ExitMatcherNode;
|
|||||||
use crate::context::RefContext;
|
use crate::context::RefContext;
|
||||||
use crate::error::Res;
|
use crate::error::Res;
|
||||||
use crate::parser::util::get_consumed;
|
use crate::parser::util::get_consumed;
|
||||||
|
use crate::types::Date;
|
||||||
|
use crate::types::DayOfMonth;
|
||||||
|
use crate::types::Hour;
|
||||||
|
use crate::types::Minute;
|
||||||
|
use crate::types::Month;
|
||||||
|
use crate::types::Repeater;
|
||||||
|
use crate::types::RepeaterType;
|
||||||
|
use crate::types::Time;
|
||||||
|
use crate::types::TimeUnit;
|
||||||
use crate::types::Timestamp;
|
use crate::types::Timestamp;
|
||||||
|
use crate::types::TimestampRangeType;
|
||||||
|
use crate::types::TimestampType;
|
||||||
|
use crate::types::WarningDelay;
|
||||||
|
use crate::types::WarningDelayType;
|
||||||
|
use crate::types::Year;
|
||||||
|
|
||||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||||
pub(crate) fn timestamp<'b, 'g, 'r, 's>(
|
pub(crate) fn timestamp<'b, 'g, 'r, 's>(
|
||||||
@@ -57,6 +71,14 @@ fn diary_timestamp<'b, 'g, 'r, 's>(
|
|||||||
remaining,
|
remaining,
|
||||||
Timestamp {
|
Timestamp {
|
||||||
source: source.into(),
|
source: source.into(),
|
||||||
|
timestamp_type: TimestampType::Diary,
|
||||||
|
range_type: TimestampRangeType::None,
|
||||||
|
start: None,
|
||||||
|
end: None,
|
||||||
|
start_time: None,
|
||||||
|
end_time: None,
|
||||||
|
repeater: None,
|
||||||
|
warning_delay: None,
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@@ -97,17 +119,26 @@ fn active_timestamp<'b, 'g, 'r, 's>(
|
|||||||
input: OrgSource<'s>,
|
input: OrgSource<'s>,
|
||||||
) -> Res<OrgSource<'s>, Timestamp<'s>> {
|
) -> Res<OrgSource<'s>, Timestamp<'s>> {
|
||||||
let (remaining, _) = tag("<")(input)?;
|
let (remaining, _) = tag("<")(input)?;
|
||||||
let (remaining, _date) = date(context, remaining)?;
|
let (remaining, start) = date(context, remaining)?;
|
||||||
let time_context = ContextElement::ExitMatcherNode(ExitMatcherNode {
|
let time_context = ContextElement::ExitMatcherNode(ExitMatcherNode {
|
||||||
class: ExitClass::Gamma,
|
class: ExitClass::Gamma,
|
||||||
exit_matcher: &active_time_rest_end,
|
exit_matcher: &active_time_rest_end,
|
||||||
});
|
});
|
||||||
let time_context = context.with_additional_node(&time_context);
|
let time_context = context.with_additional_node(&time_context);
|
||||||
let (remaining, _time) =
|
let (remaining, time) = opt(tuple((
|
||||||
opt(tuple((space1, parser_with_context!(time)(&time_context))))(remaining)?;
|
space1,
|
||||||
let (remaining, _repeater) =
|
parser_with_context!(time(true))(&time_context),
|
||||||
|
)))(remaining)?;
|
||||||
|
let remaining = if time.is_none() {
|
||||||
|
// Upstream org-mode accepts malformed timestamps. For example '<2016-02-14 Sun ++y>'.
|
||||||
|
let (remain, _) = opt(parser_with_context!(time_rest)(&time_context))(remaining)?;
|
||||||
|
remain
|
||||||
|
} else {
|
||||||
|
remaining
|
||||||
|
};
|
||||||
|
let (remaining, repeater) =
|
||||||
opt(tuple((space1, parser_with_context!(repeater)(context))))(remaining)?;
|
opt(tuple((space1, parser_with_context!(repeater)(context))))(remaining)?;
|
||||||
let (remaining, _warning_delay) = opt(tuple((
|
let (remaining, warning_delay) = opt(tuple((
|
||||||
space1,
|
space1,
|
||||||
parser_with_context!(warning_delay)(context),
|
parser_with_context!(warning_delay)(context),
|
||||||
)))(remaining)?;
|
)))(remaining)?;
|
||||||
@@ -121,6 +152,14 @@ fn active_timestamp<'b, 'g, 'r, 's>(
|
|||||||
remaining,
|
remaining,
|
||||||
Timestamp {
|
Timestamp {
|
||||||
source: source.into(),
|
source: source.into(),
|
||||||
|
timestamp_type: TimestampType::Active,
|
||||||
|
range_type: TimestampRangeType::None,
|
||||||
|
start: Some(start.clone()),
|
||||||
|
end: Some(start),
|
||||||
|
start_time: time.as_ref().map(|(_, time)| time.clone()),
|
||||||
|
end_time: time.map(|(_, time)| time),
|
||||||
|
repeater: repeater.map(|(_, repeater)| repeater),
|
||||||
|
warning_delay: warning_delay.map(|(_, warning_delay)| warning_delay),
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@@ -131,17 +170,26 @@ fn inactive_timestamp<'b, 'g, 'r, 's>(
|
|||||||
input: OrgSource<'s>,
|
input: OrgSource<'s>,
|
||||||
) -> Res<OrgSource<'s>, Timestamp<'s>> {
|
) -> Res<OrgSource<'s>, Timestamp<'s>> {
|
||||||
let (remaining, _) = tag("[")(input)?;
|
let (remaining, _) = tag("[")(input)?;
|
||||||
let (remaining, _date) = date(context, remaining)?;
|
let (remaining, start) = date(context, remaining)?;
|
||||||
let time_context = ContextElement::ExitMatcherNode(ExitMatcherNode {
|
let time_context = ContextElement::ExitMatcherNode(ExitMatcherNode {
|
||||||
class: ExitClass::Gamma,
|
class: ExitClass::Gamma,
|
||||||
exit_matcher: &inactive_time_rest_end,
|
exit_matcher: &inactive_time_rest_end,
|
||||||
});
|
});
|
||||||
let time_context = context.with_additional_node(&time_context);
|
let time_context = context.with_additional_node(&time_context);
|
||||||
let (remaining, _time) =
|
let (remaining, time) = opt(tuple((
|
||||||
opt(tuple((space1, parser_with_context!(time)(&time_context))))(remaining)?;
|
space1,
|
||||||
let (remaining, _repeater) =
|
parser_with_context!(time(true))(&time_context),
|
||||||
|
)))(remaining)?;
|
||||||
|
let remaining = if time.is_none() {
|
||||||
|
// Upstream org-mode accepts malformed timestamps. For example '<2016-02-14 Sun ++y>'.
|
||||||
|
let (remain, _) = opt(parser_with_context!(time_rest)(&time_context))(remaining)?;
|
||||||
|
remain
|
||||||
|
} else {
|
||||||
|
remaining
|
||||||
|
};
|
||||||
|
let (remaining, repeater) =
|
||||||
opt(tuple((space1, parser_with_context!(repeater)(context))))(remaining)?;
|
opt(tuple((space1, parser_with_context!(repeater)(context))))(remaining)?;
|
||||||
let (remaining, _warning_delay) = opt(tuple((
|
let (remaining, warning_delay) = opt(tuple((
|
||||||
space1,
|
space1,
|
||||||
parser_with_context!(warning_delay)(context),
|
parser_with_context!(warning_delay)(context),
|
||||||
)))(remaining)?;
|
)))(remaining)?;
|
||||||
@@ -155,6 +203,14 @@ fn inactive_timestamp<'b, 'g, 'r, 's>(
|
|||||||
remaining,
|
remaining,
|
||||||
Timestamp {
|
Timestamp {
|
||||||
source: source.into(),
|
source: source.into(),
|
||||||
|
timestamp_type: TimestampType::Inactive,
|
||||||
|
range_type: TimestampRangeType::None,
|
||||||
|
start: Some(start.clone()),
|
||||||
|
end: Some(start),
|
||||||
|
start_time: time.as_ref().map(|(_, time)| time.clone()),
|
||||||
|
end_time: time.map(|(_, time)| time),
|
||||||
|
repeater: repeater.map(|(_, repeater)| repeater),
|
||||||
|
warning_delay: warning_delay.map(|(_, warning_delay)| warning_delay),
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@@ -164,10 +220,10 @@ fn active_date_range_timestamp<'b, 'g, 'r, 's>(
|
|||||||
context: RefContext<'b, 'g, 'r, 's>,
|
context: RefContext<'b, 'g, 'r, 's>,
|
||||||
input: OrgSource<'s>,
|
input: OrgSource<'s>,
|
||||||
) -> Res<OrgSource<'s>, Timestamp<'s>> {
|
) -> Res<OrgSource<'s>, Timestamp<'s>> {
|
||||||
let (remaining, _first_timestamp) = active_timestamp(context, input)?;
|
let (remaining, first_timestamp) = active_timestamp(context, input)?;
|
||||||
// TODO: Does the space0 at the end of the active/inactive timestamp parsers cause this to be incorrect? I could use a look-behind to make sure the preceding character is not whitespace
|
// TODO: Does the space0 at the end of the active/inactive timestamp parsers cause this to be incorrect? I could use a look-behind to make sure the preceding character is not whitespace
|
||||||
let (remaining, _separator) = tag("--")(remaining)?;
|
let (remaining, _separator) = tag("--")(remaining)?;
|
||||||
let (remaining, _second_timestamp) = active_timestamp(context, remaining)?;
|
let (remaining, second_timestamp) = active_timestamp(context, remaining)?;
|
||||||
|
|
||||||
let (remaining, _trailing_whitespace) =
|
let (remaining, _trailing_whitespace) =
|
||||||
maybe_consume_object_trailing_whitespace_if_not_exiting(context, remaining)?;
|
maybe_consume_object_trailing_whitespace_if_not_exiting(context, remaining)?;
|
||||||
@@ -177,6 +233,16 @@ fn active_date_range_timestamp<'b, 'g, 'r, 's>(
|
|||||||
remaining,
|
remaining,
|
||||||
Timestamp {
|
Timestamp {
|
||||||
source: source.into(),
|
source: source.into(),
|
||||||
|
timestamp_type: TimestampType::ActiveRange,
|
||||||
|
range_type: TimestampRangeType::DateRange,
|
||||||
|
start: first_timestamp.start,
|
||||||
|
end: second_timestamp.end,
|
||||||
|
start_time: first_timestamp.start_time,
|
||||||
|
end_time: second_timestamp.end_time,
|
||||||
|
repeater: first_timestamp.repeater.or(second_timestamp.repeater),
|
||||||
|
warning_delay: first_timestamp
|
||||||
|
.warning_delay
|
||||||
|
.or(second_timestamp.warning_delay),
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@@ -187,7 +253,7 @@ fn active_time_range_timestamp<'b, 'g, 'r, 's>(
|
|||||||
input: OrgSource<'s>,
|
input: OrgSource<'s>,
|
||||||
) -> Res<OrgSource<'s>, Timestamp<'s>> {
|
) -> Res<OrgSource<'s>, Timestamp<'s>> {
|
||||||
let (remaining, _) = tag("<")(input)?;
|
let (remaining, _) = tag("<")(input)?;
|
||||||
let (remaining, _date) = date(context, remaining)?;
|
let (remaining, start_date) = date(context, remaining)?;
|
||||||
let time_context = ContextElement::ExitMatcherNode(ExitMatcherNode {
|
let time_context = ContextElement::ExitMatcherNode(ExitMatcherNode {
|
||||||
class: ExitClass::Gamma,
|
class: ExitClass::Gamma,
|
||||||
exit_matcher: &active_time_rest_end,
|
exit_matcher: &active_time_rest_end,
|
||||||
@@ -198,13 +264,15 @@ fn active_time_range_timestamp<'b, 'g, 'r, 's>(
|
|||||||
exit_matcher: &time_range_rest_end,
|
exit_matcher: &time_range_rest_end,
|
||||||
});
|
});
|
||||||
let first_time_context = time_context.with_additional_node(&first_time_context);
|
let first_time_context = time_context.with_additional_node(&first_time_context);
|
||||||
let (remaining, _first_time) =
|
let (remaining, (_, first_time)) = tuple((
|
||||||
tuple((space1, parser_with_context!(time)(&first_time_context)))(remaining)?;
|
space1,
|
||||||
|
parser_with_context!(time(false))(&first_time_context),
|
||||||
|
))(remaining)?;
|
||||||
let (remaining, _) = tag("-")(remaining)?;
|
let (remaining, _) = tag("-")(remaining)?;
|
||||||
let (remaining, _second_time) = parser_with_context!(time)(&time_context)(remaining)?;
|
let (remaining, second_time) = parser_with_context!(time(true))(&time_context)(remaining)?;
|
||||||
let (remaining, _repeater) =
|
let (remaining, repeater) =
|
||||||
opt(tuple((space1, parser_with_context!(repeater)(context))))(remaining)?;
|
opt(tuple((space1, parser_with_context!(repeater)(context))))(remaining)?;
|
||||||
let (remaining, _warning_delay) = opt(tuple((
|
let (remaining, warning_delay) = opt(tuple((
|
||||||
space1,
|
space1,
|
||||||
parser_with_context!(warning_delay)(context),
|
parser_with_context!(warning_delay)(context),
|
||||||
)))(remaining)?;
|
)))(remaining)?;
|
||||||
@@ -218,6 +286,14 @@ fn active_time_range_timestamp<'b, 'g, 'r, 's>(
|
|||||||
remaining,
|
remaining,
|
||||||
Timestamp {
|
Timestamp {
|
||||||
source: source.into(),
|
source: source.into(),
|
||||||
|
timestamp_type: TimestampType::ActiveRange,
|
||||||
|
range_type: TimestampRangeType::TimeRange,
|
||||||
|
start: Some(start_date.clone()),
|
||||||
|
end: Some(start_date),
|
||||||
|
start_time: Some(first_time),
|
||||||
|
end_time: Some(second_time),
|
||||||
|
repeater: repeater.map(|(_, repeater)| repeater),
|
||||||
|
warning_delay: warning_delay.map(|(_, warning_delay)| warning_delay),
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@@ -227,10 +303,10 @@ fn inactive_date_range_timestamp<'b, 'g, 'r, 's>(
|
|||||||
context: RefContext<'b, 'g, 'r, 's>,
|
context: RefContext<'b, 'g, 'r, 's>,
|
||||||
input: OrgSource<'s>,
|
input: OrgSource<'s>,
|
||||||
) -> Res<OrgSource<'s>, Timestamp<'s>> {
|
) -> Res<OrgSource<'s>, Timestamp<'s>> {
|
||||||
let (remaining, _first_timestamp) = inactive_timestamp(context, input)?;
|
let (remaining, first_timestamp) = inactive_timestamp(context, input)?;
|
||||||
// TODO: Does the space0 at the end of the active/inactive timestamp parsers cause this to be incorrect? I could use a look-behind to make sure the preceding character is not whitespace
|
// TODO: Does the space0 at the end of the active/inactive timestamp parsers cause this to be incorrect? I could use a look-behind to make sure the preceding character is not whitespace
|
||||||
let (remaining, _separator) = tag("--")(remaining)?;
|
let (remaining, _separator) = tag("--")(remaining)?;
|
||||||
let (remaining, _second_timestamp) = inactive_timestamp(context, remaining)?;
|
let (remaining, second_timestamp) = inactive_timestamp(context, remaining)?;
|
||||||
|
|
||||||
let (remaining, _trailing_whitespace) =
|
let (remaining, _trailing_whitespace) =
|
||||||
maybe_consume_object_trailing_whitespace_if_not_exiting(context, remaining)?;
|
maybe_consume_object_trailing_whitespace_if_not_exiting(context, remaining)?;
|
||||||
@@ -240,6 +316,17 @@ fn inactive_date_range_timestamp<'b, 'g, 'r, 's>(
|
|||||||
remaining,
|
remaining,
|
||||||
Timestamp {
|
Timestamp {
|
||||||
source: source.into(),
|
source: source.into(),
|
||||||
|
|
||||||
|
timestamp_type: TimestampType::InactiveRange,
|
||||||
|
range_type: TimestampRangeType::DateRange,
|
||||||
|
start: first_timestamp.start,
|
||||||
|
end: second_timestamp.end,
|
||||||
|
start_time: first_timestamp.start_time,
|
||||||
|
end_time: second_timestamp.end_time,
|
||||||
|
repeater: first_timestamp.repeater.or(second_timestamp.repeater),
|
||||||
|
warning_delay: first_timestamp
|
||||||
|
.warning_delay
|
||||||
|
.or(second_timestamp.warning_delay),
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@@ -250,7 +337,7 @@ fn inactive_time_range_timestamp<'b, 'g, 'r, 's>(
|
|||||||
input: OrgSource<'s>,
|
input: OrgSource<'s>,
|
||||||
) -> Res<OrgSource<'s>, Timestamp<'s>> {
|
) -> Res<OrgSource<'s>, Timestamp<'s>> {
|
||||||
let (remaining, _) = tag("[")(input)?;
|
let (remaining, _) = tag("[")(input)?;
|
||||||
let (remaining, _date) = date(context, remaining)?;
|
let (remaining, start_date) = date(context, remaining)?;
|
||||||
let time_context = ContextElement::ExitMatcherNode(ExitMatcherNode {
|
let time_context = ContextElement::ExitMatcherNode(ExitMatcherNode {
|
||||||
class: ExitClass::Gamma,
|
class: ExitClass::Gamma,
|
||||||
exit_matcher: &inactive_time_rest_end,
|
exit_matcher: &inactive_time_rest_end,
|
||||||
@@ -261,13 +348,15 @@ fn inactive_time_range_timestamp<'b, 'g, 'r, 's>(
|
|||||||
exit_matcher: &time_range_rest_end,
|
exit_matcher: &time_range_rest_end,
|
||||||
});
|
});
|
||||||
let first_time_context = time_context.with_additional_node(&first_time_context);
|
let first_time_context = time_context.with_additional_node(&first_time_context);
|
||||||
let (remaining, _first_time) =
|
let (remaining, (_, first_time)) = tuple((
|
||||||
tuple((space1, parser_with_context!(time)(&first_time_context)))(remaining)?;
|
space1,
|
||||||
|
parser_with_context!(time(false))(&first_time_context),
|
||||||
|
))(remaining)?;
|
||||||
let (remaining, _) = tag("-")(remaining)?;
|
let (remaining, _) = tag("-")(remaining)?;
|
||||||
let (remaining, _second_time) = parser_with_context!(time)(&time_context)(remaining)?;
|
let (remaining, second_time) = parser_with_context!(time(true))(&time_context)(remaining)?;
|
||||||
let (remaining, _repeater) =
|
let (remaining, repeater) =
|
||||||
opt(tuple((space1, parser_with_context!(repeater)(context))))(remaining)?;
|
opt(tuple((space1, parser_with_context!(repeater)(context))))(remaining)?;
|
||||||
let (remaining, _warning_delay) = opt(tuple((
|
let (remaining, warning_delay) = opt(tuple((
|
||||||
space1,
|
space1,
|
||||||
parser_with_context!(warning_delay)(context),
|
parser_with_context!(warning_delay)(context),
|
||||||
)))(remaining)?;
|
)))(remaining)?;
|
||||||
@@ -281,6 +370,14 @@ fn inactive_time_range_timestamp<'b, 'g, 'r, 's>(
|
|||||||
remaining,
|
remaining,
|
||||||
Timestamp {
|
Timestamp {
|
||||||
source: source.into(),
|
source: source.into(),
|
||||||
|
timestamp_type: TimestampType::InactiveRange,
|
||||||
|
range_type: TimestampRangeType::TimeRange,
|
||||||
|
start: Some(start_date.clone()),
|
||||||
|
end: Some(start_date),
|
||||||
|
start_time: Some(first_time),
|
||||||
|
end_time: Some(second_time),
|
||||||
|
repeater: repeater.map(|(_, repeater)| repeater),
|
||||||
|
warning_delay: warning_delay.map(|(_, warning_delay)| warning_delay),
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@@ -289,18 +386,33 @@ fn inactive_time_range_timestamp<'b, 'g, 'r, 's>(
|
|||||||
fn date<'b, 'g, 'r, 's>(
|
fn date<'b, 'g, 'r, 's>(
|
||||||
context: RefContext<'b, 'g, 'r, 's>,
|
context: RefContext<'b, 'g, 'r, 's>,
|
||||||
input: OrgSource<'s>,
|
input: OrgSource<'s>,
|
||||||
) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
) -> Res<OrgSource<'s>, Date<'s>> {
|
||||||
let (remaining, _year) = verify(digit1, |year: &OrgSource<'_>| year.len() == 4)(input)?;
|
let (remaining, year) = verify(digit1, |year: &OrgSource<'_>| year.len() == 4)(input)?;
|
||||||
let (remaining, _) = tag("-")(remaining)?;
|
let (remaining, _) = tag("-")(remaining)?;
|
||||||
let (remaining, _month) = verify(digit1, |month: &OrgSource<'_>| month.len() == 2)(remaining)?;
|
let (remaining, month) = verify(digit1, |month: &OrgSource<'_>| month.len() == 2)(remaining)?;
|
||||||
let (remaining, _) = tag("-")(remaining)?;
|
let (remaining, _) = tag("-")(remaining)?;
|
||||||
let (remaining, _day_of_month) = verify(digit1, |day_of_month: &OrgSource<'_>| {
|
let (remaining, day_of_month) = verify(digit1, |day_of_month: &OrgSource<'_>| {
|
||||||
day_of_month.len() == 2
|
day_of_month.len() == 2
|
||||||
})(remaining)?;
|
})(remaining)?;
|
||||||
let (remaining, _dayname) =
|
let (remaining, day_name) =
|
||||||
opt(tuple((space1, parser_with_context!(dayname)(context))))(remaining)?;
|
opt(tuple((space1, parser_with_context!(dayname)(context))))(remaining)?;
|
||||||
let source = get_consumed(input, remaining);
|
|
||||||
Ok((remaining, source))
|
let year = Year::new(Into::<&str>::into(year))
|
||||||
|
.expect("TODO: I should be able to return CustomError from nom parsers.");
|
||||||
|
let month = Month::new(Into::<&str>::into(month))
|
||||||
|
.expect("TODO: I should be able to return CustomError from nom parsers.");
|
||||||
|
let day_of_month = DayOfMonth::new(Into::<&str>::into(day_of_month))
|
||||||
|
.expect("TODO: I should be able to return CustomError from nom parsers.");
|
||||||
|
|
||||||
|
let date = Date::new(
|
||||||
|
year,
|
||||||
|
month,
|
||||||
|
day_of_month,
|
||||||
|
day_name.map(|(_, day_name)| Into::<&str>::into(day_name)),
|
||||||
|
)
|
||||||
|
.expect("TODO: I should be able to return CustomError from nom parsers.");
|
||||||
|
|
||||||
|
Ok((remaining, date))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||||
@@ -335,20 +447,39 @@ fn dayname_end<'b, 'g, 'r, 's>(
|
|||||||
}))(input)
|
}))(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const fn time<'c>(
|
||||||
|
allow_rest: bool,
|
||||||
|
) -> impl for<'b, 'g, 'r, 's> Fn(RefContext<'b, 'g, 'r, 's>, OrgSource<'s>) -> Res<OrgSource<'s>, Time<'s>>
|
||||||
|
{
|
||||||
|
move |context, input| _time(context, input, allow_rest)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||||
fn time<'b, 'g, 'r, 's>(
|
fn _time<'b, 'g, 'r, 's>(
|
||||||
context: RefContext<'b, 'g, 'r, 's>,
|
context: RefContext<'b, 'g, 'r, 's>,
|
||||||
input: OrgSource<'s>,
|
input: OrgSource<'s>,
|
||||||
) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
allow_rest: bool,
|
||||||
let (remaining, _hour) = verify(digit1, |hour: &OrgSource<'_>| {
|
) -> Res<OrgSource<'s>, Time<'s>> {
|
||||||
|
let (remaining, hour) = verify(digit1, |hour: &OrgSource<'_>| {
|
||||||
hour.len() >= 1 && hour.len() <= 2
|
hour.len() >= 1 && hour.len() <= 2
|
||||||
})(input)?;
|
})(input)?;
|
||||||
let (remaining, _) = tag(":")(remaining)?;
|
let (remaining, _) = tag(":")(remaining)?;
|
||||||
let (remaining, _minute) =
|
let (remaining, minute) =
|
||||||
verify(digit1, |minute: &OrgSource<'_>| minute.len() == 2)(remaining)?;
|
verify(digit1, |minute: &OrgSource<'_>| minute.len() == 2)(remaining)?;
|
||||||
let (remaining, _time_rest) = opt(parser_with_context!(time_rest)(context))(remaining)?;
|
let (remaining, time_rest) = if allow_rest {
|
||||||
let source = get_consumed(input, remaining);
|
opt(parser_with_context!(time_rest)(context))(remaining)?
|
||||||
Ok((remaining, source))
|
} else {
|
||||||
|
(remaining, None)
|
||||||
|
};
|
||||||
|
|
||||||
|
let hour = Hour::new(Into::<&str>::into(hour))
|
||||||
|
.expect("TODO: I should be able to return CustomError from nom parsers.");
|
||||||
|
let minute = Minute::new(Into::<&str>::into(minute))
|
||||||
|
.expect("TODO: I should be able to return CustomError from nom parsers.");
|
||||||
|
let time = Time::new(hour, minute, time_rest.map(Into::<&str>::into))
|
||||||
|
.expect("TODO: I should be able to return CustomError from nom parsers.");
|
||||||
|
|
||||||
|
Ok((remaining, time))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||||
@@ -401,8 +532,10 @@ fn time_range_rest_end<'b, 'g, 'r, 's>(
|
|||||||
) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
||||||
// We pop off the most recent context element to get a context tree with just the active/inactive_time_rest_end exit matcher (removing this function from the exit matcher chain) because the 2nd time in the range does not end when a "-TIME" pattern is found.
|
// We pop off the most recent context element to get a context tree with just the active/inactive_time_rest_end exit matcher (removing this function from the exit matcher chain) because the 2nd time in the range does not end when a "-TIME" pattern is found.
|
||||||
let parent_node = context.get_parent().expect("Two context elements are added to the tree when adding this exit matcher, so it should be impossible for this to return None.");
|
let parent_node = context.get_parent().expect("Two context elements are added to the tree when adding this exit matcher, so it should be impossible for this to return None.");
|
||||||
let exit_contents =
|
let exit_contents = recognize(tuple((
|
||||||
recognize(tuple((tag("-"), parser_with_context!(time)(&parent_node))))(input);
|
tag("-"),
|
||||||
|
parser_with_context!(time(true))(&parent_node),
|
||||||
|
)))(input);
|
||||||
exit_contents
|
exit_contents
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -410,29 +543,66 @@ fn time_range_rest_end<'b, 'g, 'r, 's>(
|
|||||||
fn repeater<'b, 'g, 'r, 's>(
|
fn repeater<'b, 'g, 'r, 's>(
|
||||||
_context: RefContext<'b, 'g, 'r, 's>,
|
_context: RefContext<'b, 'g, 'r, 's>,
|
||||||
input: OrgSource<'s>,
|
input: OrgSource<'s>,
|
||||||
) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
) -> Res<OrgSource<'s>, Repeater> {
|
||||||
// + for cumulative type
|
// + for cumulative type
|
||||||
// ++ for catch-up type
|
// ++ for catch-up type
|
||||||
// .+ for restart type
|
// .+ for restart type
|
||||||
let (remaining, _mark) = alt((tag("++"), tag("+"), tag(".+")))(input)?;
|
let (remaining, repeater_type) = alt((
|
||||||
let (remaining, _value) = digit0(remaining)?;
|
map(tag("++"), |_| RepeaterType::CatchUp),
|
||||||
|
map(tag("+"), |_| RepeaterType::Cumulative),
|
||||||
|
map(tag(".+"), |_| RepeaterType::Restart),
|
||||||
|
))(input)?;
|
||||||
|
let (remaining, value) = digit1(remaining)?;
|
||||||
|
let value = Into::<&str>::into(value)
|
||||||
|
.parse()
|
||||||
|
.expect("digit1 ensures this will parse as a number.");
|
||||||
// h = hour, d = day, w = week, m = month, y = year
|
// h = hour, d = day, w = week, m = month, y = year
|
||||||
let (remaining, _unit) = recognize(one_of("hdwmy"))(remaining)?;
|
let (remaining, unit) = alt((
|
||||||
let source = get_consumed(input, remaining);
|
map(tag("h"), |_| TimeUnit::Hour),
|
||||||
Ok((remaining, source))
|
map(tag("d"), |_| TimeUnit::Day),
|
||||||
|
map(tag("w"), |_| TimeUnit::Week),
|
||||||
|
map(tag("m"), |_| TimeUnit::Month),
|
||||||
|
map(tag("y"), |_| TimeUnit::Year),
|
||||||
|
))(remaining)?;
|
||||||
|
Ok((
|
||||||
|
remaining,
|
||||||
|
Repeater {
|
||||||
|
repeater_type,
|
||||||
|
value,
|
||||||
|
unit,
|
||||||
|
},
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||||
fn warning_delay<'b, 'g, 'r, 's>(
|
fn warning_delay<'b, 'g, 'r, 's>(
|
||||||
_context: RefContext<'b, 'g, 'r, 's>,
|
_context: RefContext<'b, 'g, 'r, 's>,
|
||||||
input: OrgSource<'s>,
|
input: OrgSource<'s>,
|
||||||
) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
) -> Res<OrgSource<'s>, WarningDelay> {
|
||||||
// - for all type
|
// - for all type
|
||||||
// -- for first type
|
// -- for first type
|
||||||
let (remaining, _mark) = alt((tag("--"), tag("-")))(input)?;
|
let (remaining, warning_delay_type) = alt((
|
||||||
let (remaining, _value) = digit0(remaining)?;
|
map(tag("--"), |_| WarningDelayType::First),
|
||||||
|
map(tag("-"), |_| WarningDelayType::All),
|
||||||
|
))(input)?;
|
||||||
|
let (remaining, value) = digit1(remaining)?;
|
||||||
|
let value = Into::<&str>::into(value)
|
||||||
|
.parse()
|
||||||
|
.expect("digit1 ensures this will parse as a number.");
|
||||||
// h = hour, d = day, w = week, m = month, y = year
|
// h = hour, d = day, w = week, m = month, y = year
|
||||||
let (remaining, _unit) = recognize(one_of("hdwmy"))(remaining)?;
|
let (remaining, unit) = alt((
|
||||||
let source = get_consumed(input, remaining);
|
map(tag("h"), |_| TimeUnit::Hour),
|
||||||
Ok((remaining, source))
|
map(tag("d"), |_| TimeUnit::Day),
|
||||||
|
map(tag("w"), |_| TimeUnit::Week),
|
||||||
|
map(tag("m"), |_| TimeUnit::Month),
|
||||||
|
map(tag("y"), |_| TimeUnit::Year),
|
||||||
|
))(remaining)?;
|
||||||
|
Ok((
|
||||||
|
remaining,
|
||||||
|
WarningDelay {
|
||||||
|
warning_delay_type,
|
||||||
|
value,
|
||||||
|
unit,
|
||||||
|
},
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
use super::macros::to_ast_node;
|
use super::macros::to_ast_node;
|
||||||
|
use super::CenterBlock;
|
||||||
|
use super::QuoteBlock;
|
||||||
|
use super::SpecialBlock;
|
||||||
use crate::types::AngleLink;
|
use crate::types::AngleLink;
|
||||||
use crate::types::BabelCall;
|
use crate::types::BabelCall;
|
||||||
use crate::types::Bold;
|
use crate::types::Bold;
|
||||||
@@ -21,7 +24,7 @@ use crate::types::ExportSnippet;
|
|||||||
use crate::types::FixedWidthArea;
|
use crate::types::FixedWidthArea;
|
||||||
use crate::types::FootnoteDefinition;
|
use crate::types::FootnoteDefinition;
|
||||||
use crate::types::FootnoteReference;
|
use crate::types::FootnoteReference;
|
||||||
use crate::types::GreaterBlock;
|
use crate::types::GetStandardProperties;
|
||||||
use crate::types::Heading;
|
use crate::types::Heading;
|
||||||
use crate::types::HorizontalRule;
|
use crate::types::HorizontalRule;
|
||||||
use crate::types::InlineBabelCall;
|
use crate::types::InlineBabelCall;
|
||||||
@@ -68,7 +71,9 @@ pub enum AstNode<'r, 's> {
|
|||||||
Paragraph(&'r Paragraph<'s>),
|
Paragraph(&'r Paragraph<'s>),
|
||||||
PlainList(&'r PlainList<'s>),
|
PlainList(&'r PlainList<'s>),
|
||||||
PlainListItem(&'r PlainListItem<'s>),
|
PlainListItem(&'r PlainListItem<'s>),
|
||||||
GreaterBlock(&'r GreaterBlock<'s>),
|
CenterBlock(&'r CenterBlock<'s>),
|
||||||
|
QuoteBlock(&'r QuoteBlock<'s>),
|
||||||
|
SpecialBlock(&'r SpecialBlock<'s>),
|
||||||
DynamicBlock(&'r DynamicBlock<'s>),
|
DynamicBlock(&'r DynamicBlock<'s>),
|
||||||
FootnoteDefinition(&'r FootnoteDefinition<'s>),
|
FootnoteDefinition(&'r FootnoteDefinition<'s>),
|
||||||
Comment(&'r Comment<'s>),
|
Comment(&'r Comment<'s>),
|
||||||
@@ -135,7 +140,9 @@ impl<'r, 's> From<&'r Element<'s>> for AstNode<'r, 's> {
|
|||||||
match value {
|
match value {
|
||||||
Element::Paragraph(inner) => inner.into(),
|
Element::Paragraph(inner) => inner.into(),
|
||||||
Element::PlainList(inner) => inner.into(),
|
Element::PlainList(inner) => inner.into(),
|
||||||
Element::GreaterBlock(inner) => inner.into(),
|
Element::CenterBlock(inner) => inner.into(),
|
||||||
|
Element::QuoteBlock(inner) => inner.into(),
|
||||||
|
Element::SpecialBlock(inner) => inner.into(),
|
||||||
Element::DynamicBlock(inner) => inner.into(),
|
Element::DynamicBlock(inner) => inner.into(),
|
||||||
Element::FootnoteDefinition(inner) => inner.into(),
|
Element::FootnoteDefinition(inner) => inner.into(),
|
||||||
Element::Comment(inner) => inner.into(),
|
Element::Comment(inner) => inner.into(),
|
||||||
@@ -199,7 +206,9 @@ to_ast_node!(&'r Section<'s>, AstNode::Section);
|
|||||||
to_ast_node!(&'r Paragraph<'s>, AstNode::Paragraph);
|
to_ast_node!(&'r Paragraph<'s>, AstNode::Paragraph);
|
||||||
to_ast_node!(&'r PlainList<'s>, AstNode::PlainList);
|
to_ast_node!(&'r PlainList<'s>, AstNode::PlainList);
|
||||||
to_ast_node!(&'r PlainListItem<'s>, AstNode::PlainListItem);
|
to_ast_node!(&'r PlainListItem<'s>, AstNode::PlainListItem);
|
||||||
to_ast_node!(&'r GreaterBlock<'s>, AstNode::GreaterBlock);
|
to_ast_node!(&'r CenterBlock<'s>, AstNode::CenterBlock);
|
||||||
|
to_ast_node!(&'r QuoteBlock<'s>, AstNode::QuoteBlock);
|
||||||
|
to_ast_node!(&'r SpecialBlock<'s>, AstNode::SpecialBlock);
|
||||||
to_ast_node!(&'r DynamicBlock<'s>, AstNode::DynamicBlock);
|
to_ast_node!(&'r DynamicBlock<'s>, AstNode::DynamicBlock);
|
||||||
to_ast_node!(&'r FootnoteDefinition<'s>, AstNode::FootnoteDefinition);
|
to_ast_node!(&'r FootnoteDefinition<'s>, AstNode::FootnoteDefinition);
|
||||||
to_ast_node!(&'r Comment<'s>, AstNode::Comment);
|
to_ast_node!(&'r Comment<'s>, AstNode::Comment);
|
||||||
@@ -249,3 +258,68 @@ to_ast_node!(&'r Subscript<'s>, AstNode::Subscript);
|
|||||||
to_ast_node!(&'r Superscript<'s>, AstNode::Superscript);
|
to_ast_node!(&'r Superscript<'s>, AstNode::Superscript);
|
||||||
to_ast_node!(&'r TableCell<'s>, AstNode::TableCell);
|
to_ast_node!(&'r TableCell<'s>, AstNode::TableCell);
|
||||||
to_ast_node!(&'r Timestamp<'s>, AstNode::Timestamp);
|
to_ast_node!(&'r Timestamp<'s>, AstNode::Timestamp);
|
||||||
|
|
||||||
|
impl<'r, 's> GetStandardProperties<'s> for AstNode<'r, 's> {
|
||||||
|
fn get_standard_properties<'b>(&'b self) -> &'b dyn crate::types::StandardProperties<'s> {
|
||||||
|
match self {
|
||||||
|
AstNode::Document(inner) => *inner,
|
||||||
|
AstNode::Heading(inner) => *inner,
|
||||||
|
AstNode::Section(inner) => *inner,
|
||||||
|
AstNode::Paragraph(inner) => *inner,
|
||||||
|
AstNode::PlainList(inner) => *inner,
|
||||||
|
AstNode::PlainListItem(inner) => *inner,
|
||||||
|
AstNode::CenterBlock(inner) => *inner,
|
||||||
|
AstNode::QuoteBlock(inner) => *inner,
|
||||||
|
AstNode::SpecialBlock(inner) => *inner,
|
||||||
|
AstNode::DynamicBlock(inner) => *inner,
|
||||||
|
AstNode::FootnoteDefinition(inner) => *inner,
|
||||||
|
AstNode::Comment(inner) => *inner,
|
||||||
|
AstNode::Drawer(inner) => *inner,
|
||||||
|
AstNode::PropertyDrawer(inner) => *inner,
|
||||||
|
AstNode::NodeProperty(inner) => *inner,
|
||||||
|
AstNode::Table(inner) => *inner,
|
||||||
|
AstNode::TableRow(inner) => *inner,
|
||||||
|
AstNode::VerseBlock(inner) => *inner,
|
||||||
|
AstNode::CommentBlock(inner) => *inner,
|
||||||
|
AstNode::ExampleBlock(inner) => *inner,
|
||||||
|
AstNode::ExportBlock(inner) => *inner,
|
||||||
|
AstNode::SrcBlock(inner) => *inner,
|
||||||
|
AstNode::Clock(inner) => *inner,
|
||||||
|
AstNode::DiarySexp(inner) => *inner,
|
||||||
|
AstNode::Planning(inner) => *inner,
|
||||||
|
AstNode::FixedWidthArea(inner) => *inner,
|
||||||
|
AstNode::HorizontalRule(inner) => *inner,
|
||||||
|
AstNode::Keyword(inner) => *inner,
|
||||||
|
AstNode::BabelCall(inner) => *inner,
|
||||||
|
AstNode::LatexEnvironment(inner) => *inner,
|
||||||
|
AstNode::Bold(inner) => *inner,
|
||||||
|
AstNode::Italic(inner) => *inner,
|
||||||
|
AstNode::Underline(inner) => *inner,
|
||||||
|
AstNode::StrikeThrough(inner) => *inner,
|
||||||
|
AstNode::Code(inner) => *inner,
|
||||||
|
AstNode::Verbatim(inner) => *inner,
|
||||||
|
AstNode::PlainText(inner) => *inner,
|
||||||
|
AstNode::RegularLink(inner) => *inner,
|
||||||
|
AstNode::RadioLink(inner) => *inner,
|
||||||
|
AstNode::RadioTarget(inner) => *inner,
|
||||||
|
AstNode::PlainLink(inner) => *inner,
|
||||||
|
AstNode::AngleLink(inner) => *inner,
|
||||||
|
AstNode::OrgMacro(inner) => *inner,
|
||||||
|
AstNode::Entity(inner) => *inner,
|
||||||
|
AstNode::LatexFragment(inner) => *inner,
|
||||||
|
AstNode::ExportSnippet(inner) => *inner,
|
||||||
|
AstNode::FootnoteReference(inner) => *inner,
|
||||||
|
AstNode::Citation(inner) => *inner,
|
||||||
|
AstNode::CitationReference(inner) => *inner,
|
||||||
|
AstNode::InlineBabelCall(inner) => *inner,
|
||||||
|
AstNode::InlineSourceBlock(inner) => *inner,
|
||||||
|
AstNode::LineBreak(inner) => *inner,
|
||||||
|
AstNode::Target(inner) => *inner,
|
||||||
|
AstNode::StatisticsCookie(inner) => *inner,
|
||||||
|
AstNode::Subscript(inner) => *inner,
|
||||||
|
AstNode::Superscript(inner) => *inner,
|
||||||
|
AstNode::TableCell(inner) => *inner,
|
||||||
|
AstNode::Timestamp(inner) => *inner,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ use super::Element;
|
|||||||
use super::GetStandardProperties;
|
use super::GetStandardProperties;
|
||||||
use super::Object;
|
use super::Object;
|
||||||
use super::StandardProperties;
|
use super::StandardProperties;
|
||||||
|
use super::Timestamp;
|
||||||
|
|
||||||
pub type PriorityCookie = u8;
|
pub type PriorityCookie = u8;
|
||||||
pub type HeadlineLevel = u16;
|
pub type HeadlineLevel = u16;
|
||||||
@@ -29,6 +30,9 @@ pub struct Heading<'s> {
|
|||||||
pub is_comment: bool,
|
pub is_comment: bool,
|
||||||
pub is_archived: bool,
|
pub is_archived: bool,
|
||||||
pub is_footnote_section: bool,
|
pub is_footnote_section: bool,
|
||||||
|
pub scheduled: Option<Timestamp<'s>>,
|
||||||
|
pub deadline: Option<Timestamp<'s>>,
|
||||||
|
pub closed: Option<Timestamp<'s>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -50,7 +54,7 @@ pub enum TodoKeywordType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> GetStandardProperties<'s> for DocumentElement<'s> {
|
impl<'s> GetStandardProperties<'s> for DocumentElement<'s> {
|
||||||
fn get_standard_properties(&'s self) -> &'s dyn StandardProperties {
|
fn get_standard_properties<'b>(&'b self) -> &'b dyn StandardProperties<'s> {
|
||||||
match self {
|
match self {
|
||||||
DocumentElement::Heading(inner) => inner,
|
DocumentElement::Heading(inner) => inner,
|
||||||
DocumentElement::Section(inner) => inner,
|
DocumentElement::Section(inner) => inner,
|
||||||
@@ -59,19 +63,19 @@ impl<'s> GetStandardProperties<'s> for DocumentElement<'s> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for Document<'s> {
|
impl<'s> StandardProperties<'s> for Document<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for Section<'s> {
|
impl<'s> StandardProperties<'s> for Section<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for Heading<'s> {
|
impl<'s> StandardProperties<'s> for Heading<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
use super::greater_element::DynamicBlock;
|
use super::greater_element::DynamicBlock;
|
||||||
use super::greater_element::FootnoteDefinition;
|
use super::greater_element::FootnoteDefinition;
|
||||||
use super::greater_element::GreaterBlock;
|
|
||||||
use super::greater_element::PlainList;
|
use super::greater_element::PlainList;
|
||||||
use super::greater_element::PropertyDrawer;
|
use super::greater_element::PropertyDrawer;
|
||||||
use super::greater_element::Table;
|
use super::greater_element::Table;
|
||||||
@@ -19,16 +18,21 @@ use super::lesser_element::Paragraph;
|
|||||||
use super::lesser_element::Planning;
|
use super::lesser_element::Planning;
|
||||||
use super::lesser_element::SrcBlock;
|
use super::lesser_element::SrcBlock;
|
||||||
use super::lesser_element::VerseBlock;
|
use super::lesser_element::VerseBlock;
|
||||||
|
use super::CenterBlock;
|
||||||
use super::Drawer;
|
use super::Drawer;
|
||||||
use super::GetStandardProperties;
|
use super::GetStandardProperties;
|
||||||
|
use super::QuoteBlock;
|
||||||
use super::SetSource;
|
use super::SetSource;
|
||||||
|
use super::SpecialBlock;
|
||||||
use super::StandardProperties;
|
use super::StandardProperties;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Element<'s> {
|
pub enum Element<'s> {
|
||||||
Paragraph(Paragraph<'s>),
|
Paragraph(Paragraph<'s>),
|
||||||
PlainList(PlainList<'s>),
|
PlainList(PlainList<'s>),
|
||||||
GreaterBlock(GreaterBlock<'s>),
|
CenterBlock(CenterBlock<'s>),
|
||||||
|
QuoteBlock(QuoteBlock<'s>),
|
||||||
|
SpecialBlock(SpecialBlock<'s>),
|
||||||
DynamicBlock(DynamicBlock<'s>),
|
DynamicBlock(DynamicBlock<'s>),
|
||||||
FootnoteDefinition(FootnoteDefinition<'s>),
|
FootnoteDefinition(FootnoteDefinition<'s>),
|
||||||
Comment(Comment<'s>),
|
Comment(Comment<'s>),
|
||||||
@@ -56,7 +60,9 @@ impl<'s> SetSource<'s> for Element<'s> {
|
|||||||
match self {
|
match self {
|
||||||
Element::Paragraph(obj) => obj.source = source,
|
Element::Paragraph(obj) => obj.source = source,
|
||||||
Element::PlainList(obj) => obj.source = source,
|
Element::PlainList(obj) => obj.source = source,
|
||||||
Element::GreaterBlock(obj) => obj.source = source,
|
Element::CenterBlock(obj) => obj.source = source,
|
||||||
|
Element::QuoteBlock(obj) => obj.source = source,
|
||||||
|
Element::SpecialBlock(obj) => obj.source = source,
|
||||||
Element::DynamicBlock(obj) => obj.source = source,
|
Element::DynamicBlock(obj) => obj.source = source,
|
||||||
Element::FootnoteDefinition(obj) => obj.source = source,
|
Element::FootnoteDefinition(obj) => obj.source = source,
|
||||||
Element::Comment(obj) => obj.source = source,
|
Element::Comment(obj) => obj.source = source,
|
||||||
@@ -81,11 +87,13 @@ impl<'s> SetSource<'s> for Element<'s> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> GetStandardProperties<'s> for Element<'s> {
|
impl<'s> GetStandardProperties<'s> for Element<'s> {
|
||||||
fn get_standard_properties(&'s self) -> &'s dyn StandardProperties {
|
fn get_standard_properties<'b>(&'b self) -> &'b dyn StandardProperties<'s> {
|
||||||
match self {
|
match self {
|
||||||
Element::Paragraph(inner) => inner,
|
Element::Paragraph(inner) => inner,
|
||||||
Element::PlainList(inner) => inner,
|
Element::PlainList(inner) => inner,
|
||||||
Element::GreaterBlock(inner) => inner,
|
Element::CenterBlock(inner) => inner,
|
||||||
|
Element::QuoteBlock(inner) => inner,
|
||||||
|
Element::SpecialBlock(inner) => inner,
|
||||||
Element::DynamicBlock(inner) => inner,
|
Element::DynamicBlock(inner) => inner,
|
||||||
Element::FootnoteDefinition(inner) => inner,
|
Element::FootnoteDefinition(inner) => inner,
|
||||||
Element::Comment(inner) => inner,
|
Element::Comment(inner) => inner,
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ use super::StandardProperties;
|
|||||||
|
|
||||||
pub trait GetStandardProperties<'s> {
|
pub trait GetStandardProperties<'s> {
|
||||||
// TODO: Can I eliminate this dynamic dispatch, perhaps using nominal generic structs? Low prioritiy since this is not used during parsing.
|
// TODO: Can I eliminate this dynamic dispatch, perhaps using nominal generic structs? Low prioritiy since this is not used during parsing.
|
||||||
fn get_standard_properties(&'s self) -> &'s dyn StandardProperties;
|
fn get_standard_properties<'b>(&'b self) -> &'b dyn StandardProperties<'s>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s, I: StandardProperties<'s>> GetStandardProperties<'s> for I {
|
impl<'s, I: StandardProperties<'s>> GetStandardProperties<'s> for I {
|
||||||
fn get_standard_properties(&'s self) -> &'s dyn StandardProperties {
|
fn get_standard_properties<'b>(&'b self) -> &'b dyn StandardProperties<'s> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,19 @@ pub enum CheckboxType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct GreaterBlock<'s> {
|
pub struct CenterBlock<'s> {
|
||||||
|
pub source: &'s str,
|
||||||
|
pub children: Vec<Element<'s>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct QuoteBlock<'s> {
|
||||||
|
pub source: &'s str,
|
||||||
|
pub children: Vec<Element<'s>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct SpecialBlock<'s> {
|
||||||
pub source: &'s str,
|
pub source: &'s str,
|
||||||
pub name: &'s str,
|
pub name: &'s str,
|
||||||
pub parameters: Option<&'s str>,
|
pub parameters: Option<&'s str>,
|
||||||
@@ -82,6 +94,7 @@ pub struct PropertyDrawer<'s> {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct NodeProperty<'s> {
|
pub struct NodeProperty<'s> {
|
||||||
pub source: &'s str,
|
pub source: &'s str,
|
||||||
|
pub name: &'s str,
|
||||||
pub value: Option<&'s str>,
|
pub value: Option<&'s str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,62 +111,80 @@ pub struct TableRow<'s> {
|
|||||||
pub children: Vec<TableCell<'s>>,
|
pub children: Vec<TableCell<'s>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum TableRowType {
|
||||||
|
Standard,
|
||||||
|
Rule,
|
||||||
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for PlainList<'s> {
|
impl<'s> StandardProperties<'s> for PlainList<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for PlainListItem<'s> {
|
impl<'s> StandardProperties<'s> for PlainListItem<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for GreaterBlock<'s> {
|
impl<'s> StandardProperties<'s> for CenterBlock<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
|
self.source
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'s> StandardProperties<'s> for QuoteBlock<'s> {
|
||||||
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
|
self.source
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'s> StandardProperties<'s> for SpecialBlock<'s> {
|
||||||
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for DynamicBlock<'s> {
|
impl<'s> StandardProperties<'s> for DynamicBlock<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for FootnoteDefinition<'s> {
|
impl<'s> StandardProperties<'s> for FootnoteDefinition<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for Drawer<'s> {
|
impl<'s> StandardProperties<'s> for Drawer<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for PropertyDrawer<'s> {
|
impl<'s> StandardProperties<'s> for PropertyDrawer<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for NodeProperty<'s> {
|
impl<'s> StandardProperties<'s> for NodeProperty<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for Table<'s> {
|
impl<'s> StandardProperties<'s> for Table<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for TableRow<'s> {
|
impl<'s> StandardProperties<'s> for TableRow<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -169,3 +200,13 @@ impl<'s> PlainListItem<'s> {
|
|||||||
.map(|(checkbox_type, _)| checkbox_type)
|
.map(|(checkbox_type, _)| checkbox_type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'s> TableRow<'s> {
|
||||||
|
pub fn get_type(&self) -> TableRowType {
|
||||||
|
if self.children.is_empty() {
|
||||||
|
TableRowType::Rule
|
||||||
|
} else {
|
||||||
|
TableRowType::Standard
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
use super::object::Object;
|
use super::object::Object;
|
||||||
use super::PlainText;
|
use super::PlainText;
|
||||||
use super::StandardProperties;
|
use super::StandardProperties;
|
||||||
|
use super::Timestamp;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Paragraph<'s> {
|
pub struct Paragraph<'s> {
|
||||||
@@ -11,6 +12,7 @@ pub struct Paragraph<'s> {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Comment<'s> {
|
pub struct Comment<'s> {
|
||||||
pub source: &'s str,
|
pub source: &'s str,
|
||||||
|
pub value: Vec<&'s str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -72,6 +74,9 @@ pub struct DiarySexp<'s> {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Planning<'s> {
|
pub struct Planning<'s> {
|
||||||
pub source: &'s str,
|
pub source: &'s str,
|
||||||
|
pub scheduled: Option<Timestamp<'s>>,
|
||||||
|
pub deadline: Option<Timestamp<'s>>,
|
||||||
|
pub closed: Option<Timestamp<'s>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -115,93 +120,106 @@ impl<'s> Paragraph<'s> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for Paragraph<'s> {
|
impl<'s> StandardProperties<'s> for Paragraph<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for TableCell<'s> {
|
impl<'s> StandardProperties<'s> for TableCell<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for Comment<'s> {
|
impl<'s> StandardProperties<'s> for Comment<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for VerseBlock<'s> {
|
impl<'s> StandardProperties<'s> for VerseBlock<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<'s> StandardProperties<'s> for CommentBlock<'s> {
|
impl<'s> StandardProperties<'s> for CommentBlock<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<'s> StandardProperties<'s> for ExampleBlock<'s> {
|
impl<'s> StandardProperties<'s> for ExampleBlock<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<'s> StandardProperties<'s> for ExportBlock<'s> {
|
impl<'s> StandardProperties<'s> for ExportBlock<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<'s> StandardProperties<'s> for SrcBlock<'s> {
|
impl<'s> StandardProperties<'s> for SrcBlock<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for Clock<'s> {
|
impl<'s> StandardProperties<'s> for Clock<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for DiarySexp<'s> {
|
impl<'s> StandardProperties<'s> for DiarySexp<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for Planning<'s> {
|
impl<'s> StandardProperties<'s> for Planning<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for FixedWidthArea<'s> {
|
impl<'s> StandardProperties<'s> for FixedWidthArea<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for HorizontalRule<'s> {
|
impl<'s> StandardProperties<'s> for HorizontalRule<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for Keyword<'s> {
|
impl<'s> StandardProperties<'s> for Keyword<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for BabelCall<'s> {
|
impl<'s> StandardProperties<'s> for BabelCall<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for LatexEnvironment<'s> {
|
impl<'s> StandardProperties<'s> for LatexEnvironment<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'s> Comment<'s> {
|
||||||
|
pub fn get_value(&self) -> String {
|
||||||
|
// TODO: maybe we should handle parsing here instead of storing the parsing result in the AST since I imagine getting the value of comments won't be a common operation.
|
||||||
|
let final_size = self.value.iter().map(|line| line.len()).sum();
|
||||||
|
let mut ret = String::with_capacity(final_size);
|
||||||
|
for line in &self.value {
|
||||||
|
ret.push_str(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
12
src/types/macros.rs
Normal file
12
src/types/macros.rs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
/// Write the implementation of From<> to convert a borrow of the type to an AstNode
|
||||||
|
macro_rules! to_ast_node {
|
||||||
|
($inp:ty, $enum:expr) => {
|
||||||
|
impl<'r, 's> From<$inp> for AstNode<'r, 's> {
|
||||||
|
fn from(value: $inp) -> Self {
|
||||||
|
$enum(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) use to_ast_node;
|
||||||
@@ -1,11 +1,14 @@
|
|||||||
|
mod ast_node;
|
||||||
mod document;
|
mod document;
|
||||||
mod element;
|
mod element;
|
||||||
mod get_standard_properties;
|
mod get_standard_properties;
|
||||||
mod greater_element;
|
mod greater_element;
|
||||||
mod lesser_element;
|
mod lesser_element;
|
||||||
|
mod macros;
|
||||||
mod object;
|
mod object;
|
||||||
mod source;
|
mod source;
|
||||||
mod standard_properties;
|
mod standard_properties;
|
||||||
|
pub(crate) use ast_node::AstNode;
|
||||||
pub use document::Document;
|
pub use document::Document;
|
||||||
pub use document::DocumentElement;
|
pub use document::DocumentElement;
|
||||||
pub use document::Heading;
|
pub use document::Heading;
|
||||||
@@ -15,11 +18,11 @@ pub use document::Section;
|
|||||||
pub use document::TodoKeywordType;
|
pub use document::TodoKeywordType;
|
||||||
pub use element::Element;
|
pub use element::Element;
|
||||||
pub use get_standard_properties::GetStandardProperties;
|
pub use get_standard_properties::GetStandardProperties;
|
||||||
|
pub use greater_element::CenterBlock;
|
||||||
pub use greater_element::CheckboxType;
|
pub use greater_element::CheckboxType;
|
||||||
pub use greater_element::Drawer;
|
pub use greater_element::Drawer;
|
||||||
pub use greater_element::DynamicBlock;
|
pub use greater_element::DynamicBlock;
|
||||||
pub use greater_element::FootnoteDefinition;
|
pub use greater_element::FootnoteDefinition;
|
||||||
pub use greater_element::GreaterBlock;
|
|
||||||
pub use greater_element::IndentationLevel;
|
pub use greater_element::IndentationLevel;
|
||||||
pub use greater_element::NodeProperty;
|
pub use greater_element::NodeProperty;
|
||||||
pub use greater_element::PlainList;
|
pub use greater_element::PlainList;
|
||||||
@@ -28,8 +31,11 @@ pub use greater_element::PlainListItemCounter;
|
|||||||
pub use greater_element::PlainListItemPreBlank;
|
pub use greater_element::PlainListItemPreBlank;
|
||||||
pub use greater_element::PlainListType;
|
pub use greater_element::PlainListType;
|
||||||
pub use greater_element::PropertyDrawer;
|
pub use greater_element::PropertyDrawer;
|
||||||
|
pub use greater_element::QuoteBlock;
|
||||||
|
pub use greater_element::SpecialBlock;
|
||||||
pub use greater_element::Table;
|
pub use greater_element::Table;
|
||||||
pub use greater_element::TableRow;
|
pub use greater_element::TableRow;
|
||||||
|
pub use greater_element::TableRowType;
|
||||||
pub use lesser_element::BabelCall;
|
pub use lesser_element::BabelCall;
|
||||||
pub use lesser_element::Clock;
|
pub use lesser_element::Clock;
|
||||||
pub use lesser_element::Comment;
|
pub use lesser_element::Comment;
|
||||||
@@ -51,14 +57,23 @@ pub use object::Bold;
|
|||||||
pub use object::Citation;
|
pub use object::Citation;
|
||||||
pub use object::CitationReference;
|
pub use object::CitationReference;
|
||||||
pub use object::Code;
|
pub use object::Code;
|
||||||
|
pub use object::Date;
|
||||||
|
pub use object::DayOfMonth;
|
||||||
|
pub use object::DayOfMonthInner;
|
||||||
pub use object::Entity;
|
pub use object::Entity;
|
||||||
pub use object::ExportSnippet;
|
pub use object::ExportSnippet;
|
||||||
pub use object::FootnoteReference;
|
pub use object::FootnoteReference;
|
||||||
|
pub use object::Hour;
|
||||||
|
pub use object::HourInner;
|
||||||
pub use object::InlineBabelCall;
|
pub use object::InlineBabelCall;
|
||||||
pub use object::InlineSourceBlock;
|
pub use object::InlineSourceBlock;
|
||||||
pub use object::Italic;
|
pub use object::Italic;
|
||||||
pub use object::LatexFragment;
|
pub use object::LatexFragment;
|
||||||
pub use object::LineBreak;
|
pub use object::LineBreak;
|
||||||
|
pub use object::Minute;
|
||||||
|
pub use object::MinuteInner;
|
||||||
|
pub use object::Month;
|
||||||
|
pub use object::MonthInner;
|
||||||
pub use object::Object;
|
pub use object::Object;
|
||||||
pub use object::OrgMacro;
|
pub use object::OrgMacro;
|
||||||
pub use object::PlainLink;
|
pub use object::PlainLink;
|
||||||
@@ -66,13 +81,24 @@ pub use object::PlainText;
|
|||||||
pub use object::RadioLink;
|
pub use object::RadioLink;
|
||||||
pub use object::RadioTarget;
|
pub use object::RadioTarget;
|
||||||
pub use object::RegularLink;
|
pub use object::RegularLink;
|
||||||
|
pub use object::Repeater;
|
||||||
|
pub use object::RepeaterType;
|
||||||
|
pub use object::RepeaterWarningDelayValueType;
|
||||||
pub use object::StatisticsCookie;
|
pub use object::StatisticsCookie;
|
||||||
pub use object::StrikeThrough;
|
pub use object::StrikeThrough;
|
||||||
pub use object::Subscript;
|
pub use object::Subscript;
|
||||||
pub use object::Superscript;
|
pub use object::Superscript;
|
||||||
pub use object::Target;
|
pub use object::Target;
|
||||||
|
pub use object::Time;
|
||||||
|
pub use object::TimeUnit;
|
||||||
pub use object::Timestamp;
|
pub use object::Timestamp;
|
||||||
|
pub use object::TimestampRangeType;
|
||||||
|
pub use object::TimestampType;
|
||||||
pub use object::Underline;
|
pub use object::Underline;
|
||||||
pub use object::Verbatim;
|
pub use object::Verbatim;
|
||||||
|
pub use object::WarningDelay;
|
||||||
|
pub use object::WarningDelayType;
|
||||||
|
pub use object::Year;
|
||||||
|
pub use object::YearInner;
|
||||||
pub(crate) use source::SetSource;
|
pub(crate) use source::SetSource;
|
||||||
pub use standard_properties::StandardProperties;
|
pub use standard_properties::StandardProperties;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
use super::GetStandardProperties;
|
use super::GetStandardProperties;
|
||||||
use super::StandardProperties;
|
use super::StandardProperties;
|
||||||
|
|
||||||
|
// TODO: Why did we make Object implement PartialEq again? Was it just for tests?
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum Object<'s> {
|
pub enum Object<'s> {
|
||||||
Bold(Bold<'s>),
|
Bold(Bold<'s>),
|
||||||
@@ -181,13 +182,260 @@ pub struct Superscript<'s> {
|
|||||||
pub source: &'s str,
|
pub source: &'s str,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub struct Timestamp<'s> {
|
pub struct Timestamp<'s> {
|
||||||
pub source: &'s str,
|
pub source: &'s str,
|
||||||
|
pub timestamp_type: TimestampType,
|
||||||
|
pub range_type: TimestampRangeType,
|
||||||
|
pub start: Option<Date<'s>>,
|
||||||
|
pub end: Option<Date<'s>>,
|
||||||
|
pub start_time: Option<Time<'s>>,
|
||||||
|
pub end_time: Option<Time<'s>>,
|
||||||
|
pub repeater: Option<Repeater>,
|
||||||
|
pub warning_delay: Option<WarningDelay>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
pub enum TimestampType {
|
||||||
|
Diary,
|
||||||
|
Active,
|
||||||
|
Inactive,
|
||||||
|
ActiveRange,
|
||||||
|
InactiveRange,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
pub enum TimestampRangeType {
|
||||||
|
None,
|
||||||
|
DateRange,
|
||||||
|
TimeRange,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type YearInner = u16;
|
||||||
|
pub type MonthInner = u8;
|
||||||
|
pub type DayOfMonthInner = u8;
|
||||||
|
pub type HourInner = u8;
|
||||||
|
pub type MinuteInner = u8;
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
pub struct Year(YearInner);
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
pub struct Month(MonthInner);
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
pub struct DayOfMonth(DayOfMonthInner);
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
pub struct Hour(HourInner);
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
pub struct Minute(MinuteInner);
|
||||||
|
|
||||||
|
impl Year {
|
||||||
|
// TODO: Make a real error type instead of a boxed any error.
|
||||||
|
pub fn new<'s>(source: &'s str) -> Result<Self, Box<dyn std::error::Error>> {
|
||||||
|
let year = source.parse::<YearInner>()?;
|
||||||
|
Ok(Year(year))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_value(&self) -> YearInner {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Month {
|
||||||
|
// TODO: Make a real error type instead of a boxed any error.
|
||||||
|
pub fn new<'s>(source: &'s str) -> Result<Self, Box<dyn std::error::Error>> {
|
||||||
|
let month = source.parse::<MonthInner>()?;
|
||||||
|
if month < 1 || month > 12 {
|
||||||
|
Err("Month exceeds possible range.")?;
|
||||||
|
}
|
||||||
|
Ok(Month(month))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_value(&self) -> MonthInner {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DayOfMonth {
|
||||||
|
// TODO: Make a real error type instead of a boxed any error.
|
||||||
|
pub fn new<'s>(source: &'s str) -> Result<Self, Box<dyn std::error::Error>> {
|
||||||
|
let day_of_month = source.parse::<DayOfMonthInner>()?;
|
||||||
|
if day_of_month < 1 || day_of_month > 31 {
|
||||||
|
Err("Day of month exceeds possible range.")?;
|
||||||
|
}
|
||||||
|
Ok(DayOfMonth(day_of_month))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_value(&self) -> DayOfMonthInner {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hour {
|
||||||
|
// TODO: Make a real error type instead of a boxed any error.
|
||||||
|
pub fn new<'s>(source: &'s str) -> Result<Self, Box<dyn std::error::Error>> {
|
||||||
|
let hour = source.parse::<HourInner>()?;
|
||||||
|
if hour > 23 {
|
||||||
|
Err("Hour exceeds possible range.")?;
|
||||||
|
}
|
||||||
|
Ok(Hour(hour))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_value(&self) -> HourInner {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Minute {
|
||||||
|
// TODO: Make a real error type instead of a boxed any error.
|
||||||
|
pub fn new<'s>(source: &'s str) -> Result<Self, Box<dyn std::error::Error>> {
|
||||||
|
let minute = source.parse::<MinuteInner>()?;
|
||||||
|
if minute > 59 {
|
||||||
|
Err("Minute exceeds possible range.")?;
|
||||||
|
}
|
||||||
|
Ok(Minute(minute))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_value(&self) -> MinuteInner {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
pub struct Date<'s> {
|
||||||
|
year: Year,
|
||||||
|
month: Month,
|
||||||
|
day_of_month: DayOfMonth,
|
||||||
|
day_name: Option<&'s str>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'s> Date<'s> {
|
||||||
|
// TODO: Make a real error type instead of a boxed any error.
|
||||||
|
pub fn new(
|
||||||
|
year: Year,
|
||||||
|
month: Month,
|
||||||
|
day_of_month: DayOfMonth,
|
||||||
|
day_name: Option<&'s str>,
|
||||||
|
) -> Result<Self, Box<dyn std::error::Error>> {
|
||||||
|
// TODO: Does org-mode support non-gregorian calendars?
|
||||||
|
// TODO: Do I want to validate leap year?
|
||||||
|
match (month.get_value(), day_of_month.get_value()) {
|
||||||
|
(1, 1..=31) => {}
|
||||||
|
(2, 1..=29) => {}
|
||||||
|
(3, 1..=31) => {}
|
||||||
|
(4, 1..=30) => {}
|
||||||
|
(5, 1..=31) => {}
|
||||||
|
(6, 1..=30) => {}
|
||||||
|
(7, 1..=31) => {}
|
||||||
|
(8, 1..=31) => {}
|
||||||
|
(9, 1..=30) => {}
|
||||||
|
(10, 1..=31) => {}
|
||||||
|
(11, 1..=30) => {}
|
||||||
|
(12, 1..=31) => {}
|
||||||
|
_ => Err("Invalid day of month for the month.")?,
|
||||||
|
};
|
||||||
|
Ok(Date {
|
||||||
|
year,
|
||||||
|
month,
|
||||||
|
day_of_month,
|
||||||
|
day_name,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_year(&self) -> &Year {
|
||||||
|
&self.year
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_month(&self) -> &Month {
|
||||||
|
&self.month
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_day_of_month(&self) -> &DayOfMonth {
|
||||||
|
&self.day_of_month
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_day_name(&self) -> Option<&'s str> {
|
||||||
|
self.day_name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
pub struct Time<'s> {
|
||||||
|
hour: Hour,
|
||||||
|
minute: Minute,
|
||||||
|
postfix: Option<&'s str>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'s> Time<'s> {
|
||||||
|
// TODO: Make a real error type instead of a boxed any error.
|
||||||
|
pub fn new(
|
||||||
|
hour: Hour,
|
||||||
|
minute: Minute,
|
||||||
|
postfix: Option<&'s str>,
|
||||||
|
) -> Result<Self, Box<dyn std::error::Error>> {
|
||||||
|
Ok(Time {
|
||||||
|
hour,
|
||||||
|
minute,
|
||||||
|
postfix,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_hour(&self) -> &Hour {
|
||||||
|
&self.hour
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_minute(&self) -> &Minute {
|
||||||
|
&self.minute
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_postfix(&self) -> Option<&'s str> {
|
||||||
|
self.postfix
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
pub enum RepeaterType {
|
||||||
|
Cumulative,
|
||||||
|
CatchUp,
|
||||||
|
Restart,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
pub enum WarningDelayType {
|
||||||
|
All,
|
||||||
|
First,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
pub enum TimeUnit {
|
||||||
|
Hour,
|
||||||
|
Day,
|
||||||
|
Week,
|
||||||
|
Month,
|
||||||
|
Year,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type RepeaterWarningDelayValueType = u16;
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
pub struct Repeater {
|
||||||
|
pub repeater_type: RepeaterType,
|
||||||
|
pub value: RepeaterWarningDelayValueType,
|
||||||
|
pub unit: TimeUnit,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
pub struct WarningDelay {
|
||||||
|
pub warning_delay_type: WarningDelayType,
|
||||||
|
pub value: RepeaterWarningDelayValueType,
|
||||||
|
pub unit: TimeUnit,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> GetStandardProperties<'s> for Object<'s> {
|
impl<'s> GetStandardProperties<'s> for Object<'s> {
|
||||||
fn get_standard_properties(&'s self) -> &'s dyn StandardProperties {
|
fn get_standard_properties<'b>(&'b self) -> &'b dyn StandardProperties<'s> {
|
||||||
match self {
|
match self {
|
||||||
Object::Bold(inner) => inner,
|
Object::Bold(inner) => inner,
|
||||||
Object::Italic(inner) => inner,
|
Object::Italic(inner) => inner,
|
||||||
@@ -221,163 +469,169 @@ impl<'s> GetStandardProperties<'s> for Object<'s> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for Bold<'s> {
|
impl<'s> StandardProperties<'s> for Bold<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for Italic<'s> {
|
impl<'s> StandardProperties<'s> for Italic<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for Underline<'s> {
|
impl<'s> StandardProperties<'s> for Underline<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for StrikeThrough<'s> {
|
impl<'s> StandardProperties<'s> for StrikeThrough<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for Code<'s> {
|
impl<'s> StandardProperties<'s> for Code<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for Verbatim<'s> {
|
impl<'s> StandardProperties<'s> for Verbatim<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for RegularLink<'s> {
|
impl<'s> StandardProperties<'s> for RegularLink<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for RadioLink<'s> {
|
impl<'s> StandardProperties<'s> for RadioLink<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for RadioTarget<'s> {
|
impl<'s> StandardProperties<'s> for RadioTarget<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for PlainLink<'s> {
|
impl<'s> StandardProperties<'s> for PlainLink<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for AngleLink<'s> {
|
impl<'s> StandardProperties<'s> for AngleLink<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for OrgMacro<'s> {
|
impl<'s> StandardProperties<'s> for OrgMacro<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for Entity<'s> {
|
impl<'s> StandardProperties<'s> for Entity<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for LatexFragment<'s> {
|
impl<'s> StandardProperties<'s> for LatexFragment<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for ExportSnippet<'s> {
|
impl<'s> StandardProperties<'s> for ExportSnippet<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for FootnoteReference<'s> {
|
impl<'s> StandardProperties<'s> for FootnoteReference<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for Citation<'s> {
|
impl<'s> StandardProperties<'s> for Citation<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for CitationReference<'s> {
|
impl<'s> StandardProperties<'s> for CitationReference<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for InlineBabelCall<'s> {
|
impl<'s> StandardProperties<'s> for InlineBabelCall<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for InlineSourceBlock<'s> {
|
impl<'s> StandardProperties<'s> for InlineSourceBlock<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for LineBreak<'s> {
|
impl<'s> StandardProperties<'s> for LineBreak<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for Target<'s> {
|
impl<'s> StandardProperties<'s> for Target<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for StatisticsCookie<'s> {
|
impl<'s> StandardProperties<'s> for StatisticsCookie<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for Subscript<'s> {
|
impl<'s> StandardProperties<'s> for Subscript<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for Superscript<'s> {
|
impl<'s> StandardProperties<'s> for Superscript<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for Timestamp<'s> {
|
impl<'s> StandardProperties<'s> for Timestamp<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'s> StandardProperties<'s> for PlainText<'s> {
|
impl<'s> StandardProperties<'s> for PlainText<'s> {
|
||||||
fn get_source(&'s self) -> &'s str {
|
fn get_source<'b>(&'b self) -> &'s str {
|
||||||
self.source
|
self.source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'s> Timestamp<'s> {
|
||||||
|
pub fn get_raw_value(&self) -> &'s str {
|
||||||
|
self.source.trim_end()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ pub trait StandardProperties<'s> {
|
|||||||
/// Get the slice of the entire AST node.
|
/// Get the slice of the entire AST node.
|
||||||
///
|
///
|
||||||
/// This corresponds to :begin to :end in upstream org-mode's standard properties.
|
/// This corresponds to :begin to :end in upstream org-mode's standard properties.
|
||||||
fn get_source(&'s self) -> &'s str;
|
fn get_source<'b>(&'b self) -> &'s str;
|
||||||
|
|
||||||
// Get the slice of the AST node's contents.
|
// Get the slice of the AST node's contents.
|
||||||
//
|
//
|
||||||
|
|||||||
Reference in New Issue
Block a user