lips
is a set of quick-and-dirty utils designed for inverse
literate programming, i.e. generating documentation from source
code.
This documentation is generated from
its source by
lips
.
$ make install
It merely copies lips/*
to /usr/local/bin
. If you don't need them
all, feel free to pick only the ones you need.
We have a JavaScript file examples/say.js
. Its comments are
written in Markdown.
// ## Your First Program
// `say` is a function that says something
var say = function(something) {
// something goes to stdout
console.log(something);
};
// #+ignore just put words below, I'll hide them for you
// test it
say('hello world');
// #+endignore
Run the command below, which does 3 things:
- uncomment all comments in
say.js
- highlight the code block, and
- ignore the test block
$ uncomment.awk codeout="highlight.sh javascript" examples/say.js | ignore.awk
It outputs a markdown documentation:
## Your First Program
`say` is a function that says something
{% highlight javascript %}
var say = function(something) {
// something goes to stdout
console.log(something);
};
{% endhighlight %}
We have a main markdown file examples/main.md
:
hello world
===========
#+sh cat intro.md
#+sh uncomment.awk codeout="highlight.sh javascript" say.js | ignore.awk
Note that the special syntax #+sh
is not a markdown syntax; it
tells lips/sh.awk
that here is a command, please execute the command
and replace here with its output. This file contains two commands cat intro.md
and uncomment.awk say.js ...
.
intro.md
(it is also located under the folder examples
) looks like
this:
## Introduction
Programming is fun. In this article we are going to teach you how to
program in JavaScript.
Include them in examples/main.md
with one command:
$ sh.awk examples/main.md
It outputs:
hello world
===========
## Introduction
Programming is fun. In this article we are going to teach you how to
program in JavaScript.
## Your First Program
`say` is a function that says something
{% highlight javascript %}
var say = function(something) {
// something goes to stdout
console.log(something);
};
{% endhighlight %}
usage: block.awk name=NAME FILENAME
Print out a named block. A named block is a block between #+block NAME
and #+endblock
.
usage: fence.sh LANG CODEBLOCK
Wrap CODEBLOCK with triple-backtick syntax. It is
designed to be a helper for generating markdown documentation in
collaborate with uncomment.awk
.
usage: highlight.sh LANG CODEBLOCK
Wrap CODEBLOCK with {% highlight LANG %}
and {% endhighlight %}
. It is designed to be a helper for generating
markdown documentation in collaborate with uncomment.awk
.
usage: ignore.awk FILENAME
Like cat FILENAME
but ignore blocks between #+ignore
and
#+endignore
, and lines containing #+ignoreline
.
usage: sh.awk [shell="/bin/sh"] FILENAME
Pipe commands after the mark #+sh
to SHELL
, and replace each mark
and command with its output.
$ cat today
Today is #+sh date +%Y-%m-%d
$ sh.awk today
Today is 2021-08-02
usage: trim.awk FILENAME
Trim blank lines in FILENAME
usage: uncomment.awk [codeout] [comment="//"] FILENAME
Uncomment FILENAME
by simply removing the leading comment starter
in each comment line, and pipe code blocks (the non-comment lines) to
the command specified by codeout
.
You need to specify another comment starter when your source code is not
commented by //
.
Some principles:
- follow KISS
- utilize common UNIX tools such as
awk
,sed
,sh
- not exceed 128 LoC for each little program
LoC of each program:
fence.sh 23
highlight.sh 27
trim.awk 28
ignore.awk 34
block.awk 39
sh.awk 50
src.awk 76
uncomment.awk 77
total 354
Run tests:
sh run_test.sh
See LICENSE.