
\documentclass[12pt]{article}
\usepackage[T2A,OT1]{fontenc}
\usepackage[default]{cantarell}
\usepackage[a4paper, top=20mm, bottom=20mm, left=20mm, right=20mm]{geometry}
\usepackage[utf8]{inputenc}
\usepackage[russian, english]{babel}
\usepackage{tabu}
\usepackage{hyperref}
\usepackage{parskip}
\usepackage{graphicx}
\usepackage{tabularx}
\usepackage{float}
\floatstyle{boxed}
\restylefloat{figure}
\usepackage{setspace}
\onehalfspacing
\author{Artyom Bologov \href{mailto:this-post-is-ed@aartaka.me}{(email)}}
\date{\today}
\title{Using ed(1) as My Static Site Generator}
\makeatletter
\def\endenv{\expandafter\end\expandafter{\@currenvir}}
\makeatother
\begin{document}
\maketitle

I have a long story with bipolar spikes making me re-evaluate my tech choices.
You can observe it with multiple of my website setups:
\href{run:tripod}{I started with Tripod, my Gemtext-oriented OOP Lisp engine}.
\href{run:this-post-is-lisp}{Then I used the DSLs Common Lisp provides to generate HTML from s-expressions}.
\href{run:this-post-is-cpp}{And, finally, I switched to C Preprocessor}.
And here’s a new flare-up, I guess?

This time I’m testing the limits of what ed-family editors can do.
\href{run:paren-regex}{Including parsing Lisp}.
\href{run:sed-ed}{And using ed as an everyday scripting environment}.

I’ve also tried ex/vi (not Vim!)
\href{https://github.com/aartaka/emvi}{To the point of making a Lisp programming config for it}.
\href{https://merveilles.town/@aartaka/113546886276193594}{But ex/vi are too troublesome, so forget it}.

Back to ed then!
\href{https://github.com/aartaka/modal.ed}{Here’s a compiler from high-level Modal system to ed, written in ed itself}.
\href{scripts/wisp.ed}{Here’s a script processing Wisp syntax extension for Lisps}.
\href{https://rosettacode.org/wiki/Category:Ed}{And here’s a whole category for ed tasks I solved on RosettaCode}.
The overarching narrative can be a transformation from one format to the other.
Like... what site generators do?
So I can use ed as my site generator, and get away with it?

\section*{Setup: Glorified ed Scripts} \label{setup}

So the way ed scripts are ran:

\begin{figure}[h!]\begin{verbatim}
ed -s file.html < script.ed
\end{verbatim}\caption{Example script run}\end{figure}

This incantation

\begin{itemize}\item Opens a \verb|file.html|,
\item Reads commands from stdin (redirected \verb|script.ed|.)
\item And saves/writes (\verb|w| command) file if there are respective commands in the stdin.
\end{itemize}

A huge advantage is that I can swap commands in the script file.
Replacing writing commands to printing ones, for example.
This way, I can print the content of the post without modifying it.
Y’know, for blog debugging (everyone does that?)

With that general formula, I can abstract article builds per format with two scripts:
a preprocessing (deabbreviation and escaped char expansion) script and the actual conversion.
Here’s how
\href{makefile}{my Makefile rule for .txt building}
looks like:

\begin{figure}[h!]\begin{verbatim}
%.txt: %.h
	-cp $^ $@
	-ed -s $@ < \href{scripts/preprocess.ed}{scripts/preprocess.ed}
	-ed -s $@ < \href{scripts/totxt.ed}{scripts/totxt.ed}
\end{verbatim}\caption{Makefile implicit rule for conversion from .h to actual output text files}\end{figure}

Repeat this for every format (my site supports five atm) with dedicated \verb|to*.ed| scripts.
And that’s it!

\section*{Advantages} \label{advantages}

I can use whatever syntax I want now!
With C Preprocessor, I was restricted to \verb|X(ARG1, ARG2, ...)| structure for all my elements.
With ed, I can go crazy with something like \verb|<cd code-here>|, imitating self-closing HTML tags.
Or whatever.
Closer to the way I model my writing.

Another upside: I don’t have to rewrite all of my posts in a new format.
My ed scripts are processing the old preprocessor-oriented format too!
So ed is capable of replacing C Preprocessor and even adds some features on top.

One more advantage is that there no longer are weird chars breaking everything.
When I see an apostrophe, my eye starts twitching.
C Preprocessor recognizes apostrophe as a char marker and reads the rest of the line verbatim.
Same goes for double quote and hash.
Special chars, forbidden magic.

In general, ed has this sloppiness of regex/substitutions.
\href{run:sed-ed}{And interactivity of a REPL (section interactive)} (well, to an extent.)
Perfect for text processing and document authoring.

\section*{Limitations} \label{limitations}

ed is stupid (I say lovingly.)
It has no file inclusion, for one.
So C Preprocessor’s \verb|#include| is no longer accessible.
I manage without it, because most of the files I include are easily hard-codeable.
But the mere inability to include arbitrary files is somewhat alarming.
\href{run:advanc-ed}{(Update: I actually managed to meta-programming-ize it!) (section self-calls)}

Another problem that I already got the taste of:
having arbitrary substitutions at the fingertips spoils me.
I might end up with some really otherworldly syntax without noticing.
And I wouldn’t be able to rollback to e.g. C Preprocessor to generate my posts.
But then, ed is so simple and more or less standard, so what can go wrong?

\paragraph{It did go wrong} \begin{quote}
Arch and Alpine package slightly different versions of ed.
Alpine version was breaking on line joining and variable substitution.
So I had to swap Alpine for Arch on the Gitlab CI.
I would have been able to stay on Alpine if I was able to debug what’s wrong with ed there.
But Gitlab (like any other CI platform?) doesn’t make it easy to debug things on CI.
\end{quote}

\section*{Should You Use ed As Site Generator?} \label{you-too}

No, not at all.
It’s a weird choice that’s only there because I’m having a new phase.
But still, it’s fun!
Try ed if you have too much free time and are bored out of your mind 😜


\par\noindent\rule{\textwidth}{0.4pt}
\href{https://creativecommons.org/licenses/by/4.0}{CC-BY 4.0} 2022-2026 by Artyom Bologov (aartaka,)
\href{https://codeberg.org/aartaka/pages/commit/a91befa}{with one commit remixing Claude-generated code}.
Any and all opinions listed here are my own and not representative of my employers; future, past and present.
\end{document}
