Browse Source

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

Carsten Dominik 15 years ago
parent
commit
39f124ed0d

+ 50 - 31
contrib/babel/lisp/langs/org-babel-C.el

@@ -58,11 +58,21 @@
 called by `org-babel-execute-src-block'."
   (let ((c-variant 'cpp)) (org-babel-C-execute body params)))
 
+(defun org-babel-expand-body:c++ (body params &optional processed-params)
+  "Expand a block of C++ code with org-babel according to it's
+header arguments (calls `org-babel-C-expand')."
+  (let ((c-variant 'cpp)) (org-babel-C-expand body params processed-params)))
+
 (defun org-babel-execute:C (body params)
   "Execute a block of C code with org-babel.  This function is
 called by `org-babel-execute-src-block'."
   (let ((c-variant 'c)) (org-babel-C-execute body params)))
 
+(defun org-babel-expand-body:c (body params &optional processed-params)
+  "Expand a block of C code with org-babel according to it's
+header arguments (calls `org-babel-C-expand')."
+  (let ((c-variant 'c)) (org-babel-C-expand body params processed-params)))
+
 (defun org-babel-C-execute (body params)
   "This should only be called by `org-babel-execute:C' or
 `org-babel-execute:c++'."
@@ -76,29 +86,7 @@ called by `org-babel-execute-src-block'."
          (tmp-out-file (make-temp-file "org-babel-C-out"))
          (cmdline (cdr (assoc :cmdline params)))
          (flags (cdr (assoc :flags params)))
-         (vars (second processed-params))
-         (main-p (not (string= (cdr (assoc :main params)) "no")))
-         (includes (or (cdr (assoc :includes params))
-                       (org-entry-get nil "includes" t)))
-         (defines (org-babel-read
-                   (or (cdr (assoc :defines params))
-                       (org-entry-get nil "defines" t))))
-         (full-body (mapconcat 'identity
-                     (list
-                      ;; includes
-                      (mapconcat
-                       (lambda (inc) (format "#include %s" inc))
-                       (if (listp includes) includes (list includes)) "\n")
-                      ;; defines
-                      (mapconcat
-                       (lambda (inc) (format "#define %s" inc))
-                       (if (listp defines) defines (list defines)) "\n")
-                      ;; variables
-                      (mapconcat 'org-babel-C-var-to-C vars "\n")
-                      ;; body
-                      "\n" (if main-p
-                               (org-babel-C-ensure-main-wrap body)
-                             body) "\n") "\n"))
+         (full-body (org-babel-C-expand body params))
          (error-buf (get-buffer-create "*Org-Babel Error Output*"))
          (compile
           (progn
@@ -116,14 +104,17 @@ called by `org-babel-execute-src-block'."
                        tmp-src-file)
                (current-buffer) 'replace error-buf)))))
     (if (= compile 0)
-        (org-babel-read
-         (org-babel-trim
-          (with-temp-buffer
-            (org-babel-shell-command-on-region
-             (point-min) (point-max)
-             (concat tmp-bin-file (if cmdline (concat " " cmdline) ""))
-             (current-buffer) 'replace)
-            (buffer-string))))
+        (org-babel-reassemble-table
+         (org-babel-read
+          (org-babel-trim
+           (with-temp-buffer
+             (org-babel-shell-command-on-region
+              (point-min) (point-max)
+              (concat tmp-bin-file (if cmdline (concat " " cmdline) ""))
+              (current-buffer) 'replace)
+             (buffer-string))))
+         (org-babel-pick-name (nth 4 processed-params) (cdr (assoc :colnames params)))
+         (org-babel-pick-name (nth 5 processed-params) (cdr (assoc :rownames params))))
       (progn
         (with-current-buffer error-buf
           (goto-char (point-max))
@@ -131,6 +122,34 @@ called by `org-babel-execute-src-block'."
           (goto-char (point-min)))
         (display-buffer error-buf) nil))))
 
+(defun org-babel-C-expand (body params &optional processed-params)
+  "Expand a block of C or C++ code with org-babel according to
+it's header arguments."
+  (let ((vars (second (or processed-params
+                          (org-babel-process-params params))))
+        (main-p (not (string= (cdr (assoc :main params)) "no")))
+        (includes (or (cdr (assoc :includes params))
+                      (org-babel-read (org-entry-get nil "includes" t))))
+        (defines (org-babel-read
+                  (or (cdr (assoc :defines params))
+                      (org-babel-read (org-entry-get nil "defines" t))))))
+    (mapconcat 'identity
+               (list
+                ;; includes
+                (mapconcat
+                 (lambda (inc) (format "#include %s" inc))
+                 (if (listp includes) includes (list includes)) "\n")
+                ;; defines
+                (mapconcat
+                 (lambda (inc) (format "#define %s" inc))
+                 (if (listp defines) defines (list defines)) "\n")
+                ;; variables
+                (mapconcat 'org-babel-C-var-to-C vars "\n")
+                ;; body
+                (if main-p
+                    (org-babel-C-ensure-main-wrap body)
+                  body) "\n") "\n")))
+
 (defun org-babel-C-ensure-main-wrap (body)
   "Wrap body in a \"main\" function call if none exists."
   (if (string-match "^[ \t]*[intvod]+[ \t]*main[ \t]*(.*)" body)

+ 38 - 18
contrib/babel/lisp/langs/org-babel-R.el

@@ -35,6 +35,26 @@
 
 (add-to-list 'org-babel-tangle-langs '("R" "R" "#!/usr/bin/env Rscript"))
 
+(defun org-babel-expand-body:R (body params &optional processed-params)
+  (let* ((processed-params (or processed-params
+                               (org-babel-process-params params)))
+	 (vars (mapcar (lambda (i) (cons (car (nth i (second processed-params)))
+					 (org-babel-reassemble-table
+					  (cdr (nth i (second processed-params)))
+					  (cdr (nth i (fifth processed-params)))
+					  (cdr (nth i (sixth processed-params))))))
+		       (number-sequence 0 (1- (length (second processed-params))))))
+         (out-file (cdr (assoc :file params))))
+    (concat
+     (if out-file (concat (org-babel-R-construct-graphics-device-call out-file params) "\n") "")
+     (mapconcat ;; define any variables
+      (lambda (pair)
+	(org-babel-R-assign-elisp (car pair) (cdr pair)
+				  (equal "yes" (cdr (assoc :colnames params)))
+				  (equal "yes" (cdr (assoc :rownames params)))))
+      vars "\n")
+     "\n" body "\n" (if out-file "dev.off()\n" ""))))
+
 (defun org-babel-execute:R (body params)
   "Execute a block of R code with org-babel.  This function is
 called by `org-babel-execute-src-block'."
@@ -43,17 +63,11 @@ called by `org-babel-execute-src-block'."
     (let* ((processed-params (org-babel-process-params params))
            (result-type (fourth processed-params))
            (session (org-babel-R-initiate-session (first processed-params) params))
-           (vars (second processed-params))
-	   (column-names-p (and (cdr (assoc :colnames params))
-				(string= "yes" (cdr (assoc :colnames params)))))
+	   (colnames-p (equal "yes" (cdr (assoc :colnames params))))
+	   (rownames-p (equal "yes" (cdr (assoc :rownames params))))
 	   (out-file (cdr (assoc :file params)))
-	   (augmented-body
-	    (concat
-	     (if out-file (concat (org-babel-R-construct-graphics-device-call out-file params) "\n") "")
-	     (mapconcat ;; define any variables
-	      (lambda (pair) (org-babel-R-assign-elisp (car pair) (cdr pair))) vars "\n")
-	     "\n" body "\n" (if out-file "dev.off()\n" "")))
-	   (result (org-babel-R-evaluate session augmented-body result-type column-names-p)))
+	   (full-body (org-babel-expand-body:R body params processed-params))
+	   (result (org-babel-R-evaluate session full-body result-type colnames-p rownames-p)))
       (or out-file result))))
 
 (defun org-babel-prep-session:R (session params)
@@ -62,7 +76,11 @@ called by `org-babel-execute-src-block'."
 	 (vars (org-babel-ref-variables params))
 	 (var-lines
 	  (mapcar
-	   (lambda (pair) (org-babel-R-assign-elisp (car pair) (cdr pair))) vars)))
+	   (lambda (pair) (org-babel-R-assign-elisp
+			   (car pair) (cdr pair)
+			   (equal (cdr (assoc :colnames params)) "yes")
+			   (equal (cdr (assoc :rownames params)) "yes")))
+	   vars)))
     (org-babel-comint-in-buffer session
       (mapc (lambda (var)
               (move-end-of-line 1) (insert var) (comint-send-input nil t)
@@ -86,7 +104,7 @@ called by `org-babel-execute-src-block'."
       (concat "\"" (mapconcat 'identity (split-string s "\"") "\"\"") "\"")
     (format "%S" s)))
 
-(defun org-babel-R-assign-elisp (name value)
+(defun org-babel-R-assign-elisp (name value colnames-p rownames-p)
   "Construct R code assigning the elisp VALUE to a variable named NAME."
   (if (listp value)
       (let ((transition-file (make-temp-file "org-babel-R-import")))
@@ -95,8 +113,10 @@ called by `org-babel-execute-src-block'."
         (with-temp-file (org-babel-maybe-remote-file transition-file)
           (insert (orgtbl-to-tsv value '(:fmt org-babel-R-quote-tsv-field)))
           (insert "\n"))
-        (format "%s <- read.table(\"%s\", header=%s, sep=\"\\t\", as.is=TRUE)"
-                name transition-file (if (eq (second value) 'hline) "TRUE" "FALSE")))
+        (format "%s <- read.table(\"%s\", header=%s, row.names=%s, sep=\"\\t\", as.is=TRUE)"
+                name transition-file
+		(if (and (eq (second value) 'hline) colnames-p) "TRUE" "FALSE")
+		(if rownames-p "1" "NULL")))
     (format "%s <- %s" name (org-babel-R-quote-tsv-field value))))
 
 (defun org-babel-R-initiate-session (session params)
@@ -140,9 +160,9 @@ called by `org-babel-execute-src-block'."
 (defvar org-babel-R-eoe-indicator "'org_babel_R_eoe'")
 (defvar org-babel-R-eoe-output "[1] \"org_babel_R_eoe\"")
 (defvar org-babel-R-wrapper-method "main <- function ()\n{\n%s\n}
-write.table(main(), file=\"%s\", sep=\"\\t\", na=\"nil\",row.names=FALSE, col.names=%s, quote=FALSE)")
+write.table(main(), file=\"%s\", sep=\"\\t\", na=\"nil\",row.names=%s, col.names=%s, quote=FALSE)")
 
-(defun org-babel-R-evaluate (session body result-type column-names-p)
+(defun org-babel-R-evaluate (session body result-type column-names-p row-names-p)
   "Pass BODY to the R process in SESSION.  If RESULT-TYPE equals
 'output then return a list of the outputs of the statements in
 BODY, if RESULT-TYPE equals 'value then return the value of the
@@ -160,7 +180,7 @@ last statement in BODY, as elisp."
 		(stderr
 		 (with-temp-buffer
 		   (insert (format org-babel-R-wrapper-method
-				   body tmp-file (if column-names-p "TRUE" "FALSE")))
+				   body tmp-file (if row-names-p "TRUE" "FALSE") (if column-names-p (if row-names-p "NA" "TRUE") "FALSE")))
 		   (setq exit-code (org-babel-shell-command-on-region
 				    (point-min) (point-max) "R --no-save" nil 'replace (current-buffer)))
 		   (buffer-string))))
@@ -175,7 +195,7 @@ last statement in BODY, as elisp."
 	      (case result-type
 		(value
 		 (mapconcat #'org-babel-chomp (list body
-						    (format "write.table(.Last.value, file=\"%s\", sep=\"\\t\", na=\"nil\",row.names=FALSE, col.names=%s, quote=FALSE)" tmp-file (if column-names-p "TRUE" "FALSE"))
+						    (format "write.table(.Last.value, file=\"%s\", sep=\"\\t\", na=\"nil\",row.names=%s, col.names=%s, quote=FALSE)" tmp-file (if row-names-p "TRUE" "FALSE") (if column-names-p  (if row-names-p "NA" "TRUE") "FALSE"))
 						    org-babel-R-eoe-indicator) "\n"))
 		(output
 		 (mapconcat #'org-babel-chomp (list body org-babel-R-eoe-indicator) "\n"))))

+ 2 - 0
contrib/babel/lisp/langs/org-babel-asymptote.el

@@ -56,6 +56,8 @@
 (defvar org-babel-default-header-args:asymptote '((:results . "file") (:exports . "results"))
   "Default arguments to use when evaluating a asymptote source block.")
 
+(defun org-babel-expand-body:asymptote (body params &optional processed-params) body)
+
 (defun org-babel-execute:asymptote (body params)
   "Execute a block of Asymptote code with org-babel.  This function is
 called by `org-babel-execute-src-block'."

+ 9 - 3
contrib/babel/lisp/langs/org-babel-clojure.el

@@ -263,12 +263,18 @@ last statement in BODY, as elisp."
       (org-babel-clojure-evaluate-session buffer body result-type)
     (org-babel-clojure-evaluate-external-process buffer body result-type)))
 
+(defun org-babel-expand-body:clojure (body params &optional processed-params)
+  (org-babel-clojure-build-full-form
+   body (second (or processed-params (org-babel-process-params params)))))
+
 (defun org-babel-execute:clojure (body params)
   "Execute a block of Clojure code with org-babel."
   (let* ((processed-params (org-babel-process-params params))
-         (vars (second processed-params))
-         (body (org-babel-clojure-build-full-form body vars))
+         (body (org-babel-expand-body:clojure body params processed-params))
          (session (org-babel-clojure-initiate-session (first processed-params))))
-    (org-babel-clojure-evaluate session body (fourth processed-params))))
+    (org-babel-reassemble-table
+     (org-babel-clojure-evaluate session body (fourth processed-params))
+     (org-babel-pick-name (nth 4 processed-params) (cdr (assoc :colnames params)))
+     (org-babel-pick-name (nth 5 processed-params) (cdr (assoc :rownames params))))))
 
 (provide 'org-babel-clojure)

+ 2 - 0
contrib/babel/lisp/langs/org-babel-css.el

@@ -36,6 +36,8 @@
 
 (add-to-list 'org-babel-tangle-langs '("css" "css" nil t))
 
+(defun org-babel-expand-body:css (body params &optional processed-params) body)
+
 (defun org-babel-execute:css (body params)
   "Execute a block of CSS code with org-babel.  This function is
 called by `org-babel-execute-src-block'."

+ 2 - 0
contrib/babel/lisp/langs/org-babel-ditaa.el

@@ -49,6 +49,8 @@
   '((:results . "file") (:exports . "results"))
   "Default arguments to use when evaluating a ditaa source block.")
 
+(defun org-babel-expand-body:ditaa (body params &optional processed-params) body)
+
 (defun org-babel-execute:ditaa (body params)
   "Execute a block of Ditaa code with org-babel.  This function is
 called by `org-babel-execute-src-block'."

+ 2 - 0
contrib/babel/lisp/langs/org-babel-dot.el

@@ -50,6 +50,8 @@
 (defvar org-babel-default-header-args:dot '((:results . "file") (:exports . "results"))
   "Default arguments to use when evaluating a dot source block.")
 
+(defun org-babel-expand-body:dot (body params &optional processed-params) body)
+
 (defun org-babel-execute:dot (body params)
   "Execute a block of Dot code with org-babel.  This function is
 called by `org-babel-execute-src-block'."

+ 25 - 11
contrib/babel/lisp/langs/org-babel-emacs-lisp.el

@@ -35,21 +35,35 @@
 
 (add-to-list 'org-babel-tangle-langs '("emacs-lisp" "el"))
 
+(defvar org-babel-default-header-args:emacs-lisp
+  '((:hlines . "yes") (:colnames . "no"))
+  "Default arguments to use when evaluating an emacs-lisp source block.")
+
+(defun org-babel-expand-body:emacs-lisp (body params &optional processed-params)
+  (let* ((processed-params (or processed-params (org-babel-process-params params)))
+         (vars (second processed-params))
+         (processed-params (org-babel-process-params params))
+         (result-params (third processed-params))
+         (print-level nil) (print-length nil)
+         (body (concat "(let ("
+                       (mapconcat
+                        (lambda (var) (format "%S" (print `(,(car var) ',(cdr var)))))
+                        vars "\n      ")
+                       ")\n"
+                       (if (or (member "code" result-params)
+                               (member "pp" result-params))
+                           (concat "(pp " body ")") body) ")")))
+    body))
+
 (defun org-babel-execute:emacs-lisp (body params)
   "Execute a block of emacs-lisp code with org-babel."
   (message "executing emacs-lisp code block...")
   (save-window-excursion
-    (let* ((processed-params (org-babel-process-params params))
-           (result-params (third processed-params))
-           (vars (second processed-params))
-           (print-level nil) (print-length nil))
-      (eval `(let ,(mapcar (lambda (var) `(,(car var) ',(cdr var)))
-                           vars)
-	       ,(read (concat "(progn "
-			      (if (or (member "code" result-params)
-				      (member "pp" result-params))
-				  (concat "(pp " body ")") body)
-			      ")")))))))
+    (let ((processed-params (org-babel-process-params params)))
+      (org-babel-reassemble-table
+       (eval (read (org-babel-expand-body:emacs-lisp body params)))
+       (org-babel-pick-name (nth 4 processed-params) (cdr (assoc :colnames params)))
+       (org-babel-pick-name (nth 5 processed-params) (cdr (assoc :rownames params)))))))
 
 (provide 'org-babel-emacs-lisp)
 ;;; org-babel-emacs-lisp.el ends here

+ 29 - 23
contrib/babel/lisp/langs/org-babel-gnuplot.el

@@ -68,13 +68,9 @@ variable names and the value to be used in the gnuplot code."
         (cdr pair))))
    (org-babel-ref-variables params)))
 
-(defun org-babel-execute:gnuplot (body params)
-  "Execute a block of Gnuplot code with org-babel.  This function is
-called by `org-babel-execute-src-block'."
-  (message "executing Gnuplot source code block")
+(defun org-babel-expand-body:gnuplot (body params &optional processed-params)
   (save-window-excursion
     (let* ((vars (org-babel-gnuplot-process-vars params))
-           (session (cdr (assoc :session params)))
            (out-file (cdr (assoc :file params)))
            (term (or (cdr (assoc :term params))
                      (when out-file (file-name-extension out-file))))
@@ -87,7 +83,6 @@ called by `org-babel-execute-src-block'."
            (timefmt (plist-get params :timefmt))
            (time-ind (or (plist-get params :timeind)
                          (when timefmt 1)))
-           (result-type (cdr (assoc :results params)))
            output)
       (flet ((add-to-body (text)
                           (setq body (concat text "\n" body))))
@@ -126,23 +121,34 @@ called by `org-babel-execute-src-block'."
         (mapc (lambda (pair)
                 (setq body (replace-regexp-in-string
                             (format "\\$%s" (car pair)) (cdr pair) body)))
-              vars)
-        ;; evaluate the code body with gnuplot
-        (if (string= session "none")
-            (let ((script-file (make-temp-file "org-babel-gnuplot-script")))
-              (with-temp-file script-file
-                (insert (concat body "\n")))
-              (message "gnuplot \"%s\"" script-file)
-              (setq output
-                    (shell-command-to-string (format "gnuplot \"%s\"" script-file)))
-              (message output))
-          (with-temp-buffer
-            (insert (concat body "\n"))
-            (gnuplot-mode)
-            (gnuplot-send-buffer-to-gnuplot)))
-        (if (member "output" (split-string result-type))
-            output
-          out-file)))))
+              vars))
+      body)))
+
+(defun org-babel-execute:gnuplot (body params)
+  "Execute a block of Gnuplot code with org-babel.  This function is
+called by `org-babel-execute-src-block'."
+  (message "executing Gnuplot source code block")
+  (let ((session (cdr (assoc :session params)))
+        (result-type (cdr (assoc :results params)))
+        (out-file (cdr (assoc :file params)))
+        (body (org-babel-expand-body:gnuplot body params)))
+    (save-window-excursion
+      ;; evaluate the code body with gnuplot
+      (if (string= session "none")
+          (let ((script-file (make-temp-file "org-babel-gnuplot-script")))
+            (with-temp-file script-file
+              (insert (concat body "\n")))
+            (message "gnuplot \"%s\"" script-file)
+            (setq output
+                  (shell-command-to-string (format "gnuplot \"%s\"" script-file)))
+            (message output))
+        (with-temp-buffer
+          (insert (concat body "\n"))
+          (gnuplot-mode)
+          (gnuplot-send-buffer-to-gnuplot)))
+      (if (member "output" (split-string result-type))
+          output
+        out-file))))
 
 (defun org-babel-prep-session:gnuplot (session params)
   "Prepare SESSION according to the header arguments specified in PARAMS."

+ 14 - 7
contrib/babel/lisp/langs/org-babel-haskell.el

@@ -54,6 +54,13 @@
 
 (defvar org-babel-haskell-eoe "\"org-babel-haskell-eoe\"")
 
+(defun org-babel-expand-body:haskell (body params &optional processed-params)
+  (let (vars (second (or processed-params (org-babel-process-params params))))
+    (concat
+     (mapconcat
+      (lambda (pair) (format "let %s = %s;" (car pair) (cdr pair)))
+      vars "\n") "\n" body "\n")))
+
 (defun org-babel-execute:haskell (body params)
   "Execute a block of Haskell code with org-babel."
   (message "executing haskell source code block")
@@ -61,10 +68,7 @@
          (session (first processed-params))
          (vars (second processed-params))
          (result-type (fourth processed-params))
-         (full-body (concat
-                     (mapconcat
-                      (lambda (pair) (format "let %s = %s;" (car pair) (cdr pair)))
-                      vars "\n") "\n" body "\n"))
+         (full-body (org-babel-expand-body:haskell body params processed-params))
          (session (org-babel-prep-session:haskell session params))
          (raw (org-babel-comint-with-output session org-babel-haskell-eoe t
                 (insert (org-babel-trim full-body))
@@ -75,9 +79,12 @@
                    #'org-babel-haskell-read-string
                    (cdr (member org-babel-haskell-eoe
                                 (reverse (mapcar #'org-babel-trim raw)))))))
-    (case result-type
-      (output (mapconcat #'identity (reverse (cdr results)) "\n"))
-      (value (org-babel-haskell-table-or-string (car results))))))
+    (org-babel-reassemble-table
+     (case result-type
+       (output (mapconcat #'identity (reverse (cdr results)) "\n"))
+       (value (org-babel-haskell-table-or-string (car results))))
+     (org-babel-pick-name (nth 4 processed-params) (cdr (assoc :colnames params)))
+     (org-babel-pick-name (nth 5 processed-params) (cdr (assoc :rownames params))))))
 
 (defun org-babel-haskell-read-string (string)
   "Strip \\\"s from around haskell string"

+ 8 - 4
contrib/babel/lisp/langs/org-babel-latex.el

@@ -43,10 +43,7 @@
   '((:results . "latex") (:exports . "results"))
   "Default arguments to use when evaluating a latex source block.")
 
-(defun org-babel-execute:latex (body params)
-  "Execute a block of Latex code with org-babel.  This function is
-called by `org-babel-execute-src-block'."
-  (message "executing Latex source code block")
+(defun org-babel-expand-body:latex (body params &optional processed-params)
   (mapc (lambda (pair) ;; replace variables
           (setq body
                 (replace-regexp-in-string
@@ -54,6 +51,13 @@ called by `org-babel-execute-src-block'."
                  (if (stringp (cdr pair))
                      (cdr pair) (format "%S" (cdr pair)))
                  body))) (second (org-babel-process-params params)))
+  body)
+
+(defun org-babel-execute:latex (body params)
+  "Execute a block of Latex code with org-babel.  This function is
+called by `org-babel-execute-src-block'."
+  (message "executing Latex source code block")
+  (setq body (org-babel-expand-body:latex body params))
   (if (cdr (assoc :file params))
       (let ((out-file (cdr (assoc :file params)))
             (tex-file (make-temp-file "org-babel-latex" nil ".tex"))

+ 2 - 0
contrib/babel/lisp/langs/org-babel-matlab.el

@@ -48,6 +48,8 @@
 (defvar org-babel-matlab-shell-command "matlab -nosplash"
   "Shell command to use to run matlab as an external process.")
 
+(defun org-babel-expand-body:matlab (body params &optional processed-params) body)
+
 (defun org-babel-execute:matlab (body params)
   "Execute a block of matlab code with org-babel."
   (org-babel-execute:octave body params 'matlab))

+ 12 - 5
contrib/babel/lisp/langs/org-babel-ocaml.el

@@ -48,22 +48,29 @@
 (defvar org-babel-ocaml-eoe-indicator "\"org-babel-ocaml-eoe\";;")
 (defvar org-babel-ocaml-eoe-output "org-babel-ocaml-eoe")
 
+(defun org-babel-expand-body:ocaml (body params &optional processed-params)
+  (let ((vars (second (or processed-params (org-babel-process-params params)))))
+    (concat
+     (mapconcat
+      (lambda (pair) (format "let %s = %s;" (car pair) (cdr pair)))
+      vars "\n") "\n" body "\n")))
+
 (defun org-babel-execute:ocaml (body params)
   "Execute a block of Ocaml code with org-babel."
   (message "executing ocaml source code block")
   (let* ((processed-params (org-babel-process-params params))
          (vars (second processed-params))
-         (full-body (concat
-                     (mapconcat
-                      (lambda (pair) (format "let %s = %s;" (car pair) (cdr pair)))
-                      vars "\n") "\n" body "\n"))
+         (full-body (org-babel-expand-body:ocaml body params processed-params))
          (session (org-babel-prep-session:ocaml session params))
          (raw (org-babel-comint-with-output session org-babel-ocaml-eoe-output t
                 (insert (concat (org-babel-chomp full-body) " ;;"))
                 (comint-send-input nil t)
                 (insert org-babel-ocaml-eoe-indicator)
                 (comint-send-input nil t))))
-    (org-babel-ocaml-parse-output (org-babel-trim (car raw)))))
+    (org-babel-reassemble-table
+     (org-babel-ocaml-parse-output (org-babel-trim (car raw)))
+     (org-babel-pick-name (nth 4 processed-params) (cdr (assoc :colnames params)))
+     (org-babel-pick-name (nth 5 processed-params) (cdr (assoc :rownames params))))))
 
 (defun org-babel-prep-session:ocaml (session params)
   "Prepare SESSION according to the header arguments specified in PARAMS."

+ 18 - 10
contrib/babel/lisp/langs/org-babel-octave.el

@@ -41,6 +41,18 @@
 (defvar org-babel-octave-shell-command "octave -q"
   "Shell command to use to run octave as an external process.")
 
+(defun org-babel-expand-body:octave (org-babel-process-params params)
+  (let ((vars (second (or processed-params (org-babel-process-params params)))))
+    (concat
+     ;; prepend code to define all arguments passed to the code block
+     ;; (may not be appropriate for all languages)
+     (mapconcat
+      (lambda (pair)
+        (format "%s=%s"
+                (car pair)
+                (org-babel-octave-var-to-octave (cdr pair))))
+      vars "\n") "\n" body "\n")))
+
 (defun org-babel-execute:octave (body params &optional matlabp)
   "Execute a block of octave code with org-babel."
   (message (format "executing %s source code block" (if matlabp "matlab" "octave")))
@@ -52,17 +64,13 @@
          (result-params (third processed-params))
          (result-type (fourth processed-params))
 	 (out-file (cdr (assoc :file params)))
-	 (augmented-body (concat
-			  ;; prepend code to define all arguments passed to the code block
-			  ;; (may not be appropriate for all languages)
-			  (mapconcat
-			   (lambda (pair)
-			     (format "%s=%s"
-				     (car pair)
-				     (org-babel-octave-var-to-octave (cdr pair))))
-			   vars "\n") "\n" body "\n"))
+	 (augmented-body (org-babel-expand-body:octave body params processed-params))
 	 (result (org-babel-octave-evaluate session augmented-body result-type matlabp)))
-    (or out-file result)))
+    (or out-file
+        (org-babel-reassemble-table
+         result
+         (org-babel-pick-name (nth 4 processed-params) (cdr (assoc :colnames params)))
+         (org-babel-pick-name (nth 5 processed-params) (cdr (assoc :rownames params)))))))
 
 (defun org-babel-octave-var-to-octave (var)
   "Convert an emacs-lisp variable into an octave variable.

+ 22 - 17
contrib/babel/lisp/langs/org-babel-oz.el

@@ -204,6 +204,23 @@ StartOzServer.oz is located.")
 	    (setq org-babel-oz-collected-result nil))))
     result))
 
+(defun org-babel-expand-body:oz (body params &optional processed-params)
+  (let ((vars (second (or processed-params (org-babel-process-params params))))))
+  (if vars
+      ;; only add var declarations if any variables are there
+      (concat
+       ;; prepend code to define all arguments passed to the code block
+       "local\n"
+       (mapconcat
+        (lambda (pair)
+          (format "%s=%s"
+                  (car pair)
+                  (org-babel-oz-var-to-oz (cdr pair))))
+        vars "\n") "\n" 
+        "in\n"
+        body 
+        "end\n")
+    body))
 
 (defun org-babel-execute:oz (body params)
   "Execute a block of Oz code with org-babel.  This function is
@@ -213,27 +230,14 @@ called by `org-babel-execute-src-block' via multiple-value-bind."
 	(vars (second processed-params))
 ;; 	(result-params (third processed-params))
 	(result-type (fourth processed-params))
-	(full-body (if vars
-		       ;; only add var declarations if any variables are there
-		     (concat
-		      ;; prepend code to define all arguments passed to the code block
-		      "local\n"
-		      (mapconcat
-		       (lambda (pair)
-			 (format "%s=%s"
-				 (car pair)
-				 (org-babel-oz-var-to-oz (cdr pair))))
-		       vars "\n") "\n" 
-		       "in\n"
-		       body 
-		       "end\n")
-		     body))
+	(full-body (org-babel-expand-body:oz body params processed-params))
 	(wait-time (plist-get params :wait-time))
         ;; set the session if the session variable is non-nil
 ;; 	(session-buffer (org-babel-oz-initiate-session session))
 ;; 	(session (org-babel-prep-session:oz session params))
 	)
-    ;; actually execute the source-code block 
+    ;; actually execute the source-code block
+    (org-babel-reassemble-table
      (case result-type
        (output
 	(progn 
@@ -245,7 +249,8 @@ called by `org-babel-execute-src-block' via multiple-value-bind."
 	  (oz-send-string-expression full-body (if wait-time
 						   wait-time
 						 1)))))
-    ))
+     (org-babel-pick-name (nth 4 processed-params) (cdr (assoc :colnames params)))
+     (org-babel-pick-name (nth 5 processed-params) (cdr (assoc :rownames params))))))
 
 ;; This function should be used to assign any variables in params in
 ;; the context of the session environment.

+ 16 - 8
contrib/babel/lisp/langs/org-babel-perl.el

@@ -35,6 +35,16 @@
 
 (add-to-list 'org-babel-tangle-langs '("perl" "pl" "#!/usr/bin/env perl"))
 
+(defun org-babel-expand-body:perl (body params &optional processed-params)
+  (let ((vars (second (or processed-params (org-babel-process-params params)))))
+    (concat
+     (mapconcat ;; define any variables
+      (lambda (pair)
+        (format "$%s=%s;"
+                (car pair)
+                (org-babel-perl-var-to-perl (cdr pair))))
+      vars "\n") "\n" (org-babel-trim body) "\n")))
+
 (defun org-babel-execute:perl (body params)
   "Execute a block of Perl code with org-babel.  This function is
 called by `org-babel-execute-src-block'."
@@ -44,15 +54,13 @@ called by `org-babel-execute-src-block'."
          (vars (second processed-params))
          (result-params (third processed-params))
          (result-type (fourth processed-params))
-         (full-body (concat
-		    (mapconcat ;; define any variables
-		     (lambda (pair)
-		       (format "$%s=%s;"
-			       (car pair)
-			       (org-babel-perl-var-to-perl (cdr pair))))
-		     vars "\n") "\n" (org-babel-trim body) "\n")) ;; then the source block body
+         (full-body (org-babel-expand-body:perl
+                     body params processed-params)) ;; then the source block body
 	(session (org-babel-perl-initiate-session session)))
-    (org-babel-perl-evaluate session full-body result-type)))
+    (org-babel-reassemble-table
+     (org-babel-perl-evaluate session full-body result-type)
+     (org-babel-pick-name (nth 4 processed-params) (cdr (assoc :colnames params)))
+     (org-babel-pick-name (nth 5 processed-params) (cdr (assoc :rownames params))))))
 
 (defun org-babel-prep-session:perl (session params)
   "Prepare SESSION according to the header arguments specified in PARAMS."

+ 17 - 10
contrib/babel/lisp/langs/org-babel-python.el

@@ -36,25 +36,32 @@
 
 (add-to-list 'org-babel-tangle-langs '("python" "py" "#!/usr/bin/env python"))
 
+(defun org-babel-expand-body:python (body params &optional processed-params)
+  (concat
+   (mapconcat ;; define any variables
+    (lambda (pair)
+      (format "%s=%s"
+              (car pair)
+              (org-babel-python-var-to-python (cdr pair))))
+    (second (or processed-params (org-babel-process-params params))) "\n")
+   "\n" (org-babel-trim body) "\n"))
+
 (defun org-babel-execute:python (body params)
   "Execute a block of Python code with org-babel.  This function is
 called by `org-babel-execute-src-block'."
   (message "executing Python source code block")
   (let* ((processed-params (org-babel-process-params params))
          (session (org-babel-python-initiate-session (first processed-params)))
-         (vars (second processed-params))
          (result-params (third processed-params))
          (result-type (fourth processed-params))
-         (full-body (concat
-                     (mapconcat ;; define any variables
-                      (lambda (pair)
-                        (format "%s=%s"
-                                (car pair)
-                                (org-babel-python-var-to-python (cdr pair))))
-                      vars "\n") "\n" (org-babel-trim body) "\n")) ;; then the source block body
-         
+         (full-body (org-babel-expand-body:python
+                     body params processed-params)) ;; then the source block body
          (result (org-babel-python-evaluate session full-body result-type)))
-    (or (cdr (assoc :file params)) result)))
+    (or (cdr (assoc :file params))
+        (org-babel-reassemble-table
+         result
+         (org-babel-pick-name (nth 4 processed-params) (cdr (assoc :colnames params)))
+         (org-babel-pick-name (nth 5 processed-params) (cdr (assoc :rownames params)))))))
 
 (defun org-babel-prep-session:python (session params)
   "Prepare SESSION according to the header arguments specified in PARAMS."

+ 17 - 9
contrib/babel/lisp/langs/org-babel-ruby.el

@@ -46,24 +46,32 @@
 
 (add-to-list 'org-babel-tangle-langs '("ruby" "rb" "#!/usr/bin/env ruby"))
 
+(defun org-babel-expand-body:ruby (body params &optional processed-params)
+  (let ((vars (second (or processed-params (org-babel-process-params params)))))
+    (concat
+     (mapconcat ;; define any variables
+      (lambda (pair)
+        (format "%s=%s"
+                (car pair)
+                (org-babel-ruby-var-to-ruby (cdr pair))))
+      vars "\n") "\n" body "\n")))
+
 (defun org-babel-execute:ruby (body params)
   "Execute a block of Ruby code with org-babel.  This function is
 called by `org-babel-execute-src-block'."
   (message "executing Ruby source code block")
   (let* ((processed-params (org-babel-process-params params))
          (session (org-babel-ruby-initiate-session (first processed-params)))
-         (vars (second processed-params))
          (result-params (third processed-params))
          (result-type (fourth processed-params))
-         (full-body (concat
-		    (mapconcat ;; define any variables
-		     (lambda (pair)
-		       (format "%s=%s"
-			       (car pair)
-			       (org-babel-ruby-var-to-ruby (cdr pair))))
-		     vars "\n") "\n" body "\n")) ;; then the source block body
+         (full-body (org-babel-expand-body:ruby
+                     body params processed-params)) ;; then the source block body
          (result (org-babel-ruby-evaluate session full-body result-type)))
-    (or (cdr (assoc :file params)) result)))
+    (or (cdr (assoc :file params))
+        (org-babel-reassemble-table
+         result
+         (org-babel-pick-name (nth 4 processed-params) (cdr (assoc :colnames params)))
+         (org-babel-pick-name (nth 5 processed-params) (cdr (assoc :rownames params)))))))
 
 (defun org-babel-prep-session:ruby (session params)
   "Prepare SESSION according to the header arguments specified in PARAMS."

+ 4 - 1
contrib/babel/lisp/langs/org-babel-sass.el

@@ -48,6 +48,8 @@
 
 (add-to-list 'org-babel-tangle-langs '("sass" "sass"))
 
+(defun org-babel-expand-body:sass (body params &optional processed-params) body)
+
 (defun org-babel-execute:sass (body params)
   "Execute a block of Sass code with org-babel.  This function is
 called by `org-babel-execute-src-block'."
@@ -58,7 +60,8 @@ called by `org-babel-execute-src-block'."
          (cmdline (cdr (assoc :cmdline params)))
          (in-file (make-temp-file "org-babel-sass-in"))
          (cmd (concat "sass " (or cmdline "") in-file " " out-file)))
-    (with-temp-file in-file (insert body)) (shell-command cmd)
+    (with-temp-file in-file
+      (insert (org-babel-expand-body:sass body params))) (shell-command cmd)
     (or file (with-temp-buffer (insert-file-contents out-file) (buffer-string)))))
 
 (defun org-babel-prep-session:sass (session params)

+ 4 - 1
contrib/babel/lisp/langs/org-babel-screen.el

@@ -50,6 +50,8 @@ In case you want to use a different screen than one selected by your $PATH")
   '((:results . "silent") (:session . "default") (:cmd . "sh") (:terminal . "xterm"))
   "Default arguments to use when running screen source blocks.")
 
+(defun org-babel-expand-body:screen (body params &optional processed-params) body)
+
 (defun org-babel-execute:screen (body params)
   "Send a block of code via screen to a terminal using org-babel.
 \"default\" session is be used when none is specified."
@@ -59,7 +61,8 @@ In case you want to use a different screen than one selected by your $PATH")
            (session (first processed-params))
            (socket (org-babel-screen-session-socketname session)))
       (unless socket (org-babel-prep-session:screen session params))
-      (org-babel-screen-session-execute-string session body))))
+      (org-babel-screen-session-execute-string
+       session (org-babel-expand-body:screen body)))))
 
 (defun org-babel-prep-session:screen (session params)
   "Prepare SESSION according to the header arguments specified in PARAMS."

+ 17 - 10
contrib/babel/lisp/langs/org-babel-sh.el

@@ -40,23 +40,30 @@
   "Command used to invoke a shell.  This will be passed to
   `shell-command-on-region'")
 
+(defun org-babel-expand-body:sh (body params &optional processed-params)
+  (let ((vars (second (or processed-params (org-babel-process-params params))))
+        (sep (cdr (assoc :separator params))))
+    (concat
+   (mapconcat ;; define any variables
+    (lambda (pair)
+      (format "%s=%s"
+              (car pair)
+              (org-babel-sh-var-to-sh (cdr pair) sep)))
+    vars "\n") "\n" body "\n\n")))
+
 (defun org-babel-execute:sh (body params)
   "Execute a block of Shell commands with org-babel.  This
 function is called by `org-babel-execute-src-block'."
   (message "executing Shell source code block")
   (let* ((processed-params (org-babel-process-params params))
          (session (org-babel-sh-initiate-session (first processed-params)))
-         (vars (second processed-params))
          (result-type (fourth processed-params))
-         (sep (cdr (assoc :separator params)))
-         (full-body (concat
-                     (mapconcat ;; define any variables
-                      (lambda (pair)
-                        (format "%s=%s"
-                                (car pair)
-                                (org-babel-sh-var-to-sh (cdr pair) sep)))
-                      vars "\n") "\n" body "\n\n"))) ;; then the source block body
-    (org-babel-sh-evaluate session full-body result-type)))
+         (full-body (org-babel-expand-body:sh
+                     body params processed-params))) ;; then the source block body
+    (org-babel-reassemble-table
+     (org-babel-sh-evaluate session full-body result-type)
+     (org-babel-pick-name (nth 4 processed-params) (cdr (assoc :colnames params)))
+     (org-babel-pick-name (nth 5 processed-params) (cdr (assoc :rownames params))))))
 
 (defun org-babel-prep-session:sh (session params)
   "Prepare SESSION according to the header arguments specified in PARAMS."

+ 9 - 2
contrib/babel/lisp/langs/org-babel-sql.el

@@ -51,6 +51,8 @@
 
 (add-to-list 'org-babel-tangle-langs '("sql" "sql"))
 
+(defun org-babel-expand-body:sql (body params &optional processed-params) body)
+
 (defun org-babel-execute:sql (body params)
   "Execute a block of Sql code with org-babel.  This function is
 called by `org-babel-execute-src-block'."
@@ -65,12 +67,17 @@ called by `org-babel-execute-src-block'."
                     ('mysql (format "mysql %s -e \"source %s\" > %s"
                                     (or cmdline "") in-file out-file))
                     (t (error "no support for the %s sql engine")))))
-    (with-temp-file in-file (insert body))
+    (with-temp-file in-file
+      (insert (org-babel-expand-body:sql body params)))
     (message command)
     (shell-command command)
     (with-temp-buffer
       (org-table-import out-file nil)
-      (org-table-to-lisp))))
+      (org-babel-reassemble-table
+       (org-table-to-lisp)
+       (org-babel-pick-name (nth 4 processed-params) (cdr (assoc :colnames params)))
+       (org-babel-pick-name (nth 5 processed-params) (cdr (assoc :rownames params)))))))
+
 
 (defun org-babel-prep-session:sql (session params)
   "Prepare SESSION according to the header arguments specified in PARAMS."

+ 2 - 1
contrib/babel/lisp/org-babel-keys.el

@@ -48,7 +48,8 @@ interactive babel functions which are assigned key bindings.")
     ("h" . org-babel-sha1-hash)
     ("g" . org-babel-goto-named-source-block)
     ("l" . org-babel-lob-ingest)
-    ("z" . org-babel-switch-to-session))
+    ("z" . org-babel-switch-to-session)
+    ("p" . org-babel-expand-src-block))
   "Org-babel keybindings.  This list associates interactive
 org-babel functions with keys.  Each element of this list will
 add an entry to the `org-mode-map' using the letter key which is

+ 14 - 5
contrib/babel/lisp/org-babel-tangle.el

@@ -177,17 +177,26 @@ code blocks by language."
                                       (format "block-%d" block-counter))))
              (src-lang (first info))
              (params (third info))
-	     (body (if (equal "no" (cdr (assoc :noweb params)))
-		       (second info)
-		     (org-babel-expand-noweb-references info)))
-             (spec (list link source-name params body (third (cdr (assoc src-lang org-babel-tangle-langs)))))
              by-lang)
         (unless (string= (cdr (assoc :tangle params)) "no") ;; maybe skip
           (unless (and lang (not (string= lang src-lang))) ;; maybe limit by language
             ;; add the spec for this block to blocks under it's language
             (setq by-lang (cdr (assoc src-lang blocks)))
             (setq blocks (delq (assoc src-lang blocks) blocks))
-            (setq blocks (cons (cons src-lang (cons spec by-lang)) blocks))))))
+            (setq blocks
+                  (cons
+                   (cons src-lang
+                         (cons (list link source-name params
+                                     (funcall
+                                      (intern
+                                       (concat "org-babel-expand-body:" src-lang))
+                                      (if (and (cdr (assoc :noweb params))
+                                               (string= "yes" (cdr (assoc :noweb params))))
+                                          (org-babel-expand-noweb-references info) (second info))
+                                      params)
+                                     (third (cdr (assoc
+                                                  src-lang org-babel-tangle-langs))))
+                               by-lang)) blocks))))))
     ;; ensure blocks in the correct order
     (setq blocks
           (mapcar (lambda (by-lang) (cons (car by-lang) (reverse (cdr by-lang)))) blocks))

+ 304 - 107
contrib/babel/lisp/org-babel.el

@@ -36,10 +36,18 @@
 then run `org-babel-execute-src-block'."
   (interactive)
   (let ((info (org-babel-get-src-block-info)))
-    (if info (progn (org-babel-execute-src-block current-prefix-arg info) t) nil)))
+    (if info
+        (progn (org-babel-execute-src-block current-prefix-arg info) t) nil)))
 
 (add-hook 'org-ctrl-c-ctrl-c-hook 'org-babel-execute-src-block-maybe)
 
