Subtext, a layered document preperation system

This repo contains the source of my groff-aesthetic document preparator subtext. It's unique in that it's an awk(1p) script that compiles a source file to a shell script that you can pipe to sh(1p).

Doing things in this multi-layered way allows me to

so I can truly write-once, run anywhere (or whatever the kids are saying these days). Plus, it looks kinda like roff(1) without having to remember all the arcane two-letter requests and macros.

Quickstart

An easy and quick way to start with subtext is to build this README:

make readme
Of course, I'd recommend reading readme.st in this repo to get a feel for the syntax as well. I've tried to use all the ways to inject control codes to illustrate it.

However, this quick start is not really a good explanation of what's going on. For that, keep reading.

The layers of subtext, the subtextual layers

There are three main layers of subtext: the awk layer, shell layer, and, for lack of something better to call it, the text layer. These layers don't really reflect the order of expansions, but rather how I think they feel to the user and how they're reflected in syntax. subtext is inherently a line-based markup language, and each of these layers has its own line marker.

Awk layer: %

The first thing that happens to any subtext source file is a pass through subtext.awk. While this awk script passes most things through to the next layers, there are two special directives at this layer you can use:

%
Comment the current line. % only works at the start of a line for comments.
%so FILE
Insert FILE verbatim at the line where this directive appears. FILE is searched in $ST_SOPATH, which by default is the current directory.

I went ahead and reserved %-lines for future directives that need to be done at awk-time.

Shell layer: #

So what does subtext do? It takes an input file or stream and converts it to a shell script which you can then pipe through sh(1). But it doesn't just do that. subtext also outputs various functions and variables and what-not to set up the environment in which the source document is expanded. Starting a line with # puts the rest of the line in the code part, enabling you to set a title, say, with or define a function for a commonly-used thing in your file. For this README, I've written #subtext()(code subtext) so I save about five characters every time.

Text layer: .

The "text layer" of subtext is actually expanded to a shell here-doc so that you can use stuff like $(...) to call shell functions. But don't worry – I've made it easier to not shoot yourself in the foot. One $ is changed to \$ in the expansion, and more than one $ is changed to one less. So $$$ becomes $$, etc. if you really want to put the process number in your output. Oh, and ` are all escaped. Those were a bad idea from go.

In addition, lines beginning with . expand to $(...), and lines beginning with ..COMMAND [ARGS] expand to $(COMMAND ARGS << .. and close the here-doc with .. on a line by itself.

You can add the << END-MARKER yourself if you want to specify your own end-marker.

Basically, this means you can write

.h1 My cool article

Here is a cool article.
It is
.i really
cool.

Here's what someone said about it:

..blockquote cite="A fan"
Wow, what a cool article!
..

The above translates to

My cool article

Here is a cool article. It is really cool.

Here's what someone said about it:

Wow, what a cool article!

Since this README was generated from subtext source, look at readme.st to get a better feel for the syntax.

Using subtext

todo

Contributing

Send me an email or whatever :) This project is licensed under the BSD-3 license. See COPYING for details.