From 66f602987e6479e73e13e78235c9a7f6316e1a7d Mon Sep 17 00:00:00 2001 From: Nicolas Berthier Date: Fri, 13 Jun 2014 15:32:54 +0200 Subject: [PATCH 1/3] ob: Support for exporting inline source code * lisp/ob-exp.el (org-babel-exp-inline-code-template): New customizable variable to export inline source code (similar to `org-babel-exp-code-template'). (org-babel-exp-code): New `type' argument to differentiate between inline and standard code blocks. * lisp/ob-core.el (org-babel-inline-src-block-regexp): Allow empty set of switches and header arguments as in "src_sh[]{echo foo;}". Also permit spaces before them. * testint/lisp/test-org-element.el (test-org-element/inline-src-block-parser): Test extended syntax for inline source code. * testing/lisp/test-ob-exp.el (ob-exp/exports-inline-code): New function for testing inline source code handling. Also add three new failing tests exhibiting unexpected results with ":results code" switches. * testing/lisp/test-ob.el (test-org-babel/org-babel-get-inline-src-block-matches): Test for inline source blocks with empty header arguments. * testing/examples/babel.org: New sections for testing (i) exported inline source code (used by `ob-exp/exports-inline-code'); (ii) parsing inline source blocks with empty header arguments (used by `test-org-babel/org-babel-get-inline-src-block-matches'). Until now pieces of inline source code were handled as standard code blocks during export. These changes enable them to be exported. --- lisp/ob-core.el | 4 +- lisp/ob-exp.el | 32 ++++++++++++-- testing/examples/babel.org | 22 ++++++++++ testing/lisp/test-ob-exp.el | 93 ++++++++++++++++++++++++++++++++++++++++ testing/lisp/test-ob.el | 71 +++++++++++++++++------------- testing/lisp/test-org-element.el | 22 ++++++++++ 6 files changed, 208 insertions(+), 36 deletions(-) diff --git a/lisp/ob-core.el b/lisp/ob-core.el index ccc0878..c5beb60 100644 --- a/lisp/ob-core.el +++ b/lisp/ob-core.el @@ -203,9 +203,9 @@ This string must include a \"%s\" which will be replaced by the results." (defvar org-babel-inline-src-block-regexp (concat ;; (1) replacement target (2) lang - "\\(?:^\\|[^-[:alnum:]]\\)\\(src_\\([^ \f\t\n\r\v]+\\)" + "\\(?:^\\|[^-[:alnum:]]\\)\\(src_\\([^ \f\t\n\r\v[]+\\)" ;; (3,4) (unused, headers) - "\\(\\|\\[\\(.*?\\)\\]\\)" + "\\(\\|\\[[ \t]*\\(.*?\\)\\]\\)" ;; (5) body "{\\([^\f\n\r\v]+?\\)}\\)") "Regexp used to identify inline src-blocks.") diff --git a/lisp/ob-exp.el b/lisp/ob-exp.el index 3a47661..492bc35 100644 --- a/lisp/ob-exp.el +++ b/lisp/ob-exp.el @@ -318,10 +318,10 @@ The function respects the value of the :exports header argument." (clean (lambda () (unless (eq type 'inline) (org-babel-remove-result info))))) (case (intern (or (cdr (assoc :exports (nth 2 info))) "code")) ('none (funcall silently) (funcall clean) "") - ('code (funcall silently) (funcall clean) (org-babel-exp-code info)) + ('code (funcall silently) (funcall clean) (org-babel-exp-code info type)) ('results (org-babel-exp-results info type nil hash) "") ('both (org-babel-exp-results info type nil hash) - (org-babel-exp-code info))))) + (org-babel-exp-code info type))))) (defcustom org-babel-exp-code-template "#+BEGIN_SRC %lang%switches%flags\n%body\n#+END_SRC" @@ -343,7 +343,29 @@ replaced with its value." :group 'org-babel :type 'string) -(defun org-babel-exp-code (info) +(defcustom org-babel-exp-inline-code-template + "src_%lang[%switches%flags]{%body}" + "Template used to export the body of inline code blocks. +This template may be customized to include additional information +such as the code block name, or the values of particular header +arguments. The template is filled out using `org-fill-template', +and the following %keys may be used. + + lang ------ the language of the code block + name ------ the name of the code block + body ------ the body of the code block + switches -- the switches associated to the code block + flags ----- the flags passed to the code block + +In addition to the keys mentioned above, every header argument +defined for the code block may be used as a key and will be +replaced with its value." + :group 'org-babel + :type 'string + :version "24.5" + :package-version '(Org . "8.3")) + +(defun org-babel-exp-code (info type) "Return the original code block formatted for export." (setf (nth 1 info) (if (string= "strip-export" (cdr (assoc :noweb (nth 2 info)))) @@ -354,7 +376,9 @@ replaced with its value." info org-babel-exp-reference-buffer) (nth 1 info)))) (org-fill-template - org-babel-exp-code-template + (if (eq type 'inline) + org-babel-exp-inline-code-template + org-babel-exp-code-template) `(("lang" . ,(nth 0 info)) ("body" . ,(org-escape-code-in-string (nth 1 info))) ("switches" . ,(let ((f (nth 3 info))) diff --git a/testing/examples/babel.org b/testing/examples/babel.org index a8015d1..8bae65b 100644 --- a/testing/examples/babel.org +++ b/testing/examples/babel.org @@ -200,6 +200,17 @@ Here is one in the middle src_sh{echo 1} of a line. Here is one at the end of a line. src_sh{echo 2} src_sh{echo 3} Here is one at the beginning of a line. +* exported inline source block +:PROPERTIES: +:ID: cd54fc88-1b6b-45b6-8511-4d8fa7fc8076 +:results: silent +:exports: code +:END: +Here is one in the middle src_sh{echo 1} of a line. +Here is one at the end of a line. src_sh{echo 2} +src_sh{echo 3} Here is one at the beginning of a line. +Here is one that is also evaluated: src_sh[:exports both]{echo 4} + * mixed blocks with exports both :PROPERTIES: :ID: 5daa4d03-e3ea-46b7-b093-62c1b7632df3 @@ -283,6 +294,17 @@ src_sh{echo "One"} block at start of line One spaced block in src_sh{ echo "middle" } of line src_sh{echo 2} blocks on the src_emacs-lisp{"same"} line Inline block with src_sh[:results silent]{ echo "parameters" }. + +* org-babel-get-inline-src-block-matches (with empty args) + :PROPERTIES: + :results: silent + :ID: d55dada7-de0e-4340-8061-787cccbedee5 + :END: +src_sh[]{echo "One"} block at start of line + One spaced block in src_sh[]{ echo "middle" } of line +src_sh[]{echo 2} blocks on the src_emacs-lisp[]{"same"} line + Inline block with src_sh[:results silent]{ echo "parameters" }. + * exporting a code block with a name :PROPERTIES: :ID: b02ddd8a-eeb8-42ab-8664-8a759e6f43d9 diff --git a/testing/lisp/test-ob-exp.el b/testing/lisp/test-ob-exp.el index 1fe810b..e319bd2 100644 --- a/testing/lisp/test-ob-exp.el +++ b/testing/lisp/test-ob-exp.el @@ -197,6 +197,99 @@ Here is one at the end of a line. =2= (org-narrow-to-subtree) (org-test-with-expanded-babel-code (buffer-string)))))) +(ert-deftest ob-exp/exports-inline-code () + (should + (string-match "\\`src_emacs-lisp\\(?:\\[]\\)?{(\\+ 1 1)}$" + (org-test-with-temp-text + "src_emacs-lisp[:exports code]{(+ 1 1)}" + (org-export-execute-babel-code) + (buffer-string)))) + (should + (string-match "\\`src_emacs-lisp\\(?:\\[]\\)?{(\\+ 1 1)}$" + (org-test-with-temp-text + "src_emacs-lisp[ :exports code ]{(+ 1 1)}" + (org-export-execute-babel-code) + (buffer-string)))) + (should + (string-match "\\`src_emacs-lisp\\(?:\\[]\\)?{(\\+ 1 1)} =2=$" + (org-test-with-temp-text + "src_emacs-lisp[:exports both]{(+ 1 1)}" + (org-export-execute-babel-code) + (buffer-string)))) + (should + (string-match "\\`=2=$" + (org-test-with-temp-text + "src_emacs-lisp[:exports results :results scalar]{(+ 1 1)}" + (org-export-execute-babel-code) + (buffer-string)))) + (should + (let ((text "foosrc_emacs-lisp[:exports code]{(+ 1 1)}")) + (string-match (regexp-quote text) + (org-test-with-temp-text + text + (org-export-execute-babel-code) + (buffer-string))))) + (should + (let ((text "src_emacs lisp{(+ 1 1)}")) + (string-match (regexp-quote text) + (org-test-with-temp-text + text + (org-export-execute-babel-code) + (buffer-string))))) + (should + (string-match + (replace-regexp-in-string + "\\\\\\[]{" "\\(?:\\[]\\)?{" ;accept both src_sh[]{...} or src_sh{...} + (regexp-quote "Here is one in the middle src_sh[]{echo 1} of a line. +Here is one at the end of a line. src_sh[]{echo 2} +src_sh[]{echo 3} Here is one at the beginning of a line. +Here is one that is also evaluated: src_sh[]{echo 4} =4=") + nil t) + (org-test-at-id "cd54fc88-1b6b-45b6-8511-4d8fa7fc8076" + (org-narrow-to-subtree) + (org-test-with-expanded-babel-code (buffer-string)))))) + +(ert-deftest ob-exp/exports-inline-code-double-eval-bug () + "Failing for now as the result actually is +`#+BEGIN_SRC emacs-lisp\n2#+END_SRC\n'. + +Based on default header arguments for inline code blocks (:exports +results), the resulting code block `src_emacs-lisp{2}' should also be +evaluated." + :expected-result :failed + (should + (string-match "\\`=2=$" + (org-test-with-temp-text + "src_emacs-lisp[:exports results :results code]{(+ 1 1)}" + (org-export-execute-babel-code) + (buffer-string))))) + +(ert-deftest ob-exp/exports-inline-code-eval-code-once-bug () + "Ibid above, except that the resulting inline code block should not +be evaluated. Result for now is +`#+BEGIN_SRC emacs-lisp :exports code\n2#+END_SRC\n'" + :expected-result :failed + (should + (string-match "\\`src_emacs-lisp\\(?:\\[]\\)?{2}$" + (org-test-with-temp-text + (concat "src_emacs-lisp[:exports results :results code " + ":results_switches \":exports code\"]{(+ 1 1)}") + (org-export-execute-babel-code) + (buffer-string))))) + +(ert-deftest ob-exp/exports-inline-code-double-eval-exports-both-bug () + "Failing for now as the result actually is +`src_emacs-lisp[]{(+ 1 1)} #+BEGIN_SRC emacs-lisp\n2#+END_SRC\n'." + :expected-result :failed + (should + (string-match (concat "\\`src_emacs-lisp\\(?:\\[]\\)?{(\\+ 1 1)} " + "src_emacs-lisp\\(?:\\[]\\)?{2}$") + (org-test-with-temp-text + (concat "src_emacs-lisp[:exports both :results code " + ":results_switches \":exports code\"]{(+ 1 1)}") + (org-export-execute-babel-code) + (buffer-string))))) + (ert-deftest ob-exp/export-call-line-information () (org-test-at-id "bec63a04-491e-4caa-97f5-108f3020365c" (org-narrow-to-subtree) diff --git a/testing/lisp/test-ob.el b/testing/lisp/test-ob.el index 1162162..fdb5a3e 100644 --- a/testing/lisp/test-ob.el +++ b/testing/lisp/test-ob.el @@ -249,38 +249,49 @@ this is simple" (should (= 14 (org-babel-execute-src-block))))) (ert-deftest test-org-babel/inline-src-blocks () - (org-test-at-id "54cb8dc3-298c-4883-a933-029b3c9d4b18" - (macrolet ((at-next (&rest body) - `(progn - (move-end-of-line 1) - (re-search-forward org-babel-inline-src-block-regexp nil t) - (goto-char (match-beginning 1)) - (save-match-data ,@body)))) - (at-next (should (equal 1 (org-babel-execute-src-block)))) - (at-next (should (equal 2 (org-babel-execute-src-block)))) - (at-next (should (equal 3 (org-babel-execute-src-block))))))) + (macrolet ((at-next (&rest body) + `(progn + (move-end-of-line 1) + (re-search-forward org-babel-inline-src-block-regexp nil t) + (goto-char (match-beginning 1)) + (save-match-data ,@body)))) + (org-test-at-id + "54cb8dc3-298c-4883-a933-029b3c9d4b18" + (at-next (should (equal 1 (org-babel-execute-src-block)))) + (at-next (should (equal 2 (org-babel-execute-src-block)))) + (at-next (should (equal 3 (org-babel-execute-src-block))))) + (org-test-at-id + "cd54fc88-1b6b-45b6-8511-4d8fa7fc8076" + (at-next (should (equal 1 (org-babel-execute-src-block)))) + (at-next (should (equal 2 (org-babel-execute-src-block)))) + (at-next (should (equal 3 (org-babel-execute-src-block)))) + (at-next (should (equal 4 (org-babel-execute-src-block))))))) (ert-deftest test-org-babel/org-babel-get-inline-src-block-matches () - (org-test-at-id "0D0983D4-DE33-400A-8A05-A225A567BC74" - (let ((test-point (point))) - (should (fboundp 'org-babel-get-inline-src-block-matches)) - (should (re-search-forward "src_" nil t)) ;; 1 - (should (org-babel-get-inline-src-block-matches)) - (should (re-search-forward "}" nil (point-at-bol))) ;; 1 - (should-not (org-babel-get-inline-src-block-matches)) - (should (re-search-forward "in" nil t)) ;; 2 - (should-not (org-babel-get-inline-src-block-matches)) - (should (re-search-forward "echo" nil t)) ;; 2 - (should (org-babel-get-inline-src-block-matches)) - (should (re-search-forward "blocks" nil t)) ;; 3 - (backward-char 8) ;; 3 - (should (org-babel-get-inline-src-block-matches)) - (forward-char 1) ;;3 - (should-not (org-babel-get-inline-src-block-matches)) - (should (re-search-forward ":results" nil t)) ;; 4 - (should (org-babel-get-inline-src-block-matches)) - (end-of-line) - (should-not (org-babel-get-inline-src-block-matches))))) + (flet ((test-at-id (id) + (org-test-at-id + id + (let ((test-point (point))) + (should (fboundp 'org-babel-get-inline-src-block-matches)) + (should (re-search-forward "src_" nil t)) ;; 1 + (should (org-babel-get-inline-src-block-matches)) + (should (re-search-forward "}" nil (point-at-bol))) ;; 1 + (should-not (org-babel-get-inline-src-block-matches)) + (should (re-search-forward "in" nil t)) ;; 2 + (should-not (org-babel-get-inline-src-block-matches)) + (should (re-search-forward "echo" nil t)) ;; 2 + (should (org-babel-get-inline-src-block-matches)) + (should (re-search-forward "blocks" nil t)) ;; 3 + (backward-char 8) ;; 3 + (should (org-babel-get-inline-src-block-matches)) + (forward-char 1) ;;3 + (should-not (org-babel-get-inline-src-block-matches)) + (should (re-search-forward ":results" nil t)) ;; 4 + (should (org-babel-get-inline-src-block-matches)) + (end-of-line) + (should-not (org-babel-get-inline-src-block-matches)))))) + (test-at-id "0D0983D4-DE33-400A-8A05-A225A567BC74") + (test-at-id "d55dada7-de0e-4340-8061-787cccbedee5"))) (ert-deftest test-org-babel/inline-src_blk-default-results-replace-line-1 () (let ((test-line "src_sh{echo 1}")) diff --git a/testing/lisp/test-org-element.el b/testing/lisp/test-org-element.el index 1705a4d..0bd8501 100644 --- a/testing/lisp/test-org-element.el +++ b/testing/lisp/test-org-element.el @@ -1051,6 +1051,28 @@ Some other text (should (org-test-with-temp-text "src_emacs-lisp{(+ 1 1)}" (org-element-map (org-element-parse-buffer) 'inline-src-block 'identity))) + ;; With switches. + (should + (org-test-with-temp-text "src_emacs-lisp[:foo bar]{(+ 1 1)}" + (org-element-map (org-element-parse-buffer) 'inline-src-block 'identity))) + (should + (org-test-with-temp-text "src_emacs-lisp[ :foo bar]{(+ 1 1)}" + (org-element-map (org-element-parse-buffer) 'inline-src-block 'identity))) + ;; Empty switches. + (should + (org-test-with-temp-text "src_emacs-lisp[]{(+ 1 1)}" + (org-element-map (org-element-parse-buffer) 'inline-src-block 'identity))) + ;; Invalid syntax. + (should-not + (org-test-with-temp-text "foosrc_emacs-lisp[]{(+ 1 1)}" + (org-element-map (org-element-parse-buffer) 'inline-src-block 'identity))) + (should-not + (org-test-with-temp-text "src_emacs-lisp[]foo{(+ 1 1)}" + (org-element-map (org-element-parse-buffer) 'inline-src-block 'identity))) + ;; Invalid language name + (should-not + (org-test-with-temp-text "src_emacs-\tlisp{(+ 1 1)}" + (org-element-map (org-element-parse-buffer) 'inline-src-block 'identity))) ;; Test parsing at the beginning of an item. (should (org-test-with-temp-text "- src_emacs-lisp{(+ 1 1)}" -- 2.0.0.rc4