refactor: rename field names to align with org-elements-api
This commit is contained in:
parent
f35c2d7bab
commit
93ed18602a
|
@ -3,7 +3,8 @@
|
|||
pub struct Block;
|
||||
|
||||
impl Block {
|
||||
pub fn parse(src: &str) -> Option<(usize, usize, usize, usize)> {
|
||||
// return (name, args, contents-begin, contents-end, end)
|
||||
pub fn parse(src: &str) -> Option<(&str, Option<&str>, usize, usize, usize)> {
|
||||
if src.len() < 17 || !src[0..8].eq_ignore_ascii_case("#+BEGIN_") {
|
||||
return None;
|
||||
}
|
||||
|
@ -15,7 +16,17 @@ impl Block {
|
|||
let content = src.find(&format!("\n#+END_{}", &src[8..name]))?;
|
||||
let end = eol!(src, content + 1);
|
||||
|
||||
Some((name, args, content, end + 1))
|
||||
Some((
|
||||
&src[8..name],
|
||||
if name == args {
|
||||
None
|
||||
} else {
|
||||
Some(&src[name..args])
|
||||
},
|
||||
args,
|
||||
content + 1,
|
||||
end + 1,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
#[cfg_attr(test, derive(PartialEq))]
|
||||
#[derive(Debug)]
|
||||
pub struct DynBlock<'a> {
|
||||
pub name: &'a str,
|
||||
pub para: &'a str,
|
||||
}
|
||||
pub struct DynBlock;
|
||||
|
||||
impl<'a> DynBlock<'a> {
|
||||
pub fn parse(src: &'a str) -> Option<(DynBlock<'a>, usize, usize)> {
|
||||
impl DynBlock {
|
||||
// return (name, parameters, contents-begin, contents-end, end)
|
||||
pub fn parse(src: &str) -> Option<(&str, Option<&str>, usize, usize, usize)> {
|
||||
if src.len() < 17 || !src[0..9].eq_ignore_ascii_case("#+BEGIN: ") {
|
||||
return None;
|
||||
}
|
||||
|
@ -19,12 +17,15 @@ impl<'a> DynBlock<'a> {
|
|||
let end = eol!(src, content + 1);
|
||||
|
||||
Some((
|
||||
DynBlock {
|
||||
name: &src[9..name],
|
||||
para: &src[name..args].trim(),
|
||||
&src[9..name],
|
||||
if name == args {
|
||||
None
|
||||
} else {
|
||||
Some(&src[name..args].trim())
|
||||
},
|
||||
content,
|
||||
end,
|
||||
args,
|
||||
content + 1,
|
||||
end + 1,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
@ -34,18 +35,11 @@ fn parse() {
|
|||
// TODO: testing
|
||||
assert_eq!(
|
||||
DynBlock::parse(
|
||||
r"#+BEGIN: clocktable :scope file :block yesterday
|
||||
r"#+BEGIN: clocktable :scope file
|
||||
CONTENTS
|
||||
#+END:
|
||||
"
|
||||
),
|
||||
Some((
|
||||
DynBlock {
|
||||
name: "clocktable",
|
||||
para: ":scope file :block yesterday"
|
||||
},
|
||||
57,
|
||||
64
|
||||
))
|
||||
Some(("clocktable", Some(":scope file"), 31, 41, 48))
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,17 +1,14 @@
|
|||
#[cfg_attr(test, derive(PartialEq))]
|
||||
#[derive(Debug)]
|
||||
pub struct FnDef<'a> {
|
||||
pub label: &'a str,
|
||||
pub contents: &'a str,
|
||||
}
|
||||
pub struct FnDef;
|
||||
|
||||
#[inline]
|
||||
fn valid_label(ch: u8) -> bool {
|
||||
ch.is_ascii_alphanumeric() || ch == b'-' || ch == b'_'
|
||||
}
|
||||
|
||||
impl<'a> FnDef<'a> {
|
||||
pub fn parse(src: &'a str) -> Option<(FnDef<'a>, usize)> {
|
||||
impl FnDef {
|
||||
pub fn parse(src: &str) -> Option<(&str, &str, usize)> {
|
||||
starts_with!(src, "[fn:");
|
||||
|
||||
let label = until_while!(src, 4, b']', valid_label);
|
||||
|
@ -22,13 +19,7 @@ impl<'a> FnDef<'a> {
|
|||
|
||||
let end = eol!(src);
|
||||
|
||||
Some((
|
||||
FnDef {
|
||||
label: &src[4..label],
|
||||
contents: &src[label + 1..end],
|
||||
},
|
||||
end,
|
||||
))
|
||||
Some((&src[4..label], &src[label + 1..end], end))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,42 +28,30 @@ fn parse() {
|
|||
assert_eq!(
|
||||
FnDef::parse("[fn:1] https://orgmode.org").unwrap(),
|
||||
(
|
||||
FnDef {
|
||||
label: "1",
|
||||
contents: " https://orgmode.org",
|
||||
},
|
||||
"1",
|
||||
" https://orgmode.org",
|
||||
"[fn:1] https://orgmode.org".len()
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
FnDef::parse("[fn:word_1] https://orgmode.org").unwrap(),
|
||||
(
|
||||
FnDef {
|
||||
label: "word_1",
|
||||
contents: " https://orgmode.org",
|
||||
},
|
||||
"word_1",
|
||||
" https://orgmode.org",
|
||||
"[fn:word_1] https://orgmode.org".len()
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
FnDef::parse("[fn:WORD-1] https://orgmode.org").unwrap(),
|
||||
(
|
||||
FnDef {
|
||||
label: "WORD-1",
|
||||
contents: " https://orgmode.org",
|
||||
},
|
||||
"WORD-1",
|
||||
" https://orgmode.org",
|
||||
"[fn:WORD-1] https://orgmode.org".len()
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
FnDef::parse("[fn:WORD]").unwrap(),
|
||||
(
|
||||
FnDef {
|
||||
label: "WORD",
|
||||
contents: "",
|
||||
},
|
||||
"[fn:WORD]".len()
|
||||
)
|
||||
("WORD", "", "[fn:WORD]".len())
|
||||
);
|
||||
assert!(FnDef::parse("[fn:] https://orgmode.org").is_none());
|
||||
assert!(FnDef::parse("[fn:wor d] https://orgmode.org").is_none());
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
#[cfg_attr(test, derive(PartialEq))]
|
||||
#[derive(Debug)]
|
||||
pub struct Keyword<'a> {
|
||||
pub key: &'a str,
|
||||
pub value: &'a str,
|
||||
}
|
||||
pub struct Keyword;
|
||||
|
||||
impl<'a> Keyword<'a> {
|
||||
pub fn parse(src: &'a str) -> Option<(Keyword<'a>, usize)> {
|
||||
impl Keyword {
|
||||
// return (key, value, offset)
|
||||
pub fn parse(src: &str) -> Option<(&str, &str, usize)> {
|
||||
if cfg!(test) {
|
||||
starts_with!(src, "#+");
|
||||
}
|
||||
|
@ -14,15 +12,9 @@ impl<'a> Keyword<'a> {
|
|||
let key = until_while!(src, 2, b':', |c: u8| c.is_ascii_uppercase() || c == b'_');
|
||||
|
||||
// includes the eol character
|
||||
let end = src.find('\n').map(|i| i + 1).unwrap_or(src.len());
|
||||
let end = src.find('\n').map(|i| i + 1).unwrap_or_else(|| src.len());
|
||||
|
||||
Some((
|
||||
Keyword {
|
||||
key: &src[2..key],
|
||||
value: &src[key + 1..end].trim(),
|
||||
},
|
||||
end,
|
||||
))
|
||||
Some((&src[2..key], &src[key + 1..end].trim(), end))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -118,43 +110,19 @@ fn parse_key<'a>(key: &'a str) -> Option<AffKeywordKey<'a>> {
|
|||
fn parse() {
|
||||
assert_eq!(
|
||||
Keyword::parse("#+KEY:").unwrap(),
|
||||
(
|
||||
Keyword {
|
||||
key: "KEY",
|
||||
value: "",
|
||||
},
|
||||
"#+KEY:".len()
|
||||
)
|
||||
("KEY", "", "#+KEY:".len())
|
||||
);
|
||||
assert_eq!(
|
||||
Keyword::parse("#+KEY: VALUE").unwrap(),
|
||||
(
|
||||
Keyword {
|
||||
key: "KEY",
|
||||
value: "VALUE",
|
||||
},
|
||||
"#+KEY: VALUE".len()
|
||||
)
|
||||
("KEY", "VALUE", "#+KEY: VALUE".len())
|
||||
);
|
||||
assert_eq!(
|
||||
Keyword::parse("#+K_E_Y: VALUE").unwrap(),
|
||||
(
|
||||
Keyword {
|
||||
key: "K_E_Y",
|
||||
value: "VALUE",
|
||||
},
|
||||
"#+K_E_Y: VALUE".len()
|
||||
)
|
||||
("K_E_Y", "VALUE", "#+K_E_Y: VALUE".len())
|
||||
);
|
||||
assert_eq!(
|
||||
Keyword::parse("#+KEY:VALUE\n").unwrap(),
|
||||
(
|
||||
Keyword {
|
||||
key: "KEY",
|
||||
value: "VALUE",
|
||||
},
|
||||
"#+KEY:VALUE\n".len()
|
||||
)
|
||||
("KEY", "VALUE", "#+KEY:VALUE\n".len())
|
||||
);
|
||||
assert!(Keyword::parse("#+KE Y: VALUE").is_none());
|
||||
assert!(Keyword::parse("#+ KEY: VALUE").is_none());
|
||||
|
|
|
@ -2,12 +2,14 @@ pub mod block;
|
|||
pub mod dyn_block;
|
||||
pub mod fn_def;
|
||||
pub mod keyword;
|
||||
pub mod list;
|
||||
pub mod rule;
|
||||
|
||||
pub use self::block::Block;
|
||||
pub use self::dyn_block::DynBlock;
|
||||
pub use self::fn_def::FnDef;
|
||||
pub use self::keyword::Keyword;
|
||||
pub use self::list::List;
|
||||
pub use self::rule::Rule;
|
||||
|
||||
#[cfg_attr(test, derive(PartialEq, Debug))]
|
||||
|
@ -18,44 +20,55 @@ pub enum Element<'a> {
|
|||
// trailing space
|
||||
trailing: usize,
|
||||
},
|
||||
Keyword(Keyword<'a>),
|
||||
FnDef(FnDef<'a>),
|
||||
|
||||
Keyword {
|
||||
key: &'a str,
|
||||
value: &'a str,
|
||||
},
|
||||
FnDef {
|
||||
label: &'a str,
|
||||
contents: &'a str,
|
||||
},
|
||||
CenterBlock {
|
||||
args: Option<&'a str>,
|
||||
content_end: usize,
|
||||
contents_end: usize,
|
||||
end: usize,
|
||||
},
|
||||
QuoteBlock {
|
||||
args: Option<&'a str>,
|
||||
content_end: usize,
|
||||
contents_end: usize,
|
||||
end: usize,
|
||||
},
|
||||
SpecialBlock {
|
||||
args: Option<&'a str>,
|
||||
name: &'a str,
|
||||
content_end: usize,
|
||||
contents_end: usize,
|
||||
end: usize,
|
||||
},
|
||||
CommentBlock {
|
||||
content: &'a str,
|
||||
args: Option<&'a str>,
|
||||
contents: &'a str,
|
||||
},
|
||||
ExampleBlock {
|
||||
content: &'a str,
|
||||
args: Option<&'a str>,
|
||||
contents: &'a str,
|
||||
},
|
||||
ExportBlock {
|
||||
content: &'a str,
|
||||
args: Option<&'a str>,
|
||||
contents: &'a str,
|
||||
},
|
||||
SrcBlock {
|
||||
content: &'a str,
|
||||
args: Option<&'a str>,
|
||||
contents: &'a str,
|
||||
},
|
||||
VerseBlock {
|
||||
content: &'a str,
|
||||
args: Option<&'a str>,
|
||||
contents: &'a str,
|
||||
},
|
||||
DynBlock {
|
||||
args: Option<&'a str>,
|
||||
name: &'a str,
|
||||
contents_end: usize,
|
||||
end: usize,
|
||||
},
|
||||
Rule,
|
||||
Comment(&'a str),
|
||||
|
@ -75,9 +88,9 @@ impl<'a> Element<'a> {
|
|||
loop {
|
||||
// Unlike other element, footnote definition must starts at column 0
|
||||
if bytes[pos] == b'[' {
|
||||
if let Some((fd, off)) = FnDef::parse(&src[pos..]) {
|
||||
if let Some((label, contents, off)) = FnDef::parse(&src[pos..]) {
|
||||
return if pos == start {
|
||||
(off + 1, Some(Element::FnDef(fd)), None)
|
||||
(off + 1, Some(Element::FnDef { label, contents }), None)
|
||||
} else {
|
||||
(
|
||||
start,
|
||||
|
@ -85,7 +98,7 @@ impl<'a> Element<'a> {
|
|||
end: pos - 1,
|
||||
trailing: pos,
|
||||
}),
|
||||
Some((Element::FnDef(fd), off + 1)),
|
||||
Some((Element::FnDef { label, contents }, off + 1)),
|
||||
)
|
||||
};
|
||||
}
|
||||
|
@ -103,7 +116,7 @@ impl<'a> Element<'a> {
|
|||
(
|
||||
start,
|
||||
Some(Element::Paragraph {
|
||||
end: end - 1,
|
||||
end,
|
||||
trailing: pos - 1,
|
||||
}),
|
||||
Some(($ele, $off)),
|
||||
|
@ -113,14 +126,7 @@ impl<'a> Element<'a> {
|
|||
}
|
||||
|
||||
if bytes[pos] == b'\n' {
|
||||
return (
|
||||
start,
|
||||
Some(Element::Paragraph {
|
||||
end: end - 1,
|
||||
trailing: pos,
|
||||
}),
|
||||
None,
|
||||
);
|
||||
return (start, Some(Element::Paragraph { end, trailing: pos }), None);
|
||||
}
|
||||
|
||||
// TODO: LaTeX environment
|
||||
|
@ -133,112 +139,99 @@ impl<'a> Element<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
if bytes[pos] == b'#' && bytes[pos + 1] == b'+' {
|
||||
if let Some((name, args, content, end)) = Block::parse(&src[pos..]) {
|
||||
match &src[pos + 8..pos + name] {
|
||||
block_name if block_name.eq_ignore_ascii_case("CENTER") => ret!(
|
||||
Element::CenterBlock {
|
||||
args: if name == args {
|
||||
None
|
||||
} else {
|
||||
Some(&src[pos + name..pos + args])
|
||||
},
|
||||
content_end: content + 1,
|
||||
end,
|
||||
},
|
||||
pos + args
|
||||
),
|
||||
block_name if block_name.eq_ignore_ascii_case("QUOTE") => ret!(
|
||||
Element::QuoteBlock {
|
||||
args: if name == args {
|
||||
None
|
||||
} else {
|
||||
Some(&src[pos + name..pos + args].trim())
|
||||
},
|
||||
content_end: content + 1,
|
||||
end,
|
||||
},
|
||||
pos + args
|
||||
),
|
||||
block_name if block_name.eq_ignore_ascii_case("COMMENT") => ret!(
|
||||
if bytes[pos] == b'#' && bytes.get(pos + 1).filter(|&&b| b == b'+').is_some() {
|
||||
if let Some((name, args, contents_beg, contents_end, end)) =
|
||||
Block::parse(&src[pos..])
|
||||
{
|
||||
match name.to_uppercase().as_str() {
|
||||
"COMMENT" => ret!(
|
||||
Element::CommentBlock {
|
||||
args: if name == args {
|
||||
None
|
||||
} else {
|
||||
Some(&src[pos + name..pos + args])
|
||||
},
|
||||
content: &src[pos + args + 1..pos + content],
|
||||
args,
|
||||
contents: &src[pos + contents_beg + 1..pos + contents_end - 1],
|
||||
},
|
||||
pos + end
|
||||
),
|
||||
block_name if block_name.eq_ignore_ascii_case("EXAMPLE") => ret!(
|
||||
"EXAMPLE" => ret!(
|
||||
Element::ExampleBlock {
|
||||
args: if name == args {
|
||||
None
|
||||
} else {
|
||||
Some(&src[pos + name..pos + args])
|
||||
},
|
||||
content: &src[pos + args + 1..pos + content],
|
||||
args,
|
||||
contents: &src[pos + contents_beg + 1..pos + contents_end - 1],
|
||||
},
|
||||
pos + end
|
||||
),
|
||||
block_name if block_name.eq_ignore_ascii_case("EXPORT") => ret!(
|
||||
"EXPORT" => ret!(
|
||||
Element::ExportBlock {
|
||||
args: if name == args {
|
||||
None
|
||||
} else {
|
||||
Some(&src[pos + name..pos + args])
|
||||
},
|
||||
content: &src[pos + args + 1..pos + content],
|
||||
args,
|
||||
contents: &src[pos + contents_beg + 1..pos + contents_end - 1],
|
||||
},
|
||||
pos + end
|
||||
),
|
||||
block_name if block_name.eq_ignore_ascii_case("SRC") => ret!(
|
||||
"SRC" => ret!(
|
||||
Element::SrcBlock {
|
||||
args: if name == args {
|
||||
None
|
||||
} else {
|
||||
Some(&src[pos + name..pos + args])
|
||||
},
|
||||
content: &src[pos + args + 1..pos + content],
|
||||
args,
|
||||
contents: &src[pos + contents_beg + 1..pos + contents_end - 1],
|
||||
},
|
||||
pos + end
|
||||
),
|
||||
block_name if block_name.eq_ignore_ascii_case("VERSE") => ret!(
|
||||
"VERSE" => ret!(
|
||||
Element::VerseBlock {
|
||||
args: if name == args {
|
||||
None
|
||||
} else {
|
||||
Some(&src[pos + name..pos + args])
|
||||
},
|
||||
content: &src[pos + args + 1..pos + content],
|
||||
args,
|
||||
contents: &src[pos + contents_beg + 1..pos + contents_end - 1],
|
||||
},
|
||||
pos + end
|
||||
),
|
||||
block_name => ret!(
|
||||
Element::SpecialBlock {
|
||||
name: block_name,
|
||||
args: if name == args {
|
||||
None
|
||||
} else {
|
||||
Some(&src[pos + name..pos + args].trim())
|
||||
},
|
||||
content_end: content + 1,
|
||||
"CENTER" => ret!(
|
||||
Element::CenterBlock {
|
||||
args,
|
||||
contents_end,
|
||||
end,
|
||||
},
|
||||
pos + args
|
||||
pos + contents_beg
|
||||
),
|
||||
"QUOTE" => ret!(
|
||||
Element::QuoteBlock {
|
||||
args,
|
||||
contents_end,
|
||||
end,
|
||||
},
|
||||
pos + contents_beg
|
||||
),
|
||||
_ => ret!(
|
||||
Element::SpecialBlock {
|
||||
name,
|
||||
args,
|
||||
contents_end,
|
||||
end,
|
||||
},
|
||||
pos + contents_beg
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
if let Some((kw, off)) = Keyword::parse(&src[pos..]) {
|
||||
ret!(Element::Keyword(kw), off)
|
||||
if let Some((name, args, contents_beg, contents_end, end)) =
|
||||
DynBlock::parse(&src[pos..])
|
||||
{
|
||||
ret!(
|
||||
Element::DynBlock {
|
||||
name,
|
||||
args,
|
||||
contents_end,
|
||||
end,
|
||||
},
|
||||
pos + contents_beg
|
||||
)
|
||||
}
|
||||
|
||||
if let Some((key, value, off)) = Keyword::parse(&src[pos..]) {
|
||||
ret!(Element::Keyword { key, value }, off)
|
||||
}
|
||||
}
|
||||
|
||||
// Comment
|
||||
if bytes[pos] == b'#' && bytes[pos + 1] == b' ' {
|
||||
let eol = eol!(src, pos);
|
||||
if bytes[pos] == b'#' && bytes.get(pos + 1).filter(|&&b| b == b' ').is_some() {
|
||||
let eol = src[pos..]
|
||||
.find('\n')
|
||||
.map(|i| i + pos + 1)
|
||||
.unwrap_or_else(|| src.len());
|
||||
ret!(Element::Comment(&src[pos + 1..eol]), eol);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use elements::{FnDef, Keyword};
|
||||
#![allow(unused_variables)]
|
||||
|
||||
use export::Handler;
|
||||
use headline::Headline;
|
||||
use objects::{Cookie, FnRef, InlineCall, InlineSrc, Link, Macros, RadioTarget, Snippet, Target};
|
||||
|
@ -53,25 +54,35 @@ impl<W: Write> Handler<W> for HtmlHandler {
|
|||
fn handle_end_special_block(&mut self, w: &mut W) -> Result<()> {
|
||||
write!(w, "</div>")
|
||||
}
|
||||
fn handle_comment_block(&mut self, w: &mut W, content: &str, args: Option<&str>) -> Result<()> {
|
||||
fn handle_comment_block(
|
||||
&mut self,
|
||||
w: &mut W,
|
||||
contents: &str,
|
||||
args: Option<&str>,
|
||||
) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
fn handle_example_block(&mut self, w: &mut W, content: &str, args: Option<&str>) -> Result<()> {
|
||||
write!(w, "<pre><code>{}</code></pre>", content)
|
||||
fn handle_example_block(
|
||||
&mut self,
|
||||
w: &mut W,
|
||||
contents: &str,
|
||||
args: Option<&str>,
|
||||
) -> Result<()> {
|
||||
write!(w, "<pre><code>{}</code></pre>", contents)
|
||||
}
|
||||
fn handle_export_block(&mut self, w: &mut W, content: &str, args: Option<&str>) -> Result<()> {
|
||||
fn handle_export_block(&mut self, w: &mut W, contents: &str, args: Option<&str>) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
fn handle_src_block(&mut self, w: &mut W, content: &str, args: Option<&str>) -> Result<()> {
|
||||
write!(w, "<pre><code>{}</code></pre>", content)
|
||||
fn handle_src_block(&mut self, w: &mut W, contents: &str, args: Option<&str>) -> Result<()> {
|
||||
write!(w, "<pre><code>{}</code></pre>", contents)
|
||||
}
|
||||
fn handle_verse_block(&mut self, w: &mut W, content: &str, args: Option<&str>) -> Result<()> {
|
||||
fn handle_verse_block(&mut self, w: &mut W, contents: &str, args: Option<&str>) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
fn handle_dyn_block_start(&mut self, w: &mut W) -> Result<()> {
|
||||
fn handle_start_dyn_block(&mut self, w: &mut W, name: &str, args: Option<&str>) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
fn handle_dyn_block_end(&mut self, w: &mut W) -> Result<()> {
|
||||
fn handle_end_dyn_block(&mut self, w: &mut W) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
fn handle_list_start(&mut self, w: &mut W) -> Result<()> {
|
||||
|
@ -89,7 +100,7 @@ impl<W: Write> Handler<W> for HtmlHandler {
|
|||
fn handle_clock(&mut self, w: &mut W) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
fn handle_comment(&mut self, w: &mut W, content: &str) -> Result<()> {
|
||||
fn handle_comment(&mut self, w: &mut W, contents: &str) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
fn handle_table_start(&mut self, w: &mut W) -> Result<()> {
|
||||
|
@ -104,10 +115,10 @@ impl<W: Write> Handler<W> for HtmlHandler {
|
|||
fn handle_latex_env(&mut self, w: &mut W) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
fn handle_fn_def(&mut self, w: &mut W, fn_def: FnDef) -> Result<()> {
|
||||
fn handle_fn_def(&mut self, w: &mut W, label: &str, contents: &str) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
fn handle_keyword(&mut self, w: &mut W, kw: Keyword) -> Result<()> {
|
||||
fn handle_keyword(&mut self, w: &mut W, key: &str, value: &str) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
fn handle_rule(&mut self, w: &mut W) -> Result<()> {
|
||||
|
@ -140,7 +151,11 @@ impl<W: Write> Handler<W> for HtmlHandler {
|
|||
Ok(())
|
||||
}
|
||||
fn handle_snippet(&mut self, w: &mut W, snippet: Snippet) -> Result<()> {
|
||||
Ok(())
|
||||
if snippet.name.eq_ignore_ascii_case("HTML") {
|
||||
write!(w, "{}", snippet.value)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
fn handle_target(&mut self, w: &mut W, target: Target) -> Result<()> {
|
||||
Ok(())
|
||||
|
@ -169,13 +184,13 @@ impl<W: Write> Handler<W> for HtmlHandler {
|
|||
fn handle_end_underline(&mut self, w: &mut W) -> Result<()> {
|
||||
write!(w, "</u>")
|
||||
}
|
||||
fn handle_verbatim(&mut self, w: &mut W, content: &str) -> Result<()> {
|
||||
write!(w, "<code>{}</code>", content)
|
||||
fn handle_verbatim(&mut self, w: &mut W, contents: &str) -> Result<()> {
|
||||
write!(w, "<code>{}</code>", contents)
|
||||
}
|
||||
fn handle_code(&mut self, w: &mut W, content: &str) -> Result<()> {
|
||||
write!(w, "<code>{}</code>", content)
|
||||
fn handle_code(&mut self, w: &mut W, contents: &str) -> Result<()> {
|
||||
write!(w, "<code>{}</code>", contents)
|
||||
}
|
||||
fn handle_text(&mut self, w: &mut W, content: &str) -> Result<()> {
|
||||
write!(w, "{}", content.replace('\n', " "))
|
||||
fn handle_text(&mut self, w: &mut W, contents: &str) -> Result<()> {
|
||||
write!(w, "{}", contents.replace('\n', " "))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ mod html;
|
|||
|
||||
pub use self::html::HtmlHandler;
|
||||
|
||||
use elements::{FnDef, Keyword};
|
||||
use headline::Headline;
|
||||
use objects::{Cookie, FnRef, InlineCall, InlineSrc, Link, Macros, RadioTarget, Snippet, Target};
|
||||
use parser::Parser;
|
||||
|
@ -26,25 +25,27 @@ pub trait Handler<W: Write> {
|
|||
args: Option<&str>,
|
||||
) -> Result<()>;
|
||||
fn handle_end_special_block(&mut self, w: &mut W) -> Result<()>;
|
||||
fn handle_comment_block(&mut self, w: &mut W, content: &str, args: Option<&str>) -> Result<()>;
|
||||
fn handle_example_block(&mut self, w: &mut W, content: &str, args: Option<&str>) -> Result<()>;
|
||||
fn handle_export_block(&mut self, w: &mut W, content: &str, args: Option<&str>) -> Result<()>;
|
||||
fn handle_src_block(&mut self, w: &mut W, content: &str, args: Option<&str>) -> Result<()>;
|
||||
fn handle_verse_block(&mut self, w: &mut W, content: &str, args: Option<&str>) -> Result<()>;
|
||||
fn handle_dyn_block_start(&mut self, w: &mut W) -> Result<()>;
|
||||
fn handle_dyn_block_end(&mut self, w: &mut W) -> Result<()>;
|
||||
fn handle_comment_block(&mut self, w: &mut W, contents: &str, args: Option<&str>)
|
||||
-> Result<()>;
|
||||
fn handle_example_block(&mut self, w: &mut W, contents: &str, args: Option<&str>)
|
||||
-> Result<()>;
|
||||
fn handle_export_block(&mut self, w: &mut W, contents: &str, args: Option<&str>) -> Result<()>;
|
||||
fn handle_src_block(&mut self, w: &mut W, contents: &str, args: Option<&str>) -> Result<()>;
|
||||
fn handle_verse_block(&mut self, w: &mut W, contents: &str, args: Option<&str>) -> Result<()>;
|
||||
fn handle_start_dyn_block(&mut self, w: &mut W, name: &str, args: Option<&str>) -> Result<()>;
|
||||
fn handle_end_dyn_block(&mut self, w: &mut W) -> Result<()>;
|
||||
fn handle_list_start(&mut self, w: &mut W) -> Result<()>;
|
||||
fn handle_list_end(&mut self, w: &mut W) -> Result<()>;
|
||||
fn handle_aff_keywords(&mut self, w: &mut W) -> Result<()>;
|
||||
fn handle_call(&mut self, w: &mut W) -> Result<()>;
|
||||
fn handle_clock(&mut self, w: &mut W) -> Result<()>;
|
||||
fn handle_comment(&mut self, w: &mut W, content: &str) -> Result<()>;
|
||||
fn handle_comment(&mut self, w: &mut W, contents: &str) -> Result<()>;
|
||||
fn handle_table_start(&mut self, w: &mut W) -> Result<()>;
|
||||
fn handle_table_end(&mut self, w: &mut W) -> Result<()>;
|
||||
fn handle_table_cell(&mut self, w: &mut W) -> Result<()>;
|
||||
fn handle_latex_env(&mut self, w: &mut W) -> Result<()>;
|
||||
fn handle_fn_def(&mut self, w: &mut W, fn_def: FnDef) -> Result<()>;
|
||||
fn handle_keyword(&mut self, w: &mut W, kw: Keyword) -> Result<()>;
|
||||
fn handle_fn_def(&mut self, w: &mut W, label: &str, contents: &str) -> Result<()>;
|
||||
fn handle_keyword(&mut self, w: &mut W, key: &str, value: &str) -> Result<()>;
|
||||
fn handle_rule(&mut self, w: &mut W) -> Result<()>;
|
||||
fn handle_cookie(&mut self, w: &mut W, cookie: Cookie) -> Result<()>;
|
||||
fn handle_fn_ref(&mut self, w: &mut W, fn_ref: FnRef) -> Result<()>;
|
||||
|
@ -63,9 +64,9 @@ pub trait Handler<W: Write> {
|
|||
fn handle_end_strike(&mut self, w: &mut W) -> Result<()>;
|
||||
fn handle_start_underline(&mut self, w: &mut W) -> Result<()>;
|
||||
fn handle_end_underline(&mut self, w: &mut W) -> Result<()>;
|
||||
fn handle_verbatim(&mut self, w: &mut W, content: &str) -> Result<()>;
|
||||
fn handle_code(&mut self, w: &mut W, content: &str) -> Result<()>;
|
||||
fn handle_text(&mut self, w: &mut W, content: &str) -> Result<()>;
|
||||
fn handle_verbatim(&mut self, w: &mut W, contents: &str) -> Result<()>;
|
||||
fn handle_code(&mut self, w: &mut W, contents: &str) -> Result<()>;
|
||||
fn handle_text(&mut self, w: &mut W, contents: &str) -> Result<()>;
|
||||
}
|
||||
|
||||
pub struct Render<'a, W: Write, H: Handler<W>> {
|
||||
|
@ -107,28 +108,31 @@ impl<'a, W: Write, H: Handler<W>> Render<'a, W, H> {
|
|||
.handle_start_special_block(&mut self.writer, name, args)?
|
||||
}
|
||||
EndSpecialBlock => self.handler.handle_end_special_block(&mut self.writer)?,
|
||||
CommentBlock { content, args } => {
|
||||
CommentBlock { contents, args } => {
|
||||
self.handler
|
||||
.handle_comment_block(&mut self.writer, content, args)?
|
||||
.handle_comment_block(&mut self.writer, contents, args)?
|
||||
}
|
||||
ExampleBlock { content, args } => {
|
||||
ExampleBlock { contents, args } => {
|
||||
self.handler
|
||||
.handle_example_block(&mut self.writer, content, args)?
|
||||
.handle_example_block(&mut self.writer, contents, args)?
|
||||
}
|
||||
ExportBlock { content, args } => {
|
||||
ExportBlock { contents, args } => {
|
||||
self.handler
|
||||
.handle_export_block(&mut self.writer, content, args)?
|
||||
.handle_export_block(&mut self.writer, contents, args)?
|
||||
}
|
||||
SrcBlock { content, args } => {
|
||||
SrcBlock { contents, args } => {
|
||||
self.handler
|
||||
.handle_src_block(&mut self.writer, content, args)?
|
||||
.handle_src_block(&mut self.writer, contents, args)?
|
||||
}
|
||||
VerseBlock { content, args } => {
|
||||
VerseBlock { contents, args } => {
|
||||
self.handler
|
||||
.handle_verse_block(&mut self.writer, content, args)?
|
||||
.handle_verse_block(&mut self.writer, contents, args)?
|
||||
}
|
||||
DynBlockStart => self.handler.handle_dyn_block_start(&mut self.writer)?,
|
||||
DynBlockEnd => self.handler.handle_dyn_block_end(&mut self.writer)?,
|
||||
StartDynBlock { name, args } => {
|
||||
self.handler
|
||||
.handle_start_dyn_block(&mut self.writer, name, args)?
|
||||
}
|
||||
EndDynBlock => self.handler.handle_end_dyn_block(&mut self.writer)?,
|
||||
ListStart => self.handler.handle_list_start(&mut self.writer)?,
|
||||
ListEnd => self.handler.handle_list_end(&mut self.writer)?,
|
||||
AffKeywords => self.handler.handle_aff_keywords(&mut self.writer)?,
|
||||
|
@ -139,8 +143,13 @@ impl<'a, W: Write, H: Handler<W>> Render<'a, W, H> {
|
|||
TableEnd => self.handler.handle_table_end(&mut self.writer)?,
|
||||
TableCell => self.handler.handle_table_cell(&mut self.writer)?,
|
||||
LatexEnv => self.handler.handle_latex_env(&mut self.writer)?,
|
||||
FnDef(f) => self.handler.handle_fn_def(&mut self.writer, f)?,
|
||||
Keyword(keyword) => self.handler.handle_keyword(&mut self.writer, keyword)?,
|
||||
FnDef { label, contents } => {
|
||||
self.handler
|
||||
.handle_fn_def(&mut self.writer, label, contents)?
|
||||
}
|
||||
Keyword { key, value } => {
|
||||
self.handler.handle_keyword(&mut self.writer, key, value)?
|
||||
}
|
||||
Rule => self.handler.handle_rule(&mut self.writer)?,
|
||||
Cookie(cookie) => self.handler.handle_cookie(&mut self.writer, cookie)?,
|
||||
FnRef(fnref) => self.handler.handle_fn_ref(&mut self.writer, fnref)?,
|
||||
|
@ -165,9 +174,9 @@ impl<'a, W: Write, H: Handler<W>> Render<'a, W, H> {
|
|||
EndStrike => self.handler.handle_end_strike(&mut self.writer)?,
|
||||
StartUnderline => self.handler.handle_start_underline(&mut self.writer)?,
|
||||
EndUnderline => self.handler.handle_end_underline(&mut self.writer)?,
|
||||
Verbatim(content) => self.handler.handle_verbatim(&mut self.writer, content)?,
|
||||
Code(content) => self.handler.handle_code(&mut self.writer, content)?,
|
||||
Text(content) => self.handler.handle_text(&mut self.writer, content)?,
|
||||
Verbatim(contents) => self.handler.handle_verbatim(&mut self.writer, contents)?,
|
||||
Code(contents) => self.handler.handle_code(&mut self.writer, contents)?,
|
||||
Text(contents) => self.handler.handle_text(&mut self.writer, contents)?,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ impl<'a> Headline<'a> {
|
|||
#[inline]
|
||||
fn parse_tags(src: &'a str) -> (Option<&'a str>, usize) {
|
||||
if let Some(last) = src.split_whitespace().last() {
|
||||
if last.starts_with(':') && last.ends_with(':') {
|
||||
if last.len() > 2 && last.starts_with(':') && last.ends_with(':') {
|
||||
(Some(last), src.rfind(':').unwrap() - last.len())
|
||||
} else {
|
||||
(None, src.len())
|
||||
|
|
|
@ -13,7 +13,7 @@ impl<'a> Cookie<'a> {
|
|||
let num1 = until_while!(src, 1, |c| c == b'%' || c == b'/', |c: u8| c
|
||||
.is_ascii_digit());
|
||||
|
||||
if src.len() > num1 && src.as_bytes()[num1 + 1] == b']' {
|
||||
if src.as_bytes()[num1] == b'%' && *src.as_bytes().get(num1 + 1)? == b']' {
|
||||
Some((
|
||||
Cookie {
|
||||
value: &src[0..num1 + 2],
|
||||
|
|
|
@ -11,10 +11,7 @@ impl<'a> Link<'a> {
|
|||
starts_with!(src, "[[");
|
||||
}
|
||||
|
||||
let path = until_while!(src, 2, b']', |c| c != b']'
|
||||
&& c != b'<'
|
||||
&& c != b'>'
|
||||
&& c != b'\n');
|
||||
let path = until_while!(src, 2, b']', |c| c != b'<' && c != b'>' && c != b'\n');
|
||||
|
||||
if cond_eq!(src, path + 1, b']') {
|
||||
Some((
|
||||
|
@ -25,10 +22,7 @@ impl<'a> Link<'a> {
|
|||
path + 2,
|
||||
))
|
||||
} else if src.as_bytes()[path + 1] == b'[' {
|
||||
let desc = until_while!(src, path + 2, b']', |c| c != b']'
|
||||
&& c != b'['
|
||||
&& c != b'\n');
|
||||
|
||||
let desc = until_while!(src, path + 2, b']', |c| c != b'[');
|
||||
expect!(src, desc + 1, b']')?;
|
||||
|
||||
Some((
|
||||
|
|
|
@ -9,14 +9,10 @@ pub enum Container {
|
|||
Section { end: usize },
|
||||
|
||||
Paragraph { end: usize, trailing: usize },
|
||||
CenterBlock { content_end: usize, end: usize },
|
||||
QuoteBlock { content_end: usize, end: usize },
|
||||
SpecialBlock { content_end: usize, end: usize },
|
||||
|
||||
Drawer,
|
||||
LatexEnv,
|
||||
List,
|
||||
Table,
|
||||
CenterBlock { contents_end: usize, end: usize },
|
||||
QuoteBlock { contents_end: usize, end: usize },
|
||||
SpecialBlock { contents_end: usize, end: usize },
|
||||
DynBlock { contents_end: usize, end: usize },
|
||||
|
||||
Italic { end: usize },
|
||||
Strike { end: usize },
|
||||
|
@ -45,30 +41,33 @@ pub enum Event<'a> {
|
|||
args: Option<&'a str>,
|
||||
},
|
||||
EndSpecialBlock,
|
||||
StartDynBlock {
|
||||
name: &'a str,
|
||||
args: Option<&'a str>,
|
||||
},
|
||||
EndDynBlock,
|
||||
|
||||
CommentBlock {
|
||||
content: &'a str,
|
||||
args: Option<&'a str>,
|
||||
contents: &'a str,
|
||||
},
|
||||
ExampleBlock {
|
||||
content: &'a str,
|
||||
args: Option<&'a str>,
|
||||
contents: &'a str,
|
||||
},
|
||||
ExportBlock {
|
||||
content: &'a str,
|
||||
args: Option<&'a str>,
|
||||
contents: &'a str,
|
||||
},
|
||||
SrcBlock {
|
||||
content: &'a str,
|
||||
args: Option<&'a str>,
|
||||
contents: &'a str,
|
||||
},
|
||||
VerseBlock {
|
||||
content: &'a str,
|
||||
args: Option<&'a str>,
|
||||
contents: &'a str,
|
||||
},
|
||||
|
||||
DynBlockStart,
|
||||
DynBlockEnd,
|
||||
ListStart,
|
||||
ListEnd,
|
||||
|
||||
|
@ -85,8 +84,14 @@ pub enum Event<'a> {
|
|||
TableCell,
|
||||
|
||||
LatexEnv,
|
||||
FnDef(FnDef<'a>),
|
||||
Keyword(Keyword<'a>),
|
||||
FnDef {
|
||||
label: &'a str,
|
||||
contents: &'a str,
|
||||
},
|
||||
Keyword {
|
||||
key: &'a str,
|
||||
value: &'a str,
|
||||
},
|
||||
Rule,
|
||||
|
||||
Cookie(Cookie<'a>),
|
||||
|
@ -172,21 +177,27 @@ impl<'a> Parser<'a> {
|
|||
trailing: trailing + self.off,
|
||||
}),
|
||||
Element::QuoteBlock {
|
||||
end, content_end, ..
|
||||
end, contents_end, ..
|
||||
} => self.stack.push(Container::QuoteBlock {
|
||||
content_end: content_end + self.off,
|
||||
contents_end: contents_end + self.off,
|
||||
end: end + self.off,
|
||||
}),
|
||||
Element::CenterBlock {
|
||||
end, content_end, ..
|
||||
end, contents_end, ..
|
||||
} => self.stack.push(Container::CenterBlock {
|
||||
content_end: content_end + self.off,
|
||||
contents_end: contents_end + self.off,
|
||||
end: end + self.off,
|
||||
}),
|
||||
Element::SpecialBlock {
|
||||
end, content_end, ..
|
||||
end, contents_end, ..
|
||||
} => self.stack.push(Container::SpecialBlock {
|
||||
content_end: content_end + self.off,
|
||||
contents_end: contents_end + self.off,
|
||||
end: end + self.off,
|
||||
}),
|
||||
Element::DynBlock {
|
||||
end, contents_end, ..
|
||||
} => self.stack.push(Container::DynBlock {
|
||||
contents_end: contents_end + self.off,
|
||||
end: end + self.off,
|
||||
}),
|
||||
_ => (),
|
||||
|
@ -239,7 +250,7 @@ impl<'a> Parser<'a> {
|
|||
Container::CenterBlock { .. } => Event::EndCenterBlock,
|
||||
Container::QuoteBlock { .. } => Event::EndQuoteBlock,
|
||||
Container::SpecialBlock { .. } => Event::EndSpecialBlock,
|
||||
_ => unimplemented!(),
|
||||
Container::DynBlock { .. } => Event::EndDynBlock,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -248,12 +259,11 @@ impl<'a> Iterator for Parser<'a> {
|
|||
type Item = Event<'a>;
|
||||
|
||||
fn next(&mut self) -> Option<Event<'a>> {
|
||||
let tail = &self.text[self.off..];
|
||||
|
||||
if self.stack.is_empty() {
|
||||
if self.off >= self.text.len() {
|
||||
None
|
||||
} else {
|
||||
let tail = &self.text[self.off..];
|
||||
Some(self.start_section_or_headline(tail))
|
||||
}
|
||||
} else {
|
||||
|
@ -261,6 +271,7 @@ impl<'a> Iterator for Parser<'a> {
|
|||
|
||||
Some(match last {
|
||||
Container::Headline { beg, end } => {
|
||||
let tail = &self.text[self.off..];
|
||||
if self.off >= end {
|
||||
self.end()
|
||||
} else if self.off == beg {
|
||||
|
@ -269,20 +280,23 @@ impl<'a> Iterator for Parser<'a> {
|
|||
self.start_headline(tail)
|
||||
}
|
||||
}
|
||||
Container::CenterBlock {
|
||||
content_end, end, ..
|
||||
Container::DynBlock {
|
||||
contents_end, end, ..
|
||||
}
|
||||
| Container::CenterBlock {
|
||||
contents_end, end, ..
|
||||
}
|
||||
| Container::QuoteBlock {
|
||||
content_end, end, ..
|
||||
contents_end, end, ..
|
||||
}
|
||||
| Container::SpecialBlock {
|
||||
content_end, end, ..
|
||||
contents_end, end, ..
|
||||
} => {
|
||||
if self.off >= content_end {
|
||||
if self.off >= contents_end {
|
||||
self.off = end;
|
||||
self.end()
|
||||
} else {
|
||||
self.next_ele(content_end)
|
||||
self.next_ele(contents_end)
|
||||
}
|
||||
}
|
||||
Container::Section { end } => {
|
||||
|
@ -311,7 +325,6 @@ impl<'a> Iterator for Parser<'a> {
|
|||
self.next_obj(end)
|
||||
}
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -344,18 +357,19 @@ impl<'a> From<Element<'a>> for Event<'a> {
|
|||
fn from(ele: Element<'a>) -> Self {
|
||||
match ele {
|
||||
Element::Comment(c) => Event::Comment(c),
|
||||
Element::FnDef(fd) => Event::FnDef(fd),
|
||||
Element::Keyword(kw) => Event::Keyword(kw),
|
||||
Element::FnDef { label, contents } => Event::FnDef { label, contents },
|
||||
Element::Keyword { key, value } => Event::Keyword { key, value },
|
||||
Element::Paragraph { .. } => Event::StartParagraph,
|
||||
Element::Rule => Event::Rule,
|
||||
Element::CenterBlock { .. } => Event::StartCenterBlock,
|
||||
Element::QuoteBlock { .. } => Event::StartQuoteBlock,
|
||||
Element::DynBlock { name, args, .. } => Event::StartDynBlock { name, args },
|
||||
Element::SpecialBlock { name, args, .. } => Event::StartSpecialBlock { name, args },
|
||||
Element::CommentBlock { args, content } => Event::CommentBlock { args, content },
|
||||
Element::ExampleBlock { args, content } => Event::ExampleBlock { args, content },
|
||||
Element::ExportBlock { args, content } => Event::ExportBlock { args, content },
|
||||
Element::SrcBlock { args, content } => Event::SrcBlock { args, content },
|
||||
Element::VerseBlock { args, content } => Event::VerseBlock { args, content },
|
||||
Element::CommentBlock { args, contents } => Event::CommentBlock { args, contents },
|
||||
Element::ExampleBlock { args, contents } => Event::ExampleBlock { args, contents },
|
||||
Element::ExportBlock { args, contents } => Event::ExportBlock { args, contents },
|
||||
Element::SrcBlock { args, contents } => Event::SrcBlock { args, contents },
|
||||
Element::VerseBlock { args, contents } => Event::VerseBlock { args, contents },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,13 +16,13 @@ macro_rules! expect {
|
|||
#[macro_export]
|
||||
macro_rules! eol {
|
||||
($src:expr) => {
|
||||
$src.find('\n').unwrap_or($src.len())
|
||||
$src.find('\n').unwrap_or_else(|| $src.len())
|
||||
};
|
||||
($src:expr, $from:expr) => {
|
||||
$src[$from..]
|
||||
.find('\n')
|
||||
.map(|i| i + $from)
|
||||
.unwrap_or($src.len())
|
||||
.unwrap_or_else(|| $src.len())
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -132,6 +132,9 @@ macro_rules! starts_with {
|
|||
|
||||
#[macro_export]
|
||||
macro_rules! skip_space {
|
||||
($src:ident) => {
|
||||
until!($src, |c| c != b' ').unwrap_or(0)
|
||||
};
|
||||
($src:ident, $from:expr) => {
|
||||
until!($src[$from..], |c| c != b' ').unwrap_or(0) + $from
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue