commit - 008fd57cb78444d1a54008b0b5fedd65be24248e
commit + d7de9ba65a1fdd87735e4358a090dc7285db40f7
blob - /dev/null
blob + c84b032e7255a77bf2eb63e0c84e393fe138b1e4 (mode 644)
--- /dev/null
+++ resources/posts/text-gemini-to-html-with-awk.gmi
+I like text/gemini. I like writing in this format. At first, it was a bit limitating, like, I want *bold*, /italic/, _underline_, ~striked~, [inline links](…), ![inline images](…), !![inline videos](…) (?) etc. But I as started writing (by the way, every post in the last 3 months was written in text/gemini) I found myself pretty accustomed to it. I really like the idea of one link-per-line.
+
+I also started writing text/gemini outside this blog. The INSTALL file for gmid is written in text/gemini. The README for tango (a new hack, will write about that later) is also written in text/gemini.
+
+=> https://git.omarpolo.com/gmid/about/ gmid repository
+=> https://git.omarpolo.com/tango/about/ tango repository
+
+(they’re only gemini-related things, so using text/gemini for documentational/presentational purpose seems appropriate.)
+
+I also have a public (HTTP-only for the time being) git repository, powered by cgit.
+
+If you sum this two things, you’ll reach the logical conclusion that I need a filter for cgit to display text/gemini over HTTP.
+
+Cgit has this cool things called filters: you can write script (or any executable really) that accept input in a particular format and output HTML and cgit will use it to render pages.
+
+There are a few text/gemini to HTML converters, but I rolled my own. NIH. Well, not really. I currently run cgit on a FreeBSD jail, and I don’t like the idea of installing too much things inside it. I could have built a (say) go executable linked statically and copied into the jail, but I don’t really like the idea.
+
+Instead, I wrote an AWK script to convert text/gemini files to HTML. I was kinda surprised that nobody had already written one in AWK (or Perl). It isn’t too ugly, and was an occasion to review the language.
+
+AWK is, in my opinion, an almost perfect scripting language. It is quick, easy to learn and to use (both as a filter in pipe and as a standalone script) and packed with nice and essential features. But it lacks something. I don’t know exactly what, but every time I use it (for more than a one-liner) I get the impression that something is missing.
+
+Anyway, here’s the script in all its glory. This time I discovered the “next” statement, that unfortunately cannot be used inside a function (probably for a good reason).
+
+(it’s open to improvements, but at the moment I’m happy with it)
+
+```awk
+#!/usr/bin/awk -f
+
+BEGIN {
+ in_pre = 0;
+ in_list = 0;
+}
+
+!in_pre && /^###/ { output("<h3>", substr($0, 4), "</h3>"); next }
+!in_pre && /^##/ { output("<h2>", substr($0, 3), "</h2>"); next }
+!in_pre && /^#/ { output("<h1>", substr($0, 2), "</h1>"); next }
+!in_pre && /^>/ { output("<blockquote>", substr($0, 2), "</blockquote>"); next }
+!in_pre && /^\*/ { output("<li>", substr($0, 2), "</li>"); next }
+
+!in_pre && /^=>/ {
+ $0 = substr($0, 3);
+ link = $1;
+ $1 = "";
+ output_link(link, $0);
+ next;
+}
+
+!in_pre && /^```/ {
+ in_pre = 1;
+ if (in_list) {
+ in_list = 0;
+ print("</ul>");
+ }
+ print "<pre>";
+ next
+}
+
+in_pre && /^```/ { in_pre = 0; print "</pre>"; next }
+!in_pre { output("<p>", $0, "</p>"); next }
+in_pre { print san($0); next }
+
+END {
+ if (in_list)
+ print "</ul>"
+ if (in_pre)
+ print "</pre>"
+}
+
+function trim(s) {
+ sub("^[ \t]*", "", s);
+ return s;
+}
+
+function san(s) {
+ gsub("&", "\\&", s)
+ gsub("<", "\\<", s)
+ gsub(">", "\\>", s)
+ return s;
+}
+
+function output(ot, content, et) {
+ content = trim(content);
+
+ if (!in_list && ot == "<li>") {
+ in_list = 1;
+ print "<ul>";
+ }
+
+ if (in_list && ot != "<li>") {
+ in_list = 0;
+ print "</ul>";
+ }
+
+ if (ot == "<p>" && content == "")
+ return;
+
+ printf("%s%s%s\n", ot, san(content), et);
+}
+
+function output_link(link, content) {
+ if (in_list) {
+ in_list = 0;
+ print "</ul>";
+ }
+
+ if (content == "")
+ content = link;
+
+ printf("<p><a href=\"%s\">%s</a></p>\n", link, trim(san(content)));
+}
+```
+
+Cheers!
blob - 76aec8e5fef73ce12b0852abac46805588fdb5df
blob + 148eddbb4406787e96f2297ab780c8b790ab15af
--- resources/posts.edn
+++ resources/posts.edn
-[{:title "The joy of elisp: an example"
+[{:title "text/gemini to HTML with AWK"
+ :slug "text-gemini-to-html-with-awk"
+ :date "2020/12/29"
+ :tags #{:awk :gemini :git}
+ :short "Fun with AWK and text/gemini"
+ :gemtext? true
+ :music {:title "Venice Queen"
+ :by "Red Hot Chili Peppers"}}
+ {:title "The joy of elisp: an example"
:slug "joy-of-elisp-sndio"
:date "2020/12/28"
:tags #{:literate-programming :lisp :emacs :OpenBSD}