Skip to content

Latest commit

 

History

History
274 lines (195 loc) · 4.99 KB

org-tangle.md

File metadata and controls

274 lines (195 loc) · 4.99 KB

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

Usage

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

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

    emacs24-nox
  • 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.