Browse Source

babel: convert org-babel-check-confirm-evaluate to defun, add test

* lisp/ob-core.el (org-babel-check-confirm-evaluate): Convert from macro
to function.
(org-babel-check-evaluate):
(org-babel-confirm-evaluate): Adapt to above change.  Convert from
defsubst to defun.
* testing/lisp/test-ob.el (ob/check-eval) New test.
(org-test-babel-confirm-evaluate): New function supporting it.
Aaron Ecay 10 years ago
parent
commit
40356ae376
2 changed files with 106 additions and 57 deletions
  1. 60 57
      lisp/ob-core.el
  2. 46 0
      testing/lisp/test-ob.el

+ 60 - 57
lisp/ob-core.el

@@ -284,75 +284,78 @@ Returns a list
 This is used by Babel to resolve references in source blocks.
 This is used by Babel to resolve references in source blocks.
 Its value is dynamically bound during export.")
 Its value is dynamically bound during export.")
 
 
-(defmacro org-babel-check-confirm-evaluate (info &rest body)
-  "Evaluate BODY with special execution confirmation variables set.
-
-Specifically; NOEVAL will indicate if evaluation is allowed,
-QUERY will indicate if a user query is required, CODE-BLOCK will
-hold the language of the code block, and BLOCK-NAME will hold the
-name of the code block."
-  (declare (indent defun))
-  (org-with-gensyms
-      (lang block-body headers name head eval eval-no export eval-no-export)
-    `(let* ((,lang           (nth 0 ,info))
-	    (,block-body     (nth 1 ,info))
-	    (,headers        (nth 2 ,info))
-	    (,name           (nth 4 ,info))
-	    (,head           (nth 6 ,info))
-	    (,eval           (or (cdr  (assoc :eval   ,headers))
-				 (when (assoc :noeval ,headers) "no")))
-	    (,eval-no        (or (equal ,eval "no")
-				 (equal ,eval "never")))
-	    (,export         org-babel-exp-reference-buffer)
-	    (,eval-no-export (and ,export (or (equal ,eval "no-export")
-					      (equal ,eval "never-export"))))
-	    (noeval          (or ,eval-no ,eval-no-export))
-	    (query           (or (equal ,eval "query")
-				 (and ,export (equal ,eval "query-export"))
-				 (if (functionp org-confirm-babel-evaluate)
-				     (save-excursion
-				       (goto-char ,head)
-				       (funcall org-confirm-babel-evaluate
-						,lang ,block-body))
-				   org-confirm-babel-evaluate)))
-	    (code-block      (if ,info (format  " %s "  ,lang) " "))
-	    (block-name      (if ,name (format " (%s) " ,name) " ")))
-       ,@body)))
-
-(defsubst org-babel-check-evaluate (info)
+(defun org-babel-check-confirm-evaluate (info)
+  "Check whether INFO allows code block evaluation.
+
+Returns nil if evaluation is disallowed, t if it is
+unconditionally allowed, and the symbol `query' if the user
+should be asked whether to allow evaluation."
+  (let* ((headers (nth 2 info))
+	 (eval (or (cdr  (assq :eval headers))
+		   (when (assq :noeval headers) "no")))
+	 (eval-no (member eval '("no" "never")))
+	 (export org-babel-exp-reference-buffer)
+	 (eval-no-export (and export (member eval '("no-export" "never-export"))))
+	 (noeval (or eval-no eval-no-export))
+	 (query (or (equal eval "query")
+		    (and export (equal eval "query-export"))
+		    (if (functionp org-confirm-babel-evaluate)
+			(save-excursion
+			  (goto-char (nth 6 info))
+			  (funcall org-confirm-babel-evaluate
+				   ;; language, code block body
+				   (nth 0 info) (nth 1 info)))
+		      org-confirm-babel-evaluate))))
+    (cond
+     (noeval nil)
+     (query 'query)
+     (t t))))
+
+(defun org-babel-check-evaluate (info)
   "Check if code block INFO should be evaluated.
   "Check if code block INFO should be evaluated.
-Do not query the user."
-  (org-babel-check-confirm-evaluate info
-    (not (when noeval
-	   (message "Evaluation of this%scode-block%sis disabled."
-                    code-block block-name)))))
 
 
- ;; dynamically scoped for asynchronous export
+Do not query the user, but do display an informative message if
+evaluation is blocked.  Returns non-nil if evaluation is not blocked."
+  (let ((evalp (org-babel-check-confirm-evaluate info)))
+    (when (null evalp)
+      (message "Evaluation of this %s code-block%sis disabled."
+	       (nth 0 info)
+	       (let ((name (nth 4 info))) (if name (format " (%s) " name) ""))))
+    evalp))
+
+;; Dynamically scoped for asynchronous export.
 (defvar org-babel-confirm-evaluate-answer-no)
 (defvar org-babel-confirm-evaluate-answer-no)
 
 
-(defsubst org-babel-confirm-evaluate (info)
+(defun org-babel-confirm-evaluate (info)
   "Confirm evaluation of the code block INFO.
   "Confirm evaluation of the code block INFO.
 
 
-If the variable `org-babel-confirm-evaluate-answer-no' is bound
-to a non-nil value, auto-answer with \"no\".
-
 This query can also be suppressed by setting the value of
 This query can also be suppressed by setting the value of
 `org-confirm-babel-evaluate' to nil, in which case all future
 `org-confirm-babel-evaluate' to nil, in which case all future
 interactive code block evaluations will proceed without any
 interactive code block evaluations will proceed without any
 confirmation from the user.
 confirmation from the user.
 
 
 Note disabling confirmation may result in accidental evaluation
 Note disabling confirmation may result in accidental evaluation
-of potentially harmful code."
-  (org-babel-check-confirm-evaluate info
-    (not (when query
-	   (unless
-	       (and (not (org-bound-and-true-p
-			  org-babel-confirm-evaluate-answer-no))
-		    (yes-or-no-p
-		     (format "Evaluate this%scode block%son your system? "
-			     code-block block-name)))
-	     (message "Evaluation of this%scode-block%sis aborted."
-                      code-block block-name))))))
+of potentially harmful code.
+
+The variable `org-babel-confirm-evaluate-answer-no' is used by
+the async export process, which requires a non-interactive
+environment, to override this check."
+  (let* ((evalp (org-babel-check-confirm-evaluate info))
+	 (lang (nth 0 info))
+	 (name (nth 4 info))
+	 (name-string (if name (format " (%s) " name) "")))
+    (pcase evalp
+      (`nil nil)
+      (`t t)
+      (`query (unless
+		  (and (not (org-bound-and-true-p
+			     org-babel-confirm-evaluate-answer-no))
+		       (yes-or-no-p
+			(format "Evaluate this %s code block%son your system? "
+				lang name-string)))
+		(message "Evaluation of this %s code-block%sis aborted."
+			 lang name-string)))
+      (x (error "Unexepcted value `%s' from `org-babel-check-confirm-evaluate'" x)))))
 
 
 ;;;###autoload
 ;;;###autoload
 (defun org-babel-execute-safely-maybe ()
 (defun org-babel-execute-safely-maybe ()

+ 46 - 0
testing/lisp/test-ob.el

@@ -1493,6 +1493,52 @@ echo \"$data\"
 		     (:result-params . 1)
 		     (:result-params . 1)
 		     (:result-type . value)))))
 		     (:result-type . value)))))
 
 
+(defun org-test-babel-confirm-evaluate (eval-value)
+  (org-test-with-temp-text (format "#+begin_src emacs-lisp :eval %s
+  nil
+#+end_src" eval-value)
+	(goto-char (point-min))
+	(let ((info (org-babel-get-src-block-info)))
+	   (org-babel-check-confirm-evaluate info))))
+
+(ert-deftest ob/check-eval ()
+  (let ((org-confirm-babel-evaluate t))
+    ;; Non-export tests
+    (dolist (pair '(("no" . nil)
+		    ("never" . nil)
+		    ("query" . query)
+		    ("yes" . query)))
+      (should (eq (org-test-babel-confirm-evaluate (car pair)) (cdr pair))))
+    ;; Export tests
+    (let ((org-babel-exp-reference-buffer t))
+      (dolist (pair '(("no" . nil)
+		      ("never" . nil)
+		      ("query" . query)
+		      ("yes" . query)
+		      ("never-export" . nil)
+		      ("no-export" . nil)
+		      ("query-export" . query)))
+	(message (car pair))
+	(should (eq (org-test-babel-confirm-evaluate (car pair)) (cdr pair))))))
+  (let ((org-confirm-babel-evaluate nil))
+    ;; Non-export tests
+    (dolist (pair '(("no" . nil)
+		    ("never" . nil)
+		    ("query" . query)
+		    ("yes" . t)))
+      (should (eq (org-test-babel-confirm-evaluate (car pair)) (cdr pair))))
+    ;; Export tests
+    (let ((org-babel-exp-reference-buffer t))
+      (dolist (pair '(("no" . nil)
+		      ("never" . nil)
+		      ("query" . query)
+		      ("yes" . t)
+		      ("never-export" . nil)
+		      ("no-export" . nil)
+		      ("query-export" . query)))
+	(message (car pair))
+	(should (eq (org-test-babel-confirm-evaluate (car pair)) (cdr pair)))))))
+
 (provide 'test-ob)
 (provide 'test-ob)
 
 
 ;;; test-ob ends here
 ;;; test-ob ends here