feat(elements): comment and fixed width elements

This commit is contained in:
PoiScript 2019-06-27 18:11:58 +08:00
parent bd1fc756bd
commit 275fbfad34
4 changed files with 85 additions and 136 deletions

View file

@ -349,4 +349,18 @@ pub enum Element<'a> {
end: usize,
value: &'a str,
},
Comment {
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
begin: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
end: usize,
value: &'a str,
},
FixedWidth {
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
begin: usize,
#[cfg_attr(all(feature = "serde", not(feature = "extra-serde-info")), serde(skip))]
end: usize,
value: &'a str,
},
}

View file

@ -156,6 +156,18 @@ pub trait HtmlHandler<E: From<Error>> {
fn fn_def<W: Write>(&mut self, mut w: W, fn_def: &FnDef<'_>) -> Result<(), E> {
Ok(())
}
fn comment<W: Write>(&mut self, mut w: W, value: &str) -> Result<(), E> {
write!(&mut w, "<!--\n")?;
self.text(&mut w, value)?;
write!(&mut w, "\n-->")?;
Ok(())
}
fn fixed_width<W: Write>(&mut self, mut w: W, value: &str) -> Result<(), E> {
write!(&mut w, "<pre>")?;
self.text(&mut w, value)?;
write!(&mut w, "</pre>")?;
Ok(())
}
}
pub struct DefaultHtmlHandler;

View file

