diff --git a/lisp/ob.el b/lisp/ob.el index 63edb76a4..089d58638 100644 --- a/lisp/ob.el +++ b/lisp/ob.el @@ -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 diff --git a/testing/examples/babel.org b/testing/examples/babel.org index acfa5c8dd..c63296426 100644 --- a/testing/examples/babel.org +++ b/testing/examples/babel.org @@ -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 + diff --git a/testing/lisp/test-ob.el b/testing/lisp/test-ob.el index 2322b5c2c..2ee44c884 100644 --- a/testing/lisp/test-ob.el +++ b/testing/lisp/test-ob.el @@ -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 \ No newline at end of file