refactor: cleanup
This commit is contained in:
parent
38380aab2c
commit
128825f148
|
@ -4,3 +4,4 @@ version = "0.1.0"
|
||||||
authors = ["PoiScript <poiscript@gmail.com>"]
|
authors = ["PoiScript <poiscript@gmail.com>"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
jetscii = "0.4.3"
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#[macro_use]
|
||||||
|
extern crate jetscii;
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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])
|
||||||
|
|
|
@ -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="),
|
||||||
(
|
(
|
||||||
|
|
|
@ -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,
|
||||||
))
|
))
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
//! Until macros
|
//! Utils macros
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! expect {
|
macro_rules! expect {
|
||||||
|
|
Loading…
Reference in a new issue