Browse Source

Merge branch 'master' of git+ssh://repo.or.cz/srv/git/org-mode

Carsten Dominik 15 years ago
parent
commit
1cf50b7eb0

+ 6 - 6
contrib/babel/lisp/org-babel-exp.el

@@ -37,14 +37,14 @@
 
 (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 #+srcname:. A
-source block is considered to be a source block function if the
-srcname is present and is followed by a parenthesised argument
-list. The parentheses may be empty or contain whitespace. An
-example is the following which generates n random
+appear in the exported version in the place of source name
+line. A source block is considered to be a source block function
+if the source name is present and is followed by a parenthesized
+argument list. The parentheses may be empty or contain
+whitespace. An example is the following which generates n random
 (uniform) numbers.
 
-#+srcname: rand(n)
+#+source: rand(n)
 #+begin_src R
   runif(n)
 #+end_src

+ 12 - 2
contrib/babel/lisp/org-babel-lob.el

@@ -54,9 +54,19 @@ add files to this list use the `org-babel-lob-ingest' command."
               (cons (cons source-name info)
                     (assq-delete-all source-name org-babel-library-of-babel)))))))
 
-;; functions for executing lob one-liners
+(defconst org-babel-lob-call-aliases '("lob" "call")
+  "These can be used interchangeably to call a source block
+  function. If you change the value of this variable then your
+  files may become unusable by other org-babel users, and vice
+  versa.")
+  
+(defconst org-babel-lob-one-liner-regexp
+  (concat "^[ \t]*#\\+\\(?:"
+	  (mapconcat #'regexp-quote org-babel-lob-call-aliases "\\|")
+	  "\\):[ \t]+\\([^\(\)\n]+\\)\(\\([^\n]*\\)\)[ \t]*\\([^\n]*\\)")
+  "Regexp to match calls to predefined source block functions")
 
-(defvar org-babel-lob-one-liner-regexp "^[ \t]*#\\+lob:[ \t]+\\([^\(\)\n]+\\)\(\\([^\n]*\\)\)[ \t]*\\([^\n]*\\)")
+;; functions for executing lob one-liners
 
 (defun org-babel-lob-execute-maybe ()
   "Detect if this is context for a org-babel Library Of Babel

+ 6 - 6
contrib/babel/lisp/org-babel-ref.el

@@ -118,9 +118,9 @@ return nil."
         (setq split-ref (match-string 2 ref))
         (find-file split-file) (setq ref split-ref))
       (goto-char (point-min))
-      (if (let ((result_regexp (concat "^#\\+\\(TBL\\|RES\\)NAME:[ \t]*"
+      (if (let ((result_regexp (concat "^#\\+\\(TBLNAME\\|RESNAME\\|RESULT\\):[ \t]*"
                                        (regexp-quote ref) "[ \t]*$"))
-                (regexp (concat "^#\\+SRCNAME:[ \t]*"
+                (regexp (concat org-babel-source-name-regexp
                                 (regexp-quote ref) "\\(\(.*\)\\)?" "[ \t]*$")))
             ;; goto ref in the current buffer
             (or (and (not args)
@@ -145,13 +145,13 @@ return nil."
           (beginning-of-line)
           (if (or (= (point) (point-min)) (= (point) (point-max)))
               (error "reference not found"))))
-      (setq params (org-babel-merge-params params args))
+      (setq params (org-babel-merge-params params args '((:results . "silent"))))
       (setq result
 	    (case type
 	      ('results-line (org-babel-read-result))
 	      ('table (org-babel-read-table))
-	      ('source-block (org-babel-execute-src-block t nil params))
-	      ('lob (org-babel-execute-src-block t lob-info params))))
+	      ('source-block (org-babel-execute-src-block nil nil params))
+	      ('lob (org-babel-execute-src-block nil lob-info params))))
       (if (symbolp result)
           (format "%S" result)
         (if (and index (listp result))
@@ -202,7 +202,7 @@ of the supported reference types are found.  Supported reference
 types are tables and source blocks."
   (cond ((org-at-table-p) 'table)
         ((looking-at "^#\\+BEGIN_SRC") 'source-block)
-        ((looking-at "^#\\+RESNAME:") 'results-line)))
+        ((looking-at org-babel-result-regexp) 'results-line)))
 
 (provide 'org-babel-ref)
 ;;; org-babel-ref.el ends here

+ 7 - 6
contrib/babel/lisp/org-babel-tangle.el

@@ -32,12 +32,13 @@
 (require 'org-babel)
 
 (defvar org-babel-tangle-langs nil
-  "Association list matching source-block languages.  The car of
-each element should be a string indicating the source block
-language, and the cdr should be a list containing the extension
-shebang(#!) line to use when writing out the language to file,
-and an optional flag indicating that the language is not
-commentable.")
+  "List of languages supported by `org-babel-tangle'.  The first
+element of each language's list is a string indicating the name
+of the language, the second element should be the file extension
+of the language, an optional third element the shebang(#!)  line
+to use when writing out the language to file, and an optional
+fourth element is a flag which when true indicates that the
+language does not support comments.")
 
 (defun org-babel-load-file (file)
   "Load the contents of the Emacs Lisp source code blocks in the

+ 241 - 78
contrib/babel/lisp/org-babel.el

@@ -80,7 +80,7 @@ then run `org-babel-pop-to-session'."
 (add-hook 'org-metadown-hook 'org-babel-pop-to-session-maybe)
 
 (defvar org-babel-default-header-args
-  '((:session . "none") (:results . "replace") (:exports . "code"))
+  '((:session . "none") (:results . "replace") (:exports . "code") (:nocache))
   "Default arguments to use when evaluating a source block.")
 
 (defvar org-babel-default-inline-header-args
@@ -93,22 +93,34 @@ then run `org-babel-pop-to-session'."
 (defvar org-babel-inline-src-block-regexp nil
   "Regexp used to test when on an inline org-babel src-block")
 
+(defvar org-babel-result-regexp
+  "#\\+res\\(ults\\|name\\)\\(\\[\\([[:alnum:]]+\\)\\]\\)?\\:"
+  "Regular expression used to match result lines.  If the
+results are associated with a hash key then the hash will be
+saved in the second match data.")
+
+(defvar org-babel-source-name-regexp
+  "#\\+\\(srcname\\|source\\|function\\):[ \t]*"
+  "Regular expression used to match a source name line.")
+
 (defvar org-babel-min-lines-for-block-output 10
   "If number of lines of output is equal to or exceeds this
-  value, the output is placed in a
-  #+begin_example...#+end_example block. Otherwise the output is
-  marked as literal by inserting colons at the starts of the
-  lines. This variable only takes effect if the :results output
-  option is in effect.")
+value, the output is placed in a #+begin_example...#+end_example
+block. Otherwise the output is marked as literal by inserting
+colons at the starts of the lines. This variable only takes
+effect if the :results output option is in effect.")
 
 (defvar org-babel-noweb-error-langs nil
   "List of language for which errors should be raised when the
-  source code block satisfying a noweb reference in this language
-  can not be resolved.")
+source code block satisfying a noweb reference in this language
+can not be resolved.")
+
+(defvar org-babel-hash-show 4
+  "Number of initial characters to show of a hidden results hash.")
 
 (defun org-babel-named-src-block-regexp-for-name (name)
   "Regexp used to match named src block."
-  (concat "#\\+srcname:[ \t]*" (regexp-quote name) "[ \t\n]*"
+  (concat org-babel-source-name-regexp (regexp-quote name) "[ \t\n]*"
 	  (substring org-babel-src-block-regexp 1)))
 
 (defun org-babel-set-interpreters (var value)
@@ -164,23 +176,27 @@ lisp code use the `org-babel-add-interpreter' function."
 
 ;;; functions
 (defun org-babel-execute-src-block (&optional arg info params)
-  "Execute the current source code block, and dump the results
-into the buffer immediately following the block.  Results are
-commented by `org-toggle-fixed-width-section'.  With optional
-prefix don't dump results into buffer but rather return the
-results in raw elisp (this is useful for automated execution of a
-source block).
+  "Execute the current source code block, and insert the results
+into the buffer.  Source code execution and the collection and
+formatting of results can be controlled through a variety of
+header arguments.
 
 Optionally supply a value for INFO in the form returned by
 `org-babel-get-src-block-info'.
 
 Optionally supply a value for PARAMS which will be merged with
-the header arguments specified at the source code block."
+the header arguments specified at the front of the source code
+block."
   (interactive)
   ;; (message "supplied params=%S" params) ;; debugging
   (let* ((info (or info (org-babel-get-src-block-info)))
          (lang (first info))
-	 (params (setf (third info) (org-babel-merge-params (third info) params)))
+	 (params (setf (third info)
+                       (sort (org-babel-merge-params (third info) params)
+                             (lambda (el1 el2) (string< (symbol-name (car el1))
+                                                   (symbol-name (car el2)))))))
+         (new-hash (unless (assoc :nocache params) (org-babel-sha1-hash info)))
+         (old-hash (org-babel-result-hash info))
          (body (setf (second info)
 		     (if (assoc :noweb params)
 			 (org-babel-expand-noweb-references info) (second info))))
@@ -193,16 +209,21 @@ the header arguments specified at the source code block."
     ;; (message "params=%S" params) ;; debugging
     (unless (member lang org-babel-interpreters)
       (error "Language is not in `org-babel-interpreters': %s" lang))
-    (when arg (setq result-params (cons "silent" result-params)))
-    (setq result (funcall cmd body params))
-    (if (eq result-type 'value)
-        (setq result (if (and (or (member "vector" result-params)
-                                  (member "table" result-params))
-                              (not (listp result)))
-                         (list (list result))
-                       result)))
-    (org-babel-insert-result result result-params info)
-    result))
+    (if (and (not arg) new-hash (equal new-hash old-hash))
+        (save-excursion ;; return cached result
+          (goto-char (org-babel-where-is-src-block-result nil info))
+          (move-end-of-line 1) (forward-char 1)
+          (setq result (org-babel-read-result))
+          (message (replace-regexp-in-string "%" "%%" (format "%S" result))) result)
+      (setq result (funcall cmd body params))
+      (if (eq result-type 'value)
+          (setq result (if (and (or (member "vector" result-params)
+                                    (member "table" result-params))
+                                (not (listp result)))
+                           (list (list result))
+                         result)))
+      (org-babel-insert-result result result-params info new-hash)
+      result)))
 
 (defun org-babel-load-in-session (&optional arg info)
   "Load the body of the current source-code block.  Evaluate the
@@ -302,15 +323,16 @@ added to the header-arguments-alist."
 	  (goto-char head)
 	  (setq info (org-babel-parse-src-block-match))
 	  (forward-line -1)
-	  (when (looking-at "#\\+srcname:[ \t]*\\([^ ()\f\t\n\r\v]+\\)\\(\(\\(.*\\)\)\\|\\)")
-	    (setq info (append info (list (org-babel-clean-text-properties (match-string 1)))))
+	  (when (looking-at (concat org-babel-source-name-regexp
+                                    "\\([^ ()\f\t\n\r\v]+\\)\\(\(\\(.*\\)\)\\|\\)"))
+	    (setq info (append info (list (org-babel-clean-text-properties (match-string 2)))))
 	    ;; Note that e.g. "name()" and "name( )" result in ((:var . "")).
 	    ;; We maintain that behaviour, and the resulting non-nil sixth
 	    ;; element is relied upon in org-babel-exp-code to detect a functional-style
 	    ;; block in those cases. However, "name" without any
 	    ;; parentheses would result in the same thing, so we
 	    ;; explicitly avoid that.
-	    (if (setq args (match-string 3))
+	    (if (setq args (match-string 4))
 		(setq info (append info (list (mapcar (lambda (ref) (cons :var ref))
 						      (org-babel-ref-split-args args))))))
 	    (unless header-vars-only
@@ -323,6 +345,136 @@ added to the header-arguments-alist."
           (org-babel-parse-inline-src-block-match)
         nil)))) ;; indicate that no source block was found
 
+(defun org-babel-sha1-hash (&optional info)
+  (interactive)
+  (let* ((info (or info (org-babel-get-src-block-info)))
+         (hash (sha1 (format "%s-%s" (mapconcat (lambda (arg) (format "%S" arg))
+                                                (third info) ":")
+                             (second info)))))
+    (when (interactive-p) (message hash))
+    hash))
+
+(defun org-babel-result-hash (&optional info)
+  (org-babel-where-is-src-block-result nil info)
+  (org-babel-clean-text-properties (match-string 3)))
+
+(defun org-babel-hide-hash ()
+  "Hide the hash in the current results line.  Only the initial
+`org-babel-hash-show' characters of the hash will remain
+visible."
+  (org-add-to-invisibility-spec '(org-babel-hide-hash . t))
+  (save-excursion
+    (when (and (re-search-forward org-babel-result-regexp nil t)
+               (match-string 3))
+      (let* ((start (match-beginning 3))
+             (hide-start (+ org-babel-hash-show start))
+             (end (match-end 3))
+             (hash (match-string 3))
+             ov1 ov2)
+        (setq ov1 (org-make-overlay start hide-start))
+        (setq ov2 (org-make-overlay hide-start end))
+        (org-overlay-put ov2 'invisible 'org-babel-hide-hash)
+        (org-overlay-put ov1 'babel-hash hash)))))
+
+(defun org-babel-hide-all-hashes ()
+  "Hide the hash in the current buffer.  Only the initial
+`org-babel-hash-show' characters of each hash will remain
+visible.  This function should be called as part of the
+`org-mode-hook'."
+  (save-excursion
+    (while (re-search-forward org-babel-result-regexp nil t)
+      (goto-char (match-beginning 0))
+      (org-babel-hide-hash)
+      (goto-char (match-end 0)))))
+(add-hook 'org-mode-hook 'org-babel-hide-all-hashes)
+
+(defun org-babel-hash-at-point (&optional point)
+  "Return the value of the hash at `point'.  The hash is also
+added as the last element of the kill ring.  This can be called
+with C-c C-c."
+  (interactive)
+  (let ((hash (car (delq nil (mapcar
+                               (lambda (ol) (org-overlay-get ol 'babel-hash))
+                              (org-overlays-at (or point (point))))))))
+    (when hash (kill-new hash) (message hash))))
+(add-hook 'org-ctrl-c-ctrl-c-hook 'org-babel-hash-at-point)
+
+(defun org-babel-result-hide-spec ()
+  (org-add-to-invisibility-spec '(org-babel-hide-result . t)))
+(add-hook 'org-mode-hook 'org-babel-result-hide-spec)
+
+(defvar org-babel-hide-result-overlays nil
+  "Overlays hiding results.")
+
+(defun org-babel-result-hide-all ()
+  "Fold all results in the current buffer."
+  (interactive)
+  (org-babel-show-result-all)
+  (save-excursion
+    (while (re-search-forward org-babel-result-regexp nil t)
+      (save-excursion (goto-char (match-beginning 0))
+                      (org-babel-hide-result-toggle-maybe)))))
+
+(defun org-babel-show-result-all ()
+  "Unfold all results in the current buffer."
+  (mapc 'org-delete-overlay org-babel-hide-result-overlays)
+  (setq org-babel-hide-result-overlays nil))
+
+(defun org-babel-hide-result-toggle-maybe ()
+  "Toggle visibility of result at point."
+  (interactive)
+  (let ((case-fold-search t))
+    (if (save-excursion
+          (beginning-of-line 1)
+          (looking-at org-babel-result-regexp))
+        (progn (org-babel-hide-result-toggle)
+               t) ;; to signal that we took action
+      nil))) ;; to signal that we did not
+
+(defun org-babel-hide-result-toggle (&optional force)
+  "Toggle the visibility of the current result."
+  (interactive)
+  (save-excursion
+    (beginning-of-line)
+    (if (re-search-forward org-babel-result-regexp nil t)
+        (let ((start (progn (beginning-of-line 2) (- (point) 1)))
+              (end (progn (goto-char (- (org-babel-result-end) 1)) (point)))
+              ov)
+          (if (memq t (mapcar (lambda (overlay)
+                                (eq (org-overlay-get overlay 'invisible)
+				    'org-babel-hide-result))
+                              (org-overlays-at start)))
+              (if (or (not force) (eq force 'off))
+                  (mapc (lambda (ov)
+                          (when (member ov org-babel-hide-result-overlays)
+                            (setq org-babel-hide-result-overlays
+                                  (delq ov org-babel-hide-result-overlays)))
+                          (when (eq (org-overlay-get ov 'invisible)
+                                    'org-babel-hide-result)
+                            (org-delete-overlay ov)))
+                        (org-overlays-at start)))
+            (setq ov (org-make-overlay start end))
+            (org-overlay-put ov 'invisible 'org-babel-hide-result)
+            ;; make the block accessible to isearch
+            (org-overlay-put
+             ov 'isearch-open-invisible
+             (lambda (ov)
+               (when (member ov org-babel-hide-result-overlays)
+                 (setq org-babel-hide-result-overlays
+                       (delq ov org-babel-hide-result-overlays)))
+               (when (eq (org-overlay-get ov 'invisible)
+                         'org-babel-hide-result)
+                 (org-delete-overlay ov))))
+            (push ov org-babel-hide-result-overlays)))
+      (error "Not looking at a result line"))))
+
+;; org-tab-after-check-for-cycling-hook
+(add-hook 'org-tab-first-hook 'org-babel-hide-result-toggle-maybe)
+;; Remove overlays when changing major mode
+(add-hook 'org-mode-hook
+	  (lambda () (org-add-hook 'change-major-mode-hook
+				   'org-babel-show-result-all 'append 'local)))
+
 (defmacro org-babel-map-source-blocks (file &rest body)
   "Evaluate BODY forms on each source-block in FILE."
   (declare (indent 1))
@@ -389,7 +541,8 @@ may be specified in the properties of the current outline entry."
 	     (lambda (arg)
 	       (if (string-match "\\([^ \f\t\n\r\v]+\\)[ \f\t\n\r\v]+\\([^ \f\t\n\r\v]+.*\\)" arg)
 		   (cons (intern (concat ":" (match-string 1 arg)))
-			 (org-babel-chomp (match-string 2 arg)))
+                         (let ((raw (org-babel-chomp (match-string 2 arg))))
+                           (if (org-babel-number-p raw) raw (eval (org-babel-read raw)))))
 		 (cons (intern (concat ":" arg)) nil)))
 	     (split-string (concat " " arg-string) "[ \f\t\n\r\v]+:" t)))))
 
@@ -411,9 +564,9 @@ block.  Specifically at the beginning of the #+BEGIN_SRC line.
 If the point is not on a source block then return nil."
   (let ((initial (point)) top bottom)
     (or
-     (save-excursion ;; on a #+srcname: line
+     (save-excursion ;; on a source name line
        (beginning-of-line 1)
-       (and (looking-at "#\\+srcname") (forward-line 1)
+       (and (looking-at org-babel-source-name-regexp) (forward-line 1)
             (looking-at org-babel-src-block-regexp)
             (point)))
      (save-excursion ;; on a #+begin_src line
@@ -440,9 +593,9 @@ If the point is not on a source block then return nil."
 
 (defun org-babel-find-named-block (name)
   "Find a named source-code block.
-Return the location of the source block identified by
-#+srcname NAME, or nil if no such block exists. Set match data
-according to org-babel-named-src-block-regexp."
+Return the location of the source block identified by source
+NAME, or nil if no such block exists. Set match data according to
+org-babel-named-src-block-regexp."
   (save-excursion
     (let ((case-fold-search t)
 	  (regexp (org-babel-named-src-block-regexp-for-name name)) msg)
@@ -456,15 +609,15 @@ according to org-babel-named-src-block-regexp."
 buffer or nil if no such result exists."
   (save-excursion
     (goto-char (point-min))
-    (when (re-search-forward ;; ellow end-of-buffer in following regexp?
-	   (concat "#\\+resname:[ \t]*" (regexp-quote name) "[ \t\n\f\v\r]") nil t)
+    (when (re-search-forward
+           (concat org-babel-result-regexp "[ \t]" (regexp-quote name) "[ \t\n\f\v\r]") nil t)
       (move-beginning-of-line 0) (point))))
 
-(defun org-babel-where-is-src-block-result (&optional insert info)
+(defun org-babel-where-is-src-block-result (&optional insert info hash)
   "Return the point at the beginning of the result of the current
-source block.  Specifically at the beginning of the #+RESNAME:
-line.  If no result exists for this block then create a
-#+RESNAME: line following the source block."
+source block.  Specifically at the beginning of the results line.
+If no result exists for this block then create a results line
+following the source block."
   (save-excursion
     (let* ((on-lob-line (progn (beginning-of-line 1)
 			       (looking-at org-babel-lob-one-liner-regexp)))
@@ -478,14 +631,17 @@ line.  If no result exists for this block then create a
 		      (if (eobp) (insert "\n") (forward-char 1))
 		      (setq end (point))
                       (or (and (not name)
-			       (progn ;; either the unnamed #+resname: line already exists
+			       (progn ;; unnamed results line already exists
 				 (re-search-forward "[^ \f\t\n\r\v]" nil t)
-				 (move-beginning-of-line 1) (looking-at "#\\+resname:\n")))
-			  ;; or (with optional insert) we need to back up and make one ourselves
+				 (move-beginning-of-line 1)
+                                 (looking-at (concat org-babel-result-regexp "\n"))))
+			  ;; or (with optional insert) back up and make one ourselves
                           (when insert
-                            (goto-char end) (open-line 2) (forward-char 1)
-                            (insert (concat "#+resname:" (if name (concat " " name)) "\n"))
-                            (move-beginning-of-line 0) t)))
+                            (goto-char end) (forward-char 1)
+                            (insert (concat "#+results" (if hash (concat "["hash"]"))
+                                            ":"(if name (concat " " name)) "\n"))
+                            (move-beginning-of-line 0)
+                            (if hash (org-babel-hide-hash)) t)))
                (point))))))
 
 (defun org-babel-read-result ()
@@ -505,7 +661,7 @@ line.  If no result exists for this block then create a
 			 (buffer-substring (point) (org-babel-result-end)) "[\r\n]+")
 			"\n")))
       (or (org-babel-number-p result-string) result-string))
-     ((looking-at "^#\\+RESNAME:")
+     ((looking-at org-babel-result-regexp)
       (save-excursion (forward-line 1) (org-babel-read-result))))))
 
 (defun org-babel-read-table ()
@@ -515,11 +671,11 @@ line.  If no result exists for this block then create a
               (mapcar #'org-babel-read row)))
           (org-table-to-lisp)))
 
-(defun org-babel-insert-result (result &optional insert info)
+(defun org-babel-insert-result (result &optional result-params info hash)
   "Insert RESULT into the current buffer after the end of the
-current source block.  With optional argument INSERT controls
-insertion of results in the org-mode file.  INSERT can take the
-following values...
+current source block.  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
@@ -550,45 +706,51 @@ code ---- the results are extracted in the syntax of the source
   (if (stringp result)
       (progn
         (setq result (org-babel-clean-text-properties result))
-        (if (member "file" insert) (setq result (org-babel-result-to-file result))))
+        (when (member "file" result-params)
+          (setq result (org-babel-result-to-file result))))
     (unless (listp result) (setq result (format "%S" result))))
-  (if (and insert (member "replace" insert) (not (member "silent" insert)))
+  (if (and result-params (member "replace" result-params)
+           (not (member "silent" result-params)))
       (org-babel-remove-result info))
   (if (= (length result) 0)
       (if (member "value" result-params)
 	  (message "No result returned by source block")
 	(message "Source block produced no output"))
-    (if (and insert (member "silent" insert))
-        (progn (message (replace-regexp-in-string "%" "%%" (format "%S" result))) result)
+    (if (and result-params (member "silent" result-params))
+        (progn (message (replace-regexp-in-string "%" "%%" (format "%S" result)))
+               result)
       (when (and (stringp result) ;; ensure results end in a newline
                  (not (or (string-equal (substring result -1) "\n")
                           (string-equal (substring result -1) "\r"))))
         (setq result (concat result "\n")))
       (save-excursion
-	(let ((existing-result (org-babel-where-is-src-block-result t info))
+	(let ((existing-result (org-babel-where-is-src-block-result t info hash))
 	      (results-switches (cdr (assoc :results_switches (third info)))))
 	  (when existing-result (goto-char existing-result) (forward-line 1))
-	  (setq results-switches (if results-switches (concat " " results-switches) ""))
+	  (setq results-switches
+                (if results-switches (concat " " results-switches) ""))
 	  (cond
 	   ;; assume the result is a table if it's not a string
 	   ((not (stringp result))
 	    (insert (concat (orgtbl-to-orgtbl
-			     (if (and (listp (car result)) (listp (cdr (car result))))
+			     (if (and (listp (car result))
+                                      (listp (cdr (car result))))
 				 result (list result))
 			     '(:fmt (lambda (cell) (format "%S" cell)))) "\n"))
 	    (forward-line -1) (org-cycle))
-	   ((member "file" insert)
+	   ((member "file" result-params)
 	    (insert result))
-	   ((member "html" insert)
+	   ((member "html" result-params)
 	    (insert (format "#+BEGIN_HTML%s\n%s#+END_HTML\n" results-switches result)))
-	   ((member "latex" insert)
+	   ((member "latex" result-params)
 	    (insert (format "#+BEGIN_LaTeX%s\n%s#+END_LaTeX\n" results-switches result)))
-	   ((member "code" insert)
+	   ((member "code" result-params)
 	    (insert (format "#+BEGIN_SRC %s%s\n%s#+END_SRC\n" lang results-switches result)))
-	   ((or (member "raw" insert) (member "org" insert))
+	   ((or (member "raw" result-params) (member "org" result-params))
 	    (save-excursion (insert result)) (if (org-at-table-p) (org-cycle)))
 	   (t
-	    (org-babel-examplize-region (point) (progn (insert result) (point)) results-switches)))))
+	    (org-babel-examplize-region
+             (point) (progn (insert result) (point)) results-switches)))))
       (message "finished"))))
 
 (defun org-babel-result-to-org-string (result)
@@ -599,9 +761,11 @@ relies on `org-babel-insert-result'."
 (defun org-babel-remove-result (&optional info)
   "Remove the result of the current source block."
   (interactive)
-  (save-excursion
-    (goto-char (org-babel-where-is-src-block-result t info)) (forward-line 1)
-    (delete-region (point) (org-babel-result-end))))
+  (let ((location (org-babel-where-is-src-block-result nil info)) start)
+    (when location
+      (save-excursion
+        (goto-char location) (setq start (point)) (forward-line 1)
+        (delete-region start (org-babel-result-end))))))
 
 (defun org-babel-result-end ()
   "Return the point at the end of the current set of results"
@@ -639,10 +803,7 @@ non-nil."
 		      (line-number-at-pos beg)))))
     (save-excursion
       (cond ((= size 0)
-	     (error "This should be impossible: a newline was appended to result if missing")
-	     (let ((result (buffer-substring beg end)))
-	       (delete-region beg end)
-	       (insert (concat ": " result))))
+	     (error "This should be impossible: a newline was appended to result if missing"))
 	    ((< size org-babel-min-lines-for-block-output)
 	     (goto-char beg)
 	     (dotimes (n size)
@@ -666,7 +827,7 @@ parameters when merging lists."
 	   ("output" "value")))
 	(exports-exclusive-groups
 	 '(("code" "results" "both" "none")))
-	params results exports tangle vars var ref)
+	params results exports tangle cache vars var ref)
     (flet ((e-merge (exclusive-groups &rest result-params)
                     ;; maintain exclusivity of mutually exclusive parameters
                     (let (output)
@@ -707,16 +868,18 @@ parameters when merging lists."
                         (:tangle
                          (setq tangle (e-merge '(("yes" "no"))
                                                tangle (split-string (cdr pair)))))
+                        (:cache (setq cache t)) (:nocache (setq cache nil))
                         (t ;; replace: this covers e.g. :session
                          (setq params (cons pair (assq-delete-all (car pair) params))))))
                     plist))
             plists))
     (setq vars (mapcar (lambda (pair) (format "%s=%s" (car pair) (cdr pair))) vars))
     (while vars (setq params (cons (cons :var (pop vars)) params)))
-    (cons (cons :tangle (mapconcat 'identity tangle " "))
-          (cons (cons :exports (mapconcat 'identity exports " "))
-                (cons (cons :results (mapconcat 'identity results " "))
-                      params)))))
+    (cons (if cache (list :cache) (list :nocache))
+          (cons (cons :tangle (mapconcat 'identity tangle " "))
+                (cons (cons :exports (mapconcat 'identity exports " "))
+                      (cons (cons :results (mapconcat 'identity results " "))
+                            params))))))
 
 (defun org-babel-expand-noweb-references (&optional info parent-buffer)
   "This function expands Noweb style references in the body of