Compare commits
18 Commits
7a4dc20dc9
...
v0.1.13
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
59222c58b1 | ||
|
|
4d95a7f244 | ||
|
|
5a8159eed7 | ||
|
|
e24fcb9ded | ||
|
|
4b94dc60d2 | ||
|
|
2046603d01 | ||
|
|
30412361e1 | ||
|
|
e846c85188 | ||
|
|
99b74095e6 | ||
|
|
6b802d36bf | ||
|
|
33ca43ca40 | ||
|
|
f5280a3090 | ||
|
|
c28d8ccea4 | ||
|
|
9690545901 | ||
|
|
eba4fb94cf | ||
|
|
565978225a | ||
|
|
cce9ca87fa | ||
|
|
683c523ece |
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "organic"
|
name = "organic"
|
||||||
version = "0.1.12"
|
version = "0.1.13"
|
||||||
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
org_mode_samples/document/empty.org
Normal file
0
org_mode_samples/document/empty.org
Normal file
4
org_mode_samples/document/only_line_breaks.org
Normal file
4
org_mode_samples/document/only_line_breaks.org
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
5
org_mode_samples/document/post_blank.org
Normal file
5
org_mode_samples/document/post_blank.org
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
* foo
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
: foo
|
||||||
|
:
|
||||||
|
: bar
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
1. foo
|
||||||
|
#+begin_src text
|
||||||
|
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
2. baz
|
||||||
3
org_mode_samples/object/target/simple.org
Normal file
3
org_mode_samples/object/target/simple.org
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<<FOO>> bar
|
||||||
|
|
||||||
|
[[FOO][baz]]
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
* foo
|
||||||
|
|
||||||
|
** bar
|
||||||
|
|
||||||
|
* baz
|
||||||
@@ -285,7 +285,7 @@ where
|
|||||||
pub(crate) fn compare_children<'b, 's, 'x, RC>(
|
pub(crate) fn compare_children<'b, 's, 'x, RC>(
|
||||||
source: &'s str,
|
source: &'s str,
|
||||||
emacs: &'b Token<'s>,
|
emacs: &'b Token<'s>,
|
||||||
rust_children: &'x Vec<RC>,
|
rust_children: &'x [RC],
|
||||||
child_status: &mut Vec<DiffEntry<'b, 's>>,
|
child_status: &mut Vec<DiffEntry<'b, 's>>,
|
||||||
this_status: &mut DiffStatus,
|
this_status: &mut DiffStatus,
|
||||||
message: &mut Option<String>,
|
message: &mut Option<String>,
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ pub(crate) fn record_event(event_type: EventType, input: OrgSource<'_>) {
|
|||||||
pub fn report(original_document: &str) {
|
pub fn report(original_document: &str) {
|
||||||
let mut db = GLOBAL_DATA.lock().unwrap();
|
let mut db = GLOBAL_DATA.lock().unwrap();
|
||||||
let db = db.get_or_insert_with(HashMap::new);
|
let db = db.get_or_insert_with(HashMap::new);
|
||||||
let mut results: Vec<_> = db.iter().map(|(k, v)| (k, v)).collect();
|
let mut results: Vec<_> = db.iter().collect();
|
||||||
results.sort_by_key(|(_k, v)| *v);
|
results.sort_by_key(|(_k, v)| *v);
|
||||||
// This would put the most common at the top, but that is a pain when there is already a lot of output from the parser.
|
// This would put the most common at the top, but that is a pain when there is already a lot of output from the parser.
|
||||||
// results.sort_by(|(_ak, av), (_bk, bv)| bv.cmp(av));
|
// results.sort_by(|(_ak, av), (_bk, bv)| bv.cmp(av));
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ pub(crate) fn broken_end<'b, 'g, 'r, 's>(
|
|||||||
match paragraph.children.first_mut() {
|
match paragraph.children.first_mut() {
|
||||||
Some(Object::PlainText(plain_text)) => {
|
Some(Object::PlainText(plain_text)) => {
|
||||||
plain_text.source = input.get_until_end_of_str(plain_text.source).into();
|
plain_text.source = input.get_until_end_of_str(plain_text.source).into();
|
||||||
|
paragraph.contents = Some(input.get_until_end_of_str(plain_text.source).into());
|
||||||
}
|
}
|
||||||
Some(obj) => {
|
Some(obj) => {
|
||||||
panic!("Unhandled first object type inside bullshitium {:?}", obj);
|
panic!("Unhandled first object type inside bullshitium {:?}", obj);
|
||||||
@@ -80,10 +81,10 @@ pub(crate) fn broken_end<'b, 'g, 'r, 's>(
|
|||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
remaining,
|
remaining,
|
||||||
Paragraph::of_text_full(
|
Paragraph::of_text(
|
||||||
input.get_until(remaining).into(),
|
input.get_until(remaining).into(),
|
||||||
body,
|
body,
|
||||||
if body.len() > 0 { Some(body) } else { None },
|
if !body.is_empty() { Some(body) } else { None },
|
||||||
post_blank.map(Into::<&str>::into),
|
post_blank.map(Into::<&str>::into),
|
||||||
),
|
),
|
||||||
))
|
))
|
||||||
@@ -123,6 +124,7 @@ pub(crate) fn broken_dynamic_block<'b, 'g, 'r, 's>(
|
|||||||
match paragraph.children.first_mut() {
|
match paragraph.children.first_mut() {
|
||||||
Some(Object::PlainText(plain_text)) => {
|
Some(Object::PlainText(plain_text)) => {
|
||||||
plain_text.source = input.get_until_end_of_str(plain_text.source).into();
|
plain_text.source = input.get_until_end_of_str(plain_text.source).into();
|
||||||
|
paragraph.contents = Some(input.get_until_end_of_str(plain_text.source).into());
|
||||||
}
|
}
|
||||||
Some(obj) => {
|
Some(obj) => {
|
||||||
panic!("Unhandled first object type inside bullshitium {:?}", obj);
|
panic!("Unhandled first object type inside bullshitium {:?}", obj);
|
||||||
@@ -133,14 +135,18 @@ pub(crate) fn broken_dynamic_block<'b, 'g, 'r, 's>(
|
|||||||
};
|
};
|
||||||
Ok((remaining, paragraph))
|
Ok((remaining, paragraph))
|
||||||
} else {
|
} else {
|
||||||
let (remaining, _trailing_ws) =
|
let (remaining, post_blank) =
|
||||||
maybe_consume_trailing_whitespace_if_not_exiting(context, lead_in_remaining)?;
|
maybe_consume_trailing_whitespace_if_not_exiting(context, lead_in_remaining)?;
|
||||||
|
|
||||||
|
let body = Into::<&str>::into(input.get_until(lead_in_remaining));
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
remaining,
|
remaining,
|
||||||
Paragraph::of_text(
|
Paragraph::of_text(
|
||||||
input.get_until(remaining).into(),
|
input.get_until(remaining).into(),
|
||||||
input.get_until(lead_in_remaining).into(),
|
body,
|
||||||
|
if !body.is_empty() { Some(body) } else { None },
|
||||||
|
post_blank.map(Into::<&str>::into),
|
||||||
),
|
),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ use std::path::Path;
|
|||||||
use nom::combinator::all_consuming;
|
use nom::combinator::all_consuming;
|
||||||
use nom::combinator::opt;
|
use nom::combinator::opt;
|
||||||
use nom::multi::many0;
|
use nom::multi::many0;
|
||||||
|
use nom::InputTake;
|
||||||
|
|
||||||
use super::headline::heading;
|
use super::headline::heading;
|
||||||
use super::in_buffer_settings::apply_in_buffer_settings;
|
use super::in_buffer_settings::apply_in_buffer_settings;
|
||||||
@@ -195,9 +196,9 @@ fn _document<'b, 'g, 'r, 's>(
|
|||||||
zeroth_section,
|
zeroth_section,
|
||||||
children,
|
children,
|
||||||
contents: if contents.len() > 0 {
|
contents: if contents.len() > 0 {
|
||||||
Some(Into::<&str>::into(contents))
|
Into::<&str>::into(contents)
|
||||||
} else {
|
} else {
|
||||||
None
|
Into::<&str>::into(remaining.take(0))
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
|
|||||||
@@ -6,20 +6,20 @@ 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;
|
||||||
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::peek;
|
||||||
use nom::combinator::recognize;
|
use nom::combinator::recognize;
|
||||||
use nom::multi::many0;
|
|
||||||
use nom::multi::many_till;
|
use nom::multi::many_till;
|
||||||
use nom::sequence::preceded;
|
|
||||||
use nom::sequence::tuple;
|
use nom::sequence::tuple;
|
||||||
|
|
||||||
use super::affiliated_keyword::parse_affiliated_keywords;
|
use super::affiliated_keyword::parse_affiliated_keywords;
|
||||||
|
use super::greater_block::leading_blank_lines_end;
|
||||||
use super::org_source::OrgSource;
|
use super::org_source::OrgSource;
|
||||||
|
use super::paragraph::empty_paragraph;
|
||||||
use super::util::maybe_consume_trailing_whitespace_if_not_exiting;
|
use super::util::maybe_consume_trailing_whitespace_if_not_exiting;
|
||||||
|
use crate::context::bind_context;
|
||||||
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;
|
||||||
@@ -28,7 +28,6 @@ use crate::context::RefContext;
|
|||||||
use crate::error::CustomError;
|
use crate::error::CustomError;
|
||||||
use crate::error::Res;
|
use crate::error::Res;
|
||||||
use crate::parser::element_parser::element;
|
use crate::parser::element_parser::element;
|
||||||
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::immediate_in_section;
|
use crate::parser::util::immediate_in_section;
|
||||||
@@ -36,7 +35,6 @@ use crate::parser::util::start_of_line;
|
|||||||
use crate::types::DynamicBlock;
|
use crate::types::DynamicBlock;
|
||||||
use crate::types::Element;
|
use crate::types::Element;
|
||||||
use crate::types::Keyword;
|
use crate::types::Keyword;
|
||||||
use crate::types::Paragraph;
|
|
||||||
|
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "tracing",
|
feature = "tracing",
|
||||||
@@ -81,23 +79,25 @@ where
|
|||||||
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)?;
|
||||||
let (remaining, leading_blank_lines) = opt(consumed(tuple((
|
let contents_begin = remaining;
|
||||||
blank_line,
|
let blank_line_context = ContextElement::ExitMatcherNode(ExitMatcherNode {
|
||||||
many0(preceded(not(exit_matcher), blank_line)),
|
class: ExitClass::Alpha,
|
||||||
))))(remaining)?;
|
exit_matcher: &leading_blank_lines_end,
|
||||||
let leading_blank_lines =
|
});
|
||||||
leading_blank_lines.map(|(source, (first_line, _remaining_lines))| {
|
let blank_line_context = parser_context.with_additional_node(&blank_line_context);
|
||||||
Element::Paragraph(Paragraph::of_text(source.into(), first_line.into()))
|
|
||||||
});
|
let (remaining, leading_blank_lines) =
|
||||||
|
opt(bind_context!(empty_paragraph, &blank_line_context))(remaining)?;
|
||||||
let (remaining, (mut children, _exit_contents)) =
|
let (remaining, (mut children, _exit_contents)) =
|
||||||
many_till(element_matcher, exit_matcher)(remaining)?;
|
many_till(element_matcher, exit_matcher)(remaining)?;
|
||||||
if let Some(lines) = leading_blank_lines {
|
if let Some(lines) = leading_blank_lines {
|
||||||
children.insert(0, lines);
|
children.insert(0, Element::Paragraph(lines));
|
||||||
}
|
}
|
||||||
|
let contents = get_consumed(contents_begin, remaining);
|
||||||
|
|
||||||
let (remaining, _end) = dynamic_block_end(&parser_context, remaining)?;
|
let (remaining, _end) = dynamic_block_end(&parser_context, remaining)?;
|
||||||
|
|
||||||
let (remaining, _trailing_ws) =
|
let (remaining, post_blank) =
|
||||||
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);
|
||||||
Ok((
|
Ok((
|
||||||
@@ -111,6 +111,12 @@ where
|
|||||||
block_name: name.into(),
|
block_name: name.into(),
|
||||||
parameters: parameters.map(|val| val.into()),
|
parameters: parameters.map(|val| val.into()),
|
||||||
children,
|
children,
|
||||||
|
contents: if contents.len() > 0 {
|
||||||
|
Some(Into::<&str>::into(contents))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
|
post_blank: post_blank.map(Into::<&str>::into),
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ use nom::InputTake;
|
|||||||
|
|
||||||
use super::affiliated_keyword::parse_affiliated_keywords;
|
use super::affiliated_keyword::parse_affiliated_keywords;
|
||||||
use super::org_source::OrgSource;
|
use super::org_source::OrgSource;
|
||||||
use super::util::maybe_consume_trailing_whitespace_if_not_exiting_mid_line;
|
use super::util::maybe_consume_trailing_whitespace_if_not_exiting;
|
||||||
use super::util::org_line_ending;
|
use super::util::org_line_ending;
|
||||||
use crate::context::parser_with_context;
|
use crate::context::parser_with_context;
|
||||||
use crate::context::RefContext;
|
use crate::context::RefContext;
|
||||||
@@ -48,8 +48,11 @@ where
|
|||||||
),
|
),
|
||||||
))(remaining)?;
|
))(remaining)?;
|
||||||
|
|
||||||
let (remaining, post_blank) =
|
let post_blank_begin = remaining;
|
||||||
maybe_consume_trailing_whitespace_if_not_exiting_mid_line(context, remaining)?;
|
let (remaining, _first_line_break) = org_line_ending(remaining)?;
|
||||||
|
let (remaining, _additional_post_blank) =
|
||||||
|
maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?;
|
||||||
|
let post_blank = get_consumed(post_blank_begin, remaining);
|
||||||
let source = get_consumed(input, remaining);
|
let source = get_consumed(input, remaining);
|
||||||
let mut value = Vec::with_capacity(remaining_lines.len() + 1);
|
let mut value = Vec::with_capacity(remaining_lines.len() + 1);
|
||||||
value.push(Into::<&str>::into(first_line));
|
value.push(Into::<&str>::into(first_line));
|
||||||
@@ -63,7 +66,11 @@ where
|
|||||||
affiliated_keywords,
|
affiliated_keywords,
|
||||||
),
|
),
|
||||||
value,
|
value,
|
||||||
post_blank: post_blank.map(Into::<&str>::into),
|
post_blank: if post_blank.len() > 0 {
|
||||||
|
Some(Into::<&str>::into(post_blank))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@@ -72,8 +79,8 @@ where
|
|||||||
fn fixed_width_area_line<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
fn fixed_width_area_line<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
||||||
start_of_line(input)?;
|
start_of_line(input)?;
|
||||||
let (remaining, _) = tuple((space0, tag(":")))(input)?;
|
let (remaining, _) = tuple((space0, tag(":")))(input)?;
|
||||||
if let Ok((remain, _line_break)) = org_line_ending(remaining) {
|
if let Ok((_remain, _line_break)) = org_line_ending(remaining) {
|
||||||
return Ok((remain, remaining.take(0)));
|
return Ok((remaining, remaining.take(0)));
|
||||||
}
|
}
|
||||||
let (remaining, _) = tag(" ")(remaining)?;
|
let (remaining, _) = tag(" ")(remaining)?;
|
||||||
let (remaining, value) = recognize(many_till(anychar, peek(org_line_ending)))(remaining)?;
|
let (remaining, value) = recognize(many_till(anychar, peek(org_line_ending)))(remaining)?;
|
||||||
|
|||||||
@@ -5,22 +5,21 @@ 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;
|
||||||
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::peek;
|
||||||
use nom::combinator::recognize;
|
use nom::combinator::recognize;
|
||||||
use nom::combinator::verify;
|
use nom::combinator::verify;
|
||||||
use nom::multi::many0;
|
|
||||||
use nom::multi::many_till;
|
use nom::multi::many_till;
|
||||||
use nom::sequence::preceded;
|
|
||||||
use nom::sequence::tuple;
|
use nom::sequence::tuple;
|
||||||
|
|
||||||
use super::affiliated_keyword::parse_affiliated_keywords;
|
use super::affiliated_keyword::parse_affiliated_keywords;
|
||||||
use super::org_source::OrgSource;
|
use super::org_source::OrgSource;
|
||||||
|
use super::paragraph::empty_paragraph;
|
||||||
use super::util::in_section;
|
use super::util::in_section;
|
||||||
use super::util::maybe_consume_trailing_whitespace_if_not_exiting;
|
use super::util::maybe_consume_trailing_whitespace_if_not_exiting;
|
||||||
|
use crate::context::bind_context;
|
||||||
use crate::context::parser_with_context;
|
use crate::context::parser_with_context;
|
||||||
use crate::context::ContextElement;
|
use crate::context::ContextElement;
|
||||||
use crate::context::ContextMatcher;
|
use crate::context::ContextMatcher;
|
||||||
@@ -37,7 +36,6 @@ use crate::parser::util::start_of_line;
|
|||||||
use crate::types::CenterBlock;
|
use crate::types::CenterBlock;
|
||||||
use crate::types::Element;
|
use crate::types::Element;
|
||||||
use crate::types::Keyword;
|
use crate::types::Keyword;
|
||||||
use crate::types::Paragraph;
|
|
||||||
use crate::types::QuoteBlock;
|
use crate::types::QuoteBlock;
|
||||||
use crate::types::SpecialBlock;
|
use crate::types::SpecialBlock;
|
||||||
|
|
||||||
@@ -102,7 +100,7 @@ fn center_block<'b, 'g, 'r, 's, AK>(
|
|||||||
where
|
where
|
||||||
AK: IntoIterator<Item = Keyword<'s>>,
|
AK: IntoIterator<Item = Keyword<'s>>,
|
||||||
{
|
{
|
||||||
let (remaining, (source, children)) = greater_block_body(
|
let (remaining, body) = greater_block_body(
|
||||||
context,
|
context,
|
||||||
input,
|
input,
|
||||||
pre_affiliated_keywords_input,
|
pre_affiliated_keywords_input,
|
||||||
@@ -112,12 +110,14 @@ where
|
|||||||
Ok((
|
Ok((
|
||||||
remaining,
|
remaining,
|
||||||
Element::CenterBlock(CenterBlock {
|
Element::CenterBlock(CenterBlock {
|
||||||
source,
|
source: body.source,
|
||||||
affiliated_keywords: parse_affiliated_keywords(
|
affiliated_keywords: parse_affiliated_keywords(
|
||||||
context.get_global_settings(),
|
context.get_global_settings(),
|
||||||
affiliated_keywords,
|
affiliated_keywords,
|
||||||
),
|
),
|
||||||
children,
|
children: body.children,
|
||||||
|
contents: body.contents,
|
||||||
|
post_blank: body.post_blank,
|
||||||
}),
|
}),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@@ -135,7 +135,7 @@ fn quote_block<'b, 'g, 'r, 's, AK>(
|
|||||||
where
|
where
|
||||||
AK: IntoIterator<Item = Keyword<'s>>,
|
AK: IntoIterator<Item = Keyword<'s>>,
|
||||||
{
|
{
|
||||||
let (remaining, (source, children)) = greater_block_body(
|
let (remaining, body) = greater_block_body(
|
||||||
context,
|
context,
|
||||||
input,
|
input,
|
||||||
pre_affiliated_keywords_input,
|
pre_affiliated_keywords_input,
|
||||||
@@ -145,12 +145,14 @@ where
|
|||||||
Ok((
|
Ok((
|
||||||
remaining,
|
remaining,
|
||||||
Element::QuoteBlock(QuoteBlock {
|
Element::QuoteBlock(QuoteBlock {
|
||||||
source,
|
source: body.source,
|
||||||
affiliated_keywords: parse_affiliated_keywords(
|
affiliated_keywords: parse_affiliated_keywords(
|
||||||
context.get_global_settings(),
|
context.get_global_settings(),
|
||||||
affiliated_keywords,
|
affiliated_keywords,
|
||||||
),
|
),
|
||||||
children,
|
children: body.children,
|
||||||
|
contents: body.contents,
|
||||||
|
post_blank: body.post_blank,
|
||||||
}),
|
}),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@@ -196,7 +198,7 @@ where
|
|||||||
AK: IntoIterator<Item = Keyword<'s>>,
|
AK: IntoIterator<Item = Keyword<'s>>,
|
||||||
{
|
{
|
||||||
let (remaining, parameters) = opt(tuple((space1, parameters)))(input)?;
|
let (remaining, parameters) = opt(tuple((space1, parameters)))(input)?;
|
||||||
let (remaining, (source, children)) = greater_block_body(
|
let (remaining, body) = greater_block_body(
|
||||||
context,
|
context,
|
||||||
remaining,
|
remaining,
|
||||||
pre_affiliated_keywords_input,
|
pre_affiliated_keywords_input,
|
||||||
@@ -206,18 +208,28 @@ where
|
|||||||
Ok((
|
Ok((
|
||||||
remaining,
|
remaining,
|
||||||
Element::SpecialBlock(SpecialBlock {
|
Element::SpecialBlock(SpecialBlock {
|
||||||
source,
|
source: body.source,
|
||||||
affiliated_keywords: parse_affiliated_keywords(
|
affiliated_keywords: parse_affiliated_keywords(
|
||||||
context.get_global_settings(),
|
context.get_global_settings(),
|
||||||
affiliated_keywords,
|
affiliated_keywords,
|
||||||
),
|
),
|
||||||
children,
|
children: body.children,
|
||||||
block_type: name,
|
block_type: name,
|
||||||
parameters: parameters.map(|(_, parameters)| Into::<&str>::into(parameters)),
|
parameters: parameters.map(|(_, parameters)| Into::<&str>::into(parameters)),
|
||||||
|
contents: body.contents,
|
||||||
|
post_blank: body.post_blank,
|
||||||
}),
|
}),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct GreaterBlockBody<'s> {
|
||||||
|
source: &'s str,
|
||||||
|
children: Vec<Element<'s>>,
|
||||||
|
contents: Option<&'s str>,
|
||||||
|
post_blank: Option<&'s str>,
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "tracing",
|
feature = "tracing",
|
||||||
tracing::instrument(ret, level = "debug", skip(context))
|
tracing::instrument(ret, level = "debug", skip(context))
|
||||||
@@ -228,7 +240,7 @@ fn greater_block_body<'c, 'b, 'g, 'r, 's>(
|
|||||||
pre_affiliated_keywords_input: OrgSource<'s>,
|
pre_affiliated_keywords_input: OrgSource<'s>,
|
||||||
name: &'c str,
|
name: &'c str,
|
||||||
context_name: &'c str,
|
context_name: &'c str,
|
||||||
) -> Res<OrgSource<'s>, (&'s str, Vec<Element<'s>>)> {
|
) -> Res<OrgSource<'s>, GreaterBlockBody<'s>> {
|
||||||
if in_section(context, context_name) {
|
if in_section(context, context_name) {
|
||||||
return Err(nom::Err::Error(CustomError::Static(
|
return Err(nom::Err::Error(CustomError::Static(
|
||||||
"Cannot nest objects of the same element",
|
"Cannot nest objects of the same element",
|
||||||
@@ -250,28 +262,43 @@ fn greater_block_body<'c, 'b, 'g, 'r, 's>(
|
|||||||
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)?;
|
||||||
let (remaining, leading_blank_lines) = opt(consumed(tuple((
|
let contents_begin = remaining;
|
||||||
blank_line,
|
|
||||||
many0(preceded(not(exit_matcher), blank_line)),
|
let blank_line_context = ContextElement::ExitMatcherNode(ExitMatcherNode {
|
||||||
))))(remaining)?;
|
class: ExitClass::Alpha,
|
||||||
let leading_blank_lines =
|
exit_matcher: &leading_blank_lines_end,
|
||||||
leading_blank_lines.map(|(source, (first_line, _remaining_lines))| {
|
});
|
||||||
Element::Paragraph(Paragraph::of_text(source.into(), first_line.into()))
|
let blank_line_context = parser_context.with_additional_node(&blank_line_context);
|
||||||
});
|
|
||||||
|
let (remaining, leading_blank_lines) =
|
||||||
|
opt(bind_context!(empty_paragraph, &blank_line_context))(remaining)?;
|
||||||
let (remaining, (mut children, _exit_contents)) =
|
let (remaining, (mut children, _exit_contents)) =
|
||||||
many_till(element_matcher, exit_matcher)(remaining)?;
|
many_till(element_matcher, exit_matcher)(remaining)?;
|
||||||
if let Some(lines) = leading_blank_lines {
|
if let Some(lines) = leading_blank_lines {
|
||||||
children.insert(0, lines);
|
children.insert(0, Element::Paragraph(lines));
|
||||||
}
|
}
|
||||||
|
let contents = get_consumed(contents_begin, remaining);
|
||||||
|
|
||||||
let (remaining, _end) = exit_with_name(&parser_context, remaining)?;
|
let (remaining, _end) = exit_with_name(&parser_context, remaining)?;
|
||||||
|
|
||||||
// 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 (remaining, _trailing_ws) =
|
let (remaining, post_blank) =
|
||||||
maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?;
|
maybe_consume_trailing_whitespace_if_not_exiting(context, remaining)?;
|
||||||
let source = get_consumed(pre_affiliated_keywords_input, remaining);
|
let source = get_consumed(pre_affiliated_keywords_input, remaining);
|
||||||
Ok((remaining, (Into::<&str>::into(source), children)))
|
Ok((
|
||||||
|
remaining,
|
||||||
|
GreaterBlockBody {
|
||||||
|
source: Into::<&str>::into(source),
|
||||||
|
children,
|
||||||
|
contents: if contents.len() > 0 {
|
||||||
|
Some(Into::<&str>::into(contents))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
|
post_blank: post_blank.map(Into::<&str>::into),
|
||||||
|
},
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
||||||
@@ -307,3 +334,14 @@ fn _greater_block_end<'b, 'g, 'r, 's, 'c>(
|
|||||||
let source = get_consumed(input, remaining);
|
let source = get_consumed(input, remaining);
|
||||||
Ok((remaining, source))
|
Ok((remaining, source))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(
|
||||||
|
feature = "tracing",
|
||||||
|
tracing::instrument(ret, level = "debug", skip(_context))
|
||||||
|
)]
|
||||||
|
pub(crate) fn leading_blank_lines_end<'b, 'g, 'r, 's, 'c>(
|
||||||
|
_context: RefContext<'b, 'g, 'r, 's>,
|
||||||
|
input: OrgSource<'s>,
|
||||||
|
) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
||||||
|
recognize(not(blank_line))(input)
|
||||||
|
}
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ fn _heading<'b, 'g, 'r, 's>(
|
|||||||
let section_matcher = bind_context!(section, context);
|
let section_matcher = bind_context!(section, context);
|
||||||
let heading_matcher = bind_context!(heading(pre_headline.star_count), context);
|
let heading_matcher = bind_context!(heading(pre_headline.star_count), context);
|
||||||
let (contents_begin, _) = opt(many0(blank_line))(remaining)?;
|
let (contents_begin, _) = opt(many0(blank_line))(remaining)?;
|
||||||
|
let maybe_post_blank = get_consumed(remaining, contents_begin);
|
||||||
let (remaining, maybe_section) =
|
let (remaining, maybe_section) =
|
||||||
opt(map(section_matcher, DocumentElement::Section))(remaining)?;
|
opt(map(section_matcher, DocumentElement::Section))(remaining)?;
|
||||||
let (remaining, _ws) = opt(tuple((start_of_line, many0(blank_line))))(remaining)?;
|
let (remaining, _ws) = opt(tuple((start_of_line, many0(blank_line))))(remaining)?;
|
||||||
@@ -83,7 +84,8 @@ fn _heading<'b, 'g, 'r, 's>(
|
|||||||
}
|
}
|
||||||
children.insert(0, section);
|
children.insert(0, section);
|
||||||
}
|
}
|
||||||
let remaining = if children.is_empty() {
|
let has_children = !children.is_empty();
|
||||||
|
let remaining = if !has_children {
|
||||||
// Support empty headings
|
// Support empty headings
|
||||||
let (remain, _ws) = many0(blank_line)(remaining)?;
|
let (remain, _ws) = many0(blank_line)(remaining)?;
|
||||||
remain
|
remain
|
||||||
@@ -119,6 +121,11 @@ fn _heading<'b, 'g, 'r, 's>(
|
|||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
},
|
},
|
||||||
|
post_blank: if has_children {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(Into::<&str>::into(maybe_post_blank))
|
||||||
|
},
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ pub(crate) fn empty_paragraph<'b, 'g, 'r, 's>(
|
|||||||
let source = get_consumed(input, remaining);
|
let source = get_consumed(input, remaining);
|
||||||
Ok((
|
Ok((
|
||||||
remaining,
|
remaining,
|
||||||
Paragraph::of_text_full(
|
Paragraph::of_text(
|
||||||
Into::<&str>::into(source),
|
Into::<&str>::into(source),
|
||||||
Into::<&str>::into(first_line_with_spaces),
|
Into::<&str>::into(first_line_with_spaces),
|
||||||
Some(Into::<&str>::into(first_line_with_spaces)),
|
Some(Into::<&str>::into(first_line_with_spaces)),
|
||||||
@@ -116,7 +116,7 @@ pub(crate) fn empty_paragraph<'b, 'g, 'r, 's>(
|
|||||||
let source = get_consumed(input, remaining);
|
let source = get_consumed(input, remaining);
|
||||||
Ok((
|
Ok((
|
||||||
remaining,
|
remaining,
|
||||||
Paragraph::of_text_full(
|
Paragraph::of_text(
|
||||||
Into::<&str>::into(source),
|
Into::<&str>::into(source),
|
||||||
Into::<&str>::into(first_line),
|
Into::<&str>::into(first_line),
|
||||||
Some(Into::<&str>::into(first_line)),
|
Some(Into::<&str>::into(first_line)),
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ 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::consumed;
|
||||||
use nom::combinator::not;
|
use nom::combinator::not;
|
||||||
use nom::combinator::opt;
|
use nom::combinator::opt;
|
||||||
use nom::combinator::peek;
|
use nom::combinator::peek;
|
||||||
@@ -67,13 +68,13 @@ where
|
|||||||
let org_mode_table_row_matcher = parser_with_context!(org_mode_table_row)(&parser_context);
|
let org_mode_table_row_matcher = parser_with_context!(org_mode_table_row)(&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, (children, _exit_contents)) =
|
let (remaining, (contents, (children, _exit_contents))) =
|
||||||
many_till(org_mode_table_row_matcher, exit_matcher)(remaining)?;
|
consumed(many_till(org_mode_table_row_matcher, exit_matcher))(remaining)?;
|
||||||
|
|
||||||
let (remaining, formulas) =
|
let (remaining, formulas) =
|
||||||
many0(parser_with_context!(table_formula_keyword)(context))(remaining)?;
|
many0(parser_with_context!(table_formula_keyword)(context))(remaining)?;
|
||||||
|
|
||||||
let (remaining, _trailing_ws) =
|
let (remaining, post_blank) =
|
||||||
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);
|
||||||
|
|
||||||
@@ -87,6 +88,8 @@ where
|
|||||||
),
|
),
|
||||||
formulas,
|
formulas,
|
||||||
children,
|
children,
|
||||||
|
contents: Into::<&str>::into(contents),
|
||||||
|
post_blank: post_blank.map(Into::<&str>::into),
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@@ -150,6 +153,7 @@ fn org_mode_table_row_rule<'b, 'g, 'r, 's>(
|
|||||||
TableRow {
|
TableRow {
|
||||||
source: source.into(),
|
source: source.into(),
|
||||||
children: Vec::new(),
|
children: Vec::new(),
|
||||||
|
contents: None,
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@@ -164,8 +168,8 @@ fn org_mode_table_row_regular<'b, 'g, 'r, 's>(
|
|||||||
) -> Res<OrgSource<'s>, TableRow<'s>> {
|
) -> Res<OrgSource<'s>, TableRow<'s>> {
|
||||||
start_of_line(input)?;
|
start_of_line(input)?;
|
||||||
let (remaining, _) = tuple((space0, tag("|")))(input)?;
|
let (remaining, _) = tuple((space0, tag("|")))(input)?;
|
||||||
let (remaining, children) =
|
let (remaining, (contents, children)) =
|
||||||
many1(parser_with_context!(org_mode_table_cell)(context))(remaining)?;
|
consumed(many1(parser_with_context!(org_mode_table_cell)(context)))(remaining)?;
|
||||||
let (remaining, _tail) = recognize(tuple((space0, org_line_ending)))(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((
|
||||||
@@ -173,6 +177,11 @@ fn org_mode_table_row_regular<'b, 'g, 'r, 's>(
|
|||||||
TableRow {
|
TableRow {
|
||||||
source: source.into(),
|
source: source.into(),
|
||||||
children,
|
children,
|
||||||
|
contents: if contents.len() > 0 {
|
||||||
|
Some(Into::<&str>::into(contents))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@@ -194,12 +203,12 @@ fn org_mode_table_cell<'b, 'g, 'r, 's>(
|
|||||||
parser_with_context!(table_cell_set_object)(&parser_context);
|
parser_with_context!(table_cell_set_object)(&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, _) = space0(input)?;
|
let (remaining, _) = space0(input)?;
|
||||||
let (remaining, (children, _exit_contents)) = verify(
|
let (remaining, (contents, (children, _exit_contents))) = consumed(verify(
|
||||||
many_till(table_cell_set_object_matcher, exit_matcher),
|
many_till(table_cell_set_object_matcher, exit_matcher),
|
||||||
|(children, exit_contents)| {
|
|(children, exit_contents)| {
|
||||||
!children.is_empty() || Into::<&str>::into(exit_contents).ends_with('|')
|
!children.is_empty() || Into::<&str>::into(exit_contents).ends_with('|')
|
||||||
},
|
},
|
||||||
)(remaining)?;
|
))(remaining)?;
|
||||||
|
|
||||||
let (remaining, _tail) = org_mode_table_cell_end(&parser_context, remaining)?;
|
let (remaining, _tail) = org_mode_table_cell_end(&parser_context, remaining)?;
|
||||||
|
|
||||||
@@ -210,6 +219,7 @@ fn org_mode_table_cell<'b, 'g, 'r, 's>(
|
|||||||
TableCell {
|
TableCell {
|
||||||
source: source.into(),
|
source: source.into(),
|
||||||
children,
|
children,
|
||||||
|
contents: Into::<&str>::into(contents),
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ pub(crate) fn target<'b, 'g, 'r, 's>(
|
|||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
let (remaining, _) = tag(">>")(remaining)?;
|
let (remaining, _) = tag(">>")(remaining)?;
|
||||||
let (remaining, _trailing_whitespace) =
|
let (remaining, post_blank) =
|
||||||
maybe_consume_object_trailing_whitespace_if_not_exiting(context, remaining)?;
|
maybe_consume_object_trailing_whitespace_if_not_exiting(context, remaining)?;
|
||||||
let source = get_consumed(input, remaining);
|
let source = get_consumed(input, remaining);
|
||||||
|
|
||||||
@@ -55,6 +55,7 @@ pub(crate) fn target<'b, 'g, 'r, 's>(
|
|||||||
Target {
|
Target {
|
||||||
source: source.into(),
|
source: source.into(),
|
||||||
value: body.into(),
|
value: body.into(),
|
||||||
|
post_blank: post_blank.map(Into::<&str>::into),
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,13 +72,6 @@ fn element_trailing_whitespace<'s>(input: OrgSource<'s>) -> Res<OrgSource<'s>, O
|
|||||||
alt((eof, recognize(many0(blank_line))))(input)
|
alt((eof, recognize(many0(blank_line))))(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(feature = "tracing", tracing::instrument(ret, level = "debug"))]
|
|
||||||
fn element_trailing_whitespace_mid_line<'s>(
|
|
||||||
input: OrgSource<'s>,
|
|
||||||
) -> Res<OrgSource<'s>, OrgSource<'s>> {
|
|
||||||
alt((eof, recognize(many0(blank_line))))(input)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "tracing",
|
feature = "tracing",
|
||||||
tracing::instrument(ret, level = "debug", skip(context))
|
tracing::instrument(ret, level = "debug", skip(context))
|
||||||
@@ -121,22 +114,6 @@ pub(crate) fn maybe_consume_trailing_whitespace_if_not_exiting<'b, 'g, 'r, 's>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(
|
|
||||||
feature = "tracing",
|
|
||||||
tracing::instrument(ret, level = "debug", skip(context))
|
|
||||||
)]
|
|
||||||
pub(crate) fn maybe_consume_trailing_whitespace_if_not_exiting_mid_line<'b, 'g, 'r, 's>(
|
|
||||||
context: RefContext<'b, 'g, 'r, 's>,
|
|
||||||
input: OrgSource<'s>,
|
|
||||||
) -> Res<OrgSource<'s>, Option<OrgSource<'s>>> {
|
|
||||||
if context.should_consume_trailing_whitespace() && exit_matcher_parser(context, input).is_err()
|
|
||||||
{
|
|
||||||
Ok(opt(element_trailing_whitespace_mid_line)(input)?)
|
|
||||||
} else {
|
|
||||||
Ok((input, None))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "tracing",
|
feature = "tracing",
|
||||||
tracing::instrument(ret, level = "debug", skip(context))
|
tracing::instrument(ret, level = "debug", skip(context))
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ pub struct Document<'s> {
|
|||||||
pub path: Option<PathBuf>,
|
pub path: Option<PathBuf>,
|
||||||
pub zeroth_section: Option<Section<'s>>,
|
pub zeroth_section: Option<Section<'s>>,
|
||||||
pub children: Vec<Heading<'s>>,
|
pub children: Vec<Heading<'s>>,
|
||||||
pub contents: Option<&'s str>,
|
pub contents: &'s str,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -36,6 +36,7 @@ pub struct Heading<'s> {
|
|||||||
pub deadline: Option<Timestamp<'s>>,
|
pub deadline: Option<Timestamp<'s>>,
|
||||||
pub closed: Option<Timestamp<'s>>,
|
pub closed: Option<Timestamp<'s>>,
|
||||||
pub contents: Option<&'s str>,
|
pub contents: Option<&'s str>,
|
||||||
|
pub post_blank: Option<&'s str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -63,14 +64,11 @@ impl<'s> StandardProperties<'s> for Document<'s> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_contents<'b>(&'b self) -> Option<&'s str> {
|
fn get_contents<'b>(&'b self) -> Option<&'s str> {
|
||||||
self.contents
|
Some(self.contents)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_post_blank(&self) -> PostBlank {
|
fn get_post_blank(&self) -> PostBlank {
|
||||||
self.into_iter()
|
0
|
||||||
.last()
|
|
||||||
.map(|child| child.get_post_blank())
|
|
||||||
.unwrap_or(0)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,10 +100,11 @@ impl<'s> StandardProperties<'s> for Heading<'s> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_post_blank(&self) -> PostBlank {
|
fn get_post_blank(&self) -> PostBlank {
|
||||||
self.children
|
self.post_blank
|
||||||
.last()
|
.map(|text| text.lines().count())
|
||||||
.map(|child| child.get_post_blank())
|
|
||||||
.unwrap_or(0)
|
.unwrap_or(0)
|
||||||
|
.try_into()
|
||||||
|
.expect("Too much post-blank to fit into a PostBlank.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -56,6 +56,8 @@ pub struct CenterBlock<'s> {
|
|||||||
pub source: &'s str,
|
pub source: &'s str,
|
||||||
pub affiliated_keywords: AffiliatedKeywords<'s>,
|
pub affiliated_keywords: AffiliatedKeywords<'s>,
|
||||||
pub children: Vec<Element<'s>>,
|
pub children: Vec<Element<'s>>,
|
||||||
|
pub contents: Option<&'s str>,
|
||||||
|
pub post_blank: Option<&'s str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -63,6 +65,8 @@ pub struct QuoteBlock<'s> {
|
|||||||
pub source: &'s str,
|
pub source: &'s str,
|
||||||
pub affiliated_keywords: AffiliatedKeywords<'s>,
|
pub affiliated_keywords: AffiliatedKeywords<'s>,
|
||||||
pub children: Vec<Element<'s>>,
|
pub children: Vec<Element<'s>>,
|
||||||
|
pub contents: Option<&'s str>,
|
||||||
|
pub post_blank: Option<&'s str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -72,6 +76,8 @@ pub struct SpecialBlock<'s> {
|
|||||||
pub block_type: &'s str,
|
pub block_type: &'s str,
|
||||||
pub parameters: Option<&'s str>,
|
pub parameters: Option<&'s str>,
|
||||||
pub children: Vec<Element<'s>>,
|
pub children: Vec<Element<'s>>,
|
||||||
|
pub contents: Option<&'s str>,
|
||||||
|
pub post_blank: Option<&'s str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -81,6 +87,8 @@ pub struct DynamicBlock<'s> {
|
|||||||
pub block_name: &'s str,
|
pub block_name: &'s str,
|
||||||
pub parameters: Option<&'s str>,
|
pub parameters: Option<&'s str>,
|
||||||
pub children: Vec<Element<'s>>,
|
pub children: Vec<Element<'s>>,
|
||||||
|
pub contents: Option<&'s str>,
|
||||||
|
pub post_blank: Option<&'s str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -124,12 +132,15 @@ pub struct Table<'s> {
|
|||||||
pub affiliated_keywords: AffiliatedKeywords<'s>,
|
pub affiliated_keywords: AffiliatedKeywords<'s>,
|
||||||
pub formulas: Vec<Keyword<'s>>,
|
pub formulas: Vec<Keyword<'s>>,
|
||||||
pub children: Vec<TableRow<'s>>,
|
pub children: Vec<TableRow<'s>>,
|
||||||
|
pub contents: &'s str,
|
||||||
|
pub post_blank: Option<&'s str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct TableRow<'s> {
|
pub struct TableRow<'s> {
|
||||||
pub source: &'s str,
|
pub source: &'s str,
|
||||||
pub children: Vec<TableCell<'s>>,
|
pub children: Vec<TableCell<'s>>,
|
||||||
|
pub contents: Option<&'s str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -180,11 +191,15 @@ impl<'s> StandardProperties<'s> for CenterBlock<'s> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_contents<'b>(&'b self) -> Option<&'s str> {
|
fn get_contents<'b>(&'b self) -> Option<&'s str> {
|
||||||
todo!()
|
self.contents
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_post_blank(&self) -> PostBlank {
|
fn get_post_blank(&self) -> PostBlank {
|
||||||
todo!()
|
self.post_blank
|
||||||
|
.map(|text| text.lines().count())
|
||||||
|
.unwrap_or(0)
|
||||||
|
.try_into()
|
||||||
|
.expect("Too much post-blank to fit into a PostBlank.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -194,11 +209,15 @@ impl<'s> StandardProperties<'s> for QuoteBlock<'s> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_contents<'b>(&'b self) -> Option<&'s str> {
|
fn get_contents<'b>(&'b self) -> Option<&'s str> {
|
||||||
todo!()
|
self.contents
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_post_blank(&self) -> PostBlank {
|
fn get_post_blank(&self) -> PostBlank {
|
||||||
todo!()
|
self.post_blank
|
||||||
|
.map(|text| text.lines().count())
|
||||||
|
.unwrap_or(0)
|
||||||
|
.try_into()
|
||||||
|
.expect("Too much post-blank to fit into a PostBlank.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,11 +227,15 @@ impl<'s> StandardProperties<'s> for SpecialBlock<'s> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_contents<'b>(&'b self) -> Option<&'s str> {
|
fn get_contents<'b>(&'b self) -> Option<&'s str> {
|
||||||
todo!()
|
self.contents
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_post_blank(&self) -> PostBlank {
|
fn get_post_blank(&self) -> PostBlank {
|
||||||
todo!()
|
self.post_blank
|
||||||
|
.map(|text| text.lines().count())
|
||||||
|
.unwrap_or(0)
|
||||||
|
.try_into()
|
||||||
|
.expect("Too much post-blank to fit into a PostBlank.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,11 +245,15 @@ impl<'s> StandardProperties<'s> for DynamicBlock<'s> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_contents<'b>(&'b self) -> Option<&'s str> {
|
fn get_contents<'b>(&'b self) -> Option<&'s str> {
|
||||||
todo!()
|
self.contents
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_post_blank(&self) -> PostBlank {
|
fn get_post_blank(&self) -> PostBlank {
|
||||||
todo!()
|
self.post_blank
|
||||||
|
.map(|text| text.lines().count())
|
||||||
|
.unwrap_or(0)
|
||||||
|
.try_into()
|
||||||
|
.expect("Too much post-blank to fit into a PostBlank.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,11 +331,15 @@ impl<'s> StandardProperties<'s> for Table<'s> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_contents<'b>(&'b self) -> Option<&'s str> {
|
fn get_contents<'b>(&'b self) -> Option<&'s str> {
|
||||||
todo!()
|
Some(self.contents)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_post_blank(&self) -> PostBlank {
|
fn get_post_blank(&self) -> PostBlank {
|
||||||
todo!()
|
self.post_blank
|
||||||
|
.map(|text| text.lines().count())
|
||||||
|
.unwrap_or(0)
|
||||||
|
.try_into()
|
||||||
|
.expect("Too much post-blank to fit into a PostBlank.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -318,11 +349,11 @@ impl<'s> StandardProperties<'s> for TableRow<'s> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_contents<'b>(&'b self) -> Option<&'s str> {
|
fn get_contents<'b>(&'b self) -> Option<&'s str> {
|
||||||
todo!()
|
self.contents
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_post_blank(&self) -> PostBlank {
|
fn get_post_blank(&self) -> PostBlank {
|
||||||
todo!()
|
0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ pub struct Comment<'s> {
|
|||||||
pub struct TableCell<'s> {
|
pub struct TableCell<'s> {
|
||||||
pub source: &'s str,
|
pub source: &'s str,
|
||||||
pub children: Vec<Object<'s>>,
|
pub children: Vec<Object<'s>>,
|
||||||
|
pub contents: &'s str,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -203,21 +204,7 @@ impl<'s> Paragraph<'s> {
|
|||||||
/// Generate a paragraph of the passed in text with no additional properties.
|
/// Generate a paragraph of the passed in text with no additional properties.
|
||||||
///
|
///
|
||||||
/// This is used for elements that support an "empty" content like greater blocks.
|
/// This is used for elements that support an "empty" content like greater blocks.
|
||||||
pub(crate) fn of_text(source: &'s str, body: &'s str) -> Self {
|
pub(crate) fn of_text(
|
||||||
// TODO: This should be replaced with of_text_full.
|
|
||||||
Paragraph {
|
|
||||||
source,
|
|
||||||
contents: None,
|
|
||||||
post_blank: None,
|
|
||||||
affiliated_keywords: AffiliatedKeywords::default(),
|
|
||||||
children: vec![Object::PlainText(PlainText { source: body })],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Generate a paragraph of the passed in text with no additional properties.
|
|
||||||
///
|
|
||||||
/// This is used for elements that support an "empty" content like greater blocks.
|
|
||||||
pub(crate) fn of_text_full(
|
|
||||||
source: &'s str,
|
source: &'s str,
|
||||||
body: &'s str,
|
body: &'s str,
|
||||||
contents: Option<&'s str>,
|
contents: Option<&'s str>,
|
||||||
@@ -257,11 +244,11 @@ impl<'s> StandardProperties<'s> for TableCell<'s> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_contents<'b>(&'b self) -> Option<&'s str> {
|
fn get_contents<'b>(&'b self) -> Option<&'s str> {
|
||||||
todo!()
|
Some(self.contents)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_post_blank(&self) -> PostBlank {
|
fn get_post_blank(&self) -> PostBlank {
|
||||||
todo!()
|
0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -266,6 +266,7 @@ pub struct LineBreak<'s> {
|
|||||||
pub struct Target<'s> {
|
pub struct Target<'s> {
|
||||||
pub source: &'s str,
|
pub source: &'s str,
|
||||||
pub value: &'s str,
|
pub value: &'s str,
|
||||||
|
pub post_blank: Option<&'s str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -923,11 +924,15 @@ impl<'s> StandardProperties<'s> for Target<'s> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_contents<'b>(&'b self) -> Option<&'s str> {
|
fn get_contents<'b>(&'b self) -> Option<&'s str> {
|
||||||
todo!()
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_post_blank(&self) -> PostBlank {
|
fn get_post_blank(&self) -> PostBlank {
|
||||||
todo!()
|
self.post_blank
|
||||||
|
.map(|post_blank| post_blank.chars().count())
|
||||||
|
.unwrap_or(0)
|
||||||
|
.try_into()
|
||||||
|
.expect("Too much post-blank to fit into a PostBlank.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1009,11 +1014,13 @@ impl<'s> StandardProperties<'s> for PlainText<'s> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_contents<'b>(&'b self) -> Option<&'s str> {
|
fn get_contents<'b>(&'b self) -> Option<&'s str> {
|
||||||
todo!()
|
// This field does not actually exist in emacs for plaintext
|
||||||
|
Some(self.source)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_post_blank(&self) -> PostBlank {
|
fn get_post_blank(&self) -> PostBlank {
|
||||||
todo!()
|
// This field does not actually exist in emacs for plaintext
|
||||||
|
0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user