pub mod elements;
pub mod output;
pub mod parsers;
use derive_more::Display;
use elements::*;
use parsers::{vimwiki, IResult, Span};
pub trait FromLanguage<'a>: Sized {
type Error;
fn from_language(language: Language<'a>) -> Result<Self, Self::Error>;
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Display)]
pub enum Language<'a> {
Vimwiki(&'a str),
Markdown(&'a str),
Mediawiki(&'a str),
}
impl<'a> Language<'a> {
pub fn from_vimwiki_str(inner: &'a str) -> Self {
Self::Vimwiki(inner)
}
pub fn from_markdown_str(inner: &'a str) -> Self {
Self::Markdown(inner)
}
pub fn from_mediawiki_str(inner: &'a str) -> Self {
Self::Mediawiki(inner)
}
pub fn is_vimwiki(&self) -> bool {
matches!(self, Self::Vimwiki(_))
}
pub fn is_markdown(&self) -> bool {
matches!(self, Self::Markdown(_))
}
pub fn is_mediawiki(&self) -> bool {
matches!(self, Self::Mediawiki(_))
}
pub fn as_inner(&self) -> &str {
match self {
Self::Vimwiki(x) => x,
Self::Markdown(x) => x,
Self::Mediawiki(x) => x,
}
}
pub fn parse<F: FromLanguage<'a>>(&self) -> Result<F, F::Error> {
FromLanguage::from_language(*self)
}
}
macro_rules! impl_from_language {
($t:ty, $f:expr) => {
impl<'a> FromLanguage<'a> for $t {
type Error = parsers::Error<'a>;
fn from_language(l: Language<'a>) -> Result<Self, Self::Error> {
match l {
Language::Vimwiki(x) => Ok($f(Span::from(x))?.1),
_ => Err(parsers::Error::unsupported()),
}
}
}
};
}
impl_from_language!(Page<'a>, vimwiki::page);
impl_from_language!(Located<BlockElement<'a>>, vimwiki::blocks::block_element);
impl_from_language!(
Located<InlineElementContainer<'a>>,
vimwiki::blocks::inline::inline_element_container
);
impl_from_language!(
Located<InlineElement<'a>>,
vimwiki::blocks::inline::inline_element
);
impl_from_language!(
Located<Blockquote<'a>>,
vimwiki::blocks::blockquotes::blockquote
);
impl_from_language!(
Located<CodeInline<'a>>,
vimwiki::blocks::inline::code::code_inline
);
impl_from_language!(
Located<Comment<'a>>,
vimwiki::blocks::inline::comments::comment
);
impl_from_language!(
Located<LineComment<'a>>,
vimwiki::blocks::inline::comments::line_comment
);
impl_from_language!(
Located<MultiLineComment<'a>>,
vimwiki::blocks::inline::comments::multi_line_comment
);
impl_from_language!(
Located<DefinitionList<'a>>,
vimwiki::blocks::definitions::definition_list
);
impl_from_language!(Located<Divider>, vimwiki::blocks::dividers::divider);
impl_from_language!(Located<Header<'a>>, vimwiki::blocks::headers::header);
impl_from_language!(Located<Link<'a>>, vimwiki::blocks::inline::links::link);
impl_from_language!(Located<List<'a>>, vimwiki::blocks::lists::list);
impl_from_language!(Located<ListItem<'a>>, parse_list_item);
fn parse_list_item<'a>(input: Span<'a>) -> IResult<Located<ListItem<'a>>> {
nom::combinator::map(
vimwiki::blocks::lists::list_item,
|(_, item): (usize, Located<ListItem>)| item,
)(input)
}
impl_from_language!(
Located<MathInline<'a>>,
vimwiki::blocks::inline::math::math_inline
);
impl_from_language!(Located<MathBlock<'a>>, vimwiki::blocks::math::math_block);
impl_from_language!(
Located<Paragraph<'a>>,
vimwiki::blocks::paragraphs::paragraph
);
impl_from_language!(
Located<Placeholder<'a>>,
vimwiki::blocks::placeholders::placeholder
);
impl_from_language!(Located<CodeBlock<'a>>, vimwiki::blocks::code::code_block);
impl_from_language!(Located<Table<'a>>, vimwiki::blocks::tables::table);
impl_from_language!(Located<Tags<'a>>, vimwiki::blocks::inline::tags::tags);
impl_from_language!(
Located<Text<'a>>,
vimwiki::blocks::inline::typefaces::text
);
impl_from_language!(
Located<DecoratedText<'a>>,
vimwiki::blocks::inline::typefaces::decorated_text
);
impl_from_language!(
Located<Keyword>,
vimwiki::blocks::inline::typefaces::keyword
);
#[cfg(test)]
mod tests {
use super::*;
mod vimwiki {
use super::*;
#[test]
fn parse_to_page() {
let input = Language::from_vimwiki_str("some text");
let _result: Page = input.parse().expect("Failed to parse");
}
#[test]
fn parse_to_located_block_element() {
let input = Language::from_vimwiki_str("some text");
let _result: Located<BlockElement> =
input.parse().expect("Failed to parse");
}
#[test]
fn parse_to_located_inline_element_container() {
let input = Language::from_vimwiki_str("some text");
let _result: Located<InlineElementContainer> =
input.parse().expect("Failed to parse");
}
#[test]
fn parse_to_located_inline_element() {
let input = Language::from_vimwiki_str("some text");
let _result: Located<InlineElement> =
input.parse().expect("Failed to parse");
}
#[test]
fn parse_to_located_blockquote() {
let input = Language::from_vimwiki_str("> some text");
let _result: Located<Blockquote> =
input.parse().expect("Failed to parse");
}
#[test]
fn parse_to_located_code_inline() {
let input = Language::from_vimwiki_str("`code`");
let _result: Located<CodeInline> =
input.parse().expect("Failed to parse");
}
#[test]
fn parse_to_located_comment() {
let input = Language::from_vimwiki_str("%% some comment");
let _result: Located<Comment> =
input.parse().expect("Failed to parse");
}
#[test]
fn parse_to_located_line_comment() {
let input = Language::from_vimwiki_str("%% some comment");
let _result: Located<LineComment> =
input.parse().expect("Failed to parse");
}
#[test]
fn parse_to_located_multi_line_comment() {
let input = Language::from_vimwiki_str("%%+ some comment +%%");
let _result: Located<MultiLineComment> =
input.parse().expect("Failed to parse");
}
#[test]
fn parse_to_located_definition_list() {
let input = Language::from_vimwiki_str("term:: definition");
let _result: Located<DefinitionList> =
input.parse().expect("Failed to parse");
}
#[test]
fn parse_to_located_divider() {
let input = Language::from_vimwiki_str("----");
let _result: Located<Divider> =
input.parse().expect("Failed to parse");
}
#[test]
fn parse_to_located_header() {
let input = Language::from_vimwiki_str("= header =");
let _result: Located<Header> =
input.parse().expect("Failed to parse");
}
#[test]
fn parse_to_located_link() {
let input = Language::from_vimwiki_str("[[link]]");
let _result: Located<Link> =
input.parse().expect("Failed to parse");
}
#[test]
fn parse_to_located_list() {
let input = Language::from_vimwiki_str("- some list item");
let _result: Located<List> =
input.parse().expect("Failed to parse");
}
#[test]
fn parse_to_located_math_inline() {
let input = Language::from_vimwiki_str("$math$");
let _result: Located<MathInline> =
input.parse().expect("Failed to parse");
}
#[test]
fn parse_to_located_math_block() {
let input = Language::from_vimwiki_str("{{$\nmath\n}}$");
let _result: Located<MathBlock> =
input.parse().expect("Failed to parse");
}
#[test]
fn parse_to_located_paragraph() {
let input = Language::from_vimwiki_str("some text");
let _result: Located<Paragraph> =
input.parse().expect("Failed to parse");
}
#[test]
fn parse_to_located_placeholder() {
let input = Language::from_vimwiki_str("%title some text");
let _result: Located<Placeholder> =
input.parse().expect("Failed to parse");
}
#[test]
fn parse_to_located_code_block() {
let input = Language::from_vimwiki_str("{{{\nsome code\n}}}");
let _result: Located<CodeBlock> =
input.parse().expect("Failed to parse");
}
#[test]
fn parse_to_located_table() {
let input = Language::from_vimwiki_str("|cell|");
let _result: Located<Table> =
input.parse().expect("Failed to parse");
}
#[test]
fn parse_to_located_tags() {
let input = Language::from_vimwiki_str(":tag:");
let _result: Located<Tags> =
input.parse().expect("Failed to parse");
}
#[test]
fn parse_to_located_text() {
let input = Language::from_vimwiki_str("some text");
let _result: Located<Text> =
input.parse().expect("Failed to parse");
}
#[test]
fn parse_to_located_decorated_text() {
let input = Language::from_vimwiki_str("*some text*");
let _result: Located<DecoratedText> =
input.parse().expect("Failed to parse");
}
#[test]
fn parse_to_located_keyword() {
let input = Language::from_vimwiki_str("TODO");
let _result: Located<Keyword> =
input.parse().expect("Failed to parse");
}
}
}