1 ;;; ob-gnuplot.el --- org-babel functions for gnuplot evaluation
3 ;; Copyright (C) 2009 Eric Schulte
5 ;; Author: Eric Schulte
6 ;; Keywords: literate programming, reproducible research
7 ;; Homepage: http://orgmode.org
12 ;; This program is free software; you can redistribute it and/or modify
13 ;; it under the terms of the GNU General Public License as published by
14 ;; the Free Software Foundation; either version 3, or (at your option)
17 ;; This program is distributed in the hope that it will be useful,
18 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 ;; GNU General Public License for more details.
22 ;; You should have received a copy of the GNU General Public License
23 ;; along with GNU Emacs; see the file COPYING. If not, write to the
24 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25 ;; Boston, MA 02110-1301, USA.
29 ;; Org-Babel support for evaluating gnuplot source code.
31 ;; This differs from most standard languages in that
33 ;; 1) we are generally only going to return results of type "file"
35 ;; 2) we are adding the "file" and "cmdline" header arguments
39 ;; - gnuplot :: http://www.gnuplot.info/
41 ;; - gnuplot-mode :: http://cars9.uchicago.edu/~ravel/software/gnuplot-mode.html
47 (defvar org-babel-default-header-args
:gnuplot
48 '((:results .
"file") (:exports .
"results") (:session . nil
))
49 "Default arguments to use when evaluating a gnuplot source block.")
51 (defvar org-babel-gnuplot-timestamp-fmt nil
)
53 (defun org-babel-gnuplot-process-vars (params)
54 "Extract variables from PARAMS and process the variables
55 dumping all vectors into files and returning an association list
56 of variable names and the related value to be used in the gnuplot
61 (car pair
) ;; variable name
62 (if (listp (cdr pair
)) ;; variable value
63 (org-babel-gnuplot-table-to-data
64 (cdr pair
) (make-temp-file "org-babel-gnuplot") params
)
66 (org-babel-ref-variables params
)))
68 (defun org-babel-expand-body:gnuplot
(body params
&optional processed-params
)
69 "Expand BODY according to PARAMS, return the expanded body."
70 (save-window-excursion
71 (let* ((vars (org-babel-gnuplot-process-vars params
))
72 (out-file (cdr (assoc :file params
)))
73 (term (or (cdr (assoc :term params
))
74 (when out-file
(file-name-extension out-file
))))
75 (cmdline (cdr (assoc :cmdline params
)))
76 (title (plist-get params
:title
))
77 (lines (plist-get params
:line
))
78 (sets (plist-get params
:set
))
79 (x-labels (plist-get params
:xlabels
))
80 (y-labels (plist-get params
:ylabels
))
81 (timefmt (plist-get params
:timefmt
))
82 (time-ind (or (plist-get params
:timeind
)
85 (flet ((add-to-body (text)
86 (setq body
(concat text
"\n" body
))))
87 ;; append header argument settings to body
88 (when title
(add-to-body (format "set title '%s'" title
))) ;; title
89 (when lines
(mapc (lambda (el) (add-to-body el
)) lines
)) ;; line
91 (mapc (lambda (el) (add-to-body (format "set %s" el
))) sets
))
94 (format "set xtics (%s)"
95 (mapconcat (lambda (pair)
96 (format "\"%s\" %d" (cdr pair
) (car pair
)))
100 (format "set ytics (%s)"
101 (mapconcat (lambda (pair)
102 (format "\"%s\" %d" (cdr pair
) (car pair
)))
105 (add-to-body "set xdata time")
106 (add-to-body (concat "set timefmt \""
108 "%Y-%m-%d-%H:%M:%S") "\"")))
109 (when out-file
(add-to-body (format "set output \"%s\"" out-file
)))
110 (when term
(add-to-body (format "set term %s" term
)))
111 ;; insert variables into code body: this should happen last
112 ;; placing the variables at the *top* of the code in case their
113 ;; values are used later
114 (add-to-body (mapconcat
115 (lambda (pair) (format "%s = \"%s\"" (car pair
) (cdr pair
)))
117 ;; replace any variable names preceded by '$' with the actual
118 ;; value of the variable
120 (setq body
(replace-regexp-in-string
121 (format "\\$%s" (car pair
)) (cdr pair
) body
)))
125 (defun org-babel-execute:gnuplot
(body params
)
126 "Execute a block of Gnuplot code with org-babel. This function is
127 called by `org-babel-execute-src-block'."
128 (message "executing Gnuplot source code block")
129 (let ((session (cdr (assoc :session params
)))
130 (result-type (cdr (assoc :results params
)))
131 (out-file (cdr (assoc :file params
)))
132 (body (org-babel-expand-body:gnuplot body params
)))
133 (save-window-excursion
134 ;; evaluate the code body with gnuplot
135 (if (string= session
"none")
136 (let ((script-file (make-temp-file "org-babel-gnuplot-script")))
137 (with-temp-file script-file
138 (insert (concat body
"\n")))
139 (message "gnuplot \"%s\"" script-file
)
141 (shell-command-to-string (format "gnuplot \"%s\"" script-file
)))
144 (insert (concat body
"\n"))
146 (gnuplot-send-buffer-to-gnuplot)))
147 (if (member "output" (split-string result-type
))
151 (defun org-babel-prep-session:gnuplot
(session params
)
152 "Prepare SESSION according to the header arguments specified in PARAMS."
153 (let* ((session (org-babel-gnuplot-initiate-session session
))
154 (vars (org-babel-ref-variables params
))
156 (lambda (pair) (format "%s = \"%s\"" (car pair
) (cdr pair
)))
158 (message "%S" session
)
159 (org-babel-comint-in-buffer session
160 (mapc (lambda (var-line)
161 (insert var-line
) (comint-send-input nil t
)
162 (org-babel-comint-wait-for-output session
)
163 (sit-for .1) (goto-char (point-max))) var-lines
))
166 (defun org-babel-load-session:gnuplot
(session body params
)
167 "Load BODY into SESSION."
168 (save-window-excursion
169 (let ((buffer (org-babel-prep-session:gnuplot session params
)))
170 (with-current-buffer buffer
171 (goto-char (process-mark (get-buffer-process (current-buffer))))
172 (insert (org-babel-chomp body
)))
175 (defun org-babel-gnuplot-initiate-session (&optional session params
)
176 "If there is not a current inferior-process-buffer in SESSION
177 then create one. Return the initialized session. The current
178 `gnuplot-mode' doesn't provide support for multiple sessions."
179 (unless (string= session
"none")
180 (save-window-excursion (gnuplot-send-string-to-gnuplot "" "line")
183 (defun org-babel-gnuplot-quote-timestamp-field (s)
184 "Convert field S from timestamp to Unix time and export to gnuplot."
185 (format-time-string org-babel-gnuplot-timestamp-fmt
(org-time-string-to-time s
)))
187 (defun org-babel-gnuplot-quote-tsv-field (s)
188 "Quote field S for export to gnuplot."
190 (setq s
(format "%s" s
)))
191 (if (string-match org-table-number-regexp s
) s
192 (if (string-match org-ts-regexp3 s
)
193 (org-babel-gnuplot-quote-timestamp-field s
)
194 (concat "\"" (mapconcat 'identity
(split-string s
"\"") "\"\"") "\""))))
196 (defun org-babel-gnuplot-table-to-data (table data-file params
)
197 "Export TABLE to DATA-FILE in a format readable by gnuplot.
198 Pass PARAMS through to `orgtbl-to-generic' when exporting TABLE."
199 (with-temp-file data-file
200 (make-local-variable 'org-babel-gnuplot-timestamp-fmt
)
201 (setq org-babel-gnuplot-timestamp-fmt
(or
202 (plist-get params
:timefmt
)
203 "%Y-%m-%d-%H:%M:%S"))
204 (insert (orgtbl-to-generic
207 '(:sep
"\t" :fmt org-babel-gnuplot-quote-tsv-field
)
211 (provide 'ob-gnuplot
)
212 ;;; ob-gnuplot.el ends here