org-tangle
takes one or several Org files as arguments and produces programs
org-tangle [options] file1.org [file2.org ...]
Options:
-E EMACS | Specify the Emacs executable. Default value is ‘emacs24-nox’ |
-O OPTIONS | Specify the options to pass to Emacs. Default value is ‘-Q –batch’ |
-q | Enable quick expansion of noweb references |
(see variable org-babel-use-quick-and-dirty-noweb-expansion). | |
-L ORGDIR | Specify an alternate directory for Org libs. |
-l lang1,lang2 | List of languages which can be evaluated in Org buffers. |
By default, only emacs-lisp is loaded | |
(see variable org-babel-load-languages) | |
-V | Show version and exit |
DIR=`pwd`
FILES=""
ORGDIR="/path/to/alternate/org-mode"
QUICK_EXPANSION=nil
EMACS=<<emacs>>
EMACS_OPTS="-Q --batch"
VERSION=0.1
<<emacs>>
=
emacs
read -d '' help_string <<"EOF"
Usage: <<usage>>
<<format-options(toptions,fmt="%-15s %s")>>
EOF
help () {
echo -ne "$help_string\n"
}
Let’s deal with command line options
while getopts "hE:O:L:l:qV" option "$@"; do
case $option in
h) help && exit 0 ;;
E) EMACS="$OPTARG" ;;
O) EMACS_OPTS="$OPTARG" ;;
q) QUICK_EXPANSION=t ;;
l) LANGUAGES="$OPTARG" ;;
L) ORGDIR="$OPTARG" ;;
V) echo "$(basename $0) $VERSION" && exit 0 ;;
esac
done ; shift $((OPTIND -1))
We need at least one file as an argument
[ "$1" ] || { help && exit 1; }
Wrap each argument in the code required to call tangle on it
for i in $@; do
FILES="$FILES \"$i\""
done
Create a temporary file
out=$(mktemp)
Now, execute emacs…
$EMACS ${EMACS_OPTS} --eval "(progn
<<escape-quotes(elisp-code)>>)"
…saving its output to a temporary file…
>${out} 2>&1
…and its return value.
ret=$?
If things went fine, display the number of tangled blocs
if [ ${ret} -eq 0 ]; then
grep -i tangled ${out}
Otherwise, display the whole output for the user to further investigate
else
cat ${out}
fi
Finally, exit with the same value as Emacs
exit ${ret}
When ORGDIR
actually exists, load Org libraries from this directory. Otherwise, we’ll use the ones that ship with Emacs or were installed using package.el
(package-initialize)
(when (file-accessible-directory-p "$ORGDIR")
(add-to-list 'load-path (expand-file-name "$ORGDIR/lisp/"))
(add-to-list 'load-path (expand-file-name "$ORGDIR/contrib/lisp/" t)))
Require Org libs
(require 'org)
(require 'ob)
(require 'ob-tangle)
Set org-babel-use-quick-and-dirty-noweb-expansion
to the value of QUICK_EXPANSION
(setq org-babel-use-quick-and-dirty-noweb-expansion ${QUICK_EXPANSION})
Do not require confirmation before evaluating code blocks
(setq org-confirm-babel-evaluate nil)
Load the languages specified via the -l
option, if any
(unless (equal "$LANGUAGES" "")
(org-babel-do-load-languages
'org-babel-load-languages
(mapcar
(lambda (str) (cons (make-symbol str) t))
(split-string "$LANGUAGES" ","))))
For each file in FILES
…
(mapc (lambda (file)
<<elisp-func>>) '($FILES))
- open it within Emacs;
(find-file (expand-file-name file "$DIR"))
- tangle it;
(org-babel-tangle)
- then close it.
(kill-buffer)
<<escape-quotes>>
=
(save-match-data
(replace-regexp-in-string "\"" "\\\\\"" str-val))
Used to escape the quotes within the elisp code before embedding it into the shell code, in order to preserve readability.
<<format-options>>
=
(mapconcat
(lambda (row)
(format fmt (car row) (cadr row))) table "\n")
Used to format the options table.