diff --git a/doc/org.texi b/doc/org.texi index 73289d209..c4b267c06 100644 --- a/doc/org.texi +++ b/doc/org.texi @@ -11086,6 +11086,13 @@ Both the code block and its results will be exported. Neither the code block nor its results will be exported. @end table +It is possible to inhibit the evaluation of code blocks during export. +Setting the the @code{org-export-babel-evaluate} variable to @code{nil} will +ensure that no code blocks are evaluated as part of the export process. This +can be useful in situations where potentially untrusted Org-mode files are +exported in an automated fashion, for example when Org-mode is used as the +markup language for a wiki. + @comment node-name, next, previous, up @comment Extracting source code, Evaluating code blocks, Exporting code blocks, Working With Source Code @node Extracting source code, Evaluating code blocks, Exporting code blocks, Working With Source Code diff --git a/lisp/ob-exp.el b/lisp/ob-exp.el index 81f6f2b14..0b6819ce0 100644 --- a/lisp/ob-exp.el +++ b/lisp/ob-exp.el @@ -47,6 +47,14 @@ (org-export-blocks-add-block '(src org-babel-exp-src-blocks nil)) +(defcustom org-export-babel-evaluate t + "Switch controlling code evaluation during export. +When set to nil no code will be exported as part of the export +process." + :group 'org-babel + :type 'boolean) +(put 'org-export-babel-evaluate 'safe-local-variable (lambda (x) (eq x nil))) + (defvar org-babel-function-def-export-keyword "function" "When exporting a source block function, this keyword will appear in the exported version in the place of source name @@ -235,56 +243,62 @@ suitable for exportation by org-mode. This function is called by `org-babel-exp-do-export'. The code block will be evaluated. Optional argument SILENT can be used to inhibit insertion of results into the buffer." - (let ((lang (nth 0 info)) - (body (nth 1 info)) - (params - ;; lets ensure that we lookup references in the original file - (mapcar - (lambda (pair) - (if (and org-current-export-file - (eq (car pair) :var) - (string-match org-babel-ref-split-regexp (cdr pair)) - (equal :ob-must-be-reference - (org-babel-ref-literal (match-string 2 (cdr pair))))) - `(:var . ,(concat (match-string 1 (cdr pair)) - "=" org-current-export-file - ":" (match-string 2 (cdr pair)))) - pair)) - (nth 2 info)))) - ;; skip code blocks which we can't evaluate - (if (fboundp (intern (concat "org-babel-execute:" lang))) - (case type - ('inline - (let ((raw (org-babel-execute-src-block - nil info '((:results . "silent")))) - (result-params (split-string (cdr (assoc :results params))))) - (unless silent - (cond ;; respect the value of the :results header argument - ((member "file" result-params) - (org-babel-result-to-file raw)) - ((or (member "raw" result-params) (member "org" result-params)) - (format "%s" raw)) - ((member "code" result-params) - (format "src_%s{%s}" lang raw)) - (t - (if (stringp raw) - (if (= 0 (length raw)) "=(no results)=" - (format "%s" raw)) - (format "%S" raw))))))) - ('block - (org-babel-execute-src-block - nil info (org-babel-merge-params - params - `((:results . ,(if silent "silent" "replace"))))) - "") - ('lob - (save-excursion - (re-search-backward org-babel-lob-one-liner-regexp nil t) - (org-babel-execute-src-block - nil info (org-babel-merge-params - params `((:results . ,(if silent "silent" "replace"))))) - ""))) - ""))) + (if org-export-babel-evaluate + (let ((lang (nth 0 info)) + (body (nth 1 info)) + (params + ;; lets ensure that we lookup references in the original file + (mapcar + (lambda (pair) + (if (and org-current-export-file + (eq (car pair) :var) + (string-match org-babel-ref-split-regexp (cdr pair)) + (equal :ob-must-be-reference + (org-babel-ref-literal + (match-string 2 (cdr pair))))) + `(:var . ,(concat (match-string 1 (cdr pair)) + "=" org-current-export-file + ":" (match-string 2 (cdr pair)))) + pair)) + (nth 2 info)))) + ;; skip code blocks which we can't evaluate + (if (fboundp (intern (concat "org-babel-execute:" lang))) + (case type + ('inline + (let ((raw (org-babel-execute-src-block + nil info '((:results . "silent")))) + (result-params (split-string + (cdr (assoc :results params))))) + (unless silent + (cond ;; respect the value of the :results header argument + ((member "file" result-params) + (org-babel-result-to-file raw)) + ((or (member "raw" result-params) + (member "org" result-params)) + (format "%s" raw)) + ((member "code" result-params) + (format "src_%s{%s}" lang raw)) + (t + (if (stringp raw) + (if (= 0 (length raw)) "=(no results)=" + (format "%s" raw)) + (format "%S" raw))))))) + ('block + (org-babel-execute-src-block + nil info (org-babel-merge-params + params + `((:results . ,(if silent "silent" "replace"))))) + "") + ('lob + (save-excursion + (re-search-backward org-babel-lob-one-liner-regexp nil t) + (org-babel-execute-src-block + nil info (org-babel-merge-params + params + `((:results . ,(if silent "silent" "replace"))))) + ""))) + "")) + "")) (provide 'ob-exp) diff --git a/lisp/ob-python.el b/lisp/ob-python.el index b27ee0544..39208fbec 100644 --- a/lisp/ob-python.el +++ b/lisp/ob-python.el @@ -31,10 +31,11 @@ (require 'ob-ref) (require 'ob-comint) (require 'ob-eval) -(require (if (featurep 'xemacs) 'python-mode 'python)) (eval-when-compile (require 'cl)) (declare-function org-remove-indentation "org" ) +(declare-function py-shell "ext:python-mode" (&optional argprompt)) +(declare-function run-python "ext:python" (&optional cmd noshow new)) (add-to-list 'org-babel-tangle-lang-exts '("python" . "py")) @@ -43,6 +44,9 @@ (defvar org-babel-python-command "python" "Name of command to use for executing python code.") +(defvar org-babel-python-mode (if (featurep 'xemacs) 'python-mode 'python) + "Preferred python mode for use in running python interactively.") + (defun org-babel-expand-body:python (body params &optional processed-params) "Expand BODY according to PARAMS, return the expanded body." (concat @@ -136,13 +140,16 @@ Emacs-lisp table, otherwise return the results as a string." (defun org-babel-python-initiate-session-by-key (&optional session) "If there is not a current inferior-process-buffer in SESSION then create. Return the initialized session." + (require org-babel-python-mode) (save-window-excursion (let* ((session (if session (intern session) :default)) (python-buffer (org-babel-python-session-buffer session))) (cond - ((fboundp 'run-python) ; python.el + ((and (equal 'python org-babel-python-mode) + (fboundp 'run-python)) ; python.el (run-python)) - ((fboundp 'py-shell) ; python-mode.el + ((and (equal 'python-mode org-babel-python-mode) + (fboundp 'py-shell)) ; python-mode.el ;; `py-shell' creates a buffer whose name is the value of ;; `py-which-bufname' with '*'s at the beginning and end (let* ((bufname (if python-buffer diff --git a/lisp/ob-tangle.el b/lisp/ob-tangle.el index 484309b11..7d140dbdb 100644 --- a/lisp/ob-tangle.el +++ b/lisp/ob-tangle.el @@ -33,6 +33,7 @@ (require 'cl)) (declare-function org-link-escape "org" (text &optional table)) +(declare-function with-temp-filebuffer "org-interaction" (file &rest body)) (defcustom org-babel-tangle-lang-exts '(("emacs-lisp" . "el")) @@ -47,6 +48,11 @@ then the name of the language is used." (string "Language name") (string "File Extension")))) +(defcustom org-babel-post-tangle-hook nil + "Hook run in code files tangled by `org-babel-tangle'." + :group 'org-babel + :type 'hook) + ;;;###autoload (defun org-babel-load-file (file) "Load the contents of the Emacs Lisp source code blocks in the @@ -99,6 +105,11 @@ exported source code blocks by language." (save-buffer) (save-excursion (let ((block-counter 0) + (org-babel-default-header-args + (if target-file + (org-babel-merge-params org-babel-default-header-args + (list (cons :tangle target-file))) + org-babel-default-header-args)) path-collector) (mapc ;; map over all languages (lambda (by-lang) @@ -120,13 +131,12 @@ exported source code blocks by language." (let* ((tangle (get-spec :tangle)) (she-bang ((lambda (sheb) (when (> (length sheb) 0) sheb)) (get-spec :shebang))) - (base-name (or (cond - ((string= "yes" tangle) - (file-name-sans-extension - (buffer-file-name))) - ((string= "no" tangle) nil) - ((> (length tangle) 0) tangle)) - target-file)) + (base-name (cond + ((string= "yes" tangle) + (file-name-sans-extension + (buffer-file-name))) + ((string= "no" tangle) nil) + ((> (length tangle) 0) tangle))) (file-name (when base-name ;; decide if we want to add ext to base-name (if (and ext (string= "yes" tangle)) @@ -138,7 +148,7 @@ exported source code blocks by language." (delete-file file-name)) ;; drop source-block to file (with-temp-buffer - (if (fboundp lang-f) (funcall lang-f)) + (when (fboundp lang-f) (funcall lang-f)) (when (and she-bang (not (member file-name she-banged))) (insert (concat she-bang "\n")) (setq she-banged (cons file-name she-banged))) @@ -160,6 +170,13 @@ exported source code blocks by language." (org-babel-tangle-collect-blocks lang)) (message "tangled %d code block%s" block-counter (if (= block-counter 1) "" "s")) + ;; run `org-babel-post-tangle-hook' in all tangled files + (when org-babel-post-tangle-hook + (mapc + (lambda (file) + (with-temp-filebuffer file + (run-hooks 'org-babel-post-tangle-hook))) + path-collector)) path-collector))) (defun org-babel-tangle-clean () diff --git a/lisp/ob.el b/lisp/ob.el index 6ac253d9c..160cdf9b7 100644 --- a/lisp/ob.el +++ b/lisp/ob.el @@ -61,6 +61,11 @@ (declare-function org-babel-ref-variables "ob-ref" (params)) (declare-function org-babel-ref-resolve-reference "ob-ref" (ref &optional params)) +(defgroup org-babel nil + "Code block evaluation and management in `org-mode' documents." + :tag "Babel" + :group 'org) + (defcustom org-confirm-babel-evaluate t "Require confirmation before interactively evaluating code blocks in Org-mode buffers. The default value of this variable diff --git a/lisp/org.el b/lisp/org.el index ac3e290ee..df511e7c0 100644 --- a/lisp/org.el +++ b/lisp/org.el @@ -106,13 +106,6 @@ (require 'org-footnote) ;; babel -(let* ((babel-path (expand-file-name - "babel" - (file-name-directory (or (buffer-file-name) - load-file-name)))) - (babel-langs-path (expand-file-name "langs" babel-path))) - (add-to-list 'load-path babel-path) - (add-to-list 'load-path babel-langs-path)) (require 'ob) (require 'ob-table) (require 'ob-lob)