UP | HOME

Support via Liberapay

Emacs Lisp Source Code Blocks in Babel

Babel support for Emacs Lisp

Introduction

Emacs Lisp is an interpreted dialect of the Lisp programming language with extensions to support text editing. Babel and Org mode are both written in Emacs Lisp.

Requirements and Setup

If your Emacs is up and running, then Emacs Lisp is installed, configured, and running. Emacs Lisp source blocks are activated by default.

Babel Features for Emacs Lisp Source Code Blocks

Header Arguments

:lexical
A switch for evaluation scoping; "yes" or t indicates lexical scoping, "no" or NIL indicates dynamic scoping. Default: "no".

Sessions

Emacs is an Emacs Lisp session.

Examples of Use

The ability to evaluate Emacs Lisp code in the context of your Emacs session is wonderful and scary at the same time. The following examples scratch the surface of this enticing practice. Caveat emptor!

Hello World!

Here is the obligatory Hello World! example. Note that it uses the elisp source language alias for emacs-lisp.

In the Org mode buffer:

#+name: emacs-lisp-hello-world
#+begin_src elisp :exports both 
(princ "Hello World!")
#+end_src

HTML export of the source block:

(princ "Hello World!")

HTML export of the results:

Hello World!

Tangle and Export Concurrently

This bit of fanciness with running code in header arguments is taken from Eric Schulte's org-scraps.

One block in the Org mode buffer to tangle:

#+BEGIN_SRC emacs-lisp :tangle yes
  (message "I am tangled")
#+END_SRC

HTML export of the source block:

(message "I am tangled")

HTML export of the results:

I am tangled

Another block in the Org mode buffer to export:

#+BEGIN_SRC emacs-lisp :exports results :var foo=(org-babel-tangle)
  (message "I just tangled %S during export." foo)
#+END_SRC

HTML export of the results:

I just tangled ("ob-doc-elisp.el") during export.

Emacs-Lisp Printing with Output to String

Another example from Eric Schulte's org-scraps.

The first source block packages the results as a string.

Source block in the Org mode buffer:

#+name: emacs-lisp-print-to-string
#+begin_src emacs-lisp :results output
  (let ((dog (sqrt 2))
        (cat 7))
    (print (format "%s %f" "Dog: " (eval dog)))
    (print (format "%s %d" "Cat: " (eval cat)) nil)
    (print "Fish."))
#+end_src

HTML export of the source block:

(let ((dog (sqrt 2))
      (cat 7))
  (print (format "%s %f" "Dog: " (eval dog)))
  (print (format "%s %d" "Cat: " (eval cat)) nil)
  (print "Fish."))

HTML export of the result:


"Dog:  1.414214"

"Cat:  7"

"Fish."

The second source block returns a table.

Second source block in the Org mode buffer:

#+name: emacs-lisp-print-to-table
#+begin_src emacs-lisp
  (let ((dog (sqrt 2))
        (cat 7))
    `((dog ,dog)
      (cat ,cat)
      (fish)))
#+end_src

HTML export of the source block:

(let ((dog (sqrt 2))
      (cat 7))
  `((dog ,dog)
    (cat ,cat)
    (fish)))

HTML export of the results:

dog 1.4142135623730951
cat 7
fish  

Executing Emacs-Lisp on Export

This example from Eric Schulte's org-scraps shows how to evaluate Emacs Lisp code during export.

Here is the source block in the Org mode buffer:

#+name: eric-error
#+begin_src emacs-lisp
  (error "eric")
#+end_src

Enabling HTML export of the source block with :exports code or :exports both aborts export with an error.

HTML export of the results when the source block isn't exported:

(error "eric")

Scalar Emacs Lisp Results

This example is from Eric Schulte's org-scraps.

Here is the source block in the Org mode buffer:

#+name: emacs-lisp-scalar
#+begin_src emacs-lisp :results scalar :exports both
  '(1 2 3)
#+end_src

HTML export of the source block:

'(1 2 3)

HTML export of the results:

(1 2 3)

Convert Results to All String

This example from Eric Schulte's org scraps shows one way to ensure that all elements in a table are rendered as strings.

Given the following table:

1 2 3 4
a b c d

And given this Emacs Lisp source block:

