浏览代码

lisp/ob-core.el: Inline source block / babel call results are replaceable

* lisp/ob-core.el (org-babel-remove-inline-result): Delete results of
  current inline src block or inline babel call if it is wrapped in a
  "{{{results(.*)}}}" macro call.

* lisp/ob-core.el (org-babel-get-lob-one-liner-matches): Ensure that
  the point ends up on the same line as, and just before, `call_'
  before setting match-data.

* ob-core.el (org-babel-get-inline-src-block-matches): Use
  `org-element-context' and friends to find inline-src-block.  When
  point is in an inline-src-block (including white space determined by
  :post-blank) set match-data and return `t'.

* lisp/ob-core.el (org-babel-insert-result): Delete any `results'
  macro following current inline src block or babel call; insert
  current value in 'results' macro possibly wrapping RESULT in an
  export snippet or inline source block first.  Use of `:results list'
  or `:results table', or use of a multiline RESULT (after stripping a
  trailing newline) or a list RESULT from an inline src block or babel
  call throws an error.
Charles Berry 10 年之前
父节点
当前提交
85ff663ce4
共有 1 个文件被更改,包括 120 次插入56 次删除
  1. 120 56
      lisp/ob-core.el

+ 120 - 56
lisp/ob-core.el

@@ -209,7 +209,7 @@ 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
@@ -228,32 +228,21 @@ not match KEY should be returned."
 (defun org-babel-get-inline-src-block-matches ()
   "Set match data if within body of an inline source block.
 Returns non-nil if match-data set"
-  (let ((src-at-0-p (save-excursion
-		      (beginning-of-line 1)
-		      (org-looking-at-p "src")))
-	(first-line-p (= (line-beginning-position) (point-min)))
-	(orig (point)))
-    (let ((search-for (cond ((and src-at-0-p first-line-p  "src_"))
-			    (first-line-p "[[:punct:] \t]src_")
-			    (t "[[:punct:] \f\t\n\r\v]src_")))
-	  (lower-limit (if first-line-p
-			   nil
-			 (- (point-at-bol) 1))))
-      (save-excursion
-	(when (or (and src-at-0-p (bobp))
-		  (and (re-search-forward "}" (point-at-eol) t)
-		       (re-search-backward search-for lower-limit t)
-		       (> orig (point))))
-	  (when (looking-at org-babel-inline-src-block-regexp)
-	    t ))))))
+ (save-excursion
+    (let ((datum (org-element-context)))
+      (when (eq (org-element-type datum) 'inline-src-block)
+	(goto-char (org-element-property :begin datum))
+	(when (looking-at org-babel-inline-src-block-regexp)
+	  t )))))
 
 (defvar org-babel-inline-lob-one-liner-regexp)
 (defun org-babel-get-lob-one-liner-matches ()
   "Set match data if on line of an lob one liner.
 Returns non-nil if match-data set"
   (save-excursion
-    (unless (= (point) (point-at-bol)) ;; move before inline block
-      (re-search-backward "[ \f\t\n\r\v]" nil t))
+    (let ((datum (org-element-context)))
+      (when (eq (org-element-type datum) 'inline-babel-call)
+	(goto-char (org-element-property :begin datum))))
     (if (looking-at org-babel-inline-lob-one-liner-regexp)
 	t
       nil)))
@@ -2063,21 +2052,27 @@ If the path of the link is a file path it is expanded using
 (defun org-babel-insert-result
   (result &optional result-params info hash indent lang)
   "Insert RESULT into the current buffer.
-By default RESULT is inserted after the end of the
-current source block.  With optional argument RESULT-PARAMS
-controls insertion of results in the org-mode file.
-RESULT-PARAMS can take the following values:
+
+By default RESULT is inserted after the end of the current source
+block.  The RESULT of an inline source block usually will be
+wrapped inside a `results' macro and placed on the same line as
+the inline source block.  The macro is stripped upon export.
+Multiline and non-scalar RESULTS from inline source blocks are
+not allowed.  With optional argument RESULT-PARAMS controls
+insertion of results in the Org mode file.  RESULT-PARAMS can
+take the following values:
 
 replace - (default option) insert results after the source block
-          replacing any previously inserted results
+          or inline source block replacing any previously
+          inserted results.
 
 silent -- no results are inserted into the Org-mode buffer but
           the results are echoed to the minibuffer and are
           ingested by Emacs (a potentially time consuming
-          process)
+          process).
 
 file ---- the results are interpreted as a file path, and are
-          inserted into the buffer using the Org-mode file syntax
+          inserted into the buffer using the Org-mode file syntax.
 
 list ---- the results are interpreted as an Org-mode list.
 
@@ -2086,8 +2081,9 @@ raw ----- results are added directly to the Org-mode file.  This
           formatted text.
 
 drawer -- results are added directly to the Org-mode file as with
-          \"raw\", but are wrapped in a RESULTS drawer, allowing
-          them to later be replaced or removed automatically.
+          \"raw\", but are wrapped in a RESULTS drawer or results
+          macro, allowing them to later be replaced or removed
+          automatically.
 
 org ----- results are added inside of a \"src_org{}\" or \"#+BEGIN_SRC
           org\" block depending on whether the current source block is
@@ -2095,20 +2091,39 @@ org ----- results are added inside of a \"src_org{}\" or \"#+BEGIN_SRC
           but Org syntax here will be discarded when exporting the
           file.
 
-html ---- results are added inside of a #+BEGIN_HTML block.  This
-          is a good option if you code block will output html
-          formatted text.
+html ---- results are added inside of a #+BEGIN_HTML block or
+          html export snippet depending on whether the current
+          source block is inline or not.  This is a good option
+          if your code block will output html formatted text.
 
-latex --- results are added inside of a #+BEGIN_LATEX block.
-          This is a good option if you code block will output
-          latex formatted text.
+latex --- results are added inside of a #+BEGIN_LATEX block or
+          latex export snippet depending on whether the current
+          source block is inline or not.  This is a good option
+          if your code block will output latex formatted text.
 
 code ---- the results are extracted in the syntax of the source
           code of the language being evaluated and are added
           inside of a source block with the source-code language
           set appropriately.  Also, source block inlining is
           preserved in this case.  Note this relies on the
-          optional LANG argument."
+          optional LANG argument.
+
+list ---- the results are rendered as a list.  This option not
+          allowed for inline src blocks.
+
+table --- the results are rendered as a table.  This option not
+          allowed for inline src blocks.
+
+INFO may provide the values of these header arguments (in the
+`header-arguments-alist' see the docstring for
+`org-babel-get-src-block-info'):
+
+:file --- the name of the file to which output should be written.
+
+:wrap --- the effect is similar to `latex' in RESULT-PARAMS but
+          using the argument supplied to specify the export block
+          or snippet type."
+
   (if (stringp result)
       (progn
         (setq result (org-no-properties result))
@@ -2128,11 +2143,19 @@ code ---- the results are extracted in the syntax of the source
 		(when (or (org-babel-get-inline-src-block-matches)
 			  (org-babel-get-lob-one-liner-matches))
 		  (goto-char (match-end 0))
-		  (insert (if (listp result) "\n" " "))
+		  (insert " ")
 		  (point))))
-	     (existing-result (unless inlinep
+	     (existing-result (if inlinep
+				  (org-babel-remove-inline-result)
 				(org-babel-where-is-src-block-result
 				 t info hash indent)))
+	     (bad-inline-p
+	      (when inlinep
+		(or
+		 (and (member "table" result-params) "`:results table'")
+		 (and (listp result) "list result")
+		 (and (org-string-match-p "\n." result) "multiline result")
+		 (and (member "list" result-params) "`:results list'"))))
 	     (results-switches
 	      (cdr (assoc :results_switches (nth 2 info))))
 	     (visible-beg (copy-marker (point-min)))
@@ -2169,7 +2192,12 @@ code ---- the results are extracted in the syntax of the source
 		 ((member "prepend" result-params)))) ; already there
 	      (setq results-switches
 		    (if results-switches (concat " " results-switches) ""))
-	      (let ((wrap (lambda (start finish &optional no-escape no-newlines)
+	      (let ((wrap (lambda (start finish &optional no-escape no-newlines
+					 inline-start inline-finish)
+			    (when inlinep
+			      (setq start inline-start)
+			      (setq finish inline-finish)
+			      (setq no-newlines t))
 			    (goto-char end)
 			    (insert (concat finish (unless no-newlines "\n")))
 			    (goto-char beg)
@@ -2182,8 +2210,11 @@ code ---- the results are extracted in the syntax of the source
 		    (proper-list-p (lambda (it) (and (listp it) (null (cdr (last it)))))))
 		;; insert results based on type
 		(cond
-		 ;; do nothing for an empty result
+		 ;; Do nothing for an empty result.
 		 ((null result))
+		 ;; Illegal inline result or params.
+		 (bad-inline-p
+		  (error "Inline error: %s cannot be used" bad-inline-p))
 		 ;; insert a list if preferred
 		 ((member "list" result-params)
 		  (insert
@@ -2208,44 +2239,59 @@ code ---- the results are extracted in the syntax of the source
 		 ((and (listp result) (not (funcall proper-list-p result)))
 		  (insert (format "%s\n" result)))
 		 ((member "file" result-params)
-		  (when inlinep (goto-char inlinep))
+		  (when inlinep
+		    (goto-char inlinep)
+		    (setq result (org-macro-escape-arguments result)))
 		  (insert result))
+		 ((and inlinep
+		       (not (member "raw" result-params)))
+		  (goto-char inlinep)
+		  (insert (org-macro-escape-arguments
+			   (org-babel-chomp result "\n"))))
 		 (t (goto-char beg) (insert result)))
 		(when (funcall proper-list-p result) (goto-char (org-table-end)))
 		(setq end (point-marker))
 		;; possibly wrap result
 		(cond
+		 (bad-inline-p) ; Do nothing.
 		 ((assoc :wrap (nth 2 info))
 		  (let ((name (or (cdr (assoc :wrap (nth 2 info))) "RESULTS")))
 		    (funcall wrap (concat "#+BEGIN_" name)
-			     (concat "#+END_" (car (org-split-string name))))))
+			     (concat "#+END_" (car (org-split-string name)))
+			     nil nil (concat "{{{results(@@" name ":") "@@)}}}")))
 		 ((member "html" result-params)
-		  (funcall wrap "#+BEGIN_HTML" "#+END_HTML"))
+		  (funcall wrap "#+BEGIN_HTML" "#+END_HTML" nil nil
+			   "{{{results(@@html:" "@@)}}}"))
 		 ((member "latex" result-params)
-		  (funcall wrap "#+BEGIN_LaTeX" "#+END_LaTeX"))
+		  (funcall wrap "#+BEGIN_LaTeX" "#+END_LaTeX" nil nil
+			   "{{{results(@@latex:" "@@)}}}"))
 		 ((member "org" result-params)
 		  (goto-char beg) (if (org-at-table-p) (org-cycle))
-		  (if inlinep
-		      (funcall wrap "src_org{" "}" nil t)
-		      (funcall wrap "#+BEGIN_SRC org" "#+END_SRC")))
+		  (funcall wrap "#+BEGIN_SRC org" "#+END_SRC" nil nil
+			   "{{{results(src_org{" "})}}}"))
 		 ((member "code" result-params)
 		  (let ((lang (or lang "none")))
-		    (if inlinep
-			(funcall wrap (format "src_%s[%s]{" lang results-switches)
-				 "}" nil t)
-			(funcall wrap (format "#+BEGIN_SRC %s%s" lang results-switches)
-				 "#+END_SRC"))))
+		    (funcall wrap (format "#+BEGIN_SRC %s%s" lang results-switches)
+			     "#+END_SRC" nil nil
+			     (format "{{{results(src_%s[%s]{" lang results-switches)
+			     "})}}}")))
 		 ((member "raw" result-params)
 		  (goto-char beg) (if (org-at-table-p) (org-cycle)))
 		 ((or (member "drawer" result-params)
 		      ;; Stay backward compatible with <7.9.2
 		      (member "wrap" result-params))
 		  (goto-char beg) (if (org-at-table-p) (org-cycle))
-		  (funcall wrap ":RESULTS:" ":END:" 'no-escape))
+		  (funcall wrap ":RESULTS:" ":END:" 'no-escape nil
+			   "{{{results(" ")}}}"))
+		 ((and inlinep (member "file" result-params))
+		  (funcall wrap nil nil nil nil "{{{results(" ")}}}"))
 		 ((and (not (funcall proper-list-p result))
 		       (not (member "file" result-params)))
-		  (org-babel-examplify-region beg end results-switches)
-		  (setq end (point)))))
+		  (let ((org-babel-inline-result-wrap
+			 ;; Hard code {{{results(...)}}} on top of customization.
+			 (format "{{{results(%s)}}}" org-babel-inline-result-wrap)))
+		    (org-babel-examplify-region beg end results-switches)
+		    (setq end (point))))))
 	      ;; possibly indent the results to match the #+results line
 	      (when (and (not inlinep) (numberp indent) indent (> indent 0)
 			 ;; in this case `table-align' does the work for us
@@ -2273,6 +2319,24 @@ code ---- the results are extracted in the syntax of the source
 	   (if keep-keyword (1+ (match-end 0)) (1- (match-beginning 0)))
 	   (progn (forward-line 1) (org-babel-result-end))))))))
 
+(defun org-babel-remove-inline-result ()
+  "Remove the result of the current inline-src-block or babel call.
+The result must be wrapped in a `results' macro to be
+  removed. Extraneous leading whitespace is trimmed."
+  (let* ((el (org-element-context))
+	 (post-blank (org-element-property :post-blank el)))
+    (when (memq (org-element-type el) '(inline-src-block inline-babel-call))
+      (org-with-wide-buffer
+        (goto-char (org-element-property :end el))
+        (let ((el (org-element-context)))
+	  (when (and (eq (org-element-type el) 'macro)
+		     (string= (org-element-property :key el) "results"))
+	    (delete-region ; And (only) extra leading whitespace.
+	     (- (org-element-property :begin el)
+		(- post-blank 1))
+	     (- (org-element-property :end el)
+		(org-element-property :post-blank el)))))))))
+
 (defun org-babel-remove-result-one-or-many (x)
   "Remove the result of the current source block.
 If called with a prefix argument, remove all result blocks