refactor: cleanup

This commit is contained in:
PoiScript 2019-01-11 22:35:06 +08:00
parent 38380aab2c
commit 128825f148
9 changed files with 87 additions and 101 deletions

View file

@ -4,3 +4,4 @@ version = "0.1.0"
authors = ["PoiScript <poiscript@gmail.com>"] authors = ["PoiScript <poiscript@gmail.com>"]
[dependencies] [dependencies]
jetscii = "0.4.3"

View file

@ -112,14 +112,14 @@ impl<'a> Headline<'a> {
// TODO: optimize // TODO: optimize
pub fn find_level(src: &str, level: usize) -> usize { pub fn find_level(src: &str, level: usize) -> usize {
let mut pos = 0; let mut pos = 0;
'outer: loop { loop {
if pos >= src.len() { if pos >= src.len() {
return src.len(); return src.len();
} }
if src.as_bytes()[pos] == b'*' && (pos == 0 || src.as_bytes()[pos - 1] == b'\n') { if src.as_bytes()[pos] == b'*' && (pos == 0 || src.as_bytes()[pos - 1] == b'\n') {
let pos_ = pos; let pos_ = pos;
'inner: loop { loop {
if pos >= src.len() { if pos >= src.len() {
return src.len(); return src.len();
} }
@ -128,7 +128,7 @@ impl<'a> Headline<'a> {
} else if src.as_bytes()[pos] == b' ' && pos - pos_ <= level { } else if src.as_bytes()[pos] == b' ' && pos - pos_ <= level {
return pos_; return pos_;
} else { } else {
break 'inner; break;
} }
} }
} }

View file

@ -1,3 +1,6 @@
#[macro_use]
extern crate jetscii;
#[macro_use] #[macro_use]
mod utils; mod utils;

View file

