Browse Source

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

Carsten Dominik 16 years ago
parent
commit
7d75d03e40

+ 76 - 37
contrib/babel/lisp/org-babel-exp.el

@@ -1,8 +1,8 @@
 ;;; org-babel-exp.el --- Exportation of org-babel source blocks
 ;;; org-babel-exp.el --- Exportation of org-babel source blocks
 
 
-;; Copyright (C) 2009 Eric Schulte
+;; Copyright (C) 2009 Eric Schulte, Dan Davison
 
 
-;; Author: Eric Schulte
+;; Author: Eric Schulte, Dan Davison
 ;; Keywords: literate programming, reproducible research
 ;; Keywords: literate programming, reproducible research
 ;; Homepage: http://orgmode.org
 ;; Homepage: http://orgmode.org
 ;; Version: 0.01
 ;; Version: 0.01
@@ -35,6 +35,27 @@
 (add-to-list 'org-export-interblocks '(src org-babel-exp-inline-src-blocks))
 (add-to-list 'org-export-interblocks '(src org-babel-exp-inline-src-blocks))
 (add-to-list 'org-export-interblocks '(lob org-babel-exp-lob-one-liners))
 (add-to-list 'org-export-interblocks '(lob org-babel-exp-lob-one-liners))
 
 
+(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
+(uniform) numbers.
+
+#+srcname: rand(n)
+#+begin_src R
+  runif(n)
+#+end_src
+")
+
+(defvar org-babel-function-def-export-indent 4
+  "When exporting a source block function, the block contents
+will be indented by this many characters. See
+`org-babel-function-def-export-name' for the definition of a
+source block function.")
+
 (defun org-babel-exp-src-blocks (body &rest headers)
 (defun org-babel-exp-src-blocks (body &rest headers)
   "Process src block for export.  Depending on the 'export'
   "Process src block for export.  Depending on the 'export'
 headers argument in replace the source code block with...
 headers argument in replace the source code block with...
@@ -49,17 +70,12 @@ results - just like none only the block is run on export ensuring
 
 
 none ----- do not display either code or results upon export"
 none ----- do not display either code or results upon export"
   (interactive)
   (interactive)
-  (unless headers (error "org-babel can't process a source block without knowing the source code"))
   (message "org-babel-exp processing...")
   (message "org-babel-exp processing...")
-  (let* ((lang (car headers))
-         (lang-headers (intern (concat "org-babel-default-header-args:" lang)))
-         (params (org-babel-merge-params
-                  org-babel-default-header-args
-                  (if (boundp lang-headers) (eval lang-headers) nil)
-                  (org-babel-params-from-properties)
-                  (org-babel-parse-header-arguments
-                   (mapconcat #'identity (cdr headers) " ")))))
-    (org-babel-exp-do-export lang body params 'block)))
+  (let ((info (save-excursion
+		(if (re-search-backward org-babel-src-block-regexp nil t)
+		    (org-babel-get-src-block-info)
+		  (error "Failed to find src block.")))))
+    (org-babel-exp-do-export info 'block)))
 
 
 (defun org-babel-exp-inline-src-blocks (start end)
 (defun org-babel-exp-inline-src-blocks (start end)
   "Process inline src blocks between START and END for export.
   "Process inline src blocks between START and END for export.
@@ -72,8 +88,7 @@ options and are taken from `org-babel-defualt-inline-header-args'."
                 (re-search-forward org-babel-inline-src-block-regexp end t))
                 (re-search-forward org-babel-inline-src-block-regexp end t))
       (let* ((info (save-match-data (org-babel-parse-inline-src-block-match)))
       (let* ((info (save-match-data (org-babel-parse-inline-src-block-match)))
              (replacement (save-match-data
              (replacement (save-match-data
-                            (org-babel-exp-do-export
-                             (first info) (second info) (third info) 'inline))))
+                            (org-babel-exp-do-export info 'inline))))
         (setq end (+ end (- (length replacement) (length (match-string 1)))))
         (setq end (+ end (- (length replacement) (length (match-string 1)))))
         (replace-match replacement t t nil 1)))))
         (replace-match replacement t t nil 1)))))
 
 
@@ -90,38 +105,61 @@ options are taken from `org-babel-default-header-args'."
 	(setq replacement
 	(setq replacement
 	      (save-match-data
 	      (save-match-data
 		(org-babel-exp-do-export
 		(org-babel-exp-do-export
-		 "emacs-lisp" "results"
-		 (org-babel-merge-params
-		  org-babel-default-header-args
-		  (org-babel-parse-header-arguments
-		   (org-babel-clean-text-properties
-		    (concat ":var results="
-			    (mapconcat #'identity (org-babel-lob-get-info) " ")))))
+		 (list "emacs-lisp" "results"
+		       (org-babel-merge-params
+			org-babel-default-header-args
+			(org-babel-parse-header-arguments
+			 (org-babel-clean-text-properties
+			  (concat ":var results="
+				  (mapconcat #'identity (org-babel-lob-get-info) " "))))))
 		 'lob)))
 		 'lob)))
 	(setq end (+ end (- (length replacement) (length (match-string 0)))))
 	(setq end (+ end (- (length replacement) (length (match-string 0)))))
 	(replace-match replacement t t)))))
 	(replace-match replacement t t)))))
 
 
-(defun org-babel-exp-do-export (lang body params type)
-  (case (intern (or (cdr (assoc :exports params)) "code"))
+(defun org-babel-exp-do-export (info type)
+  (case (intern (or (cdr (assoc :exports (third info))) "code"))
     ('none "")
     ('none "")
-    ('code (org-babel-exp-code lang body params type))
-    ('results (org-babel-exp-results lang body params type))
-    ('both (concat (org-babel-exp-code lang body params type)
+    ('code (org-babel-exp-code info type))
+    ('results (org-babel-exp-results info type))
+    ('both (concat (org-babel-exp-code info type)
                    "\n\n"
                    "\n\n"
-                   (org-babel-exp-results lang body params type)))))
-
-(defun org-babel-exp-code (lang body params type)
+                   (org-babel-exp-results info type)))))
+
+(defun org-babel-exp-code (info type)
+  (let ((lang (first info))
+	(body (second info))
+	(switches (fourth info))
+	(name (fifth info))
+	(args (sixth info))
+	(function-def-line ""))
     (case type
     (case type
-      ('inline (format "=%s=" body))
-      ('block (format "#+BEGIN_SRC %s\n%s%s\n#+END_SRC" lang body
-		      (if (string-match "\n$" body) "" "\n")))
+      ('inline (format "=%s=" (second info)))
+      ('block
+	  (when args
+	    (unless (string-match "-i\\>" switches)
+	      (setq switches (concat switches " -i")))
+	    (setq body (with-temp-buffer
+			 (insert body)
+			 (indent-code-rigidly (point-min) (point-max) org-babel-function-def-export-indent)
+			 (buffer-string)))
+	    (setq args (mapconcat #'identity
+				  (delq nil (mapcar (lambda (el) (and (length (cdr el)) (cdr el))) args))
+				  ", "))
+	    (setq function-def-line
+		  (format "#+BEGIN_SRC org-babel-lob\n%s %s(%s):\n#+END_SRC\n"
+			  org-babel-function-def-export-keyword name args)))
+        (concat function-def-line
+                (format "#+BEGIN_SRC %s %s\n%s%s#+END_SRC" lang switches body
+                        (if (string-match "\n$" body) "" "\n"))))
       ('lob (save-excursion
       ('lob (save-excursion
 	      (re-search-backward org-babel-lob-one-liner-regexp)
 	      (re-search-backward org-babel-lob-one-liner-regexp)
 	      (format "#+BEGIN_SRC org-babel-lob\n%s\n#+END_SRC"
 	      (format "#+BEGIN_SRC org-babel-lob\n%s\n#+END_SRC"
-                      (first (org-babel-lob-get-info)))))))
+                      (first (org-babel-lob-get-info))))))))
 
 
-(defun org-babel-exp-results (lang body params type)
-  (let ((params
+(defun org-babel-exp-results (info type)
+  (let ((lang (first info))
+	(body (second info))
+	(params
          ;; lets ensure that we lookup references in the original file
          ;; lets ensure that we lookup references in the original file
          (mapcar (lambda (pair)
          (mapcar (lambda (pair)
                    (if (and org-current-export-file
                    (if (and org-current-export-file
@@ -130,11 +168,12 @@ options are taken from `org-babel-default-header-args'."
                        `(:var . ,(concat (match-string 1 (cdr pair))
                        `(:var . ,(concat (match-string 1 (cdr pair))
                                          "=" org-current-export-file
                                          "=" org-current-export-file
                                          ":" (match-string 2 (cdr pair))))
                                          ":" (match-string 2 (cdr pair))))
