ob-exp.el 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. ;;; ob-exp.el --- Exportation of org-babel source blocks
  2. ;; Copyright (C) 2009 Eric Schulte, Dan Davison
  3. ;; Author: Eric Schulte, Dan Davison
  4. ;; Keywords: literate programming, reproducible research
  5. ;; Homepage: http://orgmode.org
  6. ;; Version: 0.01
  7. ;;; License:
  8. ;; This program is free software; you can redistribute it and/or modify
  9. ;; it under the terms of the GNU General Public License as published by
  10. ;; the Free Software Foundation; either version 3, or (at your option)
  11. ;; any later version.
  12. ;;
  13. ;; This program is distributed in the hope that it will be useful,
  14. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. ;; GNU General Public License for more details.
  17. ;;
  18. ;; You should have received a copy of the GNU General Public License
  19. ;; along with GNU Emacs; see the file COPYING. If not, write to the
  20. ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  21. ;; Boston, MA 02110-1301, USA.
  22. ;;; Commentary:
  23. ;; for more information see the comments in org-babel.el
  24. ;;; Code:
  25. (require 'ob)
  26. (require 'org-exp-blocks)
  27. (org-export-blocks-add-block '(src org-babel-exp-src-blocks nil))
  28. (add-to-list 'org-export-interblocks '(src org-babel-exp-inline-src-blocks))
  29. (add-to-list 'org-export-interblocks '(lob org-babel-exp-lob-one-liners))
  30. (add-hook 'org-export-blocks-postblock-hook 'org-exp-res/src-name-cleanup)
  31. (defvar org-babel-function-def-export-keyword "function"
  32. "When exporting a source block function, this keyword will
  33. appear in the exported version in the place of source name
  34. line. A source block is considered to be a source block function
  35. if the source name is present and is followed by a parenthesized
  36. argument list. The parentheses may be empty or contain
  37. whitespace. An example is the following which generates n random
  38. (uniform) numbers.
  39. #+source: rand(n)
  40. #+begin_src R
  41. runif(n)
  42. #+end_src
  43. ")
  44. (defvar org-babel-function-def-export-indent 4
  45. "When exporting a source block function, the block contents
  46. will be indented by this many characters. See
  47. `org-babel-function-def-export-name' for the definition of a
  48. source block function.")
  49. (defvar obe-marker nil)
  50. (defvar org-current-export-file)
  51. (defvar org-babel-lob-one-liner-regexp)
  52. (defvar org-babel-ref-split-regexp)
  53. (declare-function org-babel-get-src-block-info "ob" (&optional header-vars-only))
  54. (declare-function org-babel-lob-get-info "ob-lob" ())
  55. (declare-function org-babel-ref-literal "ob-ref" (ref))
  56. (defun org-babel-exp-src-blocks (body &rest headers)
  57. "Process src block for export. Depending on the 'export'
  58. headers argument in replace the source code block with...
  59. both ---- display the code and the results
  60. code ---- the default, display the code inside the block but do
  61. not process
  62. results - just like none only the block is run on export ensuring
  63. that it's results are present in the org-mode buffer
  64. none ----- do not display either code or results upon export"
  65. (interactive)
  66. (message "org-babel-exp processing...")
  67. (when (member (first headers) org-babel-interpreters)
  68. (save-excursion
  69. (goto-char (match-beginning 0))
  70. (let* ((info (org-babel-get-src-block-info))
  71. (params (third info)))
  72. ;; expand noweb references in the original file
  73. (setf (second info)
  74. (if (and (cdr (assoc :noweb params))
  75. (string= "yes" (cdr (assoc :noweb params))))
  76. (org-babel-expand-noweb-references
  77. info (get-file-buffer org-current-export-file))
  78. (second info)))
  79. (org-babel-exp-do-export info 'block)))))
  80. (defun org-babel-exp-inline-src-blocks (start end)
  81. "Process inline src blocks between START and END for export.
  82. See `org-babel-exp-src-blocks' for export options, currently the
  83. options and are taken from `org-babel-defualt-inline-header-args'."
  84. (interactive)
  85. (save-excursion
  86. (goto-char start)
  87. (while (and (< (point) end)
  88. (re-search-forward org-babel-inline-src-block-regexp end t))
  89. (let* ((info (save-match-data (org-babel-parse-inline-src-block-match)))
  90. (params (third info))
  91. (replacement
  92. (save-match-data
  93. (if (org-babel-in-example-or-verbatim)
  94. (buffer-substring (match-beginning 0) (match-end 0))
  95. ;; expand noweb references in the original file
  96. (setf (second info)
  97. (if (and (cdr (assoc :noweb params))
  98. (string= "yes" (cdr (assoc :noweb params))))
  99. (org-babel-expand-noweb-references
  100. info (get-file-buffer org-current-export-file))
  101. (second info)))
  102. (org-babel-exp-do-export info 'inline)))))
  103. (setq end (+ end (- (length replacement) (length (match-string 1)))))
  104. (replace-match replacement t t nil 1)))))
  105. (defun org-exp-res/src-name-cleanup ()
  106. "Cleanup leftover #+results and #+srcname lines as part of the
  107. org export cycle. This should only be called after all block
  108. processing has taken place."
  109. (interactive)
  110. (save-excursion
  111. (goto-char (point-min))
  112. (while (org-re-search-forward-unprotected
  113. (concat
  114. "\\("org-babel-source-name-regexp"\\|"org-babel-result-regexp"\\)")
  115. nil t)
  116. (delete-region
  117. (progn (beginning-of-line) (point))
  118. (progn (end-of-line) (+ 1 (point)))))))
  119. (defun org-babel-in-example-or-verbatim ()
  120. "Return true if the point is currently in an escaped portion of
  121. an org-mode buffer code which should be treated as normal
  122. org-mode text."
  123. (or (org-in-indented-comment-line)
  124. (save-excursion
  125. (save-match-data
  126. (goto-char (point-at-bol))
  127. (looking-at "[ \t]*:[ \t]")))
  128. (org-in-regexps-block-p "^[ \t]*#\\+begin_src" "^[ \t]*#\\+end_src")))
  129. (defun org-babel-exp-lob-one-liners (start end)
  130. "Process #+lob (Library of Babel) calls between START and END for export.
  131. See `org-babel-exp-src-blocks' for export options. Currently the
  132. options are taken from `org-babel-default-header-args'."
  133. (interactive)
  134. (let (replacement)
  135. (save-excursion
  136. (goto-char start)
  137. (while (and (< (point) end)
  138. (re-search-forward org-babel-lob-one-liner-regexp nil t))
  139. (setq replacement
  140. (let ((lob-info (org-babel-lob-get-info)))
  141. (save-match-data
  142. (org-babel-exp-do-export
  143. (list "emacs-lisp" "results"
  144. (org-babel-merge-params
  145. org-babel-default-header-args
  146. (org-babel-parse-header-arguments
  147. (org-babel-clean-text-properties
  148. (concat ":var results="
  149. (mapconcat #'identity
  150. (butlast lob-info) " ")))))
  151. (car (last lob-info)))
  152. 'lob))))
  153. (setq end (+ end (- (length replacement) (length (match-string 0)))))
  154. (replace-match replacement t t)))))
  155. (defun org-babel-exp-do-export (info type)
  156. "Return a string containing the exported content of the current
  157. code block respecting the value of the :exports header argument."
  158. (flet ((silently () (let ((session (cdr (assoc :session (third info)))))
  159. (when (and session
  160. (not (equal "none" session))
  161. (not (assoc :noeval (third info))))
  162. (org-babel-exp-results info type 'silent))))
  163. (clean () (org-babel-remove-result info)))
  164. (case (intern (or (cdr (assoc :exports (third info))) "code"))
  165. ('none (silently) (clean) "")
  166. ('code (silently) (clean) (org-babel-exp-code info type))
  167. ('results (org-babel-exp-results info type))
  168. ('both (concat (org-babel-exp-code info type)
  169. "\n\n"
  170. (org-babel-exp-results info type))))))
  171. (defun org-babel-exp-code (info type)
  172. "Return the code the current code block in a manner suitable
  173. for exportation by org-mode. This function is called by
  174. `org-babel-exp-do-export'. The code block will not be
  175. evaluated."
  176. (let ((lang (first info))
  177. (body (second info))
  178. (switches (fourth info))
  179. (name (fifth info))
  180. (args (mapcar
  181. #'cdr
  182. (remove-if-not (lambda (el) (eq :var (car el))) (third info)))))
  183. (case type
  184. ('inline (format "=%s=" body))
  185. ('block
  186. (let ((str
  187. (format "#+BEGIN_SRC %s %s\n%s%s#+END_SRC\n" lang switches body
  188. (if (and body (string-match "\n$" body))
  189. "" "\n"))))
  190. (when name
  191. (add-text-properties
  192. 0 (length str)
  193. (list 'org-caption
  194. (format "%s(%s)"
  195. name
  196. (mapconcat #'identity args ", ")))
  197. str))
  198. str))
  199. ('lob
  200. (let ((call-line (and (string-match "results=" (car args))
  201. (substring (car args) (match-end 0)))))
  202. (cond
  203. ((eq backend 'html)
  204. (format "\n#+HTML: <label class=\"org-src-name\">%s</label>\n"
  205. call-line))
  206. ((t (format ": %s\n" call-line)))))))))
  207. (defun org-babel-exp-results (info type &optional silent)
  208. "Return the results of the current code block in a manner
  209. suitable for exportation by org-mode. This function is called by
  210. `org-babel-exp-do-export'. The code block will be evaluated.
  211. Optional argument SILENT can be used to inhibit insertion of
  212. results into the buffer."
  213. (let ((lang (first info))
  214. (body (second info))
  215. (params
  216. ;; lets ensure that we lookup references in the original file
  217. (mapcar
  218. (lambda (pair)
  219. (if (and org-current-export-file
  220. (eq (car pair) :var)
  221. (string-match org-babel-ref-split-regexp (cdr pair))
  222. (null (org-babel-ref-literal (match-string 2 (cdr pair)))))
  223. `(:var . ,(concat (match-string 1 (cdr pair))
  224. "=" org-current-export-file
  225. ":" (match-string 2 (cdr pair))))
  226. pair))
  227. (third info))))
  228. (case type
  229. ('inline
  230. (let ((raw (org-babel-execute-src-block
  231. nil info '((:results . "silent"))))
  232. (result-params (split-string (cdr (assoc :results params)))))
  233. (unless silent
  234. (cond ;; respect the value of the :results header argument
  235. ((member "file" result-params)
  236. (org-babel-result-to-file raw))
  237. ((or (member "raw" result-params) (member "org" result-params))
  238. (format "%s" raw))
  239. ((member "code" result-params)
  240. (format "src_%s{%s}" lang raw))
  241. (t
  242. (if (stringp raw)
  243. (if (= 0 (length raw)) "=(no results)="
  244. (format "%s" raw))
  245. (format "%S" raw)))))))
  246. ('block
  247. (org-babel-execute-src-block
  248. nil info (org-babel-merge-params
  249. params `((:results . ,(if silent "silent" "replace")))))
  250. "")
  251. ('lob
  252. (save-excursion
  253. (re-search-backward org-babel-lob-one-liner-regexp nil t)
  254. (org-babel-execute-src-block
  255. nil info (org-babel-merge-params
  256. params `((:results . ,(if silent "silent" "replace")))))
  257. "")))))
  258. (provide 'ob-exp)
  259. ;;; ob-exp.el ends here