fix(elements): returning the correct offset
This commit is contained in:
parent
3105470cee
commit
64535641c1
|
@ -9,7 +9,7 @@ impl Keyword {
|
||||||
starts_with!(src, "#+");
|
starts_with!(src, "#+");
|
||||||
}
|
}
|
||||||
|
|
||||||
let key = until_while!(src, 2, b':', |c: u8| c.is_ascii_uppercase() || c == b'_')?;
|
let key = until_while!(src, 2, b':', |c: u8| c.is_ascii_alphabetic() || c == b'_')?;
|
||||||
|
|
||||||
// includes the eol character
|
// includes the eol character
|
||||||
let end = src.find('\n').map(|i| i + 1).unwrap_or_else(|| src.len());
|
let end = src.find('\n').map(|i| i + 1).unwrap_or_else(|| src.len());
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
use memchr::memchr_iter;
|
|
||||||
use std::iter::once;
|
|
||||||
|
|
||||||
pub struct List;
|
pub struct List;
|
||||||
|
|
||||||
macro_rules! ident {
|
macro_rules! ident {
|
||||||
|
@ -56,23 +53,16 @@ impl List {
|
||||||
// TODO: handle nested list
|
// TODO: handle nested list
|
||||||
pub fn parse_item(src: &str, ident: usize) -> (usize, usize) {
|
pub fn parse_item(src: &str, ident: usize) -> (usize, usize) {
|
||||||
let beg = src[ident..].find(' ').map(|i| ident + i + 1).unwrap();
|
let beg = src[ident..].find(' ').map(|i| ident + i + 1).unwrap();
|
||||||
let mut pos = match src.find('\n') {
|
let mut lines = lines!(src);
|
||||||
Some(i) => i + 1,
|
// skip first line
|
||||||
None => return (beg, src.len()),
|
let mut pos = lines.next().unwrap();
|
||||||
};
|
for line_end in lines {
|
||||||
while let Some(line_end) = src[pos..].find('\n').map(|i| i + pos + 1).or_else(|| {
|
let line = &src[pos..line_end];
|
||||||
if pos < src.len() {
|
if !line.trim().is_empty() && ident!(line) == ident {
|
||||||
Some(src.len())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}) {
|
|
||||||
if ident!(src[pos..]) == ident {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
pos = line_end;
|
pos = line_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
(beg, pos)
|
(beg, pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,7 +200,7 @@ fn parse() {
|
||||||
|
|
||||||
- Morbi tortor mi, dapibus vel faucibus a, iaculis sed turpis."#
|
- Morbi tortor mi, dapibus vel faucibus a, iaculis sed turpis."#
|
||||||
),
|
),
|
||||||
Some((1, false, 677, 677))
|
Some((0, false, 666, 666))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,7 +222,7 @@ fn is_item() {
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_item() {
|
fn parse_item() {
|
||||||
assert_eq!(List::parse_item("+ Item1\n+ Item2", 0), (2, 8));
|
assert_eq!(List::parse_item("+ Item1\n+ Item2", 0), (2, 8));
|
||||||
assert_eq!(List::parse_item("+ Item1\n\n+ Item2", 0), (2, 8));
|
assert_eq!(List::parse_item("+ Item1\n\n+ Item2", 0), (2, 9));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
List::parse_item(
|
List::parse_item(
|
||||||
r"+ item1
|
r"+ item1
|
||||||
|
@ -271,4 +261,28 @@ fn parse_item() {
|
||||||
),
|
),
|
||||||
(3, 119)
|
(3, 119)
|
||||||
);
|
);
|
||||||
|
assert_eq!(
|
||||||
|
List::parse_item(
|
||||||
|
r#"- Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||||
|
|
||||||
|
- Nulla et dolor vitae elit placerat sagittis. Aliquam a lobortis massa,
|
||||||
|
aliquam efficitur arcu.
|
||||||
|
|
||||||
|
- Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||||
|
|
||||||
|
- Phasellus auctor lacus a orci imperdiet, ut facilisis neque lobortis.
|
||||||
|
|
||||||
|
- Proin condimentum id orci vitae lobortis. Nunc sollicitudin risus neque,
|
||||||
|
dapibus malesuada sem faucibus vitae.
|
||||||
|
|
||||||
|
- Sed vitae dolor augue. Phasellus at rhoncus arcu. Suspendisse potenti.
|
||||||
|
|
||||||
|
- Nulla faucibus, metus ut porta hendrerit, urna lorem porta metus, in tempus
|
||||||
|
nibh orci sed sapien.
|
||||||
|
|
||||||
|
- Morbi tortor mi, dapibus vel faucibus a, iaculis sed turpis."#,
|
||||||
|
0
|
||||||
|
),
|
||||||
|
(2, 421)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,16 +134,25 @@ impl<'a> Element<'a> {
|
||||||
|| bytes[pos] == b'*'
|
|| bytes[pos] == b'*'
|
||||||
|| (bytes[pos] >= b'0' && bytes[pos] <= b'9')
|
|| (bytes[pos] >= b'0' && bytes[pos] <= b'9')
|
||||||
{
|
{
|
||||||
if let Some((ident, ordered, cont_end, end)) = List::parse(&src[end..]) {
|
if let Some((ident, ordered, cont_end, list_end)) = List::parse(&src[end..]) {
|
||||||
ret!(
|
let list = Element::List {
|
||||||
Element::List {
|
|
||||||
ident,
|
ident,
|
||||||
ordered,
|
ordered,
|
||||||
cont_end,
|
cont_end,
|
||||||
end
|
end: list_end,
|
||||||
},
|
};
|
||||||
0
|
return if pos == start {
|
||||||
);
|
(1, Some(list), None)
|
||||||
|
} else {
|
||||||
|
(
|
||||||
|
start,
|
||||||
|
Some(Element::Paragraph {
|
||||||
|
cont_end: end,
|
||||||
|
end: end,
|
||||||
|
}),
|
||||||
|
Some((list, 1)),
|
||||||
|
)
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,42 +182,13 @@ impl<'a> Element<'a> {
|
||||||
if let Some((name, args, contents_beg, cont_end, end)) =
|
if let Some((name, args, contents_beg, cont_end, end)) =
|
||||||
Block::parse(&src[pos..])
|
Block::parse(&src[pos..])
|
||||||
{
|
{
|
||||||
|
let cont = &src[pos + contents_beg + 1..pos + cont_end - 1];
|
||||||
match name.to_uppercase().as_str() {
|
match name.to_uppercase().as_str() {
|
||||||
"COMMENT" => ret!(
|
"COMMENT" => ret!(Element::CommentBlock { args, cont }, pos + end),
|
||||||
Element::CommentBlock {
|
"EXAMPLE" => ret!(Element::ExampleBlock { args, cont }, pos + end),
|
||||||
args,
|
"EXPORT" => ret!(Element::ExportBlock { args, cont }, pos + end),
|
||||||
cont: &src[pos + contents_beg + 1..pos + cont_end - 1],
|
"SRC" => ret!(Element::SrcBlock { args, cont }, pos + end),
|
||||||
},
|
"VERSE" => ret!(Element::VerseBlock { args, cont }, pos + end),
|
||||||
pos + end
|
|
||||||
),
|
|
||||||
"EXAMPLE" => ret!(
|
|
||||||
Element::ExampleBlock {
|
|
||||||
args,
|
|
||||||
cont: &src[pos + contents_beg + 1..pos + cont_end - 1],
|
|
||||||
},
|
|
||||||
pos + end
|
|
||||||
),
|
|
||||||
"EXPORT" => ret!(
|
|
||||||
Element::ExportBlock {
|
|
||||||
args,
|
|
||||||
cont: &src[pos + contents_beg + 1..pos + cont_end - 1],
|
|
||||||
},
|
|
||||||
pos + end
|
|
||||||
),
|
|
||||||
"SRC" => ret!(
|
|
||||||
Element::SrcBlock {
|
|
||||||
args,
|
|
||||||
cont: &src[pos + contents_beg + 1..pos + cont_end - 1],
|
|
||||||
},
|
|
||||||
pos + end
|
|
||||||
),
|
|
||||||
"VERSE" => ret!(
|
|
||||||
Element::VerseBlock {
|
|
||||||
args,
|
|
||||||
cont: &src[pos + contents_beg + 1..pos + cont_end - 1],
|
|
||||||
},
|
|
||||||
pos + end
|
|
||||||
),
|
|
||||||
"CENTER" => ret!(
|
"CENTER" => ret!(
|
||||||
Element::CtrBlock {
|
Element::CtrBlock {
|
||||||
args,
|
args,
|
||||||
|
|
|
@ -249,8 +249,26 @@ impl<'a> Parser<'a> {
|
||||||
}),
|
}),
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
self.off += off;
|
self.off += off;
|
||||||
ele.into()
|
|
||||||
|
match ele {
|
||||||
|
Element::Comment(c) => Event::Comment(c),
|
||||||
|
Element::CommentBlock { args, cont } => Event::CommentBlock { args, cont },
|
||||||
|
Element::CtrBlock { .. } => Event::CtrBlockBeg,
|
||||||
|
Element::DynBlock { name, args, .. } => Event::DynBlockBeg { name, args },
|
||||||
|
Element::ExampleBlock { args, cont } => Event::ExampleBlock { args, cont },
|
||||||
|
Element::ExportBlock { args, cont } => Event::ExportBlock { args, cont },
|
||||||
|
Element::FnDef { label, cont } => Event::FnDef { label, cont },
|
||||||
|
Element::Keyword { key, value } => Event::Keyword { key, value },
|
||||||
|
Element::List { ordered, .. } => Event::ListBeg { ordered },
|
||||||
|
Element::Paragraph { .. } => Event::ParagraphBeg,
|
||||||
|
Element::QteBlock { .. } => Event::QteBlockBeg,
|
||||||
|
Element::Rule => Event::Rule,
|
||||||
|
Element::SplBlock { name, args, .. } => Event::SplBlockBeg { name, args },
|
||||||
|
Element::SrcBlock { args, cont } => Event::SrcBlock { args, cont },
|
||||||
|
Element::VerseBlock { args, cont } => Event::VerseBlock { args, cont },
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
self.off += off;
|
self.off += off;
|
||||||
self.end()
|
self.end()
|
||||||
|
@ -282,7 +300,24 @@ impl<'a> Parser<'a> {
|
||||||
|
|
||||||
self.off += off;
|
self.off += off;
|
||||||
|
|
||||||
obj.into()
|
match obj {
|
||||||
|
Object::Bold { .. } => Event::BoldBeg,
|
||||||
|
Object::Code(c) => Event::Code(c),
|
||||||
|
Object::Cookie(c) => Event::Cookie(c),
|
||||||
|
Object::FnRef(f) => Event::FnRef(f),
|
||||||
|
Object::InlineCall(i) => Event::InlineCall(i),
|
||||||
|
Object::InlineSrc(i) => Event::InlineSrc(i),
|
||||||
|
Object::Italic { .. } => Event::ItalicBeg,
|
||||||
|
Object::Link(l) => Event::Link(l),
|
||||||
|
Object::Macros(m) => Event::Macros(m),
|
||||||
|
Object::RadioTarget(r) => Event::RadioTarget(r),
|
||||||
|
Object::Snippet(s) => Event::Snippet(s),
|
||||||
|
Object::Strike { .. } => Event::StrikeBeg,
|
||||||
|
Object::Target(t) => Event::Target(t),
|
||||||
|
Object::Text(t) => Event::Text(t),
|
||||||
|
Object::Underline { .. } => Event::UnderlineBeg,
|
||||||
|
Object::Verbatim(v) => Event::Verbatim(v),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next_list_item(&mut self, end: usize, ident: usize) -> Event<'a> {
|
fn next_list_item(&mut self, end: usize, ident: usize) -> Event<'a> {
|
||||||
|
@ -325,18 +360,18 @@ impl<'a> Parser<'a> {
|
||||||
| Strike { end }
|
| Strike { end }
|
||||||
| Bold { end }
|
| Bold { end }
|
||||||
| Underline { end } => {
|
| Underline { end } => {
|
||||||
assert!(self.off <= end);
|
debug_assert!(self.off <= end);
|
||||||
}
|
}
|
||||||
Paragraph { cont_end, end } => {
|
Paragraph { cont_end, end } => {
|
||||||
assert!(self.off <= end);
|
debug_assert!(self.off <= end);
|
||||||
assert!(self.off <= cont_end);
|
debug_assert!(self.off <= cont_end);
|
||||||
}
|
}
|
||||||
CtrBlock { cont_end, end }
|
CtrBlock { cont_end, end }
|
||||||
| QteBlock { cont_end, end }
|
| QteBlock { cont_end, end }
|
||||||
| SplBlock { cont_end, end }
|
| SplBlock { cont_end, end }
|
||||||
| DynBlock { cont_end, end } => {
|
| DynBlock { cont_end, end } => {
|
||||||
assert!(self.off <= cont_end);
|
debug_assert!(self.off <= cont_end);
|
||||||
assert!(self.off <= end);
|
debug_assert!(self.off <= end);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -391,7 +426,7 @@ impl<'a> Iterator for Parser<'a> {
|
||||||
self.off = end;
|
self.off = end;
|
||||||
self.end()
|
self.end()
|
||||||
} else {
|
} else {
|
||||||
self.next_list_item(end, ident)
|
self.next_list_item(cont_end, ident)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Container::ListItem { end } => {
|
Container::ListItem { end } => {
|
||||||
|
@ -399,7 +434,7 @@ impl<'a> Iterator for Parser<'a> {
|
||||||
self.end()
|
self.end()
|
||||||
} else {
|
} else {
|
||||||
// TODO: handle nested list
|
// TODO: handle nested list
|
||||||
self.next_obj(end)
|
self.next_ele(end)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Container::Section { end } => {
|
Container::Section { end } => {
|
||||||
|
@ -433,51 +468,6 @@ impl<'a> Iterator for Parser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> From<Object<'a>> for Event<'a> {
|
|
||||||
fn from(obj: Object<'a>) -> Self {
|
|
||||||
match obj {
|
|
||||||
Object::Bold { .. } => Event::BoldBeg,
|
|
||||||
Object::Code(c) => Event::Code(c),
|
|
||||||
Object::Cookie(c) => Event::Cookie(c),
|
|
||||||
Object::FnRef(f) => Event::FnRef(f),
|
|
||||||
Object::InlineCall(i) => Event::InlineCall(i),
|
|
||||||
Object::InlineSrc(i) => Event::InlineSrc(i),
|
|
||||||
Object::Italic { .. } => Event::ItalicBeg,
|
|
||||||
Object::Link(l) => Event::Link(l),
|
|
||||||
Object::Macros(m) => Event::Macros(m),
|
|
||||||
Object::RadioTarget(r) => Event::RadioTarget(r),
|
|
||||||
Object::Snippet(s) => Event::Snippet(s),
|
|
||||||
Object::Strike { .. } => Event::StrikeBeg,
|
|
||||||
Object::Target(t) => Event::Target(t),
|
|
||||||
Object::Text(t) => Event::Text(t),
|
|
||||||
Object::Underline { .. } => Event::UnderlineBeg,
|
|
||||||
Object::Verbatim(v) => Event::Verbatim(v),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> From<Element<'a>> for Event<'a> {
|
|
||||||
fn from(ele: Element<'a>) -> Self {
|
|
||||||
match ele {
|
|
||||||
Element::Comment(c) => Event::Comment(c),
|
|
||||||
Element::CommentBlock { args, cont } => Event::CommentBlock { args, cont },
|
|
||||||
Element::CtrBlock { .. } => Event::CtrBlockBeg,
|
|
||||||
Element::DynBlock { name, args, .. } => Event::DynBlockBeg { name, args },
|
|
||||||
Element::ExampleBlock { args, cont } => Event::ExampleBlock { args, cont },
|
|
||||||
Element::ExportBlock { args, cont } => Event::ExportBlock { args, cont },
|
|
||||||
Element::FnDef { label, cont } => Event::FnDef { label, cont },
|
|
||||||
Element::Keyword { key, value } => Event::Keyword { key, value },
|
|
||||||
Element::List { ordered, .. } => Event::ListBeg { ordered },
|
|
||||||
Element::Paragraph { .. } => Event::ParagraphBeg,
|
|
||||||
Element::QteBlock { .. } => Event::QteBlockBeg,
|
|
||||||
Element::Rule => Event::Rule,
|
|
||||||
Element::SplBlock { name, args, .. } => Event::SplBlockBeg { name, args },
|
|
||||||
Element::SrcBlock { args, cont } => Event::SrcBlock { args, cont },
|
|
||||||
Element::VerseBlock { args, cont } => Event::VerseBlock { args, cont },
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse() {
|
fn parse() {
|
||||||
use self::Event::*;
|
use self::Event::*;
|
||||||
|
|
Loading…
Reference in a new issue