+(defun org-babel-expand-src-block-maybe ()
+  "Detect if this is context for a org-babel src-block and if so
+then run `org-babel-expand-src-block'."
+  (interactive)
+  (let ((info (org-babel-get-src-block-info)))
+    (if info (progn (org-babel-expand-src-block current-prefix-arg info) t) nil)))
+
 (defadvice org-edit-special (around org-babel-prep-session-for-edit activate)
   "Prepare the current source block's session according to it's
 header arguments before editing in an org-src buffer.  This
@@ -50,8 +58,9 @@ prefix argument from inside of a source-code block."
            (lang (first info))
            (params (third info))
            (session (cdr (assoc :session params))))
-      (when (and info session) ;; if we are in a source-code block which has a session
-        (funcall (intern (concat "org-babel-prep-session:" lang)) session params))))
+      (when (and info session) ;; we are in a source-code block with a session
+        (funcall
+         (intern (concat "org-babel-prep-session:" lang)) session params))))
   ad-do-it)
 
 (defadvice org-open-at-point (around org-babel-open-at-point activate)
@@ -86,7 +95,8 @@ individual languages may define their own language specific
 header arguments as well.")
 
 (defvar org-babel-default-header-args
-  '((:session . "none") (:results . "replace") (:exports . "code") (:cache . "no") (:noweb . "no"))
+  '((:session . "none") (:results . "replace") (:exports . "code")
+    (:cache . "no") (:noweb . "no") (:hlines . "no"))
   "Default arguments to use when evaluating a source block.")
 
 (defvar org-babel-default-inline-header-args
@@ -133,13 +143,14 @@ can not be resolved.")
 
 (defun org-babel-set-interpreters (var value)
   (set-default var value)
-  (setq org-babel-src-block-regexp
-	(concat "^[ \t]*#\\+begin_src[ \t]+\\("       ;; (1)   lang
-		(mapconcat 'regexp-quote value "\\|")
-		"\\)[ \t]*"
-		"\\([^\":\n]*\"[^\"\n*]*\"[^\":\n]*\\|[^\":\n]*\\)" ;; (2)   switches
-		"\\([^\n]*\\)\n"                      ;; (3)   header arguments
-                "\\([^\000]+?\n\\)[ \t]*#\\+end_src"));; (4)   body
+  (setq
+   org-babel-src-block-regexp
+   (concat "^[ \t]*#\\+begin_src[ \t]+\\("       ;; (1)   lang
+           (mapconcat 'regexp-quote value "\\|")
+           "\\)[ \t]*"
+           "\\([^\":\n]*\"[^\"\n*]*\"[^\":\n]*\\|[^\":\n]*\\)" ;; (2)   switches
+           "\\([^\n]*\\)\n"                      ;; (3)   header arguments
+           "\\([^\000]+?\n\\)[ \t]*#\\+end_src"));; (4)   body
   (setq org-babel-inline-src-block-regexp
 	(concat "[ \f\t\n\r\v]\\(src_"                ;; (1)   replacement target
 		"\\("                                 ;; (2)   lang
@@ -206,14 +217,15 @@ block."
                        (sort (org-babel-merge-params (third info) params)
                              (lambda (el1 el2) (string< (symbol-name (car el1))
                                                    (symbol-name (car el2)))))))
-         (new-hash (if (and (cdr (assoc :cache params))
-                            (string= "yes" (cdr (assoc :cache params)))) (org-babel-sha1-hash info)))
+         (new-hash
+          (if (and (cdr (assoc :cache params))
+                   (string= "yes" (cdr (assoc :cache params))))
+              (org-babel-sha1-hash info)))
          (old-hash (org-babel-result-hash info))
          (body (setf (second info)
 		     (if (and (cdr (assoc :noweb params))
                               (string= "yes" (cdr (assoc :noweb params))))
-			 (org-babel-expand-noweb-references info) (second info))))
-
+                         (org-babel-expand-noweb-references info) (second info))))
          (result-params (split-string (or (cdr (assoc :results params)) "")))
          (result-type (cond ((member "output" result-params) 'output)
 			    ((member "value" result-params) 'value)
@@ -228,7 +240,7 @@ block."
          result)
     (unwind-protect
         (flet ((call-process-region (&rest args)
-                                    (apply 'org-babel-tramp-handle-call-process-region args)))
+                 (apply 'org-babel-tramp-handle-call-process-region args)))
           (unless (member lang org-babel-interpreters)
             (error "Language is not in `org-babel-interpreters': %s" lang))
           (if (and (not arg) new-hash (equal new-hash old-hash))
@@ -236,7 +248,8 @@ block."
                 (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)
+                (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)
@@ -249,6 +262,33 @@ block."
             result))
       (setq call-process-region 'call-process-region-original))))
 
+(defun org-babel-expand-body:generic (body params &optional processed-params)
+  "Expand a block of code with org-babel according to it's header
+arguments.  This generic implementation of body expansion is
+called for languages which have not defined their own specific
+org-babel-expand-body:lang function." body)
+
+(defun org-babel-expand-src-block (&optional arg info params)
+  "Expand the current source code block according to it's header
+arguments, and pop open the results in a preview buffer."
+  (interactive)
+  ;; (message "supplied params=%S" params) ;; debugging
+  (let* ((info (or info (org-babel-get-src-block-info)))
+         (lang (first info))
+	 (params (setf (third info)
+                       (sort (org-babel-merge-params (third info) params)
+                             (lambda (el1 el2) (string< (symbol-name (car el1))
+                                                   (symbol-name (car el2)))))))
+         (body (setf (second info)
+		     (if (and (cdr (assoc :noweb params))
+                              (string= "yes" (cdr (assoc :noweb params))))
+			 (org-babel-expand-noweb-references info) (second info))))
+         (cmd (intern (concat "org-babel-expand-body:" lang)))
+         (expanded (funcall (if (fboundp cmd) cmd 'org-babel-expand-body:generic)
+                            body params)))
+    (org-edit-src-code
+     nil expanded (concat "*Org-Babel Preview " (buffer-name) "[ " lang " ]*"))))
+
 (defun org-babel-load-in-session (&optional arg info)
   "Load the body of the current source-code block.  Evaluate the
 header arguments for the source block before entering the
@@ -262,7 +302,9 @@ session.  After loading the body this pops open the session."
     (unless (member lang org-babel-interpreters)
       (error "Language is not in `org-babel-interpreters': %s" lang))
     ;; if called with a prefix argument, then process header arguments
-    (pop-to-buffer (funcall (intern (concat "org-babel-load-session:" lang)) session body params))
+    (pop-to-buffer
+     (funcall (intern (concat "org-babel-load-session:" lang))
+              session body params))
     (move-end-of-line 1)))
 
 (defun org-babel-switch-to-session (&optional arg info)
@@ -282,11 +324,15 @@ of the source block to the kill ring."
     (unless (member lang org-babel-interpreters)
       (error "Language is not in `org-babel-interpreters': %s" lang))
     ;; copy body to the kill ring
-    (with-temp-buffer (insert (org-babel-trim body)) (copy-region-as-kill (point-min) (point-max)))
+    (with-temp-buffer (insert (org-babel-trim body))
+                      (copy-region-as-kill (point-min) (point-max)))
     ;; if called with a prefix argument, then process header arguments
-    (if arg (funcall (intern (concat "org-babel-prep-session:" lang)) session params))
+    (when arg
+      (funcall (intern (concat "org-babel-prep-session:" lang)) session params))
     ;; just to the session using pop-to-buffer
-    (pop-to-buffer (funcall (intern (format "org-babel-%s-initiate-session" lang)) session params))
+    (pop-to-buffer
+     (funcall (intern (format "org-babel-%s-initiate-session" lang))
+              session params))
     (move-end-of-line 1)))
 
 (defalias 'org-babel-pop-to-session 'org-babel-switch-to-session)
@@ -355,18 +401,22 @@ added to the header-arguments-alist."
 	  (goto-char head)
 	  (setq info (org-babel-parse-src-block-match))
 	  (forward-line -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)))))
