Skip to content

Latest commit

 

History

History
225 lines (197 loc) · 5.52 KB

org-tangle.org

File metadata and controls

225 lines (197 loc) · 5.52 KB

org-tangle

org-tangle takes one or several Org files as arguments and produces programs

Usage

org-tangle [options] file1.org [file2.org ...]

Options:

-E EMACSSpecify the Emacs executable. Default value is ‘emacs24-nox’
-O OPTIONSSpecify the options to pass to Emacs. Default value is ‘-Q –batch’
-qEnable quick expansion of noweb references
(see variable org-babel-use-quick-and-dirty-noweb-expansion).
-L ORGDIRSpecify an alternate directory for Org libs.
-l lang1,lang2List of languages which can be evaluated in Org buffers.
By default, only emacs-lisp is loaded
(see variable org-babel-load-languages)
-VShow version and exit

Source code

Shell code

Initial variables

DIR=`pwd`
FILES=""
ORGDIR="/path/to/alternate/org-mode"
QUICK_EXPANSION=nil
EMACS=<<emacs>>
EMACS_OPTS="-Q --batch"
VERSION=0.1

<<emacs>> =

emacs

Help function

read -d '' help_string <<"EOF"
Usage: <<usage>>

<<format-options(toptions,fmt="%-15s %s")>>
EOF

help () {
  echo -ne "$help_string\n"
}

Main part

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}

Elisp code

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)
        

Utility functions

<<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.