Update copyright notices for 2013.
[bpt/emacs.git] / lisp / org / ob-ruby.el
CommitLineData
86fbb8ca
CD
1;;; ob-ruby.el --- org-babel functions for ruby evaluation
2
ab422c4d 3;; Copyright (C) 2009-2013 Free Software Foundation, Inc.
86fbb8ca
CD
4
5;; Author: Eric Schulte
6;; Keywords: literate programming, reproducible research
7;; Homepage: http://orgmode.org
86fbb8ca
CD
8
9;; This file is part of GNU Emacs.
10
11;; GNU Emacs is free software: you can redistribute it and/or modify
12;; it under the terms of the GNU General Public License as published by
13;; the Free Software Foundation, either version 3 of the License, or
14;; (at your option) any later version.
15
16;; GNU Emacs is distributed in the hope that it will be useful,
17;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19;; GNU General Public License for more details.
20
21;; You should have received a copy of the GNU General Public License
22;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
23
24;;; Commentary:
25
26;; Org-Babel support for evaluating ruby source code.
27
28;;; Requirements:
29
30;; - ruby and irb executables :: http://www.ruby-lang.org/
14e1337f 31;;
86fbb8ca
CD
32;; - ruby-mode :: Can be installed through ELPA, or from
33;; http://github.com/eschulte/rinari/raw/master/util/ruby-mode.el
14e1337f 34;;
86fbb8ca
CD
35;; - inf-ruby mode :: Can be installed through ELPA, or from
36;; http://github.com/eschulte/rinari/raw/master/util/inf-ruby.el
37
38;;; Code:
39(require 'ob)
40(require 'ob-ref)
41(require 'ob-comint)
42(require 'ob-eval)
43(eval-when-compile (require 'cl))
44
45(declare-function run-ruby "ext:inf-ruby" (&optional command name))
3ab2c837 46(declare-function xmp "ext:rcodetools" (&optional option))
86fbb8ca 47
3ab2c837 48(defvar org-babel-tangle-lang-exts)
86fbb8ca
CD
49(add-to-list 'org-babel-tangle-lang-exts '("ruby" . "rb"))
50
51(defvar org-babel-default-header-args:ruby '())
52
53(defvar org-babel-ruby-command "ruby"
54 "Name of command to use for executing ruby code.")
55
86fbb8ca
CD
56(defun org-babel-execute:ruby (body params)
57 "Execute a block of Ruby code with Babel.
58This function is called by `org-babel-execute-src-block'."
afe98dfa
CD
59 (let* ((session (org-babel-ruby-initiate-session
60 (cdr (assoc :session params))))
61 (result-params (cdr (assoc :result-params params)))
62 (result-type (cdr (assoc :result-type params)))
63 (full-body (org-babel-expand-body:generic
64 body params (org-babel-variable-assignments:ruby params)))
3ab2c837
BG
65 (result (if (member "xmp" result-params)
66 (with-temp-buffer
8223b1d2
BG
67 (require 'rcodetools)
68 (insert full-body)
69 (xmp (cdr (assoc :xmp-option params)))
70 (buffer-string))
3ab2c837 71 (org-babel-ruby-evaluate
8223b1d2 72 session full-body result-type result-params))))
3ab2c837
BG
73 (org-babel-reassemble-table
74 result
75 (org-babel-pick-name (cdr (assoc :colname-names params))
76 (cdr (assoc :colnames params)))
77 (org-babel-pick-name (cdr (assoc :rowname-names params))
78 (cdr (assoc :rownames params))))))
86fbb8ca
CD
79
80(defun org-babel-prep-session:ruby (session params)
81 "Prepare SESSION according to the header arguments specified in PARAMS."
82 ;; (message "params=%S" params) ;; debugging
83 (let* ((session (org-babel-ruby-initiate-session session))
afe98dfa 84 (var-lines (org-babel-variable-assignments:ruby params)))
86fbb8ca
CD
85 (org-babel-comint-in-buffer session
86 (sit-for .5) (goto-char (point-max))
87 (mapc (lambda (var)
88 (insert var) (comint-send-input nil t)
89 (org-babel-comint-wait-for-output session)
90 (sit-for .1) (goto-char (point-max))) var-lines))
91 session))
92
93(defun org-babel-load-session:ruby (session body params)
94 "Load BODY into SESSION."
95 (save-window-excursion
96 (let ((buffer (org-babel-prep-session:ruby session params)))
97 (with-current-buffer buffer
98 (goto-char (process-mark (get-buffer-process (current-buffer))))
99 (insert (org-babel-chomp body)))
100 buffer)))
101
102;; helper functions
103
afe98dfa 104(defun org-babel-variable-assignments:ruby (params)
8223b1d2 105 "Return list of ruby statements assigning the block's variables."
afe98dfa
CD
106 (mapcar
107 (lambda (pair)
108 (format "%s=%s"
109 (car pair)
110 (org-babel-ruby-var-to-ruby (cdr pair))))
111 (mapcar #'cdr (org-babel-get-header params :var))))
112
86fbb8ca
CD
113(defun org-babel-ruby-var-to-ruby (var)
114 "Convert VAR into a ruby variable.
115Convert an elisp value into a string of ruby source code
116specifying a variable of the same value."
117 (if (listp var)
118 (concat "[" (mapconcat #'org-babel-ruby-var-to-ruby var ", ") "]")
119 (format "%S" var)))
120
121(defun org-babel-ruby-table-or-string (results)
122 "Convert RESULTS into an appropriate elisp value.
123If RESULTS look like a table, then convert them into an
124Emacs-lisp table, otherwise return the results as a string."
acedf35c 125 (org-babel-script-escape results))
86fbb8ca
CD
126
127(defun org-babel-ruby-initiate-session (&optional session params)
128 "Initiate a ruby session.
129If there is not a current inferior-process-buffer in SESSION
130then create one. Return the initialized session."
86fbb8ca 131 (unless (string= session "none")
e66ba1df 132 (require 'inf-ruby)
86fbb8ca
CD
133 (let ((session-buffer (save-window-excursion
134 (run-ruby nil session) (current-buffer))))
135 (if (org-babel-comint-buffer-livep session-buffer)
136 (progn (sit-for .25) session-buffer)
137 (sit-for .5)
138 (org-babel-ruby-initiate-session session)))))
139
140(defvar org-babel-ruby-eoe-indicator ":org_babel_ruby_eoe"
141 "String to indicate that evaluation has completed.")
142(defvar org-babel-ruby-f-write
143 "File.open('%s','w'){|f| f.write((_.class == String) ? _ : _.inspect)}")
144(defvar org-babel-ruby-pp-f-write
145 "File.open('%s','w'){|f| $stdout = f; pp(results); $stdout = orig_out}")
146(defvar org-babel-ruby-wrapper-method
147 "
148def main()
149%s
150end
151results = main()
152File.open('%s', 'w'){ |f| f.write((results.class == String) ? results : results.inspect) }
153")
154(defvar org-babel-ruby-pp-wrapper-method
155 "
156require 'pp'
157def main()
158%s
159end
160results = main()
161File.open('%s', 'w') do |f|
162 $stdout = f
163 pp results
164end
165")
166
167(defun org-babel-ruby-evaluate
168 (buffer body &optional result-type result-params)
169 "Pass BODY to the Ruby process in BUFFER.
170If RESULT-TYPE equals 'output then return a list of the outputs
171of the statements in BODY, if RESULT-TYPE equals 'value then
172return the value of the last statement in BODY, as elisp."
173 (if (not buffer)
174 ;; external process evaluation
175 (case result-type
176 (output (org-babel-eval org-babel-ruby-command body))
afe98dfa
CD
177 (value (let ((tmp-file (org-babel-temp-file "ruby-")))
178 (org-babel-eval
179 org-babel-ruby-command
180 (format (if (member "pp" result-params)
181 org-babel-ruby-pp-wrapper-method
182 org-babel-ruby-wrapper-method)
183 body (org-babel-process-file-name tmp-file 'noquote)))
86fbb8ca
CD
184 ((lambda (raw)
185 (if (or (member "code" result-params)
186 (member "pp" result-params))
187 raw
188 (org-babel-ruby-table-or-string raw)))
189 (org-babel-eval-read-file tmp-file)))))
190 ;; comint session evaluation
191 (case result-type
192 (output
193 (mapconcat
194 #'identity
195 (butlast
196 (split-string
197 (mapconcat
198 #'org-babel-trim
199 (butlast
200 (org-babel-comint-with-output
201 (buffer org-babel-ruby-eoe-indicator t body)
202 (mapc
203 (lambda (line)
204 (insert (org-babel-chomp line)) (comint-send-input nil t))
205 (list body org-babel-ruby-eoe-indicator))
206 (comint-send-input nil t)) 2)
207 "\n") "[\r\n]")) "\n"))
208 (value
209 ((lambda (results)
210 (if (or (member "code" result-params) (member "pp" result-params))
211 results
212 (org-babel-ruby-table-or-string results)))
afe98dfa 213 (let* ((tmp-file (org-babel-temp-file "ruby-"))
86fbb8ca
CD
214 (ppp (or (member "code" result-params)
215 (member "pp" result-params))))
216 (org-babel-comint-with-output
217 (buffer org-babel-ruby-eoe-indicator t body)
218 (when ppp (insert "require 'pp';") (comint-send-input nil t))
219 (mapc
220 (lambda (line)
221 (insert (org-babel-chomp line)) (comint-send-input nil t))
222 (append
223 (list body)
224 (if (not ppp)
afe98dfa
CD
225 (list (format org-babel-ruby-f-write
226 (org-babel-process-file-name tmp-file 'noquote)))
86fbb8ca
CD
227 (list
228 "results=_" "require 'pp'" "orig_out = $stdout"
afe98dfa
CD
229 (format org-babel-ruby-pp-f-write
230 (org-babel-process-file-name tmp-file 'noquote))))
86fbb8ca
CD
231 (list org-babel-ruby-eoe-indicator)))
232 (comint-send-input nil t))
233 (org-babel-eval-read-file tmp-file)))))))
234
235(defun org-babel-ruby-read-string (string)
236 "Strip \\\"s from around a ruby string."
237 (if (string-match "^\"\\([^\000]+\\)\"$" string)
238 (match-string 1 string)
239 string))
240
241(provide 'ob-ruby)
242
5b409b39 243
86fbb8ca
CD
244
245;;; ob-ruby.el ends here