dotemacs

My Emacs configuration
git clone git://git.entf.net/dotemacs
Log | Files | Refs | LICENSE

ob-table.el (5300B)


      1 ;;; ob-table.el --- Support for Calling Babel Functions from Tables -*- lexical-binding: t; -*-
      2 
      3 ;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
      4 
      5 ;; Author: Eric Schulte
      6 ;; Keywords: literate programming, reproducible research
      7 ;; URL: https://orgmode.org
      8 
      9 ;; This file is part of GNU Emacs.
     10 
     11 ;; GNU Emacs is free software: you can redistribute it and/or modify
     12 ;; it under the terms of the GNU General Public License as published by
     13 ;; the Free Software Foundation, either version 3 of the License, or
     14 ;; (at your option) any later version.
     15 
     16 ;; GNU Emacs is distributed in the hope that it will be useful,
     17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
     18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     19 ;; GNU General Public License for more details.
     20 
     21 ;; You should have received a copy of the GNU General Public License
     22 ;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
     23 
     24 ;;; Commentary:
     25 
     26 ;; Should allow calling functions from Org tables using the function
     27 ;; `org-sbe' as so...
     28 
     29 ;; #+begin_src emacs-lisp :results silent
     30 ;;   (defun fibbd (n) (if (< n 2) 1 (+ (fibbd (- n 1)) (fibbd (- n 2)))))
     31 ;; #+end_src
     32 
     33 ;; #+name: fibbd
     34 ;; #+begin_src emacs-lisp :var n=2 :results silent
     35 ;; (fibbd n)
     36 ;; #+end_src
     37 
     38 ;; | original | fibbd  |
     39 ;; |----------+--------|
     40 ;; |        0 |        |
     41 ;; |        1 |        |
     42 ;; |        2 |        |
     43 ;; |        3 |        |
     44 ;; |        4 |        |
     45 ;; |        5 |        |
     46 ;; |        6 |        |
     47 ;; |        7 |        |
     48 ;; |        8 |        |
     49 ;; |        9 |        |
     50 ;; #+TBLFM: $2='(org-sbe "fibbd" (n $1))
     51 
     52 ;; NOTE: The quotation marks around the function name, 'fibbd' here,
     53 ;; are optional.
     54 
     55 ;;; Code:
     56 
     57 (require 'org-macs)
     58 (org-assert-version)
     59 
     60 (require 'ob-core)
     61 (require 'org-macs)
     62 
     63 (defun org-babel-table-truncate-at-newline (string)
     64   "Replace newline character with ellipses.
     65 If STRING ends in a newline character, then remove the newline
     66 character and replace it with ellipses."
     67   (if (and (stringp string) (string-match "[\n\r]\\(.\\)?" string))
     68       (concat (substring string 0 (match-beginning 0))
     69 	      (when (match-string 1 string) "..."))
     70     string))
     71 
     72 (defmacro org-sbe (source-block &rest variables)
     73   "Return the results of calling SOURCE-BLOCK with VARIABLES.
     74 
     75 Each element of VARIABLES should be a list of two elements: the
     76 first element is the name of the variable and second element is a
     77 string of its value.
     78 
     79 So this `org-sbe' construct
     80 
     81  (org-sbe \"source-block\" (n $2) (m 3))
     82 
     83 is the equivalent of the following source code block:
     84 
     85  #+begin_src emacs-lisp :var results=source-block(n=val_at_col_2, m=3) \\
     86      :results silent
     87  results
     88  #+end_src
     89 
     90 NOTE: The quotation marks around the function name,
     91 `source-block', are optional.
     92 
     93 NOTE: By default, string variable names are interpreted as
     94 references to source-code blocks, to force interpretation of a
     95 cell's value as a string, prefix the identifier a \"$\" (e.g.,
     96 \"$$2\" instead of \"$2\" or \"$@2$2\" instead of \"@2$2\").
     97 
     98 NOTE: It is also possible to pass header arguments to the code
     99 block.  In this case a table cell should hold the string value of
    100 the header argument which can then be passed before all variables
    101 as shown in the example below.
    102 
    103 | 1 | 2 | :file nothing.png | nothing.png |
    104 #+TBLFM: @1$4=\\='(org-sbe test-sbe $3 (x $1) (y $2))"
    105   (declare (debug (form form)))
    106   (let* ((header-args (if (stringp (car variables)) (car variables) ""))
    107 	 (variables (if (stringp (car variables)) (cdr variables) variables)))
    108     (let* (quote
    109 	   (variables
    110 	    (mapcar
    111 	     (lambda (var)
    112 	       ;; ensure that all cells prefixed with $'s are strings
    113 	       (cons (car var)
    114 		     (delq nil (mapcar
    115 			      (lambda (el)
    116 				(if (eq '$ el)
    117 				    (prog1 nil (setq quote t))
    118 				  (prog1
    119 				      (cond
    120 				       (quote (format "\"%s\"" el))
    121 				       ((stringp el) (org-no-properties el))
    122 				       (t el))
    123 				    (setq quote nil))))
    124 			      (cdr var)))))
    125 	     variables)))
    126       (unless (stringp source-block)
    127 	(setq source-block (symbol-name source-block)))
    128       `(let ((result
    129               (if ,(and source-block (> (length source-block) 0))
    130                   (let ((params
    131                          ',(org-babel-parse-header-arguments
    132                             (concat
    133                              ":var results="
    134                              source-block
    135                              "[" header-args "]"
    136                              "("
    137                              (mapconcat
    138                               (lambda (var-spec)
    139                                 (if (> (length (cdr var-spec)) 1)
    140                                     (format "%S='%S"
    141                                             (car var-spec)
    142                                             (mapcar #'read (cdr var-spec)))
    143                                   (format "%S=%s"
    144                                           (car var-spec) (cadr var-spec))))
    145                               variables ", ")
    146                              ")"))))
    147                     (org-babel-execute-src-block
    148                      nil (list "emacs-lisp" "results" params)
    149                      '((:results . "silent"))))
    150                 "")))
    151          (org-trim (if (stringp result) result (format "%S" result)))))))
    152 
    153 (provide 'ob-table)
    154 
    155 ;;; ob-table.el ends here