From 7f8d501b15fbe882f6e6b67cb1eae96a2e655748 Mon Sep 17 00:00:00 2001 From: Aleksey Veresov Date: Wed, 30 Oct 2019 19:18:42 +0300 Subject: Markdown semi-working. =) --- src/markdown.cpp | 261 ++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 211 insertions(+), 50 deletions(-) (limited to 'src/markdown.cpp') diff --git a/src/markdown.cpp b/src/markdown.cpp index 0593eb9..fb538fc 100644 --- a/src/markdown.cpp +++ b/src/markdown.cpp @@ -169,15 +169,19 @@ void TexoProducerMarkdown::Put(const TexoHorizontalRule &piece) TexoImporterMarkdown::TexoImporterMarkdown(TexoProducer &producer): - TexoImporter(producer), state(text) + TexoImporter(producer), state(start), wrapping_state(error), mod_pos(-1) {} TexoImporterMarkdown::~TexoImporterMarkdown() -{} +{ + EndBlock(); +} void TexoImporterMarkdown::Put(char c) { switch (state) { + case error: break; + case start: Start(c); break; case text: Text(c); break; case header_text: HeaderText(c); break; case quote_text: QuoteText(c); break; @@ -191,10 +195,10 @@ void TexoImporterMarkdown::Put(char c) case plus: Plus(c); break; case tilde: Tilde(c); break; case newline: Newline(c); break; + case rule: Rule(c); break; case paragraph: Paragraph(c); break; case header: Header(c); break; case code: Code(c); break; - case quote: Quote(c); break; } } @@ -208,14 +212,36 @@ void TexoImporterMarkdown::Put(FILE *file) TexoImporter::Put(file); } +void TexoImporterMarkdown::Start(char c) +{ + if (c == '\n') { + state = paragraph; + } else if (c == '#') { + state = header; + header_level = 6; + } else if (c == '>') { + BlockState(quote_text); + } else if (c == '-') { + BlockState(text); + state = rule; + rule_dash_count = 1; + } else if (c == '`') { + state = code; + code_quote_count = 1; + } else { + BlockState(text); + Put(c); + } +} + void TexoImporterMarkdown::Text(char c) { - wrapping_state = text; switch (c) { case '\\': state = backslash; break; case '\n': state = newline; break; case '*': state = asterisk; break; case '_': state = underline; break; + case '+': state = plus; break; case '~': state = tilde; break; case '`': Backquote(); break; default: producer.Put(c); @@ -224,12 +250,12 @@ void TexoImporterMarkdown::Text(char c) void TexoImporterMarkdown::HeaderText(char c) { - wrapping_state = header_text; switch (c) { case '\\': state = backslash; break; - case '\n': EndHeader(); break; + case '\n': state = paragraph; break; case '*': state = asterisk; break; case '_': state = underline; break; + case '+': state = plus; break; case '~': state = tilde; break; case '`': Backquote(); break; default: producer.Put(c); @@ -238,22 +264,69 @@ void TexoImporterMarkdown::HeaderText(char c) void TexoImporterMarkdown::QuoteText(char c) { - wrapping_state = header_text; switch (c) { case '\\': state = backslash; break; case '\n': state = quote_newline; break; case '*': state = asterisk; break; case '_': state = underline; break; + case '+': state = plus; break; case '~': state = tilde; break; case '`': Backquote(); break; default: producer.Put(c); } } -void TexoImporterMarkdown::QuoteNewline(char c); -void TexoImporterMarkdown::CodeText(char c); -void TexoImporterMarkdown::CodeNewline(char c); -void TexoImporterMarkdown::CodeEnd(char c); +void TexoImporterMarkdown::QuoteNewline(char c) +{ + if (c == '>') { + state = quote_text; + } else { + state = paragraph; + Put(c); + } +} + +void TexoImporterMarkdown::CodeText(char c) +{ + switch (c) { + case '\\': state = backslash; break; + case '\n': state = code_newline; break; + case '*': state = asterisk; break; + case '_': state = underline; break; + case '+': state = plus; break; + case '~': state = tilde; break; + case '`': state = error; break; + default: producer.Put(c); + } +} + +void TexoImporterMarkdown::CodeNewline(char c) +{ + if (c == '`') { + state = code_end; + code_quote_count = 1; + } else { + producer.Put('\n'); + state = code_text; + Put(c); + } +} + +void TexoImporterMarkdown::CodeEnd(char c) +{ + if (c == '`') { + ++code_quote_count; + } else if (c == '\n') { + if (code_quote_count == 3) { + state = paragraph; + Put(c); + } else { + state = error; + } + } else { + state = error; + } +} void TexoImporterMarkdown::Backslash(char c) { @@ -265,12 +338,18 @@ void TexoImporterMarkdown::Asterisk(char c) { state = wrapping_state; if (c == '*') { - producer.Put(TexoBold(is_bold)); - is_bold = !is_bold; + if (CheckMods(bold)) { + producer.Put(TexoBold(Mod(bold))); + } else { + state = error; + } } else { - producer.Put(TexoItalic(is_italic)); - is_italic = !is_italic; - Put(c); + if (CheckMods(italic)) { + producer.Put(TexoItalic(Mod(italic))); + Put(c); + } else { + state = error; + } } } @@ -278,12 +357,18 @@ void TexoImporterMarkdown::Underline(char c) { state = wrapping_state; if (c == '_') { - producer.Put(TexoBold(is_bold)); - is_bold = !is_bold; + if (CheckMods(bold)) { + producer.Put(TexoBold(Mod(bold))); + } else { + state = error; + } } else { - producer.Put(TexoItalic(is_italic)); - is_italic = !is_italic; - Put(c); + if (CheckMods(italic)) { + producer.Put(TexoItalic(Mod(italic))); + Put(c); + } else { + state = error; + } } } @@ -291,8 +376,11 @@ void TexoImporterMarkdown::Plus(char c) { state = wrapping_state; if (c == '+') { - producer.Put(TexoUnderline(is_underline)); - is_underline = !is_underline; + if (CheckMods(underlined)) { + producer.Put(TexoUnderline(Mod(underlined))); + } else { + state = error; + } } else { producer.Put('+'); Put(c); @@ -303,20 +391,17 @@ void TexoImporterMarkdown::Tilde(char c) { state = wrapping_state; if (c == '~') { - producer.Put(TexoStrike(is_strike)); - is_strike = !is_strike; + if (CheckMods(strike)) { + producer.Put(TexoStrike(Mod(strike))); + } else { + state = error; + } } else { producer.Put('~'); Put(c); } } -void TexoImporterMarkdown::Backquote() -{ - producer.Put(TexoMono(is_mono)); - is_mono = !is_mono; -} - void TexoImporterMarkdown::Newline(char c) { if (c == '\n') { @@ -325,7 +410,7 @@ void TexoImporterMarkdown::Newline(char c) state = header; header_level = 6; } else if (c == '>') { - state = quote; + BlockState(quote_text); } else if (c == '-') { state = rule; rule_dash_count = 1; @@ -343,37 +428,35 @@ void TexoImporterMarkdown::Rule(char c) { if (c == '-') { ++rule_dash_count; + } else if (c == '\n' && rule_dash_count >= 3) { + producer.Put(TexoHorizontalRule()); + state = newline; } else { - if (rule_dash_count >= 3) { - producer.Put(TexoHorizontalRule()); - } else { - if (wrapping_state == paragraph) { - producer.Put(TexoParagraph()); - } - for (int i = 0; i < rule_dash_count; ++i) { - producer.Put('-'); - } + producer.Put(' '); + for (int i = 0; i < rule_dash_count; ++i) { + producer.Put('-'); } + state = wrapping_state; + Put(c); } } void TexoImporterMarkdown::Paragraph(char c) { - wrapping_state = paragraph; if (c == '#') { state = header; header_level = 6; } else if (c == '>') { - state = quote; + BlockState(quote_text); } else if (c == '-') { + BlockState(text); state = rule; rule_dash_count = 1; } else if (c == '`') { state = code; code_quote_count = 1; } else { - producer.Put(TexoParagraph()); - state = text; + BlockState(text); Put(c); } } @@ -383,15 +466,93 @@ void TexoImporterMarkdown::Header(char c) if (c == '#') { if (header_level > 1) { --header_level; + } else { + state = error; } } else { - producer.Put(TexoHeader(header_level)); - state = header_text; + BlockState(header_text); + header_level_last = header_level; + Put(c); } } -void TexoImporterMarkdown::EndHeader() +void TexoImporterMarkdown::Code(char c) { - producer.Put(TexoHeader(header_level, true)); - state = paragraph; + if (c == '`') { + ++code_quote_count; + } else if (c == '\n') { + if (code_quote_count == 3) { + BlockState(code_text); + } else { + state = error; + } + } else { + state = error; + } +} + +void TexoImporterMarkdown::Backquote() +{ + if (CheckMods(mono)) { + producer.Put(TexoMono(Mod(mono))); + } else { + state = error; + } +} + +bool TexoImporterMarkdown::CheckMods(Modificator mod) +{ + bool ok = true; + for (int i = 0; ok && i < mod_pos; ++i) { + ok = mods[i] != mod; + } + return ok; +} + +bool TexoImporterMarkdown::Mod(Modificator mod) +{ + if (mod_pos == -1 || mods[mod_pos] != mod) { + ++mod_pos; + mods[mod_pos] = mod; + return false; + } + --mod_pos; + return true; +} + +void TexoImporterMarkdown::BlockState(State st) +{ + if (mod_pos == -1) { + state = st; + EndBlock(); + if (st == text) { + producer.Put(TexoParagraph()); + } else if (st == quote_text) { + producer.Put(TexoQuote()); + } else if (st == code_text) { + producer.Put(TexoCode()); + } else if (st == header_text) { + producer.Put(TexoHeader(header_level)); + } else { + state = error; + } + wrapping_state = st; + } else { + state = error; + } +} + +void TexoImporterMarkdown::EndBlock() +{ + if (wrapping_state == text) { + producer.Put(TexoParagraph(true)); + } else if (wrapping_state == quote_text) { + producer.Put(TexoQuote(true)); + } else if (wrapping_state == code_text) { + producer.Put(TexoCode(true)); + } else if (wrapping_state == header_text) { + producer.Put(TexoHeader(header_level_last, true)); + } else if (wrapping_state != error) { + state = error; + } } -- cgit v1.2.3