-                     pair)) params)))
+                     pair))
+		 (third info))))
     (case type
     (case type
       ('inline
       ('inline
         (let ((raw (org-babel-execute-src-block
         (let ((raw (org-babel-execute-src-block
-                    nil (list lang body params) '((:results . "silent"))))
+                    nil info '((:results . "silent"))))
               (result-params (split-string (cdr (assoc :results params)))))
               (result-params (split-string (cdr (assoc :results params)))))
           (cond ;; respect the value of the :results header argument
           (cond ;; respect the value of the :results header argument
            ((member "file" result-params)
            ((member "file" result-params)

+ 6 - 5
contrib/babel/lisp/org-babel-lob.el

@@ -1,8 +1,8 @@
 ;;; org-babel-lob.el --- The Library of Babel: off-the-shelf functions for data analysis and plotting using org-babel
 ;;; org-babel-lob.el --- The Library of Babel: off-the-shelf functions for data analysis and plotting using org-babel
 
 
-;; Copyright (C) 2009 Dan Davison, Eric Schulte
+;; Copyright (C) 2009 Eric Schulte, Dan Davison
 
 
-;; Author: Dan Davison, Eric Schulte
+;; Author: Eric Schulte, Dan Davison
 ;; Keywords: literate programming, reproducible research
 ;; Keywords: literate programming, reproducible research
 ;; Homepage: http://orgmode.org
 ;; Homepage: http://orgmode.org
 ;; Version: 0.01
 ;; Version: 0.01
@@ -31,6 +31,7 @@
 ;;; Code:
 ;;; Code:
 (require 'org-babel)
 (require 'org-babel)
 (require 'org-babel-table)
 (require 'org-babel-table)
+(require 'org-babel-exp)
 
 
 (defvar org-babel-library-of-babel nil
 (defvar org-babel-library-of-babel nil
   "Library of source-code blocks.  This is an association list.
   "Library of source-code blocks.  This is an association list.
@@ -46,8 +47,8 @@ add files to this list use the `org-babel-lob-ingest' command."
   "Add all source-blocks defined in FILE to `org-babel-library-of-babel'."
   "Add all source-blocks defined in FILE to `org-babel-library-of-babel'."
   (interactive "f")
   (interactive "f")
   (org-babel-map-source-blocks file
   (org-babel-map-source-blocks file
-    (let ((source-name (intern (org-babel-get-src-block-name)))
-          (info (org-babel-get-src-block-info)))
+    (let* ((info (org-babel-get-src-block-info))
+	   (source-name (intern (fifth info))))
       (when source-name
       (when source-name
         (setq org-babel-library-of-babel
         (setq org-babel-library-of-babel
               (cons (cons source-name info)
               (cons (cons source-name info)
@@ -94,7 +95,7 @@ the word 'call'."
     (org-babel-execute-src-block nil (list "emacs-lisp" "results" params))))
     (org-babel-execute-src-block nil (list "emacs-lisp" "results" params))))
 
 
 (define-generic-mode org-babel-lob-mode
 (define-generic-mode org-babel-lob-mode
-  '("#") nil nil nil nil
+  '("#") (list org-babel-function-def-export-keyword) nil nil nil
   "Major mode for fontification of library of babel lines on export")
   "Major mode for fontification of library of babel lines on export")
 
 
 (provide 'org-babel-lob)
 (provide 'org-babel-lob)

+ 4 - 4
contrib/babel/lisp/org-babel-tangle.el

@@ -1,8 +1,8 @@
 ;;; org-babel-tangle.el --- Extract source code from org-mode files
 ;;; org-babel-tangle.el --- Extract source code from org-mode files
 
 
-;; Copyright (C) 2009 Dan Davison, Eric Schulte
+;; Copyright (C) 2009 Eric Schulte
 
 
-;; Author: Dan Davison, Eric Schulte
+;; Author: Eric Schulte
 ;; Keywords: literate programming, reproducible research
 ;; Keywords: literate programming, reproducible research
 ;; Homepage: http://orgmode.org
 ;; Homepage: http://orgmode.org
 ;; Version: 0.01
 ;; Version: 0.01
@@ -153,9 +153,9 @@ code blocks by language."
       (setq block-counter (+ 1 block-counter))
       (setq block-counter (+ 1 block-counter))
       (let* ((link (progn (call-interactively 'org-store-link)
       (let* ((link (progn (call-interactively 'org-store-link)
                           (org-babel-clean-text-properties (car (pop org-stored-links)))))
                           (org-babel-clean-text-properties (car (pop org-stored-links)))))
-             (source-name (intern (or (org-babel-get-src-block-name)
-                                      (format "block-%d" block-counter))))
              (info (org-babel-get-src-block-info))
              (info (org-babel-get-src-block-info))
+             (source-name (intern (or (fifth info)
+                                      (format "block-%d" block-counter))))
              (src-lang (first info))
              (src-lang (first info))
              (body (org-babel-expand-noweb-references info))
              (body (org-babel-expand-noweb-references info))
              (params (third info))
              (params (third info))

+ 40 - 46
contrib/babel/lisp/org-babel.el

@@ -109,11 +109,12 @@ then run `org-babel-pop-to-session'."
 (defun org-babel-set-interpreters (var value)
 (defun org-babel-set-interpreters (var value)
   (set-default var value)
   (set-default var value)
   (setq org-babel-src-block-regexp
   (setq org-babel-src-block-regexp
-	(concat "^[ \t]*#\\+begin_src[ \t]+\\("
+	(concat "^[ \t]*#\\+begin_src[ \t]+\\("       ;; (1)   lang
 		(mapconcat 'regexp-quote value "\\|")
 		(mapconcat 'regexp-quote value "\\|")
 		"\\)[ \t]*"
 		"\\)[ \t]*"
-                "\\([ \t]+\\([^\n]+\\)\\)?\n" ;; match header arguments
-                "\\([^\000]+?\\)#\\+end_src"))
+		"\\([^:\n]*\\)"                       ;; (2)   switches
+		"\\([^\n]*\\)\n"                      ;; (3)   header arguments
+                "\\([^\000]+?\\)#\\+end_src"))        ;; (4)   body
   (setq org-babel-inline-src-block-regexp
   (setq org-babel-inline-src-block-regexp
 	(concat "[ \f\t\n\r\v]\\(src_"                ;; (1)   replacement target
 	(concat "[ \f\t\n\r\v]\\(src_"                ;; (1)   replacement target
 		"\\("                                 ;; (2)   lang
 		"\\("                                 ;; (2)   lang
@@ -174,8 +175,7 @@ the header arguments specified at the source code block."
   ;; (message "supplied params=%S" params) ;; debugging
   ;; (message "supplied params=%S" params) ;; debugging
   (let* ((info (or info (org-babel-get-src-block-info)))
   (let* ((info (or info (org-babel-get-src-block-info)))
          (lang (first info))
          (lang (first info))
-         (params (org-babel-merge-params
-                  (third info) (org-babel-get-src-block-function-args) params))
+         (params (org-babel-merge-params (third info) params))
          (body (if (assoc :noweb params)
          (body (if (assoc :noweb params)
                    (org-babel-expand-noweb-references info) (second info)))
                    (org-babel-expand-noweb-references info) (second info)))
          (processed-params (org-babel-process-params params))
          (processed-params (org-babel-process-params params))
@@ -299,51 +299,41 @@ concerned with creating elisp versions of results. "
     (org-babel-execute-buffer)
     (org-babel-execute-buffer)
     (widen)))
     (widen)))
 
 
-(defun org-babel-get-src-block-name ()
-  "Return the name of the current source block if one exists.
-
-This function is analogous to org-babel-lob-get-info. For both
-functions, after they are called, (match-string 1) matches the
-function name, and (match-string 3) matches the function
-arguments inside the parentheses. I think perhaps these functions
-should be renamed to bring out this similarity, perhaps involving
-the word 'call'.
-
-Currently the function `org-babel-get-src-block-function-args'
-relies on the match-data from a match in this function.  I think
-splitting a match and the use of it's data is bad form, and we
-should re-work these two functions, perhaps combining them into
-one function which returns more data than just the name. [Eric]"
-  (let ((case-fold-search t)
-	(head (org-babel-where-is-src-block-head)))
-    (if head
-	(save-excursion
-	  (goto-char head)
-	  (if (save-excursion
-		(forward-line -1)
-                ;; the second match of this regexp is used later to
-                ;; find arguments in the "functional" style, where
-                ;; they are passed as part of the source name line
-		(looking-at "#\\+srcname:[ \t]*\\([^ ()\f\t\n\r\v]+\\)\\(\(\\(.*\\)\)\\|\\)"))
-	      (org-babel-clean-text-properties (match-string 1)))))))
-
-(defun org-babel-get-src-block-info ()
-  "Return the information of the current source block as a list
-of the following form.  (language body header-arguments-alist)"
-  (let ((case-fold-search t) head)
+(defun org-babel-get-src-block-info (&optional header-vars-only)
+  "Get information of the current source block.
+Returns a list
+ (language body header-arguments-alist switches name function-args).
+Unless HEADER-VARS-ONLY is non-nil, any variable
+references provided in 'function call style' (i.e. in a
+parenthesised argument list following the src block name) are
+added to the header-arguments-alist."
+  (let ((case-fold-search t) head info args)
     (if (setq head (org-babel-where-is-src-block-head))
     (if (setq head (org-babel-where-is-src-block-head))
-        (save-excursion (goto-char head) (org-babel-parse-src-block-match))
+        (save-excursion
+	  (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)))))
+	    ;; 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))
+		(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)))))
+	  info)
       (if (save-excursion ;; inline source block
       (if (save-excursion ;; inline source block
             (re-search-backward "[ \f\t\n\r\v]" nil t)
             (re-search-backward "[ \f\t\n\r\v]" nil t)
             (looking-at org-babel-inline-src-block-regexp))
             (looking-at org-babel-inline-src-block-regexp))
           (org-babel-parse-inline-src-block-match)
           (org-babel-parse-inline-src-block-match)
         nil)))) ;; indicate that no source block was found
         nil)))) ;; indicate that no source block was found
 
 
-(defun org-babel-get-src-block-function-args ()
-  (when (org-babel-get-src-block-name)
-    (mapcar (lambda (ref) (cons :var ref))
-	    (org-babel-ref-split-args (match-string 3)))))
-
 (defmacro org-babel-map-source-blocks (file &rest body)
 (defmacro org-babel-map-source-blocks (file &rest body)
   "Evaluate BODY forms on each source-block in FILE."
   "Evaluate BODY forms on each source-block in FILE."
   (declare (indent 1))
   (declare (indent 1))
@@ -373,8 +363,10 @@ may be specified in the properties of the current outline entry."
 (defun org-babel-parse-src-block-match ()
 (defun org-babel-parse-src-block-match ()
   (let* ((lang (org-babel-clean-text-properties (match-string 1)))
   (let* ((lang (org-babel-clean-text-properties (match-string 1)))
          (lang-headers (intern (concat "org-babel-default-header-args:" lang)))
          (lang-headers (intern (concat "org-babel-default-header-args:" lang)))
+	 (switches (match-string 2))
          (body (org-babel-clean-text-properties (match-string 4)))
          (body (org-babel-clean-text-properties (match-string 4)))
-	 (preserve-indentation org-src-preserve-indentation))
+	 (preserve-indentation (or org-src-preserve-indentation
+				   (string-match "-i\\>" switches))))
     (list lang
     (list lang
           ;; get src block body removing properties, protective commas, and indentation
           ;; get src block body removing properties, protective commas, and indentation
           (with-temp-buffer
           (with-temp-buffer
@@ -386,7 +378,8 @@ may be specified in the properties of the current outline entry."
 	   org-babel-default-header-args
 	   org-babel-default-header-args
            (org-babel-params-from-properties)
            (org-babel-params-from-properties)
 	   (if (boundp lang-headers) (eval lang-headers) nil)
 	   (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 ()
 (defun org-babel-parse-inline-src-block-match ()
   (let* ((lang (org-babel-clean-text-properties (match-string 2)))
   (let* ((lang (org-babel-clean-text-properties (match-string 2)))
@@ -488,7 +481,8 @@ line.  If no result exists for this block then create a
   (save-excursion
   (save-excursion
     (let* ((on-lob-line (progn (beginning-of-line 1)
     (let* ((on-lob-line (progn (beginning-of-line 1)
 			       (looking-at org-babel-lob-one-liner-regexp)))
 			       (looking-at org-babel-lob-one-liner-regexp)))
-	   (name (if on-lob-line (first (org-babel-lob-get-info)) (org-babel-get-src-block-name)))
+	   (name (if on-lob-line (first (org-babel-lob-get-info))
+		   (fifth (org-babel-get-src-block-info))))
 	   (head (unless on-lob-line (org-babel-where-is-src-block-head))) end)
 	   (head (unless on-lob-line (org-babel-where-is-src-block-head))) end)
       (when head (goto-char head))
       (when head (goto-char head))
       (or (and name (org-babel-find-named-result name))
       (or (and name (org-babel-find-named-result name))