+	  (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.
+	    ;; 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 4))
-		(setq info (append info (list (mapcar (lambda (ref) (cons :var ref))
-						      (org-babel-ref-split-args args))))))
+                (setq info
+                      (append info (list
+                                    (mapcar (lambda (ref) (cons :var ref))
+                                            (org-babel-ref-split-args args))))))
 	    (unless header-vars-only
 	      (setf (third info)
 		    (org-babel-merge-params (sixth info) (third info)))))
@@ -517,7 +567,7 @@ with C-c C-c."
          (goto-char (match-beginning 0))
          (save-match-data ,@body)
          (goto-char (match-end 0))))
-     (unless visited-p (kill-buffer (file-name-nondirectory file)))))
+     (unless visited-p (kill-buffer (file-name-nondirectory ,file)))))
 
 (defun org-babel-params-from-properties ()
   "Return an association list of any source block params which
@@ -543,7 +593,7 @@ may be specified in the properties of the current outline entry."
 	 (preserve-indentation (or org-src-preserve-indentation
 				   (string-match "-i\\>" switches))))
     (list lang
-          ;; get src block body removing properties, protective commas, and indentation
+          ;; get block body less properties, protective commas, and indentation
           (with-temp-buffer
             (save-match-data
               (insert (org-babel-strip-protective-commas body))
@@ -553,19 +603,22 @@ may be specified in the properties of the current outline entry."
 	   org-babel-default-header-args
            (org-babel-params-from-properties)
 	   (if (boundp lang-headers) (eval lang-headers) nil)
-	   (org-babel-parse-header-arguments (org-babel-clean-text-properties (or (match-string 3) ""))))
+	   (org-babel-parse-header-arguments
+            (org-babel-clean-text-properties (or (match-string 3) ""))))
 	  switches)))
 
 (defun org-babel-parse-inline-src-block-match ()
   (let* ((lang (org-babel-clean-text-properties (match-string 2)))
          (lang-headers (intern (concat "org-babel-default-header-args:" lang))))
     (list lang
-          (org-babel-strip-protective-commas (org-babel-clean-text-properties (match-string 5)))
+          (org-babel-strip-protective-commas
+           (org-babel-clean-text-properties (match-string 5)))
           (org-babel-merge-params
            org-babel-default-inline-header-args
            (org-babel-params-from-properties)
            (if (boundp lang-headers) (eval lang-headers) nil)
-           (org-babel-parse-header-arguments (org-babel-clean-text-properties (or (match-string 4) "")))))))
+           (org-babel-parse-header-arguments
+            (org-babel-clean-text-properties (or (match-string 4) "")))))))
 
 (defun org-babel-parse-header-arguments (arg-string)
   "Parse a string of header arguments returning an alist."
@@ -573,24 +626,125 @@ may be specified in the properties of the current outline entry."
       (delq nil
 	    (mapcar
 	     (lambda (arg)
-	       (if (string-match "\\([^ \f\t\n\r\v]+\\)[ \f\t\n\r\v]+\\([^ \f\t\n\r\v]+.*\\)" 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)))
                          (let ((raw (org-babel-chomp (match-string 2 arg))))
-                           (if (org-babel-number-p raw) raw (org-babel-read raw))))
+                           (if (org-babel-number-p raw)
+                               raw (org-babel-read raw))))
 		 (cons (intern (concat ":" arg)) nil)))
 	     (split-string (concat " " arg-string) "[ \f\t\n\r\v]+:" t)))))
 
 (defun org-babel-process-params (params)
   "Parse params and resolve references.
 
-Return a list (session vars result-params result-type)."
+Return a list (session vars result-params result-type colnames rownames)."
   (let* ((session (cdr (assoc :session params)))
-	 (vars (org-babel-ref-variables params))
+         (vars-and-names (org-babel-disassemble-tables
+                          (org-babel-ref-variables params)
+                          (cdr (assoc :hlines params))
+                          (cdr (assoc :colnames params))
+                          (cdr (assoc :rownames params))))
+         (vars     (car   vars-and-names))
+         (colnames (cadr  vars-and-names))
+         (rownames (caddr vars-and-names))
 	 (result-params (split-string (or (cdr (assoc :results params)) "")))
 	 (result-type (cond ((member "output" result-params) 'output)
 			    ((member "value" result-params) 'value)
 			    (t 'value))))
-    (list session vars result-params result-type)))
+    (list session vars result-params result-type colnames rownames)))
+
+;; row and column names
+(defun org-babel-del-hlines (table)
+  "Remove all 'hlines from TABLE."
+  (remove 'hline table))
+
+(defun org-babel-get-colnames (table)
+  "Return a cons cell, the `car' of which contains the TABLE
+        less colnames, and the `cdr' of which contains a list of the
+        column names"
+  (if (equal 'hline (second table))
+      (cons (cddr table) (car table))
+    (list table)))
+
+(defun org-babel-get-rownames (table)
+  "Return a cons cell, the `car' of which contains the TABLE less
+     colnames, and the `cdr' of which contains a list of the column
+     names.  Note: this function removes any hlines in TABLE"
+  (flet ((trans (table) (apply #'mapcar* #'list table)))
+    (let* ((width (apply 'max (mapcar (lambda (el) (if (listp el) (length el) 0)) table)))
+           (table (trans (mapcar (lambda (row)
+                                   (if (not (equal row 'hline))
+                                       row
+                                     (setq row '())
+                                     (dotimes (n width) (setq row (cons 'hline row)))
+                                     row))
+                                 table))))
+      (cons (mapcar (lambda (row) (if (equal (car row) 'hline) 'hline row))
+                    (trans (cdr table)))
+            (remove 'hline (car table))))))
+
+(defun org-babel-put-colnames (table colnames)
+  "Add COLNAMES to TABLE if they exist."
+  (if colnames (apply 'list colnames 'hline table) table))
+
+(defun org-babel-put-rownames (table rownames)
+  "Add ROWNAMES to TABLE if they exist."
+  (if rownames
+      (mapcar (lambda (row)
+                (if (listp row)
+                    (cons (or (pop rownames) "") row)
+                  row)) table)
+    table))
+
+(defun org-babel-pick-name (names selector)
+  "Select one out of an alist of row or column names."
+  (when names
+    (if (and selector (symbolp selector) (not (equal t selector)))
+        (cdr (assoc selector names))
+      (if (integerp selector)
+          (nth (- selector 1) names)
+        (cdr (car (last names)))))))
+
+(defun org-babel-disassemble-tables (vars hlines colnames rownames)
+  "Process the variables in VARS according to the HLINES,
+ROWNAMES and COLNAMES header arguments.  Return a list consisting
+of the vars, cnames and rnames."
+  (let (cnames rnames)
+    (list
+     (mapcar
+      (lambda (var)
+        (when (listp (cdr var))
+          (when (and (not (equal colnames "no"))
+                     (or colnames (and (equal (second (cdr var)) 'hline)
+                                       (not (member 'hline (cddr (cdr var)))))))
+            (let ((both (org-babel-get-colnames (cdr var))))
+              (setq cnames (cons (cons (car var) (cdr both))
+                                 cnames))
+              (setq var (cons (car var) (car both)))))
+          (when (and rownames (not (equal rownames "no")))
+            (let ((both (org-babel-get-rownames (cdr var))))
+              (setq rnames (cons (cons (car var) (cdr both))
+                                 rnames))
+              (setq var (cons (car var) (car both)))))
+          (when (and hlines (not (equal hlines "yes")))
+            (setq var (cons (car var) (org-babel-del-hlines (cdr var))))))
+        var)
+      vars)
+     cnames rnames)))
+
+(defun org-babel-reassemble-table (table colnames rownames)
+  "Given a TABLE and set of COLNAMES and ROWNAMES add the names
+to the table for reinsertion to org-mode."
+  (if (listp table)
+      ((lambda (table)
+         (if (and colnames (listp (car table)) (= (length (car table))
+                                                  (length colnames)))
+             (org-babel-put-colnames table colnames) table))
+       (if (and rownames (= (length table) (length rownames)))
+           (org-babel-put-rownames table rownames) table))
+    table))
 
 (defun org-babel-where-is-src-block-head ()
   "Return the point at the beginning of the current source
@@ -644,7 +798,8 @@ buffer or nil if no such result exists."
   (save-excursion
     (goto-char (point-min))
     (when (re-search-forward
-           (concat org-babel-result-regexp "[ \t]" (regexp-quote name) "[ \t\n\f\v\r]") nil t)
+           (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 hash)
@@ -668,13 +823,18 @@ following the source block."
 			       (progn ;; unnamed results line already exists
 				 (re-search-forward "[^ \f\t\n\r\v]" nil t)
 				 (move-beginning-of-line 1)
-                                 (looking-at (concat org-babel-result-regexp "\n"))))
-			  ;; or (with optional insert) back up and make one ourselves
+                                 (looking-at
+                                  (concat org-babel-result-regexp "\n"))))
+			  ;; or (with optional insert) back up and
+			  ;; make one ourselves
                           (when insert
                             (goto-char end)
-			    (if (looking-at "[\n\r]") (forward-char 1) (insert "\n"))
-                            (insert (concat "#+results" (if hash (concat "["hash"]"))
-                                            ":"(if name (concat " " name)) "\n"))
+			    (if (looking-at "[\n\r]")
+                                (forward-char 1) (insert "\n"))
+                            (insert (concat "#+results"
+                                            (when hash (concat "["hash"]"))
+                                            ":"
+                                            (when name (concat " " name)) "\n"))
                             (move-beginning-of-line 0)
                             (if hash (org-babel-hide-hash)) t)))
                (point))))))
@@ -689,12 +849,14 @@ following the source block."
      ((looking-at ": ")
       (setq result-string
 	    (org-babel-trim
-	     (mapconcat (lambda (line) (if (and (> (length line) 1)
-						(string= ": " (substring line 0 2)))
-					   (substring line 2)
-					 line))
+	     (mapconcat (lambda (line)
+                          (if (and (> (length line) 1)
+                                   (string= ": " (substring line 0 2)))
+                              (substring line 2)
+                            line))
 			(split-string
-			 (buffer-substring (point) (org-babel-result-end)) "[\r\n]+")
+			 (buffer-substring
+                          (point) (org-babel-result-end)) "[\r\n]+")
 			"\n")))
       (or (org-babel-number-p result-string) result-string))
      ((looking-at org-babel-result-regexp)
@@ -776,7 +938,8 @@ code ---- the results are extracted in the syntax of the source
         (setq result (concat result "\n")))
       (save-excursion
 	(let ((existing-result (org-babel-where-is-src-block-result t info hash))
-	      (results-switches (cdr (assoc :results_switches (third info)))) beg)
+	      (results-switches
+               (cdr (assoc :results_switches (third info)))) beg)
 	  (when existing-result (goto-char existing-result) (forward-line 1))
 	  (setq results-switches
                 (if results-switches (concat " " results-switches) ""))
@@ -794,11 +957,14 @@ code ---- the results are extracted in the syntax of the source
 	   ((member "file" result-params)
 	    (insert result))
 	   ((member "html" result-params)
-	    (insert (format "#+BEGIN_HTML%s\n%s#+END_HTML\n" results-switches result)))
+	    (insert (format "#+BEGIN_HTML%s\n%s#+END_HTML\n"
+                            results-switches result)))
 	   ((member "latex" result-params)
-	    (insert (format "#+BEGIN_LaTeX%s\n%s#+END_LaTeX\n" results-switches result)))
+	    (insert (format "#+BEGIN_LaTeX%s\n%s#+END_LaTeX\n"
+                            results-switches result)))
 	   ((member "code" result-params)
-	    (insert (format "#+BEGIN_SRC %s%s\n%s#+END_SRC\n" lang results-switches result)))
+	    (insert (format "#+BEGIN_SRC %s%s\n%s#+END_SRC\n"
+                            lang results-switches result)))
 	   ((or (member "raw" result-params) (member "org" result-params))
 	    (save-excursion (insert result)) (if (org-at-table-p) (org-cycle)))
 	   (t
@@ -852,7 +1018,8 @@ directory then expand relative links."
    (if (and default-directory
             buffer-file-name
             (not (string= (expand-file-name default-directory)
-                          (expand-file-name (file-name-directory buffer-file-name)))))
+                          (expand-file-name
+                           (file-name-directory buffer-file-name)))))
        (expand-file-name result default-directory)
      result)))
 
@@ -863,7 +1030,8 @@ directory then expand relative links."
 		      (line-number-at-pos beg)))))
     (save-excursion
       (cond ((= size 0)
-	     (error "This should be impossible: a newline was appended to result if missing"))
+	     (error (concat "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)
@@ -882,66 +1050,85 @@ elements of PLISTS override the values of previous element.  This
 takes into account some special considerations for certain
 parameters when merging lists."
   (let ((results-exclusive-groups
-	 '(("file" "vector" "table" "scalar" "raw" "org" "html" "latex" "code" "pp")
+	 '(("file" "vector" "table" "scalar" "raw" "org"
+            "html" "latex" "code" "pp")
 	   ("replace" "silent")
 	   ("output" "value")))
 	(exports-exclusive-groups
 	 '(("code" "results" "both" "none")))
 	params results exports tangle noweb cache vars var ref shebang comments)
     (flet ((e-merge (exclusive-groups &rest result-params)
-                    ;; maintain exclusivity of mutually exclusive parameters
-                    (let (output)
-                      (mapc (lambda (new-params)
-                              (mapc (lambda (new-param)
-                                      (mapc (lambda (exclusive-group)
-                                              (when (member new-param exclusive-group)
-                                                (mapcar (lambda (excluded-param)
-                                                          (setq output (delete excluded-param output)))
-                                                        exclusive-group)))
-                                            exclusive-groups)
-                                      (setq output (org-uniquify (cons new-param output))))
-                                    new-params))
-                            result-params)
-                      output)))
+             ;; maintain exclusivity of mutually exclusive parameters
+             (let (output)
+               (mapc (lambda (new-params)
+                       (mapc (lambda (new-param)
+                               (mapc (lambda (exclusive-group)
+                                       (when (member new-param exclusive-group)
+                                         (mapcar (lambda (excluded-param)
+                                                   (setq output
+                                                         (delete
+                                                          excluded-param
+                                                          output)))
+                                                 exclusive-group)))
+                                     exclusive-groups)
+                               (setq output (org-uniquify
+                                             (cons new-param output))))
+                             new-params))
+                     result-params)
+               output)))
       (mapc (lambda (plist)
               (mapc (lambda (pair)
                       (case (car pair)
                         (:var
                          ;; we want only one specification per variable
-                         (when (string-match "^\\([^= \f\t\n\r\v]+\\)[ \t]*=[ \t]*\\([^\f\n\r\v]+\\)$" (cdr pair))
+                         (when (string-match
+                                (concat "^\\([^= \f\t\n\r\v]+\\)[ \t]*="
+                                        "[ \t]*\\([^\f\n\r\v]+\\)$") (cdr pair))
                            ;; TODO: When is this not true?
                            (setq var (intern (match-string 1 (cdr pair)))
                                  ref (match-string 2 (cdr pair))
-                                 vars (cons (cons var ref) (assq-delete-all var vars)))))
+                                 vars (cons (cons var ref)
+                                            (assq-delete-all var vars)))))
                         (:results
                          (setq results
-			       (e-merge results-exclusive-groups results (split-string (cdr pair)))))
+			       (e-merge results-exclusive-groups
+                                        results (split-string (cdr pair)))))
 			(:file
 			 (when (cdr pair)
-			   (setq results (e-merge results-exclusive-groups results '("file")))
+			   (setq results (e-merge results-exclusive-groups
+                                                  results '("file")))
 			   (unless (or (member "both" exports)
                                        (member "none" exports)
                                        (member "code" exports))
-			     (setq exports (e-merge exports-exclusive-groups exports '("results"))))
-			   (setq params (cons pair (assq-delete-all (car pair) params)))))
+			     (setq exports (e-merge exports-exclusive-groups
+                                                    exports '("results"))))
+			   (setq params
+                                 (cons pair
+                                       (assq-delete-all (car pair) params)))))
                         (:exports
-                         (setq exports (e-merge exports-exclusive-groups
-                                                exports (split-string (cdr pair)))))
+                         (setq exports
+                               (e-merge exports-exclusive-groups
+                                        exports (split-string (cdr pair)))))
                         (:tangle ;; take the latest -- always overwrite
                          (setq tangle (or (list (cdr pair)) tangle)))
                         (:noweb
-                         (setq noweb (e-merge '(("yes" "no"))
-                                              noweb (split-string (or (cdr pair) "")))))
+                         (setq noweb
+                               (e-merge '(("yes" "no")) noweb
+                                        (split-string (or (cdr pair) "")))))
                         (:cache
-                         (setq cache (e-merge '(("yes" "no"))
-                                              cache (split-string (or (cdr pair) "")))))
+                         (setq cache
+                               (e-merge '(("yes" "no")) cache
+                                        (split-string (or (cdr pair) "")))))
                         (:shebang ;; take the latest -- always overwrite
                          (setq shebang (or (list (cdr pair)) shebang)))
                         (:comments
-                         (setq comments (e-merge '(("yes" "no"))
-                                                 comments (split-string (or (cdr pair) "")))))
+                         (setq comments
+                               (e-merge '(("yes" "no")) comments
+                                        (split-string (or (cdr pair) "")))))
                         (t ;; replace: this covers e.g. :session
-                         (setq params (cons pair (assq-delete-all (car pair) params))))))
+                         (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))
@@ -951,9 +1138,12 @@ parameters when merging lists."
                 (cons (cons :cache (mapconcat 'identity cache " "))
                       (cons (cons :noweb (mapconcat 'identity noweb " "))
                             (cons (cons :tangle (mapconcat 'identity tangle " "))
-                                  (cons (cons :exports (mapconcat 'identity exports " "))
-                                        (cons (cons :results (mapconcat 'identity results " "))
-                                              params)))))))))
+                                  (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
@@ -999,9 +1189,10 @@ block but are passed literally to the \"example-block\"."
           (save-match-data (setf source-name (match-string 1)))
           (save-match-data (setq evaluate (string-match "\(.*\)" source-name)))
           (save-match-data
-            (setq prefix (buffer-substring (match-beginning 0)
-                                           (save-excursion
-                                             (move-beginning-of-line 1) (point)))))
+            (setq prefix
+                  (buffer-substring (match-beginning 0)
+                                    (save-excursion
+                                      (move-beginning-of-line 1) (point)))))
           ;; add interval to new-body (removing noweb reference)
           (goto-char (match-beginning 0))
           (nb-add (buffer-substring index (point)))
@@ -1020,13 +1211,15 @@ block but are passed literally to the \"example-block\"."
                           (if point
                               (save-excursion
                                 (goto-char point)
-                                (org-babel-trim (org-babel-expand-noweb-references
-                                                 (org-babel-get-src-block-info))))
+                                (org-babel-trim
+                                 (org-babel-expand-noweb-references
+                                  (org-babel-get-src-block-info))))
                             ;; optionally raise an error if named
                             ;; source-block doesn't exist
                             (if (member lang org-babel-noweb-error-langs)
                                 (error
-                                 "<<%s>> could not be resolved (see `org-babel-noweb-error-langs')"
+                                 (concat "<<%s>> could not be resolved "
+                                         "(see `org-babel-noweb-error-langs')")
                                  source-name)
                               "")))) "[\n\r]") (concat "\n" prefix)))))
         (nb-add (buffer-substring index (point-max)))))
