Synopsis
Syntax
Example 1
Example 2
tt [-cCODE_PREFIX] [-dDOC_PREFIX] [-oOUT_PREFIX] destinations [...]
tt is a tool for source code organization and/or literate programming, which takes source code organized in a human-friendly manner and 'tangles' it into source code organized in a computer-friendly manner.
It takes any number of destination files as command-line arguments and source input on the standard input -- for example:
$ tt computerfriendly.c < humanfriendly.c
<<top>>
, <<middle>>
and <<bottom>>
.-> top
, -> middle
and -> bottom
. For instance, all code following -> top
will be inserted at any location marked by <<top>>
in the destination files.code line ::= CODE_PREFIX anything
documentation line ::= DOC_PREFIX anything [reference]
reference ::= "->" [whitespace] identifier [whitespace]
identifier ::= not whitespace
The default value of CODE_PREFIX is ' ' (four spaces), while DOC_PREFIX, by default, is empty.
Documentation lines containing references cause all subsequent code lines to be
tangled to the corresponding identifier(s) in destination files (until the next documentation line containing a reference).
destination line ::= [indentation] "<<" identifier ">>"
plain text line ::= anything
indentation ::= " " [indentation]
Any indentation preceding an identifier will be preserved when the code lines from the source input are inserted.
Assuming the files
plugins/nerdtree.vim |
plugins/vimtex.vim |
vimrc |
" -> plugins |
" -> plugins |
call plug#begin('~/.vim/plug') |
then the shell command
$ tt -d\" -c -o$HOME/. vimrc < plugins/nerdtree.vim < plugins/vimtex.vim
would create the file $HOME/.vimrc with the following contents:
$HOME/.vimrc |
call plug#begin('~/.vim/plug') |
tt is also well-suited for more traditional literate programming, and its default options work especially well with Markdown syntax.
It differs, however, from most other literate programming tools in that it doesn't resolve references within the same file. If this is desired, then multiple passes are required.
Assuming the files
program.markdown |
program.c |
# My program -> program.c |
<<program.c>> |
then the shell commands
$ mkdir 1 2 out
$ tt -d"#" -o1/ program.markdown < program.markdown
$ tt -d"#" -o2/ program.markdown < 1/program.markdown
$ tt -d"#" -oout/ program.c < 2/program.markdown
would create the file out/program.c with the following contents:
out/program.c |
char *line; |
Three separate passes are required, because there are, in total, three re-locations of source code:
This could conceivably be automated with a simple shell script:
#!/bin/sh
mkdir tmp out
file=program.markdown
i=0
cp $file tmp/$i$file
while grep '^ *<<[^\s]>>$' tmp/$i$file > /dev/null; do
tt -d"#" -otmp/$((++i)) $file < tmp/$((i-1))$file
done
tt -d"#" -oout/ program.c < $i$file