Browse Source

Merge branch 'master' of git@github.com:eschulte/rorg

Dan Davison 16 years ago
parent
commit
17a1d71e6a
6 changed files with 212 additions and 38 deletions
  1. 41 0
      litorgy/init.el
  2. 46 0
      litorgy/litorgy-R.el
  3. 4 1
      litorgy/litorgy-lisp.el
  4. 49 14
      litorgy/litorgy-reference.el
  5. 44 23
      litorgy/litorgy.el
  6. 28 0
      rorg.org

+ 41 - 0
litorgy/init.el

@@ -0,0 +1,41 @@
+;;; init.el --- loads litorgy
+
+;; Copyright (C) 2009 Eric Schulte, Dan Davison, Austin F. Frank
+
+;; Author: Eric Schulte, Dan Davison, Austin F. Frank
+;; Keywords: literate programming, reproducible research
+;; Homepage: http://orgmode.org
+;; Version: 0.01
+
+;;; License:
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+;;
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; for more information see the comments in litorgy.el
+
+;;; Code:
+(require 'org)
+(require 'litorgy)
+(require 'litorgy-reference)
+
+;; language specific files
+(require 'litorgy-R)
+(require 'litorgy-lisp)
+(require 'litorgy-script)
+
+;;; init.el ends here

+ 46 - 0
litorgy/litorgy-R.el

@@ -0,0 +1,46 @@
+;;; litorgy-R.el --- litorgy functions for R code evaluation
+
+;; Copyright (C) 2009 Eric Schulte, Dan Davison, Austin F. Frank
+
+;; Author: Eric Schulte, Dan Davison, Austin F. Frank
+;; Keywords: literate programming, reproducible research
+;; Homepage: http://orgmode.org
+;; Version: 0.01
+
+;;; License:
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+;;
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; Litorgy support for evaluating R code
+
+;;; Code:
+(require 'litorgy)
+
+(litorgy-add-interpreter "emacs-R")
+
+(defun litorgy-execute:emacs-R (body params)
+  "Execute a block of emacs-R code with litorgy.  This
+function is called by `litorgy-execute-src-block'."
+  (save-window-excursion
+    (let ((vars (litorgy-reference-variables params))
+          results)
+      ;;TODO: implement
+      (error "`litorgy-execute:emacs-R' is not implemented"))))
+
+(provide 'litorgy-R)
+;;; litorgy-R.el ends here

+ 4 - 1
litorgy/litorgy-lisp.el

@@ -40,7 +40,10 @@ function is called by `litorgy-execute-src-block'."
     (let ((vars (litorgy-reference-variables params))
     (let ((vars (litorgy-reference-variables params))
           (print-level nil) (print-length nil) results)
           (print-level nil) (print-length nil) results)
       (message "executing emacs-lisp code block...")
       (message "executing emacs-lisp code block...")
-      (format "%S" (eval (read body))))))
+      (setq results
+            (eval `(let ,(mapcar (lambda (var) `(,(car var) ',(cdr var))) vars)
+                     ,(read body))))
+      (if (listp results) results (format "%S" results)))))
 
 
 (provide 'litorgy-lisp)
 (provide 'litorgy-lisp)
 ;;; litorgy-lisp.el ends here
 ;;; litorgy-lisp.el ends here

+ 49 - 14
litorgy/litorgy-reference.el

@@ -53,11 +53,31 @@
 ;;; Code:
 ;;; Code:
 (require 'litorgy)
 (require 'litorgy)
 
 
+(defun litorgy-read-cell (cell)
+  "Convert the string value of CELL to a number if appropriate.
+Otherwise if cell looks like a list (meaning it starts with a
+'(') then read it as lisp, otherwise return it unmodified as a
+string.
+
+This is taken almost directly from `org-read-prop'."
+  (if (and (stringp cell) (not (equal cell "")))
+      (let ((out (string-to-number cell)))
+	(if (equal out 0)
+	    (if (or (equal "(" (substring cell 0 1))
+                    (equal "'" (substring cell 0 1)))
+                (read cell)
+	      (if (string-match "^\\(+0\\|-0\\|0\\)$" cell)
+		  0
+		(progn (set-text-properties 0 (length cell) nil cell)
+		       cell)))
+	  out))
+    cell))
+
 (defun litorgy-reference-variables (params)
 (defun litorgy-reference-variables (params)
   "Takes a parameter alist, and return an alist of variable
   "Takes a parameter alist, and return an alist of variable
 names, and the string representation of the related value."
 names, and the string representation of the related value."
   (mapcar #'litorgy-reference-parse
   (mapcar #'litorgy-reference-parse
-   (delq nil (mapcar (lambda (pair) (if (= (car pair) :var) (cdr pair))) params))))
+   (delq nil (mapcar (lambda (pair) (if (eq (car pair) :var) (cdr pair))) params))))
 
 
 (defun litorgy-reference-parse (reference)
 (defun litorgy-reference-parse (reference)
   "Parse a reference to an external resource returning a list
   "Parse a reference to an external resource returning a list
@@ -65,19 +85,34 @@ with two elements.  The first element of the list will be the
 name of the variable, and the second will be an emacs-lisp
 name of the variable, and the second will be an emacs-lisp
 representation of the value of the variable."
 representation of the value of the variable."
   (save-excursion
   (save-excursion
-    (if (string-match "(.+)=(.+)" reference)
-      (let ((var (match-string 1 reference))
-            (ref (match-string 2 reference)))
-        (when (string-match "(.+):(.+)" reference)
-          (find-file (match-string 1 reference))
-          (setf ref (match-string 2 reference)))
-        ;; follow the reference in the current file
-        (case ref
-          ("previous"
-           )
-          ("next")
-          (t ))
-        ))))
+    (if (string-match "\\(.+\\)=\\(.+\\)" reference)
+        (let ((var (match-string 1 reference))
+              (ref (match-string 2 reference))
+              direction)
+          (when (string-match "\\(.+\\):\\(.+\\)" reference)
+            (find-file (match-string 1 reference))
+            (setf ref (match-string 2 reference)))
+          (cons (intern var)
+                (progn
+                  (cond ;; follow the reference in the current file
+                   ((string= ref "previous") (setq direction -1))
+                   ((string= ref "next") (setq direction 1))
+                   (t
+                    (goto-char (point-min))
+                    (setq direction 1)
+                    (unless (re-search-forward
+                             (concat "^#\\+TBLNAME:[ \t]*" (regexp-quote ref) "[ \t]*$") nil t)
+                      (setq id-loc (org-id-find name-or-id 'marker)
+                            buffer (marker-buffer id-loc)
+                            loc (marker-position id-loc))
+                      (move-marker id-loc nil))))
+                  (while (not (org-at-table-p))
+                    (forward-line direction)
+                    (if (or (= (point) (point-min)) (= (point) (point-max)))
+                        (error "no table found")))
+                  (mapcar (lambda (row)
+                            (mapcar #'litorgy-read-cell row))
+                          (org-table-to-lisp))))))))
 
 
 (provide 'litorgy-reference)
 (provide 'litorgy-reference)
 ;;; litorgy-reference.el ends here
 ;;; litorgy-reference.el ends here

+ 44 - 23
litorgy/litorgy.el

@@ -105,7 +105,9 @@ prefix don't dump results into buffer."
     (unless (member lang litorgy-interpreters)
     (unless (member lang litorgy-interpreters)
       (error "Language is not in `litorgy-interpreters': %s" lang))
       (error "Language is not in `litorgy-interpreters': %s" lang))
     (setq result (funcall cmd body params))
     (setq result (funcall cmd body params))
-    (unless arg (litorgy-insert-result result (assoc :replace params)))))
+    (if arg
+        (message (format "%S" result))
+      (litorgy-insert-result result (assoc :replace params)))))
 
 
 (defun litorgy-eval-buffer (&optional arg)
 (defun litorgy-eval-buffer (&optional arg)
   "Replace EVAL snippets in the entire buffer."
   "Replace EVAL snippets in the entire buffer."
@@ -141,42 +143,61 @@ form.  (language body header-arguments-alist)"
   (delq nil
   (delq nil
         (mapcar
         (mapcar
          (lambda (arg) (if (string-match "\\([^ \f\t\n\r\v]+\\)[ \f\t\n\r\v]*\\([^ \f\t\n\r\v]*\\)" arg)
          (lambda (arg) (if (string-match "\\([^ \f\t\n\r\v]+\\)[ \f\t\n\r\v]*\\([^ \f\t\n\r\v]*\\)" arg)
-                      (cons (intern (concat ":" (match-string 1 arg))) (match-string 2 arg))))
+                           (cons (intern (concat ":" (match-string 1 arg))) (match-string 2 arg))))
          (split-string (concat " " arg-string) "[ \f\t\n\r\v]+:"))))
          (split-string (concat " " arg-string) "[ \f\t\n\r\v]+:"))))
 
 
 (defun litorgy-insert-result (result &optional replace)
 (defun litorgy-insert-result (result &optional replace)
   "Insert RESULT into the current buffer after the end of the
   "Insert RESULT into the current buffer after the end of the
 current source block.  With optional argument REPLACE replace any
 current source block.  With optional argument REPLACE replace any
 existing results currently located after the source block."
 existing results currently located after the source block."
-  (if replace (litorgy-remove-result))
-  (unless (or (string-equal (substring result -1)
-                            "\n")
-              (string-equal (substring result -1)
-                            "\r"))
+  (if replace (litorgy-remove-result (listp result)))
+  (when (and (stringp result)
+             (not (or (string-equal (substring result -1) "\n")
+                      (string-equal (substring result -1) "\r"))))
     (setq result (concat result "\n")))
     (setq result (concat result "\n")))
   (save-excursion
   (save-excursion
     (re-search-forward "^#\\+end_src" nil t) (open-line 1) (forward-char 2)
     (re-search-forward "^#\\+end_src" nil t) (open-line 1) (forward-char 2)
-    (let ((beg (point))
-          (end (progn (insert result)
-                      (point))))
-      (save-excursion
-        (set-mark beg)
-        (goto-char end)
-        (org-toggle-fixed-width-section nil)))))
-
-(defun litorgy-remove-result ()
-  "Remove the result following the current source block"
+    (if (stringp result)
+        (litorgy-examplize-region (point) (progn (insert result) (point)))
+      (progn
+        (insert ;; for now lets assume the result is a table if it's not a string
+         (concat (orgtbl-to-orgtbl
+                  (if (consp (car result)) result (list result))
+                  '(:fmt (lambda (cell) (format "%S" cell)))) "\n"))
+        (forward-line -1)
+        (org-cycle)))))
+
+(defun litorgy-remove-result (&optional table)
+  "Remove the result following the current source block.  If
+optional argument TABLE is supplied then remove the table
+following the block rather than the fixed width example."
   (save-excursion
   (save-excursion
     (re-search-forward "^#\\+end_src" nil t)
     (re-search-forward "^#\\+end_src" nil t)
     (forward-char 1)
     (forward-char 1)
     (delete-region (point)
     (delete-region (point)
                    (save-excursion (forward-line 1)
                    (save-excursion (forward-line 1)
-                                   (while (if (looking-at ": ")
-                                              (progn (while (looking-at ": ")
-                                                       (forward-line 1)) t))
-                                     (forward-line 1))
-                                   (forward-line -1)
-                                   (point)))))
+                                   (if table
+                                       (org-table-end)
+                                     (while (if (looking-at ": ")
+                                                (progn (while (looking-at ": ")
+                                                         (forward-line 1)) t))
+                                       (forward-line 1))
+                                     (forward-line -1)
+                                     (point))))))
+
+(defun litorgy-examplize-region (beg end)
+  "Comment out region using the ': ' org example quote."
+  (interactive "*r")
+  (let ((size (abs (- (line-number-at-pos end)
+		      (line-number-at-pos beg)))))
+    (if (= size 0)
+	(let ((result (buffer-substring beg end)))
+	  (delete-region beg end)
+	  (insert (concat ": " result)))
+      (save-excursion
+        (goto-char beg)
+        (dotimes (n size)
+          (move-beginning-of-line 1) (insert ": ") (forward-line 1))))))
 
 
 (defun litorgy-clean-text-properties (text)
 (defun litorgy-clean-text-properties (text)
   "Strip all properties from text return."
   "Strip all properties from text return."

+ 28 - 0
rorg.org

@@ -736,6 +736,34 @@ cell =0,0= through =0,3= of the table
 |                 |
 |                 |
 
 
 
 
+** litorgy plays with tables
+Alright, this should demonstrate both the ability of litorgy to read
+tables into a lisp source code block, and to then convert the results
+of the source code block into an org table.  It's using the classic
+"lisp is elegant" demonstration transpose function.  To try this
+out...
+
+1. evaluate [[file:litorgy/init.el]] to load litorgy and friends
+2. evaluate the transpose definition =\C-u \C-c\C-c= on the beginning of
+   the source block (prefix arg to inhibit output)
+3. evaluate the next source code block, this should read in the table
+   because of the =:var table=previous=, then transpose the table, and
+   finally it should insert the transposed table into the buffer
+   immediately following the block
+
+#+begin_src emacs-lisp
+(defun transpose (table)
+  (apply #'mapcar* #'list table))
+#+end_src
+
+| 1 |       2 | 3 |
+| 4 | schulte | 6 |
+
+#+begin_src emacs-lisp :var table=previous :replace t
+(transpose table)
+#+end_src
+
+
 * COMMENT Commentary
 * COMMENT Commentary
 I'm seeing this as like commit notes, and a place for less formal
 I'm seeing this as like commit notes, and a place for less formal
 communication of the goals of our changes.
 communication of the goals of our changes.