@@ -1107,14 +1300,16 @@ the table is trivial, then return it as a scalar."
 STRING.  Default regexp used is \"[ \f\t\n\r\v]\" but can be
 overwritten by specifying a regexp as a second argument."
   (let ((regexp (or regexp "[ \f\t\n\r\v]")))
-    (while (and (> (length string) 0) (string-match regexp (substring string -1)))
+    (while (and (> (length string) 0)
+                (string-match regexp (substring string -1)))
       (setq string (substring string 0 -1)))
     string))
 
 (defun org-babel-trim (string &optional regexp)
   "Like `org-babel-chomp' only it runs on both the front and back of the string"
   (org-babel-chomp (org-babel-reverse-string
-                    (org-babel-chomp (org-babel-reverse-string string) regexp)) regexp))
+                    (org-babel-chomp (org-babel-reverse-string string) regexp))
+                   regexp))
 
 (defun org-babel-tramp-handle-call-process-region
   (start end program &optional delete buffer display &rest args)
@@ -1125,12 +1320,14 @@ Fixes a bug in `tramp-handle-call-process-region'."
 	(write-region start end tmpfile)
 	(when delete (delete-region start end))
 	(unwind-protect
-	    ;;	(apply 'call-process program tmpfile buffer display args) ;; bug in tramp
+	    ;;	(apply 'call-process program tmpfile buffer display args)
+            ;; bug in tramp
 	    (apply 'process-file program tmpfile buffer display args)
 	  (delete-file tmpfile)))
     ;; call-process-region-original is the original emacs definition. It
     ;; is in scope from the let binding in org-babel-execute-src-block
-    (apply call-process-region-original start end program delete buffer display args)))
+    (apply call-process-region-original
+           start end program delete buffer display args)))
 
 (defun org-babel-maybe-remote-file (file)
   (if (file-remote-p default-directory)
@@ -1151,12 +1348,13 @@ Normally display output (if any) in temp buffer `*Shell Command Output*';
 Prefix arg means replace the region with it.  Return the exit code of
 COMMAND.
 
-To specify a coding system for converting non-ASCII characters
-in the input and output to the shell command, use \\[universal-coding-system-argument]
-before this command.  By default, the input (from the current buffer)
-is encoded in the same coding system that will be used to save the file,
-`buffer-file-coding-system'.  If the output is going to replace the region,
-then it is decoded from that same coding system.
+To specify a coding system for converting non-ASCII characters in
+the input and output to the shell command, use
+\\[universal-coding-system-argument] before this command.  By
+default, the input (from the current buffer) is encoded in the
+same coding system that will be used to save the file,
+`buffer-file-coding-system'.  If the output is going to replace
+the region, then it is decoded from that same coding system.
 
 The noninteractive arguments are START, END, COMMAND,
 OUTPUT-BUFFER, REPLACE, ERROR-BUFFER, and DISPLAY-ERROR-BUFFER.
@@ -1323,6 +1521,5 @@ specifies the value of ERROR-BUFFER."
       (delete-file error-file))
     exit-status))
 
