瀏覽代碼

ob-exp: Fix code execution in some corner cases

* lisp/ob-exp.el (org-babel-exp-process-buffer): Make processing more
  robust when results are inserted before source block or when source
  block is followed by multiple blank lines.
* testing/lisp/test-ob-exp.el (ob-export/export-with-results-before-block):
  Add test.
Nicolas Goaziou 11 年之前
父節點
當前提交
3f9a6916aa
共有 2 個文件被更改,包括 49 次插入28 次删除
  1. 29 28
      lisp/ob-exp.el
  2. 20 0
      testing/lisp/test-ob-exp.el

+ 29 - 28
lisp/ob-exp.el

@@ -169,8 +169,12 @@ this template."
 			    (backward-char)
 			    (save-match-data (org-element-context))))
 		 (type (org-element-type element))
-		 (beg-el (org-element-property :begin element))
-		 (end-el (org-element-property :end 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))
@@ -181,24 +185,21 @@ this template."
 			   (org-babel-expand-noweb-references
 			    info (org-babel-exp-get-export-buffer))
 			 (nth 1 info)))
-		 (goto-char beg-el)
+		 (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 beg-el
-				      (progn (goto-char end-el)
+		       (delete-region begin
+				      (progn (goto-char end)
 					     (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)))
+		     (delete-region begin end)
 		     (insert replacement)))))
 	      ((babel-call inline-babel-call)
 	       (let* ((lob-info (org-babel-lob-get-info))
@@ -229,8 +230,8 @@ this template."
 		 ;; results.
 		 (if (equal rep "")
 		     (delete-region
-		      beg-el
-		      (progn (goto-char end-el)
+		      begin
+		      (progn (goto-char end)
 			     (if (not (eq type 'babel-call))
 				 (progn (skip-chars-forward " \t") (point))
 			       (skip-chars-forward " \r\t\n")
@@ -238,25 +239,17 @@ this template."
 		   ;; 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)))
+		   (goto-char begin)
+		   (delete-region begin end)
 		   (insert rep))))
 	      (src-block
-	       (let* ((match-start (match-beginning 0))
-		      ;; Make sure we don't remove any blank lines
-		      ;; after the block when replacing it.
-		      (block-end (save-excursion
-				   (goto-char end-el)
-				   (skip-chars-backward " \r\t\n")
-				   (line-end-position)))
+	       (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)))
+			(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
@@ -264,12 +257,17 @@ this template."
 		 ;; 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))
+		   (cond ((not replacement) (goto-char end))
 			 ((equal replacement "")
-			  (delete-region beg-el end-el))
+			  (goto-char end)
+			  (skip-chars-forward " \r\t\n")
+			  (beginning-of-line)
+			  (delete-region begin (point)))
 			 (t
 			  (goto-char match-start)
-			  (delete-region (point) block-end)
+			  (delete-region (point)
+					 (save-excursion (goto-char end)
+							 (line-end-position)))
 			  (insert replacement)
 			  (if (org-element-property :preserve-indent element)
 			      ;; Indent only the code block markers.
@@ -278,7 +276,10 @@ this template."
 					      (goto-char match-start)
 					      (indent-line-to ind))
 			    ;; Indent everything.
-			    (indent-rigidly match-start (point) ind))))))))))))))
+			    (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.

+ 20 - 0
testing/lisp/test-ob-exp.el

@@ -282,6 +282,26 @@ Here is one at the end of a line. =2=
       (should (string-match (regexp-quote (format nil "%S" '(:foo :bar)))
 			    ascii)))))
 
+(ert-deftest ob-export/export-with-results-before-block ()
+  "Test export when results are inserted before source block."
+  (should
+   (equal
+    "#+RESULTS: src1
+: 2
+
+#+NAME: src1
+#+BEGIN_SRC emacs-lisp 
+\(+ 1 1)
+#+END_SRC"
+    (org-test-with-temp-text
+	"#+RESULTS: src1
+
+#+NAME: src1
+#+BEGIN_SRC emacs-lisp :exports both
+\(+ 1 1)
+#+END_SRC"
+      (org-export-execute-babel-code)
+      (buffer-string)))))
 
 (provide 'test-ob-exp)