Browse Source

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 years ago
parent
commit
85ff663ce4
1 changed files with 120 additions and 56 deletions
  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
 (defvar org-babel-inline-src-block-regexp
   (concat
   (concat
    ;; (1) replacement target (2) lang
    ;; (1) replacement target (2) lang
-   "\\(?:^\\|[^-[:alnum:]]\\)\\(src_\\([^ \f\t\n\r\v[]+\\)"
+   "\\(?:^\\|[^-[:alnum:]]?\\)\\(src_\\([^ \f\t\n\r\v[]+\\)"
    ;; (3,4) (unused, headers)
    ;; (3,4) (unused, headers)
    "\\(\\|\\[[ \t]*\\(.*?\\)\\]\\)"
    "\\(\\|\\[[ \t]*\\(.*?\\)\\]\\)"
    ;; (5) body
    ;; (5) body
@@ -228,32 +228,21 @@ not match KEY should be returned."
 (defun org-babel-get-inline-src-block-matches ()
 (defun org-babel-get-inline-src-block-matches ()
   "Set match data if within body of an inline source block.
   "Set match data if within body of an inline source block.
 Returns non-nil if match-data set"
 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)
 (defvar org-babel-inline-lob-one-liner-regexp)
 (defun org-babel-get-lob-one-liner-matches ()
 (defun org-babel-get-lob-one-liner-matches ()
   "Set match data if on line of an lob one liner.
   "Set match data if on line of an lob one liner.
 Returns non-nil if match-data set"
 Returns non-nil if match-data set"
   (save-excursion
   (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)
     (if (looking-at org-babel-inline-lob-one-liner-regexp)
 	t
 	t
       nil)))
       nil)))
@@ -2063,21 +2052,27 @@ If the path of the link is a file path it is expanded using
 (defun org-babel-insert-result
 (defun org-babel-insert-result
   (result &optional result-params info hash indent lang)
   (result &optional result-params info hash indent lang)
   "Insert RESULT into the current buffer.
   "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
 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
 silent -- no results are inserted into the Org-mode buffer but
           the results are echoed to the minibuffer and are
           the results are echoed to the minibuffer and are
           ingested by Emacs (a potentially time consuming
           ingested by Emacs (a potentially time consuming
-          process)
+          process).
 
 
 file ---- the results are interpreted as a file path, and are
 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.
 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.
           formatted text.
 
 
 drawer -- results are added directly to the Org-mode file as with
 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 ----- results are added inside of a \"src_org{}\" or \"#+BEGIN_SRC
           org\" block depending on whether the current source block is
           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
           but Org syntax here will be discarded when exporting the
           file.
           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 ---- the results are extracted in the syntax of the source
           code of the language being evaluated and are added
           code of the language being evaluated and are added
           inside of a source block with the source-code language
           inside of a source block with the source-code language
           set appropriately.  Also, source block inlining is
           set appropriately.  Also, source block inlining is
           preserved in this case.  Note this relies on the
           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)
   (if (stringp result)
       (progn
       (progn
         (setq result (org-no-properties result))
         (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)
 		(when (or (org-babel-get-inline-src-block-matches)
 			  (org-babel-get-lob-one-liner-matches))
 			  (org-babel-get-lob-one-liner-matches))
 		  (goto-char (match-end 0))
 		  (goto-char (match-end 0))
-		  (insert (if (listp result) "\n" " "))
+		  (insert " ")
 		  (point))))
 		  (point))))
