From c7f45fc76ed342ce54a9b43d9046629848968189 Mon Sep 17 00:00:00 2001
From: wrmr
Date: Fri, 4 Apr 2025 21:01:31 -0500
Subject: add --inline, fix code blocks
---
main.c | 218 ++++++++++++++++++++++++++++++++++++++++++++++++-----------------
1 file changed, 163 insertions(+), 55 deletions(-)
diff --git a/main.c b/main.c
index e749d58..0cddf91 100644
--- a/main.c
+++ b/main.c
@@ -12,6 +12,19 @@
#include "arena.h"
#include "args.h"
+typedef struct {
+ int standalone;
+ int from_stdin;
+ Str stylesheet;
+ int inlinep;
+ int csslink;
+ Str hvarv[1024];
+ Str title;
+ int hvarc;
+} Options;
+
+Options opts = { 0 };
+
#define ARENA(n, sz) Arena n; { static char arena_backarr[sz];\
n.beg = arena_backarr; n.end = arena_backarr + sizeof(arena_backarr);\
__asm("":"+r"(n.beg)); __asm("":"+r"(n.end)); }
@@ -65,15 +78,18 @@ void str_cat_uri(Str *s, Str uri, Arena *a) {
str_catc(s, '\'', a);
}
+void str_catc_html(Str *s, char c, Arena *a) {
+ switch (c) {
+ case '&': str_cat(s, S("&"), a); break;
+ case '<': str_cat(s, S("<"), a); break;
+ case '>': str_cat(s, S(">"), a); break;
+ default: str_catc(s, c, a); break;
+ }
+}
+
void str_cat_html(Str *s, Str uri, Arena *a) {
for (isize i = 0; i < uri.n; i++) {
- char c = uri.s[i];
- switch (c) {
- case '&': str_cat(s, S("&"), a); break;
- case '<': str_cat(s, S("<"), a); break;
- case '>': str_cat(s, S(">"), a); break;
- default: str_catc(s, c, a); break;
- }
+ str_catc_html(s, uri.s[i], a);
}
}
@@ -214,25 +230,24 @@ BlockList blk_gather(Str src, Arena *perm) {
Line *lptr = NULL;
while (next_line(&src, &line)) {
LineType t = classify_line(line, last);
- if (last == LN_CODE) {
- if (t == LN_CODE) last = LN_NONE;
- } else if (t == LN_CODE) {
- last = LN_CODE;
- } else {
- Block *b = blk.len > 0 ? &blk.data[blk.len-1] : NULL;
- if (!b || t != b->type) {
- b = blk_push(&blk, &lptr, t, perm);
- }
- Line *l = new(perm, Line);
- LineType nt = line_init(l, line, t);
- if (b->type != nt) {
- if (b->lines) b = blk_push(&blk, &lptr, nt, perm);
- else b->type = nt;
- }
- if (lptr) lptr->next = l;
- lptr = l;
- if (!b->lines) b->lines = lptr;
+ if (t == LN_CODE) {
+ last = last == LN_CODE ? LN_NONE : LN_CODE;
+ continue;
+ }
+ if (last == LN_CODE) t = LN_CODE;
+ Block *b = blk.len > 0 ? &blk.data[blk.len-1] : NULL;
+ if (!b || t != b->type) {
+ b = blk_push(&blk, &lptr, t, perm);
+ }
+ Line *l = new(perm, Line);
+ LineType nt = line_init(l, line, t);
+ if (b->type != nt) {
+ if (b->lines) b = blk_push(&blk, &lptr, nt, perm);
+ else b->type = nt;
}
+ if (lptr) lptr->next = l;
+ lptr = l;
+ if (!b->lines) b->lines = lptr;
last = t;
}
for (size_t i = 0; i < blk.len; i++) {
@@ -247,11 +262,103 @@ BlockList blk_gather(Str src, Arena *perm) {
}
#define O(s) str_cat_html(out, s, perm)
+#define Oi(s) markup_inline(&ist, out, s, scratch, perm)
#define Os(s) str_cat(out, S(s), perm)
-#define Ot(a, s, b) Os(a), O(s), Os(b)
+#define Ot(a, s, b) Os(a), Oi(s), Os(b)
#define Otl(a, f, b) for (Line *l = blk->lines; l; l = l->next) Ot(a, f, b)
-void str_cat_blk(Str *out, Block *blk, Arena *perm, Arena *scratch) {
+typedef enum {
+ IM_NONE,
+ IM_ITAL,
+ IM_CODE
+} InlineMarkup;
+
+typedef struct {
+ int stkc;
+ InlineMarkup *stkv;
+} InlineState;
+
+InlineMarkup im_last(InlineState *ms) {
+ if (ms->stkc > 0) {
+ return ms->stkv[ms->stkc - 1];
+ } else {
+ return IM_NONE;
+ }
+}
+
+void im_cat_op(Str *out, InlineMarkup mu, Arena *perm) {
+ switch (mu) {
+ case IM_ITAL: str_cat(out, S(""), perm); break;
+ case IM_CODE: str_cat(out, S(""), perm); break;
+ default: break;
+ }
+}
+
+void im_cat_cl(Str *out, InlineMarkup mu, Arena *perm) {
+ switch (mu) {
+ case IM_ITAL: str_cat(out, S("
"), perm); break;
+ case IM_CODE: str_cat(out, S(""), perm); break;
+ default: break;
+ }
+}
+
+InlineMarkup im_pop(InlineState *ms) {
+ if (ms->stkc > 0) return ms->stkv[--ms->stkc];
+ return IM_NONE;
+}
+
+InlineMarkup im_push(InlineState *ms, InlineMarkup mu, Arena *scratch) {
+ if (ms->stkc > 0) {
+ ms->stkv = resize(scratch, ms->stkv, ms->stkc, ms->stkc + 1);
+ } else {
+ ms->stkv = new(scratch, InlineMarkup);
+ }
+ ms->stkv[ms->stkc++] = mu;
+ return mu;
+}
+
+void im_op(InlineState *ms, Str *out, InlineMarkup mu, Arena *scratch, Arena *perm) {
+ im_cat_op(out, im_push(ms, mu, scratch), perm);
+}
+
+void im_cl(InlineState *ms, Str *out, Arena *perm) {
+ im_cat_cl(out, im_pop(ms), perm);
+}
+
+void markup_inline(InlineState *ms, Str *out, Str src, Arena *scratch, Arena *perm) {
+ if (!opts.inlinep) {
+ str_cat_html(out, src, perm);
+ return;
+ }
+ for (int i = 0; i < src.n; i++) {
+ char c = src.s[i];
+ if (im_last(ms) == IM_CODE) {
+ if (c == '`') {
+ im_cl(ms, out, perm);
+ } else {
+ str_catc_html(out, src.s[i], perm);
+ }
+ } else {
+ if (c == '`') {
+ im_op(ms, out, IM_CODE, scratch, perm);
+ } else if (c == '*') {
+ if (im_last(ms) == IM_ITAL) {
+ im_cl(ms, out, perm);
+ } else {
+ im_op(ms, out, IM_ITAL, scratch, perm);
+ }
+ } else if (str_starts(str_skip(src, i), S("---"))) {
+ str_cat(out, S("—"), perm);
+ i += 2;
+ } else {
+ str_catc_html(out, src.s[i], perm);
+ }
+ }
+ }
+}
+
+void markup_block(Str *out, Block *blk, Arena *perm, Arena *scratch) {
+ InlineState ist = { 0 };
switch (blk->type) {
case LN_CODE:
Os("
");
@@ -270,7 +377,13 @@ void str_cat_blk(Str *out, Block *blk, Arena *perm, Arena *scratch) {
: str_replace_end(l->url,
S(".gmi"), S(".html"),
scratch), perm);
- Ot(">", l->txt.n > 0 ? l->txt : l->url, "\n");
+ str_catc(out, '>', perm);
+ if (l->txt.n > 0) {
+ markup_inline(&ist, out, l->txt, scratch, perm);
+ } else {
+ str_cat_html(out, l->url, perm);
+ }
+ str_cat(out, S("\n"), perm);
}
Os("");
break;
@@ -315,13 +428,14 @@ void str_cat_blk(Str *out, Block *blk, Arena *perm, Arena *scratch) {
case LN_PAR:
Os("");
for (Line *l = blk->lines; l; l = l->next) {
- O(l->txt);
+ Oi(l->txt);
if (l->next) Os("
\n");
}
Os("
");
break;
}
Os("\n");
+ while (ist.stkc > 0) im_cl(&ist, out, perm);
}
int wdoc(FILE *f, Doc **dp, Arena *perm, Arena *scratch) {
@@ -333,7 +447,7 @@ int wdoc(FILE *f, Doc **dp, Arena *perm, Arena *scratch) {
if (blk.data[i].type == LN_HDR1 && !d->title.s) {
d->title = blk.data[i].lines->txt;
}
- str_cat_blk(&d->html, &blk.data[i], perm, scratch);
+ markup_block(&d->html, &blk.data[i], perm, scratch);
if (i + 1 < blk.len) str_cat(&d->html, S("\n"), perm);
}
*dp = d;
@@ -369,7 +483,7 @@ int hvar_calc(Str param, Str *name, Str *val, Str filename) {
void usage(const char *cmd) {
fprintf(stderr, "usage: %s -?\n"
- " %s [-s] [[-l] -c FILE] [-t TITLE] [-h NAME:ARG1[,ARG2,ARG3...]] [FILES...]\n"
+ " %s [-s] [-i] [[-l] -c FILE] [-t TITLE] [-h NAME:ARG1[,ARG2,ARG3...]] [FILES...]\n"
"\n"
" -? --help show this help text\n"
" -s --standalone prefix with html metadata\n"
@@ -378,37 +492,28 @@ void usage(const char *cmd) {
" -c --css embed the given file within a \n"), m);
}
- if (o->stylesheet.s) {
- if (o->csslink) {
+ if (opts.stylesheet.s) {
+ if (opts.csslink) {
str_cat(&h, S(""), m);
} else {
- FILE *f = fopen(str_to_cstr(o->stylesheet, m), "r/o");
+ FILE *f = fopen(str_to_cstr(opts.stylesheet, m), "r/o");
if (!f) {
- str_putf(o->stylesheet, stderr);
+ str_putf(opts.stylesheet, stderr);
fprintf(stderr, ": %s\n", strerror(errno));
exit(1);
}
@@ -455,16 +560,16 @@ int main(int argc, const char **argv) {
ARENA(scratch, 1 << 20)
Doc *doc = 0;
- Options opts = { 0 };
int r;
ArgsState a = args_begin(argv);
Str param = { 0 };
opts.from_stdin = 1;
- while ((r = arg_get(&a, "?slc:h:t:", ¶m,
+ while ((r = arg_get(&a, "?slic:h:t:", ¶m,
"help", '?',
"standalone", 's',
+ "inline", 'i',
":title", 't',
":css", 'c',
"link", 'l',
@@ -478,6 +583,9 @@ int main(int argc, const char **argv) {
case 's':
opts.standalone = 1;
break;
+ case 'i':
+ opts.inlinep = 1;
+ break;
case 'c':
opts.stylesheet = param;
break;
@@ -546,7 +654,7 @@ int main(int argc, const char **argv) {
}
if (opts.standalone) {
- str_put(html_head(&opts, &perm, &scratch));
+ str_put(html_head(&perm, &scratch));
str_put(S("\n"));
}
--
cgit 1.4.1-2-gfad0