-
 (provide 'org-babel)
 ;;; org-babel.el ends here

+ 6 - 0
lisp/ChangeLog

@@ -63,6 +63,12 @@
 	(org-export-html-close-lists-maybe): Allow to splice raw HTML into
 	and out of lists.
 
+2010-04-22  Dan Davison  <davison@stats.ox.ac.uk>
+
+	* org-src.el (org-edit-src-code): Allow the org-src edit buffer to
+	be used in a read-only mode.
+	(org-edit-src-code): Different message in read-only mode
+
 2010-04-21  Carsten Dominik  <carsten.dominik@gmail.com>
 
 	* org-src.el (org-edit-src-find-region-and-lang): Test for

+ 75 - 63
lisp/org-src.el

@@ -187,7 +187,7 @@ This minor mode is turned on in two situations:
 There is a mode hook, and keybindings for `org-edit-src-exit' and
 `org-edit-src-save'")
 
-(defun org-edit-src-code (&optional context)
+(defun org-edit-src-code (&optional context code edit-buffer-name)
   "Edit the source code example at point.
 The example is copied to a separate buffer, and that buffer is switched
 to the correct language mode.  When done, exit with \\[org-edit-src-exit].
@@ -200,19 +200,22 @@ the edited version. Optional argument CONTEXT is used by
   (let ((line (org-current-line))
 	(col (current-column))
 	(case-fold-search t)
-	(msg (substitute-command-keys
-	      "Edit, then exit with C-c ' (C-c and single quote)"))
 	(info (org-edit-src-find-region-and-lang))
 	(org-mode-p (eq major-mode 'org-mode))
 	(beg (make-marker))
 	(end (make-marker))
 	(preserve-indentation org-src-preserve-indentation)
-	block-nindent total-nindent ovl lang lang-f single lfmt code begline buffer)
+	block-nindent total-nindent ovl lang lang-f single lfmt begline buffer msg)
     (if (not info)
 	nil
       (setq beg (move-marker beg (nth 0 info))
 	    end (move-marker end (nth 1 info))
-	    code (buffer-substring-no-properties beg end)
+	    allow-write-back-p (null code)
+	    msg (if allow-write-back-p
+		    (substitute-command-keys
+		     "Edit, then exit with C-c ' (C-c and single quote)")
+		  "Exit with C-c ' (C-c and single quote)")
+	    code (or code (buffer-substring-no-properties beg end))
 	    lang (or (cdr (assoc (nth 2 info) org-src-lang-modes))
                      (nth 2 info))
 	    lang (if (symbolp lang) (symbol-name lang) lang)
@@ -241,16 +244,17 @@ the edited version. Optional argument CONTEXT is used by
 		(delete-overlay org-edit-src-overlay)))
 	  (kill-buffer buffer))
 	(setq buffer (generate-new-buffer
-		      (org-src-construct-edit-buffer-name (buffer-name) lang)))
+		      (or edit-buffer-name
+			  (org-src-construct-edit-buffer-name (buffer-name) lang))))
 	(setq ovl (make-overlay beg end))
 	(overlay-put ovl 'edit-buffer buffer)
 	(overlay-put ovl 'help-echo "Click with mouse-1 to switch to buffer editing this segment")
 	(overlay-put ovl 'face 'secondary-selection)
 	(overlay-put ovl
-			 'keymap
-			 (let ((map (make-sparse-keymap)))
-			   (define-key map [mouse-1] 'org-edit-src-continue)
-			   map))
+		     'keymap
+		     (let ((map (make-sparse-keymap)))
+		       (define-key map [mouse-1] 'org-edit-src-continue)
+		       map))
 	(overlay-put ovl :read-only "Leave me alone")
 	(org-src-switch-to-buffer buffer 'edit)
 	(if (eq single 'macro-definition)
@@ -264,6 +268,7 @@ the edited version. Optional argument CONTEXT is used by
 	  (funcall lang-f))
 	(set (make-local-variable 'org-edit-src-force-single-line) single)
 	(set (make-local-variable 'org-edit-src-from-org-mode) org-mode-p)
+	(set (make-local-variable 'org-edit-src-allow-write-back-p) allow-write-back-p)
 	(set (make-local-variable 'org-src-preserve-indentation) preserve-indentation)
 	(when lfmt
 	  (set (make-local-variable 'org-coderef-label-format) lfmt))
@@ -406,7 +411,7 @@ the fragment in the Org-mode buffer."
 	 ((eq org-edit-fixed-width-region-mode 'artist-mode)
 	  (fundamental-mode)
 	  (artist-mode 1))
-       (t (funcall org-edit-fixed-width-region-mode)))
+	 (t (funcall org-edit-fixed-width-region-mode)))
 	(set (make-local-variable 'org-edit-src-force-single-line) nil)
 	(set (make-local-variable 'org-edit-src-from-org-mode) org-mode-p)
 	(set (make-local-variable 'org-edit-src-picture) t)
@@ -529,7 +534,7 @@ the language, a switch telling if the content should be in a single line."
 (defun org-edit-src-exit (&optional context)
   "Exit special edit and protect problematic lines."
   (interactive)
-  (unless org-edit-src-from-org-mode
+  (unless (org-bound-and-true-p org-edit-src-from-org-mode)
     (error "This is not a sub-editing buffer, something is wrong..."))
   (widen)
   (let* ((beg org-edit-src-beg-marker)
@@ -541,57 +546,61 @@ the language, a switch telling if the content should be in a single line."
 	 (total-nindent (+ (or org-edit-src-block-indentation 0)
 			   org-edit-src-content-indentation))
 	 (preserve-indentation org-src-preserve-indentation)
+	 (allow-write-back-p (org-bound-and-true-p org-edit-src-allow-write-back-p))
 	 (delta 0) code line col indent)
-    (unless preserve-indentation (untabify (point-min) (point-max)))
-    (save-excursion
-      (goto-char (point-min))
-      (if (looking-at "[ \t\n]*\n") (replace-match ""))
-      (unless macro
-	(if (re-search-forward "\n[ \t\n]*\\'" nil t) (replace-match ""))))
+    (when allow-write-back-p
+      (unless preserve-indentation (untabify (point-min) (point-max)))
+      (save-excursion
+	(goto-char (point-min))
+	(if (looking-at "[ \t\n]*\n") (replace-match ""))
+	(unless macro
+	  (if (re-search-forward "\n[ \t\n]*\\'" nil t) (replace-match "")))))
     (setq line (if (org-bound-and-true-p org-edit-src-force-single-line)
 		   1
 		 (org-current-line))
 	  col (current-column))
-    (when single
-      (goto-char (point-min))
-      (if (re-search-forward "\\s-+\\'" nil t) (replace-match ""))
-      (goto-char (point-min))
-      (let ((cnt 0))
-	(while (re-search-forward "\n" nil t)
-	  (setq cnt (1+ cnt))
-	  (replace-match (if macro "\\n" " ") t t))
-	(when (and macro (> cnt 0))
-	  (goto-char (point-max)) (insert "\\n")))
-      (goto-char (point-min))
-      (if (looking-at "\\s-*") (replace-match " ")))
-    (when (org-bound-and-true-p org-edit-src-from-org-mode)
-      (goto-char (point-min))
-      (while (re-search-forward
-	      (if (org-mode-p) "^\\(.\\)" "^\\([*]\\|[ \t]*#\\+\\)") nil t)
-	(if (eq (org-current-line) line) (setq delta (1+ delta)))
-	(replace-match ",\\1")))
-    (when (org-bound-and-true-p org-edit-src-picture)
-      (setq preserve-indentation nil)
-      (untabify (point-min) (point-max))
-      (goto-char (point-min))
-      (while (re-search-forward "^" nil t)
-	(replace-match ": ")))
-    (unless (or single preserve-indentation (= total-nindent 0))
-      (setq indent (make-string total-nindent ?\ ))
-      (goto-char (point-min))
-      (while (re-search-forward "^" nil t)
-	(replace-match indent)))
-    (if (org-bound-and-true-p org-edit-src-picture)
-	(setq total-nindent (+ total-nindent 2)))
-    (setq code (buffer-string))
-    (set-buffer-modified-p nil)
+    (when allow-write-back-p
+      (when single
+	(goto-char (point-min))
+	(if (re-search-forward "\\s-+\\'" nil t) (replace-match ""))
+	(goto-char (point-min))
+	(let ((cnt 0))
+	  (while (re-search-forward "\n" nil t)
+	    (setq cnt (1+ cnt))
+	    (replace-match (if macro "\\n" " ") t t))
+	  (when (and macro (> cnt 0))
+	    (goto-char (point-max)) (insert "\\n")))
+	(goto-char (point-min))
+	(if (looking-at "\\s-*") (replace-match " ")))
+      (when (org-bound-and-true-p org-edit-src-from-org-mode)
+	(goto-char (point-min))
+	(while (re-search-forward
+		(if (org-mode-p) "^\\(.\\)" "^\\([*]\\|[ \t]*#\\+\\)") nil t)
+	  (if (eq (org-current-line) line) (setq delta (1+ delta)))
+	  (replace-match ",\\1")))
+      (when (org-bound-and-true-p org-edit-src-picture)
+	(setq preserve-indentation nil)
+	(untabify (point-min) (point-max))
+	(goto-char (point-min))
+	(while (re-search-forward "^" nil t)
+	  (replace-match ": ")))
+      (unless (or single preserve-indentation (= total-nindent 0))
+	(setq indent (make-string total-nindent ?\ ))
+	(goto-char (point-min))
+	(while (re-search-forward "^" nil t)
+	  (replace-match indent)))
+      (if (org-bound-and-true-p org-edit-src-picture)
+	  (setq total-nindent (+ total-nindent 2)))
+      (setq code (buffer-string))
+      (set-buffer-modified-p nil))
     (org-src-switch-to-buffer (marker-buffer beg) (or context 'exit))
     (kill-buffer buffer)
     (goto-char beg)
-    (delete-region beg end)
-    (insert code)
-    (goto-char beg)
-    (if single (just-one-space))
+    (when allow-write-back-p
+      (delete-region beg end)
+      (insert code)
+      (goto-char beg)
+      (if single (just-one-space)))
     (if (memq t (mapcar (lambda (overlay)
 			  (eq (overlay-get overlay 'invisible)
 			      'org-hide-block))
@@ -625,15 +634,18 @@ the language, a switch telling if the content should be in a single line."
     (message (or msg ""))))
 
 (defun org-src-mode-configure-edit-buffer ()
-  (when org-edit-src-from-org-mode
-    (setq buffer-offer-save t)
-    (setq buffer-file-name
-	  (concat (buffer-file-name (marker-buffer org-edit-src-beg-marker))
-		  "[" (buffer-name) "]"))
-    (set (if (featurep 'xemacs) 'write-contents-hooks 'write-contents-functions)
-	 '(org-edit-src-save))
+  (when (org-bound-and-true-p org-edit-src-from-org-mode)
     (org-add-hook 'kill-buffer-hook
-		  '(lambda () (delete-overlay org-edit-src-overlay)) nil 'local)))
+		  '(lambda () (delete-overlay org-edit-src-overlay)) nil 'local)
+    (if (org-bound-and-true-p org-edit-src-allow-write-back-p)
+	(progn
+	  (setq buffer-offer-save t)
+	  (setq buffer-file-name
+		(concat (buffer-file-name (marker-buffer org-edit-src-beg-marker))
+			"[" (buffer-name) "]"))
+	  (set (if (featurep 'xemacs) 'write-contents-hooks 'write-contents-functions)
+	       '(org-edit-src-save)))
+      (setq buffer-read-only t))))
 
 (org-add-hook 'org-src-mode-hook 'org-src-mode-configure-edit-buffer)