@ -22,6 +22,8 @@ pub enum Container<'a> {
pub enum Event<'a> {
Start(Container<'a>),
End(Container<'a>),
Rule,
BabelCall(&'a BabelCall<'a>),
Clock(&'a Clock<'a>),
Cookie(&'a Cookie<'a>),
Drawer(&'a Drawer<'a>),
@ -34,14 +36,14 @@ pub enum Event<'a> {
Macros(&'a Macros<'a>),
Planning(Planning<'a>),
RadioTarget(&'a RadioTarget<'a>),
Rule,
Snippet(&'a Snippet<'a>),
Target(&'a Target<'a>),
Timestamp(&'a Timestamp<'a>),
Text(&'a str),
Code(&'a str),
Comment(&'a str),
FixedWidth(&'a str),
Text(&'a str),
Verbatim(&'a str),
BabelCall(&'a BabelCall<'a>),
}
enum State {
@ -277,6 +279,14 @@ impl<'a> Iter<'a> {
self.state = State::Start;
Some(Event::Timestamp(timestamp))
}
Element::FixedWidth { value, .. } => {
self.state = State::Start;
Some(Event::FixedWidth(value))
}
Element::Comment { value, .. } => {
self.state = State::Start;
Some(Event::Comment(value))
}
}
}
@ -287,22 +297,6 @@ impl<'a> Iter<'a> {
self.state = State::Finished;
None
}
Element::BabelCall { call, .. } => {
self.state = State::End;
Some(Event::BabelCall(call))
}
Element::Verbatim { value, .. } => {
self.state = State::End;
Some(Event::Verbatim(value))
}
Element::Code { value, .. } => {
self.state = State::End;
Some(Event::Code(value))
}
Element::Text { value, .. } => {
self.state = State::End;
Some(Event::Text(value))
}
Element::Block { block, .. } => {
self.state = State::End;
Some(Event::End(Container::Block(block)))
@ -351,97 +345,7 @@ impl<'a> Iter<'a> {
self.state = State::End;
Some(Event::End(Container::Underline))
}
Element::Clock { clock, .. } => {
self.state = State::End;
Some(Event::Clock(clock))
}
Element::Cookie { cookie, .. } => {
self.state = State::End;
Some(Event::Cookie(cookie))
}
Element::Drawer { drawer, .. } => {
self.state = State::End;
Some(Event::Drawer(drawer))
}
Element::FnDef { fn_def, .. } => {
self.state = State::End;
Some(Event::FnDef(fn_def))
}
Element::FnRef { fn_ref, .. } => {
self.state = State::End;
Some(Event::FnRef(fn_ref))
}
Element::InlineCall { inline_call, .. } => {
self.state = State::End;
Some(Event::InlineCall(inline_call))
}
Element::InlineSrc { inline_src, .. } => {
self.state = State::End;
Some(Event::InlineSrc(inline_src))
}
Element::Keyword { keyword, .. } => {
self.state = State::End;
Some(Event::Keyword(keyword))
}
Element::Link { link, .. } => {
self.state = State::End;
Some(Event::Link(link))
}
Element::Macros { macros, .. } => {
self.state = State::End;
Some(Event::Macros(macros))
}
Element::Planning {
deadline,
scheduled,
closed,
..
} => {
self.state = State::End;
Some(Event::Planning(Planning {
deadline: deadline.and_then(|id| {
if let Element::Timestamp { timestamp, .. } = &self.arena[id].data {
Some(timestamp)
} else {
None
}
}),
scheduled: scheduled.and_then(|id| {
if let Element::Timestamp { timestamp, .. } = &self.arena[id].data {
Some(timestamp)
} else {
None
}
}),
closed: closed.and_then(|id| {
if let Element::Timestamp { timestamp, .. } = &self.arena[id].data {
Some(timestamp)
} else {
None
}
}),
}))
}
Element::RadioTarget { radio_target, .. } => {
self.state = State::End;
Some(Event::RadioTarget(radio_target))
}
Element::Rule { .. } => {
self.state = State::End;
Some(Event::Rule)
}
Element::Snippet { snippet, .. } => {
self.state = State::End;
Some(Event::Snippet(snippet))
}
Element::Target { target, .. } => {
self.state = State::End;
Some(Event::Target(target))
}
Element::Timestamp { timestamp, .. } => {
self.state = State::End;
Some(Event::Timestamp(timestamp))
}
_ => unreachable!(),
}
}
}

View file

@ -73,6 +73,8 @@ impl<'a> Org<'a> {
Verbatim(e) => handler.verbatim(&mut writer, e)?,
BabelCall(e) => handler.babel_call(&mut writer, e)?,
Rule => handler.rule(&mut writer)?,
Comment(e) => handler.comment(&mut writer, e)?,
FixedWidth(e) => handler.fixed_width(&mut writer, e)?,
}
}
@ -271,12 +273,12 @@ impl<'a> Org<'a> {
let (end, _) = skip_empty_lines(&text[pos + i..]);
let new_node = self.arena.new_node(Element::Paragraph {
begin: begin + last_end,
end: begin + pos + 1 + i + end,
end: begin + pos + i + end,
contents_begin: begin + last_end,
contents_end: begin + pos,
});
node.append(new_node, &mut self.arena).unwrap();
pos += i + end + 1;
pos += i + end;
last_end = pos;
} else if let Some((ty, off)) = self.parse_element(begin + pos, end) {
if last_end != pos {
@ -346,8 +348,7 @@ impl<'a> Org<'a> {
// TODO: LaTeX environment
if tail.starts_with("\\begin{") {}
// rule
if tail.starts_with("-----") {
if tail.starts_with('-') {
if let Some(end) = Rule::parse(tail) {
let rule = Element::Rule {
begin,
@ -370,30 +371,48 @@ impl<'a> Org<'a> {
}
}
// fixed width
if tail.starts_with(": ") || tail.starts_with(":\n") {
// let end = line_ends
// .skip_while(|&i| {
// text[i + 1..].starts_with(": ") || text[i + 1..].starts_with(":\n")
// })
// .next()
// .map(|i| i + 1)
// .unwrap_or_else(|| text.len());
// let off = end - pos;
// brk!(Element::FixedWidth(&tail[0..off]), off);
if tail == ":" || tail.starts_with(": ") || tail.starts_with(":\n") {
let mut last_end = 1; // ":"
for i in memchr_iter(b'\n', text.as_bytes()) {
last_end = i + 1;
let line = &text[last_end..];
if !(line == ":" || line.starts_with(": ") || line.starts_with(":\n")) {
let fixed_width = Element::FixedWidth {
value: &text[0..i + 1],
begin,
end: begin + i + 1,
};
return Some((fixed_width, i + 1));
}
}
let fixed_width = Element::FixedWidth {
value: &text[0..last_end],
begin,
end: begin + last_end,
};
return Some((fixed_width, last_end));
}
// comment
if tail.starts_with("# ") || tail.starts_with("#\n") {
// let end = line_ends
// .skip_while(|&i| {
// text[i + 1..].starts_with("# ") || text[i + 1..].starts_with("#\n")
// })
// .next()
// .map(|i| i + 1)
// .unwrap_or_else(|| text.len());
// let off = end - pos;
// brk!(Element::Comment(&tail[0..off]), off);
if tail == "#" || tail.starts_with("# ") || tail.starts_with("#\n") {
let mut last_end = 1; // "#"
for i in memchr_iter(b'\n', text.as_bytes()) {
last_end = i + 1;
let line = &text[last_end..];
if !(line == "#" || line.starts_with("# ") || line.starts_with("#\n")) {
let fixed_width = Element::Comment {
value: &text[0..i + 1],
begin,
end: begin + i + 1,
};
return Some((fixed_width, i + 1));
}
}
let fixed_width = Element::Comment {
value: &text[0..last_end],
begin,
end: begin + last_end,
};
return Some((fixed_width, last_end));
}
if tail.starts_with("#+") {