diff --git a/existing_tools/org-eval-light.el b/existing_tools/org-eval-light.el new file mode 100644 index 000000000..c571ea0bb --- /dev/null +++ b/existing_tools/org-eval-light.el @@ -0,0 +1,200 @@ +;;; org-eval-light.el --- Display result of evaluating code in various languages (light) + +;; Copyright (C) 2008 Free Software Foundation, Inc. + +;; Author: Carsten Dominik , +;; Eric Schulte +;; Keywords: outlines, hypermedia, calendar, wp, literate programming, +;; reproducible research +;; Homepage: http://orgmode.org +;; Version: 0.04 + +;; This file is not yet part of GNU Emacs. + +;; GNU Emacs 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. + +;; GNU Emacs 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: + +;; This file is based off of org-eval, with the following changes. +;; +;; 1) forms are only executed manually, (allowing for the execution of +;; an entire subtree of forms) +;; 2) use the org-mode style src blocks, rather than the muse style +;; blocks +;; 3) forms are not replaced by their outputs, but rather the output +;; is placed in the buffer immediately following the src block +;; commented by `org-eval-light-make-region-example' (when +;; evaluated with a prefix argument no output is placed in the +;; buffer) +;; 4) add defadvice to org-ctrl-c-ctrl-c so that when called inside of +;; a source block it will call `org-eval-light-current-snippet' + +;;; Code: +(require 'org) + +(defgroup org-eval-light nil + "Options concerning including output from commands into the Org-mode buffer." + :tag "Org Eval" + :group 'org) + +(defvar org-eval-light-example-size-cutoff 10 + "The number of lines under which an example is considered +'small', and is exported with the '^:' syntax instead of in a +large example block") + +(defvar org-eval-light-regexp nil) + +(defun org-eval-light-set-interpreters (var value) + (set-default var value) + (setq org-eval-light-regexp + (concat "#\\+begin_src \\(" + (mapconcat 'regexp-quote value "\\|") + "\\)\\([^\000]+?\\)#\\+end_src"))) + +(defcustom org-eval-light-interpreters '("lisp" "emacs-lisp" "ruby" "shell") + "Interpreters allows for evaluation tags. +This is a list of program names (as strings) that can evaluate code and +insert the output into an Org-mode buffer. Valid choices are + +lisp Interpret Emacs Lisp code and display the result +shell Pass command to the shell and display the result +perl The perl interpreter +python Thy python interpreter +ruby The ruby interpreter" + :group 'org-eval-light + :set 'org-eval-light-set-interpreters + :type '(set :greedy t + (const "lisp") + (const "emacs-lisp") + (const "perl") + (const "python") + (const "ruby") + (const "shell"))) + +;;; functions +(defun org-eval-light-inside-snippet () + (interactive) + (save-excursion + (let ((case-fold-search t) + (start-re "^#\\+begin_src\\( \\([^ \t\n]+\\)\\)?.*\n") + (end-re "\n#\\+end_src") + (pos (point)) + beg end) + (if (and (setq beg (re-search-backward start-re nil t)) + (setq end (re-search-forward end-re nil t)) + (<= beg pos) (>= end pos)) + t)))) + +(defun org-eval-light-make-region-example (beg end) + "Comment out region using either the '^:' or the BEGIN_EXAMPLE +syntax based on the size of the region as compared to +`org-eval-light-example-size-cutoff'." + (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))) + (if (<= size org-eval-light-example-size-cutoff) + (save-excursion + (goto-char beg) + (dotimes (n size) + (move-beginning-of-line 1) (insert ": ") (forward-line 1))) + (let ((result (buffer-substring beg end))) + (delete-region beg end) + (insert (concat "#+BEGIN_EXAMPLE\n" result "#+END_EXAMPLE\n"))))))) + +(defun org-eval-light-current-snippet (&optional arg) + "Execute the current #+begin_src #+end_src block, and dump the +results into the buffer immediately following the src block, +commented by `org-eval-light-make-region-example'." + (interactive "P") + (let ((line (org-current-line)) + (case-fold-search t) + (info (org-edit-src-find-region-and-lang)) + beg end lang result) + (setq beg (nth 0 info) + end (nth 1 info) + lang (nth 2 info)) + (unless (member lang org-eval-light-interpreters) + (error "Language is not in `org-eval-light-interpreters': %s" lang)) + (goto-line line) + (setq result (org-eval-light-code lang (buffer-substring beg end))) + (unless arg + (save-excursion + (re-search-forward "^#\\+end_src" nil t) (open-line 1) (forward-char 2) + (let ((beg (point)) + (end (progn (insert result) + (point)))) + (message (format "from %S %S" beg end)) + (org-eval-light-make-region-example beg end)))))) + +(defun org-eval-light-eval-subtree (&optional arg) + "Replace EVAL snippets in the entire subtree." + (interactive "P") + (save-excursion + (org-narrow-to-subtree) + (goto-char (point-min)) + (while (re-search-forward org-eval-light-regexp nil t) + (org-eval-light-current-snippet arg)) + (widen))) + +(defun org-eval-light-code (interpreter code) + (cond + ((member interpreter '("lisp" "emacs-lisp")) + (org-eval-light-lisp (concat "(progn\n" code "\n)"))) + ((equal interpreter "shell") + (shell-command-to-string code)) + ((member interpreter '("perl" "python" "ruby")) + (org-eval-light-run (executable-find interpreter) code)) + (t (error "Cannot evaluate code type %s" interpreter)))) + +(defun org-eval-light-lisp (form) + "Evaluate the given form and return the result as a string." + (require 'pp) + (save-match-data + (condition-case err + (let ((object (eval (read form)))) + (cond + ((stringp object) object) + ((and (listp object) + (not (eq object nil))) + (let ((string (pp-to-string object))) + (substring string 0 (1- (length string))))) + ((numberp object) + (number-to-string object)) + ((eq object nil) "") + (t + (pp-to-string object)))) + (error + (org-display-warning (format "%s: Error evaluating %s: %s" + "???" form err)) + "; INVALID LISP CODE")))) + +(defun org-eval-light-run (cmd code) + (with-temp-buffer + (insert code) + (shell-command-on-region (point-min) (point-max) cmd nil 'replace) + (buffer-string))) + +(defadvice org-ctrl-c-ctrl-c (around org-cc-eval-source activate) + (if (org-eval-light-inside-snippet) + (call-interactively 'org-eval-light-current-snippet) + ad-do-it)) + +(provide 'org-eval-light) +;;; org-eval-light.el ends here \ No newline at end of file diff --git a/rorg.org b/rorg.org index 6c01793ab..34b893e2b 100644 --- a/rorg.org +++ b/rorg.org @@ -1,4 +1,15 @@ #+TITLE: rorg --- R and org-mode +#+SEQ_TODO: TODO PROPOSED | DONE DROPPED MAYBE + +* Commentary + +** Eric <2009-02-06 Fri 15:41> +I think we're getting close to a comprehensive set of objectives +(although since you two are the real R user's I leave that decision up +to you). Once we've agreed on a set of objectives and agreed on at +least to broad strokes of implementation, I think we should start +listing out and assigning tasks. + * Objectives ** Send data to R from org @@ -20,14 +31,26 @@ files. Org tables are first exported to a temporary csv file using [[file:existing_tools/org-R.el::defun%20org%20R%20export%20to%20csv%20csv%20file%20options][org-R-export-to-csv]]. **** org-exp-blocks +org-exp-blocks uses [[org-interblock-R-command-to-string]] to send +commands to an R process running in a comint buffer through ESS. +org-exp-blocks has no support for dumping table data to R process, or +vice versa. + **** RweaveOrg NA -** evaluate R code from org and deal with output appropriately + +** Evaluate R code from org and deal with output appropriately *** vector output When R code evaluation generates vectors and 2-dimensional arrays, this should be formatted appropriately in org buffers (orgtbl-mode) as well as in export targets (html, latex) + + Agreed, if we can convert the vector data to lists then we can use + the many orgtbl-to-* functions to convert the list to whatever + output format we desire. See `orgtbl-to-orgtbl, `orgtbl-to-latex', + `orgtbl-to-html', `orgtbl-to-csv', etc... + **** Implementations ***** org-R org-R converts R output (vectors, or matrices / 2d-arrays) to an @@ -45,13 +68,28 @@ org file This should have the automatic consequence that it is included appropriately in subsequent export targets (html, latex). + **** Implementations ***** org-R org-R does (1) if no output file is specified and (2) otherwise ***** org-exp-blocks + org-exp-blocks tries to do 2, but I don't think that part was + every really working + ***** RweaveOrg +** Evaluate R code on export +At first I was leaning towards leaving the exporting to Sweave, but it +seems that once we have evaluation or R working, it will not be +difficult to implement full evaluation of R blocks, one-liners, and +creation of R graphics on export directly in elisp. + +I think that this would be worth the effort since it would eliminate +the need for using Sweave, and would allow for exportation to any +target format supported by org-mode. + + * Notes ** Special editing and evaluation of source code in R blocks Unfortunately org-mode how two different block types, both useful. @@ -64,6 +102,58 @@ Note that upper and lower case are not relevant in block headings. +*** PROPOSED R-block proposal +I (Eric) propose that we use the syntax of source code blocks as they +currently exist in org-mode with the addition of *evaluation*, +*header-arguments*, *exportation*, *single-line-blocks*, and +*references-to-table-data*. + +1) *evaluation*: These blocks can be evaluated through =\C-c\C-c= with + a slight addition to the code already present and working in + [[file:existing_tools/org-eval-light.el][org-eval-light.el]]. All we should need to add for R support would + be an appropriate entry in [[org-eval-light-interpreters]] with a + corresponding evaluation function. For an example usinga + org-eval-light see [[* src block evaluation w/org-eval-light]]. + +2) *header-arguments*: These can be implemented along the lines of + Austin's header arguments in [[file:existing_tools/RweaveOrg/org-sweave.el][org-sweave.el]]. + +3) *exportation*: Should be as similar as possible to that done by + Sweave, and hopefully can re-use some of the code currently present + in [[file:existing_tools/exp-blocks/org-exp-blocks.el ][org-exp-blocks.el]]. + +4) *single-line-blocks*: It seems that it is useful to be able to + place a single line of R code on a line by itself. Should we add + syntax for this similar to Dan's =#+R:= lines? I would lean + towards something here that can be re-used for any type of source + code in the same manner as the =#+begin_src R= blocks, maybe + =#+src_R=? + +5) *references-to-table-data*: I get this impression that this is + vital to the efficient use of R code in an org file, so we should + come up with a way to reference table data from a single-line-block + or from an R source-code block. It looks like Dan has already done + this in [[file:existing_tools/org-R.el][org-R.el]]. + +What do you think? Does this accomplish everything we want to be able +to do with embedded R source code blocks? + +**** src block evaluation w/org-eval-light +here's an example using org-eval-light.el + +first load the org-eval-light.el file + +[[elisp:(load (expand-file-name "org-eval-light.el" (expand-file-name "existing_tools" (file-name-directory buffer-file-name))))]] + +then press =\C-c\C-c= inside of the following src code snippet. The +results should appear in a comment immediately following the source +code block. It shouldn't be too hard to add R support to this +function through the `org-eval-light-interpreters' variable. + +#+begin_src shell +date +#+end_src + *** Source code blocks Org has an extremely useful method of editing source code and examples in their native modes. In the case of R code, we want to @@ -104,8 +194,23 @@ a have the advantage of accepting options to the Sweave preprocessor following the #+BEGIN_R declaration. +** Interaction with the R process + +We should take care to implement this in such a way that all of the +different components which have to interactive with R including: +- evaluation of source code blocks +- automatic evaluation on export +- evaluation of \R{} snippets +- evaluation of single source code lines +- sending/recieving vector data + +I think we currently have two implementation of interaction with R +processes; [[file:existing_tools/org-R.el][org-R.el]] and [[file:existing_tools/exp-blocks/org-exp-blocks.el ][org-exp-blocks.el]]. We should be sure to take +the best of each of these approaches. + + +* Tasks -* tasks * buffer dictionary LocalWords: DBlocks dblocks