@ -29,14 +29,14 @@ impl Emphasis {
|| ch == b'}'); || ch == b'}');
} }
Some(end - 1) Some(end)
} }
} }
#[test] #[test]
fn parse() { fn parse() {
assert_eq!(Emphasis::parse("*bold*", b'*').unwrap(), "bold".len()); assert_eq!(Emphasis::parse("*bold*", b'*').unwrap(), "*bold".len());
assert_eq!(Emphasis::parse("*bo\nld*", b'*').unwrap(), "bo\nld".len()); assert_eq!(Emphasis::parse("*bo\nld*", b'*').unwrap(), "*bo\nld".len());
assert!(Emphasis::parse("*bold*a", b'*').is_none()); assert!(Emphasis::parse("*bold*a", b'*').is_none());
assert!(Emphasis::parse("*bold*", b'/').is_none()); assert!(Emphasis::parse("*bold*", b'/').is_none());
assert!(Emphasis::parse("*bold *", b'*').is_none()); assert!(Emphasis::parse("*bold *", b'*').is_none());

View file

@ -1,3 +1,5 @@
use jetscii::Substring;
#[cfg_attr(test, derive(PartialEq, Debug))] #[cfg_attr(test, derive(PartialEq, Debug))]
pub struct Macros<'a> { pub struct Macros<'a> {
pub name: &'a str, pub name: &'a str,
@ -27,12 +29,12 @@ impl<'a> Macros<'a> {
name + 3, name + 3,
)) ))
} else { } else {
let end = &src[name..].find("}}}").map(|i| i + name)?; let end = Substring::new("}}}").find(&src[name..]).map(|i| i + name)?;
expect!(src, end - 1, b')')?; expect!(src, end - 1, b')')?;
Some(( Some((
Macros { Macros {
name: &src[3..name], name: &src[3..name],
args: if name == *end { args: if name == end {
None None
} else { } else {
Some(&src[name + 1..end - 1]) Some(&src[name + 1..end - 1])

View file

@ -32,6 +32,7 @@ pub enum Object<'a> {
Snippet(Snippet<'a>), Snippet(Snippet<'a>),
Target(Target<'a>), Target(Target<'a>),
// `end` indicates the position of the second marker
Bold { end: usize }, Bold { end: usize },
Italic { end: usize }, Italic { end: usize },
Strike { end: usize }, Strike { end: usize },
@ -52,19 +53,13 @@ impl<'a> Object<'a> {
// TODO: refactor with src[..].find(..) // TODO: refactor with src[..].find(..)
for pos in 0..src.len() - 2 { for pos in 0..src.len() - 2 {
macro_rules! parse { macro_rules! ret {
($obj:ident) => { ($obj:expr, $off:expr) => {
if let Some((obj, off)) = $obj::parse(&src[pos..]) { return if pos == 0 {
return if pos == 0 { ($obj, $off, None)
(Object::$obj(obj), off, None) } else {
} else { (Object::Text(&src[0..pos]), pos, Some(($obj, $off)))
( };
Object::Text(&src[0..pos]),
pos,
Some((Object::$obj(obj), off)),
)
};
}
}; };
} }
@ -73,29 +68,43 @@ impl<'a> Object<'a> {
let third = bytes[pos + 2]; let third = bytes[pos + 2];
if first == b'@' && second == b'@' { if first == b'@' && second == b'@' {
parse!(Snippet); if let Some((snippet, off)) = Snippet::parse(&src[pos..]) {
ret!(Object::Snippet(snippet), off);
}
} }
if first == b'[' { if first == b'[' {
if second == b'f' && third == b'n' { if second == b'f' && third == b'n' {
parse!(FnRef); if let Some((fn_ref, off)) = FnRef::parse(&src[pos..]) {
ret!(Object::FnRef(fn_ref), off);
}
} else if second == b'[' { } else if second == b'[' {
parse!(Link); if let Some((link, off)) = Link::parse(&src[pos..]) {
ret!(Object::Link(link), off);
}
} else { } else {
parse!(Cookie); if let Some((cookie, off)) = Cookie::parse(&src[pos..]) {
ret!(Object::Cookie(cookie), off);
}
// TODO: Timestamp // TODO: Timestamp
} }
} }
if first == b'{' && second == b'{' && third == b'{' { if first == b'{' && second == b'{' && third == b'{' {
parse!(Macros); if let Some((macros, off)) = Macros::parse(&src[pos..]) {
ret!(Object::Macros(macros), off);
}
} }
if first == b'<' && second == b'<' { if first == b'<' && second == b'<' {
if third == b'<' { if third == b'<' {
parse!(RadioTarget); if let Some((target, off)) = RadioTarget::parse(&src[pos..]) {
ret!(Object::RadioTarget(target), off);
}
} else if third != b'<' && third != b'\n' { } else if third != b'<' && third != b'\n' {
parse!(Target); if let Some((target, off)) = Target::parse(&src[pos..]) {
ret!(Object::Target(target), off);
}
} }
} }
@ -115,62 +124,29 @@ impl<'a> Object<'a> {
|| first == b'~') || first == b'~')
&& !second.is_ascii_whitespace() && !second.is_ascii_whitespace()
{ {
if let Some(end) = Emphasis::parse(&src[pos..], first).map(|i| i + pos) { if let Some(end) = Emphasis::parse(&src[pos..], first) {
macro_rules! emph {
($obj:ident) => {
return if pos == 0 {
(Object::$obj { end }, 1, None)
} else {
(
Object::Text(&src[0..pos]),
pos,
Some((Object::$obj { end }, end)),
)
};
};
}
match first { match first {
b'*' => emph!(Bold), b'*' => ret!(Object::Bold { end }, 1),
b'+' => emph!(Strike), b'+' => ret!(Object::Strike { end }, 1),
b'/' => emph!(Italic), b'/' => ret!(Object::Italic { end }, 1),
b'_' => emph!(Underline), b'_' => ret!(Object::Underline { end }, 1),
b'~' => { b'~' => ret!(Object::Code(&src[pos + 1..pos + end]), end + 1),
return if pos == 0 { b'=' => ret!(Object::Verbatim(&src[pos + 1..pos + end]), end + 1),
(Object::Code(&src[1..end + 1]), end + 2, None)
} else {
(
Object::Text(&src[0..pos]),
pos,
Some((Object::Code(&src[pos + 1..end + 1]), end - pos + 2)),
)
};
}
b'=' => {
return if pos == 0 {
(Object::Verbatim(&src[1..end + 1]), end + 2, None)
} else {
(
Object::Text(&src[0..pos]),
pos,
Some((
Object::Verbatim(&src[pos + 1..end + 1]),
end - pos + 2,
)),
)
};
}
_ => unreachable!(), _ => unreachable!(),
} }
} }
} }
if first == b'c' && second == b'a' && third == b'l' { if first == b'c' && second == b'a' && third == b'l' {
parse!(InlineCall); if let Some((call, off)) = InlineCall::parse(&src[pos..]) {
ret!(Object::InlineCall(call), off);
}
} }
if first == b's' && second == b'r' && third == b'c' { if first == b's' && second == b'r' && third == b'c' {
parse!(InlineSrc); if let Some((src, off)) = InlineSrc::parse(&src[pos..]) {
ret!(Object::InlineSrc(src), off);
}
} }
} }
} }
@ -182,7 +158,7 @@ impl<'a> Object<'a> {
#[test] #[test]
fn next_2() { fn next_2() {
// TODO: more tests // TODO: more tests
assert_eq!(Object::next_2("*bold*"), (Object::Bold { end: 4 }, 1, None)); assert_eq!(Object::next_2("*bold*"), (Object::Bold { end: 5 }, 1, None));
assert_eq!( assert_eq!(
Object::next_2("Normal =verbatim="), Object::next_2("Normal =verbatim="),
( (

View file

@ -1,3 +1,5 @@
use jetscii::Substring;
#[cfg_attr(test, derive(PartialEq, Debug))] #[cfg_attr(test, derive(PartialEq, Debug))]
pub struct Snippet<'a> { pub struct Snippet<'a> {
pub name: &'a str, pub name: &'a str,
@ -14,12 +16,14 @@ impl<'a> Snippet<'a> {
return None; return None;
} }
let end = &src[name + 1..].find("@@").map(|i| i + name + 1)?; let end = Substring::new("@@")
.find(&src[name + 1..])
.map(|i| i + name + 1)?;
Some(( Some((
Snippet { Snippet {
name: &src[2..name], name: &src[2..name],
value: &src[name + 1..*end], value: &src[name + 1..end],
}, },
end + 2, end + 2,
)) ))

View file

@ -156,58 +156,56 @@ impl<'a> Parser<'a> {
} }
fn next_ele(&mut self, end: usize) -> Event<'a> { fn next_ele(&mut self, end: usize) -> Event<'a> {
let (ele, off) = if let Some((ele, off)) = std::mem::replace(&mut self.ele_buf, None) { let (ele, off) = self
(Some(ele), off) .ele_buf
} else { .take()
let (off, ele, next_2) = Element::next_2(&self.text[self.off..end]); .map(|(ele, off)| (Some(ele), off))
self.ele_buf = next_2; .unwrap_or_else(|| {
(ele, off) let (off, ele, next_2) = Element::next_2(&self.text[self.off..end]);
}; self.ele_buf = next_2;
(ele, off)
self.off += off; });
if let Some(ele) = ele { if let Some(ele) = ele {
match ele { match ele {
Element::Paragraph { end, trailing } => self.stack.push(Container::Paragraph { Element::Paragraph { end, trailing } => self.stack.push(Container::Paragraph {
end: end + self.off - off, end: end + self.off,
trailing: trailing + self.off - off, trailing: trailing + self.off,
}), }),
Element::QuoteBlock { Element::QuoteBlock {
end, content_end, .. end, content_end, ..
} => self.stack.push(Container::QuoteBlock { } => self.stack.push(Container::QuoteBlock {
content_end: content_end + self.off - off, content_end: content_end + self.off,
end: end + self.off - off, end: end + self.off,
}), }),
Element::CenterBlock { Element::CenterBlock {
end, content_end, .. end, content_end, ..
} => self.stack.push(Container::CenterBlock { } => self.stack.push(Container::CenterBlock {
content_end: content_end + self.off - off, content_end: content_end + self.off,
end: end + self.off - off, end: end + self.off,
}), }),
Element::SpecialBlock { Element::SpecialBlock {
end, content_end, .. end, content_end, ..
} => self.stack.push(Container::SpecialBlock { } => self.stack.push(Container::SpecialBlock {
content_end: content_end + self.off - off, content_end: content_end + self.off,
end: end + self.off - off, end: end + self.off,
}), }),
_ => (), _ => (),
} }
self.off += off;
ele.into() ele.into()
} else { } else {
self.off += off;
self.end() self.end()
} }
} }
fn next_obj(&mut self, end: usize) -> Event<'a> { fn next_obj(&mut self, end: usize) -> Event<'a> {
let (obj, off) = if let Some((obj, off)) = std::mem::replace(&mut self.obj_buf, None) { let (obj, off) = self.obj_buf.take().unwrap_or_else(|| {
(obj, off)
} else {
let (obj, off, next_2) = Object::next_2(&self.text[self.off..end]); let (obj, off, next_2) = Object::next_2(&self.text[self.off..end]);
self.obj_buf = next_2; self.obj_buf = next_2;
(obj, off) (obj, off)
}; });
self.off += off;
match obj { match obj {
Object::Underline { end } => self.stack.push(Container::Underline { Object::Underline { end } => self.stack.push(Container::Underline {
@ -225,6 +223,8 @@ impl<'a> Parser<'a> {
_ => (), _ => (),
} }
self.off += off;
obj.into() obj.into()
} }

View file

@ -1,4 +1,4 @@
//! Until macros //! Utils macros
#[macro_export] #[macro_export]
macro_rules! expect { macro_rules! expect {