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.
This commit is contained in:
Nicolas Berthier 2014-06-13 15:32:54 +02:00 committed by Nicolas Goaziou
parent 767895c970
commit 795c004396
6 changed files with 208 additions and 36 deletions

View File

@ -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.")

View File

@ -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)))

View File

@ -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

View File

@ -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)

View File

@ -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}"))

View File

@ -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)}"