babel: now allows multi-line header arguments with #+headers: before code block

for example, from the test of this functionality
* multi-line header arguments
  :PROPERTIES:
  :ID:       b77c8857-6c76-4ea9-8a61-ddc2648d96c4
  :END:

  (map 'list #'list numbers letters)

| 1 | a |
| 2 | b |
| 3 | c |
| 4 | d |
| 5 | e |
| 6 | f |
| 7 | g |

* lisp/ob.el (org-babel-multi-line-header-regexp): new variable for
  matching header lines preceding code blocks

  (org-babel-src-name-w-name-regexp): now includes possible header
  lines between source name and code block

  (org-babel-get-src-block-info): now also collecting header arguments
  from preceding header lines

  (org-babel-src-block-names): updated match-string to reflect new
  value of org-babel-src-name-w-name-regexp

  (org-babel-merge-params): fixed error in variable string regexp
This commit is contained in:
Eric Schulte 2010-10-15 15:46:20 -06:00 committed by Dan Davison
parent 05054d5227
commit 9ba9ef99a6
3 changed files with 75 additions and 12 deletions

View File

@ -109,8 +109,15 @@ remove code block execution from the C-c C-c keybinding."
"^[ \t]*#\\+\\(srcname\\|source\\|function\\):[ \t]*"
"Regular expression used to match a source name line.")
(defvar org-babel-multi-line-header-regexp
"^[ \t]*#\\+headers?:[ \t]*\\([^\n]*\\)$"
"Regular expression used to match multi-line header arguments.")
(defvar org-babel-src-name-w-name-regexp
(concat org-babel-src-name-regexp
"\\("
org-babel-multi-line-header-regexp
"\\)*"
"\\([^ ()\f\t\n\r\v]+\\)\\(\(\\(.*\\)\)\\|\\)")
"Regular expression matching source name lines with a name.")
@ -164,13 +171,20 @@ Returns a list
(setq info (butlast info))
(forward-line -1)
(when (looking-at org-babel-src-name-w-name-regexp)
(setq name (org-babel-clean-text-properties (match-string 2)))
(when (match-string 4)
(setq name (org-babel-clean-text-properties (match-string 3)))
(when (match-string 5)
(setf (nth 2 info) ;; merge functional-syntax vars and header-args
(org-babel-merge-params
(mapcar (lambda (ref) (cons :var ref))
(org-babel-ref-split-args (match-string 4)))
(nth 2 info))))))
(org-babel-ref-split-args (match-string 5)))
(nth 2 info)))))
(goto-char head)
(while (and (forward-line -1)
(looking-at org-babel-multi-line-header-regexp))
(setf (nth 2 info)
(org-babel-merge-params
(org-babel-parse-header-arguments (match-string 1))
(nth 2 info)))))
;; inline source block
(when (save-excursion (re-search-backward "[ \f\t\n\r\v]" nil t)
(looking-at org-babel-inline-src-block-regexp))
@ -1071,7 +1085,7 @@ org-babel-named-src-block-regexp."
(when file (find-file file)) (goto-char (point-min))
(let (names)
(while (re-search-forward org-babel-src-name-w-name-regexp nil t)
(setq names (cons (org-babel-clean-text-properties (match-string 2))
(setq names (cons (org-babel-clean-text-properties (match-string 3))
names)))
names)))
@ -1534,9 +1548,9 @@ parameters when merging lists."
(let ((name (if (listp (cdr pair))
(cadr pair)
(string-match
".+=[ \t]*\\([^\f\n\r\v]+\\)$"
"^\\([^= \f\t\n\r\v]+\\)[ \t]*="
(cdr pair))
(intern (match-string 1)))))
(intern (match-string 1 (cdr pair))))))
(unless (member name (mapcar #'car vars))
(setq vars (cons (cons name (cdr pair)) vars)))))
(:results

View File

@ -75,3 +75,38 @@
#+results:
: 4
* multi-line header arguments
:PROPERTIES:
:ID: b77c8857-6c76-4ea9-8a61-ddc2648d96c4
:END:
#+headers: :var letters='(a b c d e f g)
#+begin_src emacs-lisp :var numbers='(1 2 3 4 5 6 7)
(map 'list #'list numbers letters)
#+end_src
#+results:
| 1 | a |
| 2 | b |
| 3 | c |
| 4 | d |
| 5 | e |
| 6 | f |
| 7 | g |
* simple named code block
:PROPERTIES:
:ID: 0d82b52d-1bb9-4916-816b-2c67c8108dbb
:END:
#+source: i-have-a-name
#+begin_src emacs-lisp
42
#+end_src
#+results:
: 42
#+results: i-have-a-name
: 42

View File

@ -20,23 +20,23 @@
(require 'org-test-ob-consts))
;;; ob-get-src-block-info
(ert-deftest test-org-babel-get-src-block-info-language ()
(ert-deftest test-org-babel/get-src-block-info-language ()
(org-test-at-marker nil org-test-file-ob-anchor
(let ((info (org-babel-get-src-block-info)))
(should (string= "emacs-lisp" (nth 0 info))))))
(ert-deftest test-org-babel-get-src-block-info-body ()
(ert-deftest test-org-babel/get-src-block-info-body ()
(org-test-at-marker nil org-test-file-ob-anchor
(let ((info (org-babel-get-src-block-info)))
(should (string-match (regexp-quote org-test-file-ob-anchor)
(nth 1 info))))))
(ert-deftest test-org-babel-get-src-block-info-tangle ()
(ert-deftest test-org-babel/get-src-block-info-tangle ()
(org-test-at-marker nil org-test-file-ob-anchor
(let ((info (org-babel-get-src-block-info)))
(should (string= "no" (cdr (assoc :tangle (nth 2 info))))))))
(ert-deftest test-org-babel-elisp-in-header-arguments ()
(ert-deftest test-org-babel/elisp-in-header-arguments ()
"Test execution of elisp forms in header arguments."
;; at the babel.org:elisp-forms-in-header-arguments header
(org-test-at-id "22d67284-bf14-4cdc-8319-f4bd876829d7"
@ -44,12 +44,26 @@
(let ((info (org-babel-get-src-block-info)))
(should (= 4 (org-babel-execute-src-block))))))
(ert-deftest test-org-babel-simple-variable-resolution ()
(ert-deftest test-org-babel/simple-named-code-block ()
"Test that simple named code blocks can be evaluated."
(org-test-at-id "0d82b52d-1bb9-4916-816b-2c67c8108dbb"
(org-babel-next-src-block 1)
(should (= 42 (org-babel-execute-src-block)))))
(ert-deftest test-org-babel/simple-variable-resolution ()
"Test that simple variable resolution is working."
(org-test-at-id "f68821bc-7f49-4389-85b5-914791ee3718"
(org-babel-next-src-block 2)
(should (= 4 (org-babel-execute-src-block)))))
(ert-deftest test-org-babel/multi-line-header-arguments ()
"Test that multi-line header arguments and can be read."
(org-test-at-id "b77c8857-6c76-4ea9-8a61-ddc2648d96c4"
(org-babel-next-src-block)
(let ((results (org-babel-execute-src-block)))
(should (equal 'a (cadr (assoc 1 results))))
(should (equal 'd (cadr (assoc 4 results)))))))
(provide 'test-ob)
;;; test-ob ends here