tt ('tangle to')
Synopsis
Syntax
Example 1
Example 2
Synopsis
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
- Destination files are templates for the 'tangled' (computer-friendly) source code. They contain special sequences marking destinations: for example,
<<top>>
,<<middle>>
and<<bottom>>
. - Source input, in turn, contains special sequences referencing these destinations:
-> top
,-> middle
and-> bottom
. For instance, all code following-> top
will be inserted at any location marked by<<top>>
in the destination files.
Syntax
Source input
Source files contain code lines and documentation lines, formatted accordingly: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 files
The files given as command-line arguments to tt, in this case scripts.ahk, contain destination lines and plain text lines.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.
Example 1: Pulling separate modules into a single file
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') |
Example 2: Creating source code from literate program
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:
- → main.options
- → main, declarations
- → program.c
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