;;; ob-exp.el --- Exportation of org-babel source blocks
-;; Copyright (C) 2009-2014 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2016 Free Software Foundation, Inc.
;; Authors: Eric Schulte
;; Dan Davison
;;; Code:
(require 'ob-core)
+(require 'org-src)
(eval-when-compile
(require 'cl))
(defcustom org-export-babel-evaluate t
"Switch controlling code evaluation during export.
When set to nil no code will be evaluated as part of the export
-process. When set to 'inline-only, only inline code blocks will
+process. When set to `inline-only', only inline code blocks will
be executed."
:group 'org-babel
:version "24.1"
(defun org-babel-exp-src-block (&rest headers)
"Process source block for export.
-Depending on the 'export' headers argument, replace the source
+Depending on the `export' headers argument, replace the source
code block like this:
both ---- display the code and the results
:type 'string)
(defvar org-babel-default-lob-header-args)
-(defun org-babel-exp-non-block-elements (start end)
- "Process inline source and call lines between START and END for export."
+(defun org-babel-exp-process-buffer ()
+ "Execute all Babel blocks in current buffer."
(interactive)
- (save-excursion
- (goto-char start)
- (unless (markerp end)
- (let ((m (make-marker)))
- (set-marker m end (current-buffer))
- (setq end m)))
- (let ((rx (concat "\\(?:" org-babel-inline-src-block-regexp
- "\\|" org-babel-lob-one-liner-regexp "\\)")))
- (while (re-search-forward rx end t)
- (save-excursion
+ (save-window-excursion
+ (save-excursion
+ (let ((case-fold-search t)
+ (regexp (concat org-babel-inline-src-block-regexp "\\|"
+ org-babel-lob-one-liner-regexp "\\|"
+ "^[ \t]*#\\+BEGIN_SRC")))
+ (goto-char (point-min))
+ (while (re-search-forward regexp nil t)
(let* ((element (save-excursion
;; If match is inline, point is at its
;; end. Move backward so
;; object, not the following one.
(backward-char)
(save-match-data (org-element-context))))
- (type (org-element-type element)))
- (when (memq type '(babel-call inline-babel-call inline-src-block))
- (let ((beg-el (org-element-property :begin element))
- (end-el (org-element-property :end element)))
- (case type
- (inline-src-block
- (let* ((info (org-babel-parse-inline-src-block-match))
- (params (nth 2 info)))
- (setf (nth 1 info)
- (if (and (cdr (assoc :noweb params))
- (string= "yes" (cdr (assoc :noweb params))))
- (org-babel-expand-noweb-references
- info (org-babel-exp-get-export-buffer))
- (nth 1 info)))
- (goto-char beg-el)
- (let ((replacement (org-babel-exp-do-export info 'inline)))
- (if (equal replacement "")
- ;; Replacement code is empty: completely
- ;; remove inline src block, including extra
- ;; white space that might have been created
- ;; when inserting results.
- (delete-region beg-el
- (progn (goto-char end-el)
- (skip-chars-forward " \t")
- (point)))
- ;; Otherwise: remove inline src block but
- ;; preserve following white spaces. Then
- ;; insert value.
- (delete-region beg-el
- (progn (goto-char end-el)
- (skip-chars-backward " \t")
- (point)))
- (insert replacement)))))
- ((babel-call inline-babel-call)
- (let* ((lob-info (org-babel-lob-get-info))
- (results
- (org-babel-exp-do-export
- (list "emacs-lisp" "results"
- (apply #'org-babel-merge-params
- org-babel-default-header-args
- org-babel-default-lob-header-args
- (append
- (org-babel-params-from-properties)
- (list
- (org-babel-parse-header-arguments
- (org-no-properties
- (concat
- ":var results="
- (mapconcat 'identity
- (butlast lob-info 2)
- " ")))))))
- "" (nth 3 lob-info) (nth 2 lob-info))
- 'lob))
- (rep (org-fill-template
- org-babel-exp-call-line-template
- `(("line" . ,(nth 0 lob-info))))))
- ;; If replacement is empty, completely remove the
- ;; object/element, including any extra white space
- ;; that might have been created when including
- ;; results.
- (if (equal rep "")
- (delete-region
- beg-el
- (progn (goto-char end-el)
- (if (not (eq type 'babel-call))
- (progn (skip-chars-forward " \t") (point))
- (skip-chars-forward " \r\t\n")
- (line-beginning-position))))
- ;; Otherwise, preserve following white
- ;; spaces/newlines and then, insert replacement
- ;; string.
- (goto-char beg-el)
- (delete-region beg-el
- (progn (goto-char end-el)
- (skip-chars-backward " \r\t\n")
- (point)))
- (insert rep)))))))))))))
-
-(defvar org-src-preserve-indentation) ; From org-src.el
-(defun org-babel-exp-process-buffer ()
- "Execute all blocks in visible part of buffer."
- (interactive)
- (save-window-excursion
- (let ((case-fold-search t)
- (pos (point-min)))
- (goto-char pos)
- (while (re-search-forward "^[ \t]*#\\+BEGIN_SRC" nil t)
- (let ((element (save-match-data (org-element-at-point))))
- (when (eq (org-element-type element) 'src-block)
- (let* ((match-start (copy-marker (match-beginning 0)))
- (begin (copy-marker (org-element-property :begin element)))
- ;; Make sure we don't remove any blank lines after
- ;; the block when replacing it.
- (block-end (save-excursion
- (goto-char (org-element-property :end element))
- (skip-chars-backward " \r\t\n")
- (copy-marker (line-end-position))))
- (ind (org-get-indentation))
- (headers
- (cons
- (org-element-property :language element)
- (let ((params (org-element-property :parameters element)))
- (and params (org-split-string params "[ \t]+"))))))
- ;; Execute all non-block elements between POS and
- ;; current block.
- (org-babel-exp-non-block-elements pos begin)
- ;; Take care of matched block: compute replacement
- ;; string. In particular, a nil REPLACEMENT means the
- ;; block should be left as-is while an empty string
- ;; should remove the block.
- (let ((replacement (progn (goto-char match-start)
- (org-babel-exp-src-block headers))))
- (cond ((not replacement) (goto-char block-end))
- ((equal replacement "")
+ (type (org-element-type element))
+ (begin (copy-marker (org-element-property :begin element)))
+ (end (copy-marker
+ (save-excursion
+ (goto-char (org-element-property :end element))
+ (skip-chars-backward " \r\t\n")
+ (point)))))
+ (case type
+ (inline-src-block
+ (let* ((info (org-babel-parse-inline-src-block-match))
+ (params (nth 2 info)))
+ (setf (nth 1 info)
+ (if (and (cdr (assoc :noweb params))
+ (string= "yes" (cdr (assoc :noweb params))))
+ (org-babel-expand-noweb-references
+ info (org-babel-exp-get-export-buffer))
+ (nth 1 info)))
+ (goto-char begin)
+ (let ((replacement (org-babel-exp-do-export info 'inline)))
+ (if (equal replacement "")
+ ;; Replacement code is empty: remove inline src
+ ;; block, including extra white space that
+ ;; might have been created when inserting
+ ;; results.
(delete-region begin
- (progn (goto-char block-end)
- (skip-chars-forward " \r\t\n")
- (if (eobp) (point)
- (line-beginning-position)))))
- (t
- (goto-char match-start)
- (delete-region (point) block-end)
- (insert replacement)
- (if (org-element-property :preserve-indent element)
- ;; Indent only the code block markers.
- (save-excursion (skip-chars-backward " \r\t\n")
- (indent-line-to ind)
- (goto-char match-start)
- (indent-line-to ind))
- ;; Indent everything.
- (indent-rigidly match-start (point) ind)))))
- (setq pos (line-beginning-position))
- ;; Cleanup markers.
- (set-marker match-start nil)
- (set-marker begin nil)
- (set-marker block-end nil)))))
- ;; Eventually execute all non-block Babel elements between last
- ;; src-block and end of buffer.
- (org-babel-exp-non-block-elements pos (point-max)))))
+ (progn (goto-char end)
+ (skip-chars-forward " \t")
+ (point)))
+ ;; Otherwise: remove inline src block but
+ ;; preserve following white spaces. Then insert
+ ;; value.
+ (delete-region begin end)
+ (insert replacement)))))
+ ((babel-call inline-babel-call)
+ (let* ((lob-info (org-babel-lob-get-info))
+ (results
+ (org-babel-exp-do-export
+ (list "emacs-lisp" "results"
+ (apply #'org-babel-merge-params
+ org-babel-default-header-args
+ org-babel-default-lob-header-args
+ (append
+ (org-babel-params-from-properties)
+ (list
+ (org-babel-parse-header-arguments
+ (org-no-properties
+ (concat
+ ":var results="
+ (mapconcat 'identity
+ (butlast lob-info 2)
+ " ")))))))
+ "" (nth 3 lob-info) (nth 2 lob-info))
+ 'lob))
+ (rep (org-fill-template
+ org-babel-exp-call-line-template
+ `(("line" . ,(nth 0 lob-info))))))
+ ;; If replacement is empty, completely remove the
+ ;; object/element, including any extra white space
+ ;; that might have been created when including
+ ;; results.
+ (if (equal rep "")
+ (delete-region
+ begin
+ (progn (goto-char end)
+ (if (not (eq type 'babel-call))
+ (progn (skip-chars-forward " \t") (point))
+ (skip-chars-forward " \r\t\n")
+ (line-beginning-position))))
+ ;; Otherwise, preserve following white
+ ;; spaces/newlines and then, insert replacement
+ ;; string.
+ (goto-char begin)
+ (delete-region begin end)
+ (insert rep))))
+ (src-block
+ (let* ((match-start (copy-marker (match-beginning 0)))
+ (ind (org-get-indentation))
+ (headers
+ (cons
+ (org-element-property :language element)
+ (let ((params (org-element-property :parameters
+ element)))
+ (and params (org-split-string params "[ \t]+"))))))
+ ;; Take care of matched block: compute replacement
+ ;; string. In particular, a nil REPLACEMENT means
+ ;; the block should be left as-is while an empty
+ ;; string should remove the block.
+ (let ((replacement (progn (goto-char match-start)
+ (org-babel-exp-src-block headers))))
+ (cond ((not replacement) (goto-char end))
+ ((equal replacement "")
+ (goto-char end)
+ (skip-chars-forward " \r\t\n")
+ (beginning-of-line)
+ (delete-region begin (point)))
+ (t
+ (goto-char match-start)
+ (delete-region (point)
+ (save-excursion (goto-char end)
+ (line-end-position)))
+ (insert replacement)
+ (if (or org-src-preserve-indentation
+ (org-element-property :preserve-indent
+ element))
+ ;; Indent only the code block markers.
+ (save-excursion (skip-chars-backward " \r\t\n")
+ (indent-line-to ind)
+ (goto-char match-start)
+ (indent-line-to ind))
+ ;; Indent everything.
+ (indent-rigidly match-start (point) ind)))))
+ (set-marker match-start nil))))
+ (set-marker begin nil)
+ (set-marker end nil)))))))
(defun org-babel-in-example-or-verbatim ()
"Return true if point is in example or verbatim code.
(org-babel-exp-code info)))))
(defcustom org-babel-exp-code-template
- "#+BEGIN_SRC %lang%flags\n%body\n#+END_SRC"
+ "#+BEGIN_SRC %lang%switches%flags\n%body\n#+END_SRC"
"Template used to export the body of code blocks.
This template may be customized to include additional information
such as the code block name, or the values of particular header
lang ------ the language of the code block
name ------ the name of the code block
body ------ the body of the code block
+ switches -- the switches associated to the code block
flags ----- the flags passed to the code block
In addition to the keys mentioned above, every header argument
org-babel-exp-code-template
`(("lang" . ,(nth 0 info))
("body" . ,(org-escape-code-in-string (nth 1 info)))
+ ("switches" . ,(let ((f (nth 3 info)))
+ (and (org-string-nw-p f) (concat " " f))))
+ ("flags" . ,(let ((f (assq :flags (nth 2 info))))
+ (and f (concat " " (cdr f)))))
,@(mapcar (lambda (pair)
(cons (substring (symbol-name (car pair)) 1)
(format "%S" (cdr pair))))
(nth 2 info))
- ("flags" . ,(let ((f (nth 3 info))) (when f (concat " " f))))
("name" . ,(or (nth 4 info) "")))))
(defun org-babel-exp-results (info type &optional silent hash)