-	     (existing-result (unless inlinep
+	     (existing-result (if inlinep
+				  (org-babel-remove-inline-result)
 				(org-babel-where-is-src-block-result
 				(org-babel-where-is-src-block-result
 				 t info hash indent)))
 				 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
 	     (results-switches
 	      (cdr (assoc :results_switches (nth 2 info))))
 	      (cdr (assoc :results_switches (nth 2 info))))
 	     (visible-beg (copy-marker (point-min)))
 	     (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
 		 ((member "prepend" result-params)))) ; already there
 	      (setq results-switches
 	      (setq results-switches
 		    (if results-switches (concat " " 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)
 			    (goto-char end)
 			    (insert (concat finish (unless no-newlines "\n")))
 			    (insert (concat finish (unless no-newlines "\n")))
 			    (goto-char beg)
 			    (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)))))))
 		    (proper-list-p (lambda (it) (and (listp it) (null (cdr (last it)))))))
 		;; insert results based on type
 		;; insert results based on type
 		(cond
 		(cond
-		 ;; do nothing for an empty result
+		 ;; Do nothing for an empty result.
 		 ((null 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
 		 ;; insert a list if preferred
 		 ((member "list" result-params)
 		 ((member "list" result-params)
 		  (insert
 		  (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)))
 		 ((and (listp result) (not (funcall proper-list-p result)))
 		  (insert (format "%s\n" result)))
 		  (insert (format "%s\n" result)))
 		 ((member "file" result-params)
 		 ((member "file" result-params)
-		  (when inlinep (goto-char inlinep))
+		  (when inlinep
+		    (goto-char inlinep)
+		    (setq result (org-macro-escape-arguments result)))
 		  (insert 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)))
 		 (t (goto-char beg) (insert result)))
 		(when (funcall proper-list-p result) (goto-char (org-table-end)))
 		(when (funcall proper-list-p result) (goto-char (org-table-end)))
 		(setq end (point-marker))
 		(setq end (point-marker))
 		;; possibly wrap result
 		;; possibly wrap result
 		(cond
 		(cond
+		 (bad-inline-p) ; Do nothing.
 		 ((assoc :wrap (nth 2 info))
 		 ((assoc :wrap (nth 2 info))
 		  (let ((name (or (cdr (assoc :wrap (nth 2 info))) "RESULTS")))
 		  (let ((name (or (cdr (assoc :wrap (nth 2 info))) "RESULTS")))
 		    (funcall wrap (concat "#+BEGIN_" name)
 		    (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)
 		 ((member "html" result-params)
-		  (funcall wrap "#+BEGIN_HTML" "#+END_HTML"))
+		  (funcall wrap "#+BEGIN_HTML" "#+END_HTML" nil nil
+			   "{{{results(@@html:" "@@)}}}"))
 		 ((member "latex" result-params)
 		 ((member "latex" result-params)
-		  (funcall wrap "#+BEGIN_LaTeX" "#+END_LaTeX"))
+		  (funcall wrap "#+BEGIN_LaTeX" "#+END_LaTeX" nil nil
+			   "{{{results(@@latex:" "@@)}}}"))
 		 ((member "org" result-params)
 		 ((member "org" result-params)
 		  (goto-char beg) (if (org-at-table-p) (org-cycle))
 		  (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)
 		 ((member "code" result-params)
 		  (let ((lang (or lang "none")))
 		  (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)
 		 ((member "raw" result-params)
 		  (goto-char beg) (if (org-at-table-p) (org-cycle)))
 		  (goto-char beg) (if (org-at-table-p) (org-cycle)))
 		 ((or (member "drawer" result-params)
 		 ((or (member "drawer" result-params)
 		      ;; Stay backward compatible with <7.9.2
 		      ;; Stay backward compatible with <7.9.2
 		      (member "wrap" result-params))
 		      (member "wrap" result-params))
 		  (goto-char beg) (if (org-at-table-p) (org-cycle))
 		  (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))
 		 ((and (not (funcall proper-list-p result))
 		       (not (member "file" result-params)))
 		       (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
 	      ;; possibly indent the results to match the #+results line
 	      (when (and (not inlinep) (numberp indent) indent (> indent 0)
 	      (when (and (not inlinep) (numberp indent) indent (> indent 0)
 			 ;; in this case `table-align' does the work for us
 			 ;; 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)))
 	   (if keep-keyword (1+ (match-end 0)) (1- (match-beginning 0)))
 	   (progn (forward-line 1) (org-babel-result-end))))))))
 	   (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)
 (defun org-babel-remove-result-one-or-many (x)
   "Remove the result of the current source block.
   "Remove the result of the current source block.
 If called with a prefix argument, remove all result blocks
 If called with a prefix argument, remove all result blocks