2023-10-18 12:32:48 -04:00
|
|
|
use nom::branch::alt;
|
2023-10-18 11:57:39 -04:00
|
|
|
use nom::bytes::complete::tag_no_case;
|
2023-10-18 12:32:48 -04:00
|
|
|
use nom::character::complete::anychar;
|
2023-10-18 11:57:39 -04:00
|
|
|
use nom::character::complete::space0;
|
2023-10-18 12:32:48 -04:00
|
|
|
use nom::multi::many_till;
|
2023-10-18 11:57:39 -04:00
|
|
|
use nom::sequence::tuple;
|
|
|
|
|
|
|
|
use super::paragraph::paragraph;
|
2023-10-18 12:17:57 -04:00
|
|
|
use super::util::maybe_consume_trailing_whitespace_if_not_exiting;
|
2023-10-18 11:57:39 -04:00
|
|
|
use super::util::org_line_ending;
|
|
|
|
use super::util::start_of_line;
|
|
|
|
use super::OrgSource;
|
2023-10-18 12:32:48 -04:00
|
|
|
use crate::context::bind_context;
|
2023-10-18 11:57:39 -04:00
|
|
|
use crate::context::RefContext;
|
2023-10-18 12:36:06 -04:00
|
|
|
use crate::error::CustomError;
|
2023-10-18 11:57:39 -04:00
|
|
|
use crate::error::Res;
|
2023-10-18 12:36:06 -04:00
|
|
|
use crate::parser::macros::element;
|
2023-10-18 11:57:39 -04:00
|
|
|
use crate::types::Object;
|
|
|
|
use crate::types::Paragraph;
|
|
|
|
|
|
|
|
#[cfg_attr(
|
|
|
|
feature = "tracing",
|
|
|
|
tracing::instrument(ret, level = "debug", skip(context))
|
|
|
|
)]
|
|
|
|
pub(crate) fn bullshitium<'b, 'g, 'r, 's>(
|
|
|
|
context: RefContext<'b, 'g, 'r, 's>,
|
|
|
|
input: OrgSource<'s>,
|
|
|
|
) -> Res<OrgSource<'s>, Paragraph<'s>> {
|
2023-10-18 12:32:48 -04:00
|
|
|
alt((
|
|
|
|
bind_context!(broken_end, context),
|
|
|
|
bind_context!(broken_dynamic_block, context),
|
|
|
|
))(input)
|
2023-10-18 11:57:39 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg_attr(
|
|
|
|
feature = "tracing",
|
|
|
|
tracing::instrument(ret, level = "debug", skip(context))
|
|
|
|
)]
|
|
|
|
pub(crate) fn detect_bullshitium<'b, 'g, 'r, 's>(
|
|
|
|
context: RefContext<'b, 'g, 'r, 's>,
|
|
|
|
input: OrgSource<'s>,
|
|
|
|
) -> Res<OrgSource<'s>, ()> {
|
2023-10-18 12:36:06 -04:00
|
|
|
element!(detect_broken_end, context, input);
|
|
|
|
element!(detect_broken_dynamic_block, context, input);
|
|
|
|
Err(nom::Err::Error(CustomError::Static("No bullshitium.")))
|
2023-10-18 11:57:39 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg_attr(
|
|
|
|
feature = "tracing",
|
|
|
|
tracing::instrument(ret, level = "debug", skip(context))
|
|
|
|
)]
|
|
|
|
pub(crate) fn broken_end<'b, 'g, 'r, 's>(
|
|
|
|
context: RefContext<'b, 'g, 'r, 's>,
|
|
|
|
input: OrgSource<'s>,
|
|
|
|
) -> Res<OrgSource<'s>, Paragraph<'s>> {
|
|
|
|
start_of_line(input)?;
|
|
|
|
let (remaining, _) = space0(input)?;
|
|
|
|
let (remaining, _) = tag_no_case(":end:")(remaining)?;
|
|
|
|
let (lead_in_remaining, _) = tuple((space0, org_line_ending))(remaining)?;
|
|
|
|
if let Ok((remaining, mut paragraph)) =
|
|
|
|
paragraph(std::iter::empty(), lead_in_remaining, context, input)
|
2023-10-18 12:32:48 -04:00
|
|
|
{
|
|
|
|
match paragraph.children.first_mut() {
|
|
|
|
Some(Object::PlainText(plain_text)) => {
|
|
|
|
plain_text.source = input.get_until_end_of_str(plain_text.source).into();
|
|
|
|
}
|
|
|
|
Some(obj) => {
|
|
|
|
panic!("Unhandled first object type inside bullshitium {:?}", obj);
|
|
|
|
}
|
|
|
|
None => {
|
|
|
|
unreachable!("Paragraph must have children.");
|
|
|
|
}
|
|
|
|
};
|
|
|
|
Ok((remaining, paragraph))
|
|
|
|
} else {
|
2023-12-15 15:40:17 -05:00
|
|
|
let (remaining, post_blank) =
|
2023-10-18 12:32:48 -04:00
|
|
|
maybe_consume_trailing_whitespace_if_not_exiting(context, lead_in_remaining)?;
|
|
|
|
|
2023-12-15 15:40:17 -05:00
|
|
|
let body = Into::<&str>::into(input.get_until(lead_in_remaining));
|
|
|
|
|
2023-10-18 12:32:48 -04:00
|
|
|
Ok((
|
|
|
|
remaining,
|
2023-12-15 15:40:17 -05:00
|
|
|
Paragraph::of_text_full(
|
2023-10-23 17:22:52 -04:00
|
|
|
input.get_until(remaining).into(),
|
2023-12-15 15:40:17 -05:00
|
|
|
body,
|
|
|
|
if body.len() > 0 { Some(body) } else { None },
|
|
|
|
post_blank.map(Into::<&str>::into),
|
2023-10-23 17:22:52 -04:00
|
|
|
),
|
2023-10-18 12:32:48 -04:00
|
|
|
))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-18 12:36:06 -04:00
|
|
|
#[cfg_attr(
|
|
|
|
feature = "tracing",
|
2023-10-18 12:42:09 -04:00
|
|
|
tracing::instrument(ret, level = "debug", skip(_context))
|
2023-10-18 12:36:06 -04:00
|
|
|
)]
|
|
|
|
pub(crate) fn detect_broken_end<'b, 'g, 'r, 's>(
|
|
|
|
_context: RefContext<'b, 'g, 'r, 's>,
|
|
|
|
input: OrgSource<'s>,
|
|
|
|
) -> Res<OrgSource<'s>, ()> {
|
|
|
|
start_of_line(input)?;
|
|
|
|
let (remaining, _) = space0(input)?;
|
|
|
|
let (remaining, _) = tag_no_case(":end:")(remaining)?;
|
|
|
|
let (_remaining, _) = tuple((space0, org_line_ending))(remaining)?;
|
|
|
|
Ok((input, ()))
|
|
|
|
}
|
|
|
|
|
2023-10-18 12:32:48 -04:00
|
|
|
#[cfg_attr(
|
|
|
|
feature = "tracing",
|
|
|
|
tracing::instrument(ret, level = "debug", skip(context))
|
|
|
|
)]
|
|
|
|
pub(crate) fn broken_dynamic_block<'b, 'g, 'r, 's>(
|
|
|
|
context: RefContext<'b, 'g, 'r, 's>,
|
|
|
|
input: OrgSource<'s>,
|
|
|
|
) -> Res<OrgSource<'s>, Paragraph<'s>> {
|
|
|
|
start_of_line(input)?;
|
|
|
|
let (remaining, _) = space0(input)?;
|
|
|
|
let (remaining, _) = tag_no_case("#+BEGIN:")(remaining)?;
|
|
|
|
let (lead_in_remaining, _) = many_till(anychar, org_line_ending)(remaining)?;
|
|
|
|
if let Ok((remaining, mut paragraph)) =
|
|
|
|
paragraph(std::iter::empty(), lead_in_remaining, context, input)
|
2023-10-18 11:57:39 -04:00
|
|
|
{
|
|
|
|
match paragraph.children.first_mut() {
|
|
|
|
Some(Object::PlainText(plain_text)) => {
|
|
|
|
plain_text.source = input.get_until_end_of_str(plain_text.source).into();
|
|
|
|
}
|
|
|
|
Some(obj) => {
|
|
|
|
panic!("Unhandled first object type inside bullshitium {:?}", obj);
|
|
|
|
}
|
|
|
|
None => {
|
|
|
|
unreachable!("Paragraph must have children.");
|
|
|
|
}
|
|
|
|
};
|
|
|
|
Ok((remaining, paragraph))
|
|
|
|
} else {
|
2023-10-18 12:17:57 -04:00
|
|
|
let (remaining, _trailing_ws) =
|
|
|
|
maybe_consume_trailing_whitespace_if_not_exiting(context, lead_in_remaining)?;
|
|
|
|
|
2023-10-18 11:57:39 -04:00
|
|
|
Ok((
|
2023-10-18 12:17:57 -04:00
|
|
|
remaining,
|
2023-10-23 17:22:52 -04:00
|
|
|
Paragraph::of_text(
|
|
|
|
input.get_until(remaining).into(),
|
|
|
|
input.get_until(lead_in_remaining).into(),
|
|
|
|
),
|
2023-10-18 11:57:39 -04:00
|
|
|
))
|
|
|
|
}
|
|
|
|
}
|
2023-10-18 12:36:06 -04:00
|
|
|
|
|
|
|
#[cfg_attr(
|
|
|
|
feature = "tracing",
|
2023-10-18 12:42:09 -04:00
|
|
|
tracing::instrument(ret, level = "debug", skip(_context))
|
2023-10-18 12:36:06 -04:00
|
|
|
)]
|
|
|
|
pub(crate) fn detect_broken_dynamic_block<'b, 'g, 'r, 's>(
|
|
|
|
_context: RefContext<'b, 'g, 'r, 's>,
|
|
|
|
input: OrgSource<'s>,
|
|
|
|
) -> Res<OrgSource<'s>, ()> {
|
|
|
|
start_of_line(input)?;
|
|
|
|
let (remaining, _) = space0(input)?;
|
|
|
|
let (_remaining, _) = tag_no_case("#+BEGIN:")(remaining)?;
|
|
|
|
Ok((input, ()))
|
|
|
|
}
|