#+name: all-to-string
#+begin_src emacs-lisp :var tbl='()
  (defun all-to-string (tbl)
    (if (listp tbl)
        (mapcar #'all-to-string tbl)
      (if (stringp tbl)
          tbl
        (format "%s" tbl))))
  (all-to-string tbl)
#+end_src
(defun all-to-string (tbl)
  (if (listp tbl)
      (mapcar #'all-to-string tbl)
    (if (stringp tbl)
        tbl
      (format "%s" tbl))))
(all-to-string tbl)

Then a reference to hetero-table indicates a mixture of strings and non-strings:

#+name: do-not-pass-to-all-string
#+begin_src emacs-lisp :var tbl=hetero-table
  (mapcar (lambda (row) (mapcar (lambda (cell) (stringp cell)) row)) tbl)
#+end_src
(mapcar (lambda (row) (mapcar (lambda (cell) (stringp cell)) row)) tbl)
nil nil nil nil
t t t t

But passing hetero-table through all-to-string in the header argument ensures that all the elements are strings:

#+name: pass-to-all-to-string
#+begin_src emacs-lisp :var tbl=all-to-string(hetero-table)
  (mapcar (lambda (row) (mapcar (lambda (cell) (stringp cell)) row)) tbl)
#+end_src
(mapcar (lambda (row) (mapcar (lambda (cell) (stringp cell)) row)) tbl)
t t t t
t t t t

Tangling with Variables

If you are tangling an elisp source block which accepts a :var variable, there are some issues to consider. (note)

Let's say you have an e-lisp source code block something like this. (The <<lex_check>> is a noweb fragment; see below):

#+begin_src elisp :tangle worgx.el
;;; ...  -*- lexical-binding: t -*-

(require 'cl-lib)

(cl-defstruct struct
  (name nil))

(let ((worg-x "Bill"))
  <<lex_check>>
  (let ((str (make-struct :name worg-x)))
    (message (struct-name str))))
#+end_src

But now you decide to pass the value of the worg-x variable using a :var construct on the header line, something like this:

#+begin_src elisp :var worg-x-value="Bill" :tangle worgx2.el
;;; ...  -*- lexical-binding: t -*-

(require 'cl-lib)

(cl-defstruct struct
  (name nil))

(let ((worg-x worg-x-value))
  <<lex_check>>
  (let ((str (make-struct :name worg-x)))
    (message (struct-name str))))
#+end_src

Now, the tangled file will look something like this

(let ((worg-x-value '"Bill"))
;;; ...  -*- lexical-binding: t -*-

(require 'cl-lib)

(cl-defstruct struct
  (name nil))

(let ((worg-x worg-x-value))
  ;; check to make sure lexical-binding has been enabled...

  (defun lex-indirect ()
    (let ((worg-x "Jill"))
      (ignore worg-x)
      (if (fboundp 'lex-check)
          (lex-check))))

  (defun lex-check ()
    worg-x)

  (if (and (fboundp 'lex-check) (fboundp 'lex-indirect))
      (cl-assert (equal (lex-check) (lex-indirect))))

  (let ((str (make-struct :name worg-x)))
    (message (struct-name str))))
)

Evaluating this code results in

Assertion failed: (equal (lex-check) (lex-indirect))

The code had expected to have lexical binding enabled, but it is no longer enabled, as the first line of the file no longer contains the magical -*- lexical-binding: t -*- to enable lexical binding: org-mode has embedded all the code in a let construct in order to pass the value of the variable worg-x-value, and that includes the directive enabling lexical binding.

To keep the variable, but make sure lexical binding is enabled, we might do something like this

#+begin_src sh :eval never-export :results none
(echo ';;; --- -*- lexical-binding: t -*-' && cat worgx2.el) > worgx2l.el
#+end_src

Now all is well again. Or, is it?

#+begin_src sh :results org :eval never-export
  (
      echo run worgx2l.el
      echo
      emacs --batch -l worgx2l.el
      echo && echo
      echo now, byte compile worgx2l.el
      echo
      emacs --batch -f batch-byte-compile worgx2l.el
      echo && echo
      echo and, run worgx2l.elc
      echo
      emacs --batch -l worgx2l.elc
  ) 2>&1
#+END_SRC
run worgx2l.el

Bill


now, byte compile worgx2l.el


In toplevel form:
worgx2l.el:7:15: Warning: reference to free variable ‘struct’

In end of data:
worgx2l.el:26:15: Warning: the function ‘struct-name’ is not known to be defined.
worgx2l.el:25:15: Warning: the function ‘make-struct’ is not known to be defined.
worgx2l.el:8:4: Warning: the function ‘name’ is not known to be defined.
worgx2l.el:7:2: Warning: the function ‘cl-defstruct’ might not be defined at runtime.


and, run worgx2l.elc

Symbol’s value as variable is void: struct

Error: void-variable (struct)
  byte-code("\301\302!\210\303\10\304\305!\"\210\306\307\310\"\210\306\311\312\313\314\"\"\210\315\311!\203,\0\315\307!\203,\0\316\311 \307 \232!\210\317\320\314\"\321\322\2!!\210\207" [struct require cl-lib cl-defstruct name nil defalias lex-indirect #f(compiled-function () #<bytecode -0x30e31725c738c20>) lex-check make-closure #f(compiled-function () #<bytecode 0xaffa5f1a9bb9>) "Bill" fboundp cl-assert make-struct :name message struct-name] 5)
  command-line-1(("-l" "worgx2l.elc"))
  command-line()
  normal-top-level()

We are using lexical binding, but there is still some problem.

Here's why: As a result of passing the variable worg-x-value by embedding the code of the source block in a let construct, the (require 'cl-lib) (in this example) is no longer at the top level of the resulting source. This means that when the source is byte compiled, the byte compiler will not learn about any macros defined in, in this case, cl-lib, which can cause warnings or even errors. In the case of the above source, loading the byte compiled file results in an error.

We can deal with these errors when byte compiling by surrounding the (require 'cl-lib) statement with eval-and-compile, such as

#+begin_src elisp :var worg-x-value="Bill" :tangle worgx3.el
  ;;; ...  -*- lexical-binding: t -*-

  (eval-and-compile
    (require 'cl-lib))

  (cl-defstruct struct
    (name nil))

  (let ((worg-x worg-x-value))
    <<lex_check>>
    (let ((str (make-struct :name worg-x)))
      (message (struct-name str))))
#+end_src
#+begin_src sh :eval never-export :results none
(echo ';;; --- -*- lexical-binding: t -*-' && cat worgx3.el) > worgx3l.el
#+end_src
#+begin_src sh :eval never-export :results org
  (
      echo run worgx3l.el
      echo
      emacs --batch -l worgx3l.el
      echo && echo
      echo now, byte compile worgx3l.el
      echo
      emacs --batch -f batch-byte-compile worgx3l.el
      echo && echo
      echo and, run worgx3l.elc
      echo
      emacs --batch -l worgx3l.elc
  ) 2>&1
#+END_SRC
run worgx3l.el

Bill


now, byte compile worgx3l.el



and, run worgx3l.elc

Bill

All good.

However …

There is another way around both problems, falling back on an old computer science saying (often attributed to Butler Lampson) that there is no problem in computer science that can't be solved by using an extra level of indirection.

The idea is to use <<noweb>> syntax to pull into the source code block of interest the results of a new source code block which

  • receives the value from a header :var argument
  • produces that value as its result
  • is not itself tangled (just supplies a value to a source code block that is tangled)
#+begin_src elisp :var x="Bill"
  (format "\"%s\"" x)
#+end_src

Then, the results of that function are brought into the source block of interest using <<noweb()>>, i.e., the version of <<noweb> that inserts the results of the evaluation of the named source block, rather than the contents of the source block itself.

#+begin_src elisp :tangle worgx4.el
  ;;; ...  -*- lexical-binding: t -*-

  (require 'cl-lib)

  (cl-defstruct struct
    (name nil))

  (let ((worg-x <<intervar()>>))
    <<lex_check>>
    (let ((str (make-struct :name worg-x)))
      (message (struct-name str))))
#+end_src

If the above two blocks have been evaluated, evaluating the following block will show no errors.

#+begin_src sh :results verbatim :eval never-export
  (
      echo
      echo compile worgx4.el
      emacs --batch -f batch-byte-compile worgx4.el
      echo
      echo load worgx4.elc
      emacs --batch -l worgx4.elc
      echo
      echo done
  ) 2>&1
#+end_src

compile worgx4.el

load worgx4.elc
Bill

done

This method is maybe more cumbersome, but taste is intensely personal. An advantage of this method is that there is no need for an extra step to replace the header enabling lexical binding, as in this case, with no :var in the header, the source code block is tangled with the header still in the first line.

Notes

  • Setup

    By the way, the node for this section starts with the following

    #+property: header-args :noweb no-export :lexical yes
    #+property: header-args:sh :results verbatim :eval never
    #+options: ^:{}
    

    Also, the elisp and shell source blocks have mostly been processed to wrap them inside org source blocks, to expose the #+begin_src lines.

  • lex_check

    This is a <<noweb>> fragment, named <<lex_check>>, we use for expository purposes to check whether a code block is running with lexical binding (rather than dynamic binding).

    #+begin_src elisp
    ;; check to make sure lexical-binding has been enabled...
    
    (defun lex-indirect ()
      (let ((worg-x "Jill"))
        (ignore worg-x)
        (if (fboundp 'lex-check)
            (lex-check))))
    
    (defun lex-check ()
      worg-x)
    
    (if (and (fboundp 'lex-check) (fboundp 'lex-indirect))
        (cl-assert (equal (lex-check) (lex-indirect))))
    
    #+end_src
    

Documentation from the orgmode.org/worg/ website (either in its HTML format or in its Org format) is licensed under the GNU Free Documentation License version 1.3 or later. The code examples and css stylesheets are licensed under the GNU General Public License v3 or later.