Skip to content

Latest commit

 

History

History
613 lines (495 loc) · 17.2 KB

lisp-babel.org

File metadata and controls

613 lines (495 loc) · 17.2 KB

lisp-babel

1 How to use this document

You should look at this document in its Org mode source form. The PDF rendering is useful to see the results of some of the export options, but the syntax of the source block is only seen in the source text.

2 Version information

(princ (concat (format "Emacs version: %s\n" (emacs-version))
               (format "org version: %s\n" (org-version))))
Emacs version: GNU Emacs 24.5.1 (x86_64-unknown-linux-gnu, GTK+ Version 3.10.8)
 of 2015-05-04 on dflt1w
org version: 8.3.2

3 using a table as input for a src block

3.1 simple example

We first create a table from a lisp list of lists. Each inner list will form a row in the resulting table. I already insert a header row with the names of three columns. A separator line can be obtained by putting the hline symbol into the resulting list.

(cons '(col1 col2 col3)
      (cons 'hline
            (loop for i from 5 to 15 collect `(,i ,(* i 5) ""))))
col1col2col3
525
630
735
840
945
1050
1155
1260
1365
1470
1575

We now can fill the third column by passing the table into the next source block. We force babel to treat the first row as table header by using the :colnames yes header argument. This also causes the result table to contain the headers (as long as the new table has the same number of columns as the original table)

Here I also demonstrate the use of the -n option that will export the code with line numbers.

(let (result)
  (dolist (row tbl result)
    (setf (nth 2 row) (* 2 (nth 1 row)))
    (setq result (cons row result)))
  (reverse result))
col1col2col3
52550
63060
73570
84080
94590
1050100
1155110
1260120
1365130
1470140
1575150

3.2 passing a sub-range

It is possible to specify a sub-range for the table that is handed over through :var. But currently it does not work well with the :colnames yes option, as the following example shows.

(let (result)
  (dolist (row tbl result)
    (setf (nth 2 row) (* 2 (nth 1 row)))
    (setq result (cons row result)))
  (reverse result))
735
84080
94590
1050100
1155110

3.3 Investigating how tables are passed to the src block

col1col2col3
10strtwo strings
20.5str22 strings
(pp tbl)
((10 "str" "two strings")
 (20.5 "str2" "2 strings"))

Note that the raw value output of the source block does not yield the same. It loses the string quotes of the single entries!

tbl

((10 str two strings) (20 str2 2 strings))

4 TODO using a list as input for a source block

  • item1
  • item2
    1. subitem2.1
    2. subitem2.2
  • item3
    • subitem3.1
  • item4

Let’s look at the resulting structure that is passed to a source block

(pp lst)

This is different from the current entry in the Manual (info:org#var), where it is said that only top level items are passed along. But this complete passing along of the structure opens nice and interesting ways of using lists. Need to ask whether this interface will remain stable.

One important point to clarify is, why is the returned structure not exactly the result of what the Org function org-list-to-lisp returns? Comparing with that output we see that the current handing over of a list by the :var argument is losing the outermost layer of information that describes whether the top level list is of the ordered, unordered, … type.

 (pp (save-excursion
	  (goto-char (point-min))
	  (unless (search-forward-regexp (concat  "#\\\+NAME: .*" lname) nil t)
	    (error "No list of this name found: %s" lname))
	  (forward-line 1)
	  (org-list-to-lisp)))

5 calling source blocks as a function

5.1 Chaining source block execution

I can have another piece of code implicitly called by using its name as an input variable in another code block. So, I could directly fill the third column of our initial example table without ever having to print out that table table. We can just pass into the next function a variable tbl and the name of the initial code block make-table1.

(let (result)
  (dolist (row tbl result)
    (setf (nth 2 row) (* 2 (nth 1 row)))
    (setq result (cons row result)))
  (reverse result))
col1col2col3
52550
63060
73570
84080
94590
1050100
1155110
1260120
1365130
1470140
1575150

5.2 simple call syntax using CALL

We first define a function in a named code block called mydouble. The variable x will be passed in by defining a header argument :var x

(* 2 x)

Now we can call this babel function by using the code block’s name mydouble from any place in the document. For example:

Another example where we pass in two variables x and y.

(/ x y)

Note that you can/must pass additional header arguments to the call. The ones added at the end influence the final result (e.g. putting it into a drawer), while the ones added in [] are evaluated in the context of the original definition (e.g whether to capture the output or return a value).

Another alternative calling syntax

5.3 calling a source block function from elisp

This function is also used for table formulas

(org-sbe mydivide (x 10) (y 3))
(princ (concat s1 " " s2))
(princ (org-sbe srcRepeatStrings (s1 $"hello") (s2 $"world")))
(org-babel-execute-src-block nil
               		     '("emacs-lisp" "results"
               		       ((:var . "results=mydivide[](x=30, y=5)")))
                    	     '((:results . "silent")))
(org-babel-execute-src-block nil
                         	   '("emacs-lisp" "(princ (format \"%s haahahaa\n\"results))"
                         	     ((:var . "results=mydivide[](x=30, y=5)")))
                           '((:results . "silent")))

5.4 Naming an output table produced by a CALL

If the called function produces an output table that one wants to use in subsequent function calls or in table formulas (using the remote keyword) one can give the CALL a name utilizing the syntax used for other org elements:

col1col2col3
525
630
735
840
945
1050
1155
1260
1365
1470
1575

6 Inline src calls

Basic inline source calls:

  • src_emacs-lisp[:var tbl=table1]{(nth 0 (nth (- (length tbl) 1) tbl))} {{{results(15)}}}
  • src_emacs-lisp[:results value]{(org-table-get-remote-range “table1” “@>$1” )} {{{results(15)}}}

Note, that the result gets wrapped into an ORG MACRO syntax using three curly brackets. This allows org to replace the results of the evaluation if the inline call is executed multiple times.

If one uses the :results raw option, the results are placed “as is” into the buffer, so multiple executions will lead to multiple insertions of the result.

src_emacs-lisp[:results raw]{(org-table-get-remote-range “table1” “@>$1” )} 15

Inline source code is only supposed to create one-line results. If you write code that generates multiple result lines, an error is raised: Inline error: multiline result cannot be used

src_emacs-lisp[:results value]{(princ “hahha\nyesyesyes” )}

7 Defining buffer wide variables for src blocks

One can use a verbatim block like this. I define a named block myvar and I pass it into the variable s of the following code block. This lends itself to some nice ideas of inserting test in form of templates with some custom variable replacement

world
(concat "hello " s)
hello world

8 Using a :post function for post-formatting and executing generated tables

Often I produce multiple tables from a source block (e.g. printing several pandas data frames). These tables do not get aligned in the org document after the execution of the code block (even though they will get aligned upon exporting the document). Also, I may want to have table calculations using #+TBLFM lines executed, instead of manually having to execute them in the resulting tables.

The following function can be used in a :post argument for getting all tables in the output aligned and their TBLFM instructions executed, as shown further below

(with-temp-buffer
  (erase-buffer)
  (cl-assert text nil "PostAlignTables received nil instead of text ")
  (insert text)
  (beginning-of-buffer)
  (org-mode)
  (while
      (search-forward-regexp org-table-any-line-regexp nil t)
    (org-table-align)
    (org-table-recalculate 'iterate)
    (goto-char (org-table-end)))
  (buffer-string))
|  5 | 22222 |
|  0 |       |
| 12 |    45 |
|----+-------|
| 17 |       |
#+TBLFM:@>$1=vsum(@1..@-1)

|  1 | 22222 |
|  0 |       |
| 12 |    45 |

Example without using the :post function:

(princ
 (concat
  "#+CAPTION: Test1\n"
  "|A|B|C|\n"
  "|---\n"
  "|1|20|300|\n"
  "|200|30|4|\n"
  "|---\n"
  "||||\n"
  "#+TBLFM: @>$1..@>$3=vsum(@I..@II)\n"
  "\n#+CAPTION: Test2\n"
  "|A|B|C|\n"
  "|---\n"
  "|1|20|300|\n"
  "|200|30|4|\n"
  ))
ABC
120300
200304
ABC
120300
200304

The same example with the :post function:

(princ
 (concat
  "#+CAPTION: Test1\n"
  "|A|B|C|\n"
  "|---\n"
  "|1|20|300|\n"
  "|200|30|4|\n"
  "|---\n"
  "||||\n"
  "#+TBLFM: @>$1..@>$3=vsum(@I..@II)\n"
  "\n#+CAPTION: Test2\n"
  "|A|B|C|\n"
  "|---\n"
  "|1|20|300|\n"
  "|200|30|4|\n"
  ))
ABC
120300
200304
20150304
ABC
120300
200304

9 Library of babel

The “Library of Babel” feature provides a kind of primitive function library system for org files. It allows running source blocks that have been added to it in every org file. The library is implemented as an association list with the source block names as the keys. It is stored in the org-babel-library-of-babel variable.

Execute the following source block to load the source code blocks of the test file lib-of-babel-test.org into the library of babel.

For example, the post table alignment function of the last section is a useful generic function. I renamed it in the lib-of-babel-test.org file to srcPostAlignTablesLIB to demonstrate that it indeed is the definition from that file.

I can call the function like any normally defined named source code block which produces:

But more interesting for this example, I can also use it in the :post block:

(princ text)
A22222
B
C45
22267
X3
Y4
Z5
12

Note: Originally, I thought I could have the babel library as a local variable by executing the org-babel-lob-ingest on a file local variable in the local variable section of the file (using first make-local-variable and the using the ingest). But it turns out that during the ingest the buffer associated with the sourced file is active, so the local variable in this buffer remains unset. This is regrettable, because this means that the library of babel is always global. One could set the org-babel-library-of-babel variable directly to the final value instead of using the ingest function, but this would break the abstraction.