commit 0d53d6e8b4ed96eb0f686f9dd41ee0e74201f939 (patch)
parent a18a54a3ae97e1e6ff5aae196449587a8492b4ff
Author: Alex Karle <alex@alexkarle.com>
Date: Sat, 18 Dec 2021 01:12:30 -0500
Add support for nested lists
Wooee it's getting complicated up in here! I'm not sure the feature is
worth the complexity (might revert), but it's a fun problem to solve!
There were multiple bumps--needing to store the previndent of the last
list item (not the last line), needing to add while-loops to closeblock
to support "dangling" nested lists, etc.
Diffstat:
M | blag.c | | | 81 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------- |
1 file changed, 65 insertions(+), 16 deletions(-)
diff --git a/blag.c b/blag.c
@@ -10,9 +10,9 @@
*
* <p> tags around paragraphs
*
- * - bullets (non-nested), breaks allowed if indented
+ * - bullets, breaks allowed if indented
*
- * 1. numerical lists (non-nested), breaks allowed if indented
+ * 1. numerical lists, breaks allowed if indented
*
* > quotes
*
@@ -86,9 +86,13 @@ typedef struct State {
int escape;
char lnkbuf[2048];
int lnkidx;
+ int indent;
+ int previndent;
+ int listdepth;
} state;
void closeblock(state *s) {
+ s->indent = 0;
if (s->in == HEADER) {
s->in = NONE;
printf("</h%d>", s->hlvl);
@@ -111,12 +115,20 @@ void closeblock(state *s) {
s->in = ULIST_BREAK;
} else if (s->in == ULIST_BREAK) {
s->in = NONE;
- printf("\n</li>\n</ul>\n");
+ s->previndent = 0;
+ while (s->listdepth > 0) {
+ printf("\n</li>\n</ul>\n");
+ s->listdepth--;
+ }
} else if (s->in == OLIST) {
s->in = OLIST_BREAK;
} else if (s->in == OLIST_BREAK) {
s->in = NONE;
- printf("\n</li>\n</ol>\n");
+ s->previndent = 0;
+ while (s->listdepth > 0) {
+ printf("\n</li>\n</ol>\n");
+ s->listdepth--;
+ }
} else {
/* keep in as is */
}
@@ -143,7 +155,10 @@ int parse() {
.in_bold = 0,
.escape = 0,
.lnkbuf = {0},
- .lnkidx = 0
+ .lnkidx = 0,
+ .indent = 0,
+ .previndent = 0,
+ .listdepth = 0,
};
while ((c = getchar()) != EOF) {
@@ -162,6 +177,14 @@ int parse() {
if (s.in_link == LINK_URL_PARSE && c != ']') {
s.lnkbuf[s.lnkidx++] = c;
}
+
+ /* first non-space char in a list continuation breaks break */
+ if (s.in == ULIST_BREAK && c != ' ' && c != '-' && c != '\n') {
+ s.in = ULIST;
+ }
+ if (s.in == OLIST_BREAK && c != ' ' && (c < 48 || c > 58) && c != '\n') {
+ s.in = OLIST;
+ }
/* Handle unique state changes by char */
switch (c) {
@@ -184,25 +207,29 @@ int parse() {
printf("<h%d>", s.hlvl);
s.in = HEADER;
} else if (s.in == ULIST_START) {
- printf("<ul>\n<li>\n");
+ s.previndent = s.indent;
+ printf("\n<ul>\n<li>\n");
s.in = ULIST;
+ s.listdepth++;
} else if (s.in == ULIST_PARSE) {
printf("\n</li>\n<li>\n");
s.in = ULIST;
} else if (s.in == OLIST_START) {
- printf("<ol>\n<li>\n");
+ s.previndent = s.indent;
+ printf("\n<ol>\n<li>\n");
s.in = OLIST;
+ s.listdepth++;
} else if (s.in == OLIST_PARSE) {
printf("\n</li>\n<li>\n");
s.in = OLIST;
} else if (s.in == NONE) {
- /* no op */
+ s.indent++;
} else if (s.in == ULIST_BREAK) {
- /* assume it's a continuation! */
- s.in = ULIST;
+ s.indent++;
+ putesc(c);
} else if (s.in == OLIST_BREAK) {
- /* assume it's a continuation! */
- s.in = OLIST;
+ s.indent++;
+ putesc(c);
} else if (s.in_link == LINK_URL_PARSE) {
s.in_link = LINK_DESC_PARSE;
printf("\">");
@@ -300,8 +327,20 @@ int parse() {
} else if (s.in == ULIST_START || s.in == ULIST_PARSE) {
/* no op */
} else if (s.in == ULIST_BREAK) {
- /* next list item */
- s.in = ULIST_PARSE;
+ /* printf("\n>> %d | %d \n", s.previndent, s.indent); */
+ if (s.previndent < s.indent) {
+ /* new sublist */
+ s.in = ULIST_START;
+ } else if (s.previndent > s.indent) {
+ /* end of a sublist */
+ printf("\n</li>\n</ul>\n");
+ s.previndent = s.indent;
+ s.listdepth--;
+ s.in = ULIST_PARSE;
+ } else {
+ /* next list item */
+ s.in = ULIST_PARSE;
+ }
} else {
putesc(c);
}
@@ -321,8 +360,18 @@ int parse() {
} else if (s.in == OLIST_START || s.in == OLIST_PARSE) {
/* no op */
} else if (s.in == OLIST_BREAK) {
- /* next list item */
- s.in = OLIST_PARSE;
+ if (s.previndent < s.indent) {
+ /* new sublist */
+ s.in = OLIST_START;
+ } else if (s.previndent > s.indent) {
+ /* end of a sublist */
+ printf("\n</li>\n</ol>\n");
+ s.listdepth--;
+ s.in = OLIST_PARSE;
+ } else {
+ /* next list item */
+ s.in = OLIST_PARSE;
+ }
} else {
putesc(c);
}