litorgy-R.el 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. ;;; litorgy-R.el --- litorgy functions for R code evaluation
  2. ;; Copyright (C) 2009 Eric Schulte
  3. ;; Author: Eric Schulte
  4. ;; Keywords: literate programming, reproducible research, R, statistics
  5. ;; Homepage: http://orgmode.org
  6. ;; Version: 0.01
  7. ;;; License:
  8. ;; This program is free software; you can redistribute it and/or modify
  9. ;; it under the terms of the GNU General Public License as published by
  10. ;; the Free Software Foundation; either version 3, or (at your option)
  11. ;; any later version.
  12. ;;
  13. ;; This program is distributed in the hope that it will be useful,
  14. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. ;; GNU General Public License for more details.
  17. ;;
  18. ;; You should have received a copy of the GNU General Public License
  19. ;; along with GNU Emacs; see the file COPYING. If not, write to the
  20. ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  21. ;; Boston, MA 02110-1301, USA.
  22. ;;; Commentary:
  23. ;; Litorgy support for evaluating R code
  24. ;;; Code:
  25. (require 'litorgy)
  26. (litorgy-add-interpreter "R")
  27. (defvar litorgy-R-var-name "litorgy_R_variable")
  28. (defvar litorgy-R-var-as-table
  29. "write.org.table <- function (x, write.rownames = TRUE)
  30. {
  31. if(!is.null(dim(x)) && length(dim(x)) > 2)
  32. stop(\"Object must be 1- or 2-dimensional\") ;
  33. if(is.vector(x) || is.table(x) || is.factor(x) || is.array(x))
  34. x <- as.matrix(x) ;
  35. if(!(is.matrix(x) || inherits(x, c('matrix', 'data.frame')))) {
  36. invisible() ;
  37. print(x) ;
  38. stop(\"Object not recognised as 1- or 2-dimensional\") ;
  39. } ;
  40. x
  41. }")
  42. (defun litorgy-execute:R (body params)
  43. "Execute a block of R code with litorgy. This function is
  44. called by `litorgy-execute-src-block'."
  45. (message "executing R source code block...")
  46. (save-window-excursion
  47. (let ((vars (litorgy-ref-variables params))
  48. results)
  49. (message (format "--%S--" vars))
  50. (mapc (lambda (pair)
  51. (litorgy-R-input-command
  52. (format "%s <- %s" (car pair) (cdr pair))))
  53. vars)
  54. (litorgy-R-initiate-R-buffer)
  55. (litorgy-R-command-to-string body))))
  56. (defun litorgy-R-table-or-scalar (var-name)
  57. "Determine whether the variable in `litorgy-R-buffer' named
  58. VAR-NAME has any associated dimensions. If it does have
  59. dimensions then return it as a list, otherwise just read it as a
  60. single variable."
  61. (if (litorgy-R-multidimensional-p var-name)
  62. (litorgy-R-vecotr-to-elisp-list var-name)
  63. (read result)))
  64. (defun litorgy-R-multidimensional-p (var-name)
  65. "Return t if the variable named VAR-NAME in `litorgy-R-buffer'
  66. is multidimensional."
  67. )
  68. (defun litorgy-R-vector-to-elisp-list (var-name)
  69. "Assumes that var-name is multidimensional in which case it
  70. then converts it's value into an Emacs-lisp list which is
  71. returned."
  72. )
  73. ;; functions for evaluation of R code
  74. (defvar litorgy-R-buffer nil
  75. "Holds the buffer for the current R process")
  76. (defun litorgy-R-initiate-R-buffer ()
  77. "If there is not a current R process then create one."
  78. (unless (and (buffer-live-p litorgy-R-buffer) (get-buffer litorgy-R-buffer))
  79. (save-excursion
  80. (R)
  81. (setf litorgy-R-buffer (current-buffer))
  82. (litorgy-R-wait-for-output)
  83. (litorgy-R-input-command ""))))
  84. (defun litorgy-R-command-to-string (command)
  85. "Send a command to R, and return the results as a string."
  86. (litorgy-R-input-command command)
  87. (litorgy-R-last-output))
  88. (defun litorgy-R-input-command (command)
  89. "Pass COMMAND to the R process running in `litorgy-R-buffer'."
  90. (save-excursion
  91. (save-match-data
  92. (set-buffer litorgy-R-buffer)
  93. (goto-char (process-mark (get-buffer-process (current-buffer))))
  94. (insert command)
  95. (comint-send-input)
  96. (litorgy-R-wait-for-output))))
  97. (defun litorgy-R-wait-for-output ()
  98. "Wait until output arrives"
  99. (save-excursion
  100. (save-match-data
  101. (set-buffer litorgy-R-buffer)
  102. (while (progn
  103. (goto-char comint-last-input-end)
  104. (not (re-search-forward comint-prompt-regexp nil t)))
  105. (accept-process-output (get-buffer-process (current-buffer)))))))
  106. (defun litorgy-R-last-output ()
  107. "Return the last R output as a string"
  108. (save-excursion
  109. (save-match-data
  110. (set-buffer litorgy-R-buffer)
  111. (goto-char (process-mark (get-buffer-process (current-buffer))))
  112. (forward-line 0)
  113. (let ((raw (buffer-substring comint-last-input-end (- (point) 1)))
  114. output output-flag)
  115. (mapconcat
  116. (lambda (el)
  117. (if (stringp el)
  118. (format "%s" el)
  119. (format "%S" el)))
  120. (delq nil
  121. (mapcar
  122. (lambda (line)
  123. (unless (string-match "^>" line)
  124. (and (string-match "\\[[[:digit:]]+\\] *\\(.*\\)$" line)
  125. (match-string 1 line))))
  126. ;; drop first, because it's the last line of input
  127. (cdr (split-string raw "[\n\r]")))) "\n")))))
  128. (defun litorgy-R-table-or-results (results)
  129. "If the results look like a matrix, then convert them into an
  130. Emacs-lisp table otherwise return the results as a string."
  131. ;; TODO: these simple assumptions will probably need some tweaking
  132. (when (string-match "[ \f\t\n\r\v]+" results)
  133. (concat "(" (mapconcat #'litorgy-R-tale-or-results
  134. (split-string results) " ") ")"))
  135. results)
  136. (provide 'litorgy-R)
  137. ;;; litorgy-R.el ends here