forked from mirrors/org-mode
A "functional-style" source block is one in which the name is followed immediately by a parenthesised argument. An example is the following "function", which generates n uniform random numbers: \#+srcname: rand(n) \#+begin_src R runif(n) \#+end_src With these changes, such source blocks are passed over to the export machinery in the following form: \#+begin_src org-babel-lob <function-def-keyword> rand(n): \#+end_src \#+begin_src R <switches> <indent>runif(n) \#+end_src where <function-def-keyword> is the value of org-babel-function-def-export-keyword, which defaults to "function", <switches> are the src block switches that belonged to the original block, and <indent> is the whitespace indent of the function body, the width of which is determined by org-babel-function-def-export-indent. org-babel-lob is a simple major mode responsible for fontification of the blocks corresponding to the function definition line (as opposed to the function body).
203 lines
7.7 KiB
EmacsLisp
203 lines
7.7 KiB
EmacsLisp
;;; org-babel-exp.el --- Exportation of org-babel source blocks
|
|
|
|
;; Copyright (C) 2009 Eric Schulte, Dan Davison
|
|
|
|
;; Author: Eric Schulte, Dan Davison
|
|
;; Keywords: literate programming, reproducible research
|
|
;; Homepage: http://orgmode.org
|
|
;; Version: 0.01
|
|
|
|
;;; License:
|
|
|
|
;; This program is free software; you can redistribute it and/or modify
|
|
;; it under the terms of the GNU General Public License as published by
|
|
;; the Free Software Foundation; either version 3, or (at your option)
|
|
;; any later version.
|
|
;;
|
|
;; This program is distributed in the hope that it will be useful,
|
|
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
;; GNU General Public License for more details.
|
|
;;
|
|
;; You should have received a copy of the GNU General Public License
|
|
;; along with GNU Emacs; see the file COPYING. If not, write to the
|
|
;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
;; Boston, MA 02110-1301, USA.
|
|
|
|
;;; Commentary:
|
|
|
|
;; for more information see the comments in org-babel.el
|
|
|
|
;;; Code:
|
|
(require 'org-babel)
|
|
(require 'org-exp-blocks)
|
|
(org-export-blocks-add-block '(src org-babel-exp-src-blocks nil))
|
|
(add-to-list 'org-export-interblocks '(src org-babel-exp-inline-src-blocks))
|
|
(add-to-list 'org-export-interblocks '(lob org-babel-exp-lob-one-liners))
|
|
|
|
(defvar org-babel-function-def-export-keyword "function"
|
|
"When exporting a source block function, this keyword will
|
|
appear in the exported version in the place of #+srcname:. A
|
|
source block is considered to be a source block function if the
|
|
srcname is present and is followed by a parenthesised argument
|
|
list. The parentheses may be empty or contain whitespace. An
|
|
example is the following which generates n random
|
|
(uniform) numbers.
|
|
|
|
#+srcname: rand(n)
|
|
#+begin_src R
|
|
runif(n)
|
|
#+end_src
|
|
")
|
|
|
|
(defvar org-babel-function-def-export-indent 4
|
|
"When exporting a source block function, the block contents
|
|
will be indented by this many characters. See
|
|
`org-babel-function-def-export-name' for the definition of a
|
|
source block function.")
|
|
|
|
(defun org-babel-exp-src-blocks (body &rest headers)
|
|
"Process src block for export. Depending on the 'export'
|
|
headers argument in replace the source code block with...
|
|
|
|
both ---- display the code and the results
|
|
|
|
code ---- the default, display the code inside the block but do
|
|
not process
|
|
|
|
results - just like none only the block is run on export ensuring
|
|
that it's results are present in the org-mode buffer
|
|
|
|
none ----- do not display either code or results upon export"
|
|
(interactive)
|
|
(message "org-babel-exp processing...")
|
|
(let ((info (save-excursion
|
|
(if (re-search-backward org-babel-src-block-regexp nil t)
|
|
(org-babel-get-src-block-info)
|
|
(error "Failed to find src block.")))))
|
|
(org-babel-exp-do-export info 'block)))
|
|
|
|
(defun org-babel-exp-inline-src-blocks (start end)
|
|
"Process inline src blocks between START and END for export.
|
|
See `org-babel-exp-src-blocks' for export options, currently the
|
|
options and are taken from `org-babel-defualt-inline-header-args'."
|
|
(interactive)
|
|
(save-excursion
|
|
(goto-char start)
|
|
(while (and (< (point) end)
|
|
(re-search-forward org-babel-inline-src-block-regexp end t))
|
|
(let* ((info (save-match-data (org-babel-parse-inline-src-block-match)))
|
|
(replacement (save-match-data
|
|
(org-babel-exp-do-export info 'inline))))
|
|
(setq end (+ end (- (length replacement) (length (match-string 1)))))
|
|
(replace-match replacement t t nil 1)))))
|
|
|
|
(defun org-babel-exp-lob-one-liners (start end)
|
|
"Process #+lob (Library of Babel) calls between START and END for export.
|
|
See `org-babel-exp-src-blocks' for export options. Currently the
|
|
options are taken from `org-babel-default-header-args'."
|
|
(interactive)
|
|
(let (replacement)
|
|
(save-excursion
|
|
(goto-char start)
|
|
(while (and (< (point) end)
|
|
(re-search-forward org-babel-lob-one-liner-regexp nil t))
|
|
(setq replacement
|
|
(save-match-data
|
|
(org-babel-exp-do-export
|
|
(list "emacs-lisp" "results"
|
|
(org-babel-merge-params
|
|
org-babel-default-header-args
|
|
(org-babel-parse-header-arguments
|
|
(org-babel-clean-text-properties
|
|
(concat ":var results="
|
|
(mapconcat #'identity (org-babel-lob-get-info) " "))))))
|
|
'lob)))
|
|
(setq end (+ end (- (length replacement) (length (match-string 0)))))
|
|
(replace-match replacement t t)))))
|
|
|
|
(defun org-babel-exp-do-export (info type)
|
|
(case (intern (or (cdr (assoc :exports (third info))) "code"))
|
|
('none "")
|
|
('code (org-babel-exp-code info type))
|
|
('results (org-babel-exp-results info type))
|
|
('both (concat (org-babel-exp-code info type)
|
|
"\n\n"
|
|
(org-babel-exp-results info type)))))
|
|
|
|
(defun org-babel-exp-code (info type)
|
|
(let ((lang (first info))
|
|
(body (second info))
|
|
(switches (fourth info))
|
|
(name (fifth info))
|
|
(args (sixth info))
|
|
(function-def-line ""))
|
|
(case type
|
|
('inline (format "=%s=" (second info)))
|
|
('block
|
|
(when args
|
|
(unless (string-match "-i\\>" switches)
|
|
(setq switches (concat switches " -i")))
|
|
(setq body (with-temp-buffer
|
|
(insert body)
|
|
(indent-code-rigidly (point-min) (point-max) org-babel-function-def-export-indent)
|
|
(buffer-string)))
|
|
(setq args (mapconcat #'identity
|
|
(delq nil (mapcar (lambda (el) (and (length (cdr el)) (cdr el))) args))
|
|
", "))
|
|
(setq function-def-line
|
|
(format "#+BEGIN_SRC org-babel-lob\n%s %s(%s):\n#+END_SRC\n"
|
|
org-babel-function-def-export-keyword name args)))
|
|
(concat function-def-line
|
|
(format "#+BEGIN_SRC %s %s\n%s%s#+END_SRC" lang switches body
|
|
(if (string-match "\n$" body) "" "\n"))))
|
|
('lob (save-excursion
|
|
(re-search-backward org-babel-lob-one-liner-regexp)
|
|
(format "#+BEGIN_SRC org-babel-lob\n%s\n#+END_SRC"
|
|
(first (org-babel-lob-get-info))))))))
|
|
|
|
(defun org-babel-exp-results (info type)
|
|
(let ((lang (first info))
|
|
(body (second info))
|
|
(params
|
|
;; lets ensure that we lookup references in the original file
|
|
(mapcar (lambda (pair)
|
|
(if (and org-current-export-file
|
|
(eq (car pair) :var)
|
|
(string-match org-babel-ref-split-regexp (cdr pair)))
|
|
`(:var . ,(concat (match-string 1 (cdr pair))
|
|
"=" org-current-export-file
|
|
":" (match-string 2 (cdr pair))))
|
|
pair))
|
|
(third info))))
|
|
(case type
|
|
('inline
|
|
(let ((raw (org-babel-execute-src-block
|
|
nil info '((:results . "silent"))))
|
|
(result-params (split-string (cdr (assoc :results params)))))
|
|
(cond ;; respect the value of the :results header argument
|
|
((member "file" result-params)
|
|
(org-babel-result-to-file raw))
|
|
((or (member "raw" result-params) (member "org" result-params))
|
|
raw)
|
|
((member "code" result-params)
|
|
(format "src_%s{%s}" lang raw))
|
|
(t
|
|
(if (stringp raw)
|
|
(if (= 0 (length raw)) "=(no results)="
|
|
(format "=%s=" raw))
|
|
(format "=%S=" raw))))))
|
|
('block
|
|
(save-excursion ;; org-exp-blocks places us at the end of the block
|
|
(re-search-backward org-babel-src-block-regexp nil t)
|
|
(org-babel-execute-src-block
|
|
nil nil (org-babel-merge-params params '((:results . "replace")))) ""))
|
|
('lob
|
|
(save-excursion
|
|
(re-search-backward org-babel-lob-one-liner-regexp nil t)
|
|
(org-babel-execute-src-block
|
|
nil (list lang body (org-babel-merge-params params '((:results . "replace"))))) "")))))
|
|
|
|
(provide 'org-babel-exp)
|
|
;;; org-babel-exp.el ends here
|