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>"]
[dependencies]
jetscii = "0.4.3"

View file

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

View file

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

View file

@ -29,14 +29,14 @@ impl Emphasis {
|| ch == b'}');
}
Some(end - 1)
Some(end)
}
}
#[test]
fn parse() {
assert_eq!(Emphasis::parse("*bold*", b'*').unwrap(), "bold".len());
assert_eq!(Emphasis::parse("*bo\nld*", b'*').unwrap(), "bo\nld".len());
assert_eq!(Emphasis::parse("*bold*", b'*').unwrap(), "*bold".len());
assert_eq!(Emphasis::parse("*bo\nld*", b'*').unwrap(), "*bo\nld".len());
assert!(Emphasis::parse("*bold*a", 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))]
pub struct Macros<'a> {
pub name: &'a str,
@ -27,12 +29,12 @@ impl<'a> Macros<'a> {
name + 3,
))
} 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')')?;
Some((
Macros {
name: &src[3..name],
args: if name == *end {
args: if name == end {
None
} else {
Some(&src[name + 1..end - 1])

View file

@ -32,6 +32,7 @@ pub enum Object<'a> {
Snippet(Snippet<'a>),
Target(Target<'a>),
// `end` indicates the position of the second marker
Bold { end: usize },
Italic { end: usize },
Strike { end: usize },
@ -52,19 +53,13 @@ impl<'a> Object<'a> {
// TODO: refactor with src[..].find(..)
for pos in 0..src.len() - 2 {
macro_rules! parse {
($obj:ident) => {
if let Some((obj, off)) = $obj::parse(&src[pos..]) {
return if pos == 0 {
(Object::$obj(obj), off, None)
} else {
(
Object::Text(&src[0..pos]),
pos,
Some((Object::$obj(obj), off)),
)
};
}
macro_rules! ret {
($obj:expr, $off:expr) => {
return if pos == 0 {
($obj, $off, None)
} else {
(Object::Text(&src[0..pos]), pos, Some(($obj, $off)))
};
};
}
@ -73,29 +68,43 @@ impl<'a> Object<'a> {
let third = bytes[pos + 2];
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 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'[' {
parse!(Link);
if let Some((link, off)) = Link::parse(&src[pos..]) {
ret!(Object::Link(link), off);
}
} else {
parse!(Cookie);
if let Some((cookie, off)) = Cookie::parse(&src[pos..]) {
ret!(Object::Cookie(cookie), off);
}
// TODO: Timestamp
}
}
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 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' {
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'~')
&& !second.is_ascii_whitespace()
{
if let Some(end) = Emphasis::parse(&src[pos..], first).map(|i| i + pos) {
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)),
)
};
};
}
if let Some(end) = Emphasis::parse(&src[pos..], first) {
match first {
b'*' => emph!(Bold),
b'+' => emph!(Strike),
b'/' => emph!(Italic),
b'_' => emph!(Underline),
b'~' => {
return if pos == 0 {
(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,
)),
)
};
}
b'*' => ret!(Object::Bold { end }, 1),
b'+' => ret!(Object::Strike { end }, 1),
b'/' => ret!(Object::Italic { end }, 1),
b'_' => ret!(Object::Underline { end }, 1),
b'~' => ret!(Object::Code(&src[pos + 1..pos + end]), end + 1),
b'=' => ret!(Object::Verbatim(&src[pos + 1..pos + end]), end + 1),
_ => unreachable!(),
}
}
}
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' {
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]
fn next_2() {
// 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!(
Object::next_2("Normal =verbatim="),
(

View file

@ -1,3 +1,5 @@
use jetscii::Substring;
#[cfg_attr(test, derive(PartialEq, Debug))]
pub struct Snippet<'a> {
pub name: &'a str,
@ -14,12 +16,14 @@ impl<'a> Snippet<'a> {
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((
Snippet {
name: &src[2..name],
value: &src[name + 1..*end],
value: &src[name + 1..end],
},
end + 2,
))

View file

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

View file

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