Skip to content

Instantly share code, notes, and snippets.

@szdytom
Created July 31, 2023 12:22
Show Gist options
  • Save szdytom/186b36dcb2b2da98af1081202c5bf80e to your computer and use it in GitHub Desktop.
Save szdytom/186b36dcb2b2da98af1081202c5bf80e to your computer and use it in GitHub Desktop.
6cc - Markdown Foldblock Extension
#include <bits/stdc++.h>
using namespace std;
int now;
string s;
vector<int> sta;
bool match(string t) {
if (now + t.size() > s.size())
return false;
if (s.substr(now, t.size()) != t)
return false;
now += t.size();
return true;
}
bool matchg() {
int old = now;
while (now < min(old + 4, (int)s.size()) && s[now] == ' ')
now++;
if (now - old < 4 && match(">"))
return match(" "), true;
return now = old, false;
}
int matchl() {
int old = now;
while (now < min(old + 4, (int)s.size()) && s[now] == ' ')
now++;
if (now - old < 4) {
bool matched = 0;
if (match("+ ") || match("- ") || match("* "))
matched = 1;
if (!matched) {
bool digit = 0;
while (now < s.size() && isdigit(s[now]))
digit = 1, now++;
if (digit && match(". "))
matched = 1;
}
if (matched) {
for (int i = 0; i <= 3; i++)
match(" ");
return now - old;
}
}
return now = old, 0;
}
void matchcb(int &codemode) {
int old = now;
while (now < min(old + 4, (int)s.size()) && s[now] == ' ')
now++;
if (now - old < 4) {
if ((codemode == 0 || codemode == 1) && match("```"))
return void(codemode = codemode ^ 1);
if ((codemode == 0 || codemode == 2) && match("~~~"))
return void(codemode = codemode ^ 2);
}
now = old;
}
void printsta() {
for (int x : sta) {
if (x == -1)
printf("> ");
else if (x != -2)
printf("%s", string(x, ' ').c_str());
}
}
void popblank() {
while (!s.empty() && isblank(s.back()))
s.pop_back();
reverse(s.begin(), s.end());
while (!s.empty() && isblank(s.back()))
s.pop_back();
reverse(s.begin(), s.end());
}
void foundblock(int type) {
printsta();
printf("<details open%s>",
type == -2 ? "" : " class=\"detail-fold-default-closed\"");
s = s.substr(now);
popblank();
if (s.empty())
puts("");
else
printf("<summary>%s</summary>\n", s.c_str());
sta.push_back(-2);
printsta(), puts("");
}
string text;
void printhelp(const char *name) {
printf("6cc the extended commonmark compiler, built on %s.\n"
"Usage: %s <inputfile> <outputfile>\n",
__DATE__, name);
exit(1);
}
int main(int argc, char **argv) {
if (argc != 3)
printhelp(argv[0]);
freopen(argv[1], "r", stdin);
freopen(argv[2], "w", stdout);
bool ended = 0;
int codemode = 0;
while (!cin.eof() || !ended) {
if (cin.eof())
ended = 1, s = "";
else
getline(cin, s);
text += s + "\n";
now = 0;
if (codemode) {
for (int t = 0; t < sta.size(); t++) {
int x = sta[t];
if (x < 0)
assert(matchg());
else
assert(match(string(x, ' ')));
}
printsta();
printf("%s\n", s.substr(now).c_str());
matchcb(codemode);
continue;
}
int t = 0;
bool flag = 0;
for (; t < sta.size(); t++) {
int x = sta[t];
if (x < 0) {
if (matchg()) {
flag = 1;
continue;
}
break;
} else {
assert(x);
if (match(string(x, ' '))) {
flag = 0;
continue;
}
break;
}
}
for (int p = now; p < s.size(); p++)
if (s[p] != ' ')
goto PS;
for (; t < sta.size(); ++t)
if (sta[t] < 0)
goto PS;
printsta(), puts("");
continue;
PS:
int type = -1;
if (flag) {
if (match("[+]"))
type = -2;
else if (match("[-]"))
type = -3;
if (type != -1)
t--;
}
while (sta.size() > t) {
int x = sta.back();
sta.pop_back();
if (x == -2) {
printsta();
puts("</details>");
}
}
if (type == -1)
while (matchg()) {
if (match("[+]"))
type = -2;
else if (match("[-]"))
type = -3;
if (type != -1)
break;
sta.push_back(-1);
}
if (type != -1) {
match(" ");
foundblock(type);
continue;
}
printsta();
printf("%s\n", s.substr(now).c_str());
int x = matchl();
if (x)
sta.push_back(x);
matchcb(codemode);
}
printf("<!--\n%s-->", text.c_str());
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment