瀏覽代碼

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
Eric Schulte 14 年之前
父節點
當前提交
9ba9ef99a6
共有 3 個文件被更改,包括 75 次插入12 次删除
  1. 21 7
      lisp/ob.el
  2. 35 0
      testing/examples/babel.org
  3. 19 5
      testing/lisp/test-ob.el

+ 21 - 7
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

+ 35 - 0
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
+

+ 19 - 5
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