*** empty log message ***
[ess.git] / lisp / essd-r.el
blobf26feb01ed58ddf8e6562f2a53368612bc3a8de2
1 ;;; essd-r.el --- R customization
3 ;; Copyright (C) 1997--2005 A.J. Rossini, Rich M. Heiberger, Martin
4 ;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen.
6 ;; Original Author: A.J. Rossini
7 ;; Created: 12 Jun 1997
8 ;; Maintainers: ESS-core <ESS-core@stat.math.ethz.ch>
10 ;; Keywords: start up, configuration.
12 ;; This file is part of ESS.
14 ;; This file is free software; you can redistribute it and/or modify
15 ;; it under the terms of the GNU General Public License as published by
16 ;; the Free Software Foundation; either version 2, or (at your option)
17 ;; any later version.
19 ;; This file is distributed in the hope that it will be useful,
20 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
21 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 ;; GNU General Public License for more details.
24 ;; You should have received a copy of the GNU General Public License
25 ;; along with GNU Emacs; see the file COPYING. If not, write to
26 ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
28 ;;; Commentary:
29 ;;; This file defines all the R customizations for ESS. See essl-s.el
30 ;;; for general S language customizations.
32 ;;; Autoloads and Requires
34 (ess-message "[essd-r:] (require 'essl-s)")
35 (require 'essl-s)
37 ;; modify S Syntax table:
38 (setq R-syntax-table S-syntax-table)
39 ;; R >= 1.8: back tick `string` -- unfortunately no *pair* checking:
40 ;; breaks when things like `..' are used:
41 ;; (modify-syntax-entry ?` "\"" R-syntax-table)
42 (modify-syntax-entry ?_ "_" R-syntax-table) ; foo_bar is symbol in R >=1.9
44 (ess-message "[essd-r:] (autoload ..) & (def** ..)")
46 (autoload 'inferior-ess "ess-inf" "Run an ESS process.")
47 (autoload 'ess-mode "ess-mode" "Edit an ESS process.")
49 ;;; Code:
51 (defvar R-customize-alist
52 (append
53 '((ess-local-customize-alist . 'R-customize-alist)
54 (ess-dialect . "R")
55 (ess-suffix . "R")
56 (ess-dump-filename-template . (ess-replace-regexp-in-string
57 "S$" ess-suffix ; in the one from custom:
58 ess-dump-filename-template-proto))
59 (ess-mode-syntax-table . R-syntax-table)
60 (ess-mode-editing-alist . R-editing-alist)
61 (ess-change-sp-regexp . ess-R-change-sp-regexp)
62 (ess-help-sec-regex . ess-help-R-sec-regex)
63 (ess-help-sec-keys-alist . ess-help-R-sec-keys-alist)
64 (ess-loop-timeout . ess-S-loop-timeout);fixme: dialect spec.
65 (ess-cmd-delay . ess-R-cmd-delay)
66 (ess-function-pattern . ess-R-function-pattern)
67 (ess-object-name-db-file . "ess-r-namedb.el" )
68 (ess-retr-lastvalue-command . "assign(\".Last.value\", .ess.lvsave, envir=baseenv())\n")
69 (ess-save-lastvalue-command . "assign(\".ess.lvsave\", get(\".Last.value\", envir=baseenv()))\n")
70 (ess-imenu-mode-function . 'ess-imenu-R)
71 (inferior-ess-program . inferior-R-program-name)
72 (inferior-ess-objects-command . inferior-R-objects-command)
73 (inferior-ess-font-lock-keywords . inferior-ess-R-font-lock-keywords)
74 (inferior-ess-search-list-command . "search()\n")
75 (inferior-ess-help-command . "help(\"%s\", htmlhelp=FALSE)\n")
76 (inferior-ess-exit-command . "q()")
77 (inferior-ess-exit-prompt . "Save workspace image? [y/n/c]: ")
78 (inferior-ess-primary-prompt . "\\([A-Z][][A-Za-z0-9.]*\\)*> ")
79 (inferior-ess-secondary-prompt . "+ ?")
80 ;;harmful for shell-mode's C-a: -- but "necessary" for ESS-help?
81 (inferior-ess-start-file . nil) ;; "~/.ess-R"
82 (inferior-ess-start-args . "")
83 (ess-STERM . "iESS")
84 (ess-editor . R-editor)
85 (ess-pager . R-pager)
87 S-common-cust-alist)
88 "Variables to customize for R")
90 (defvar ess-r-versions '("R-1" "R-2" "R-devel" "R-patched")
91 "List of partial strings for versions of R to access within ESS.
92 Each string specifies the start of a filename. If a filename
93 beginning with one of these strings is found on `exec-path', a M-x
94 command for that version of R is made available. For example, if the
95 file \"R-1.8.1\" is found and this variable includes the string
96 \"R-1\", a function called `M-x R-1.8.1' will be available to run that
97 version of R.
98 If duplicate versions of the same program are found (which happens if
99 the same path is listed on `exec-path' more than once), they are
100 ignored by calling `ess-uniq-list'.
101 Set this variable to nil to disable searching for other versions of R.
102 If you set this variable, you need to restart Emacs (and set this variable
103 before ess-site is loaded) for it to take effect.")
105 ;;;### autoload
106 (defun R (&optional start-args)
107 "Call 'R', the 'GNU S' system from the R Foundation.
108 Optional prefix (C-u) allows to set command line arguments, such as
109 --vsize. This should be OS agnostic.
110 If you have certain command line arguments that should always be passed
111 to R, put them in the variable `inferior-R-args'."
112 (interactive "P")
113 (setq ess-customize-alist R-customize-alist)
114 (ess-write-to-dribble-buffer ;; for debugging only
115 (format
116 "\n(R): ess-dialect=%s, buf=%s, start-arg=%s\n current-prefix-arg=%s\n"
117 ess-dialect (current-buffer) start-args current-prefix-arg))
118 (let* ((r-always-arg
119 (if (or ess-microsoft-p (eq system-type 'cygwin))
120 "--ess "
121 "--no-readline "))
122 (r-start-args
123 (concat r-always-arg
124 inferior-R-args " " ; add space just in case
125 (if start-args
126 (read-string
127 (concat "Starting Args [other than `"
128 r-always-arg
129 "'] ? "))
130 nil)))
131 ;;Micro$ ?: default-process-coding-system ;-breaks UTF locales on Unix:
133 (if ess-microsoft-p
134 (setq default-process-coding-system '(undecided-dos . undecided-dos)))
135 (inferior-ess r-start-args) ;; (R)
136 (ess-write-to-dribble-buffer
137 (format "(R): inferior-ess-language-start=%s\n"
138 inferior-ess-language-start))
139 ;; currently rely on baseenv() which is in R only since version 2.2:
140 (ess-eval-linewise
141 "if(!exists(\"baseenv\", mode=\"function\")) baseenv <- function() NULL")
142 (if inferior-ess-language-start
143 (ess-eval-linewise inferior-ess-language-start))))
145 ;;;### autoload
146 (defun R-mode (&optional proc-name)
147 "Major mode for editing R source. See `ess-mode' for more help."
148 (interactive)
149 (setq ess-customize-alist R-customize-alist)
150 ;;(setq imenu-generic-expression R-imenu-generic-expression)
151 (ess-mode R-customize-alist proc-name)
152 (if (fboundp 'ess-add-toolbar) (ess-add-toolbar))
153 ;; ECB needs seminatic stuff.
154 ;; (if (featurep 'semantic)
155 ;; (setq semantic-toplevel-bovine-table r-toplevel-bovine-table))
156 (if ess-imenu-use-S
157 (progn (require 'ess-menu)
158 (ess-imenu-R)))
159 ;; MM: ^^^^^^^^^^^ should really use ess-imenu-mode-function from the
160 ;; alist above!
164 (fset 'r-mode 'R-mode)
166 (defun ess-r-versions-create ()
167 "Generate the `M-x R-X.Y' functions for starting other versions of R.
168 See `ess-r-versions' for strings that determine which functions are created.
170 The local variable `ess-r-versions-created' is used to return list of
171 the new R defuns, if any, that were created. The defuns will normally
172 be placed on the menubar upon ESS initialisation."
175 (if (not ess-r-versions)
176 nil ;nothing to return
177 ;; else, if ess-r-versions is non-nil, let's try to find those R versions.
178 ;; This works by creating a temp buffer where the template function is
179 ;; edited so that X.Y is replaced by the version name
180 (let ((template "")
181 (beg)
182 (versions)
183 (version)
184 (eval-buf (get-buffer-create "*ess-temp-r-evals*"))
185 (ess-r-versions-created)
187 ;; This is the template function used for creating M-x R-X.Y.
188 (setq template "(defun R-X.Y (&optional start-args)
189 \"Call R-X.Y, i.e., the R version 'R-X.Y' using ESS.
190 This function was generated by `ess-r-versions-create'.\"
191 (interactive \"P\")
192 (let ((inferior-R-program-name \"R-X.Y\"))
193 (R start-args)))
196 (save-excursion
197 (set-buffer eval-buf)
198 ;; clear the buffer.
199 (delete-region (point-min) (point-max))
201 ;; Find which versions of R we want. Remove the pathname, leaving just
202 ;; the name of the executable.
203 (setq versions
204 (ess-uniq-list
205 (mapcar 'file-name-nondirectory
206 (apply 'nconc
207 (mapcar 'ess-find-exec-completions
208 ess-r-versions)))))
209 (ess-write-to-dribble-buffer
210 (format "(R): ess-r-versions-create making M-x defuns for %s"
211 (mapconcat 'identity versions " ")))
212 (setq ess-r-versions-created versions) ;keep copy for returning at end.
213 ;; Iterate over each string in VERSIONS, creating a new defun each time.
214 (while versions
215 (setq version (car versions)
216 versions (cdr versions))
217 (setq beg (point))
218 (insert template)
219 (goto-char beg)
220 (while (search-forward "R-X.Y" nil t)
221 (replace-match version t t))
222 (goto-char (point-max))
224 ;; buffer has now been created with defuns, so eval them!
225 (eval-buffer)
226 (kill-buffer eval-buf)
228 ess-r-versions-created)))
231 (defun ess-find-rterm (&optional ess-R-root-dir)
232 "Find the full path of all occurences of Rterm.exe under the ESS-R-ROOT-DIR.
233 If ESS-R-ROOT-DIR is nil, construct it by looking for an occurence of Rterm.exe
234 in the exec-path. If there are no occurences of Rterm.exe in the exec-path,
235 then use \"c:/progra~1/R\" which is the default location for the R distribution."
236 (let* ((Rpath)
237 (rwxxyy)
238 (rw)
239 (Rterm nil))
240 (if (not ess-R-root-dir)
241 (progn
242 (setq Rpath (executable-find "Rterm"))
243 (setq ess-R-root-dir
244 (if Rpath
245 (expand-file-name
246 (concat
247 (file-name-directory Rpath)
248 "../../"))
249 "c:/progra~1/R"))))
250 (setq rwxxyy (append (file-name-all-completions "rw" ess-R-root-dir)
251 (file-name-all-completions "R-1" ess-R-root-dir)
252 (file-name-all-completions "R-2" ess-R-root-dir)
253 (file-name-all-completions "R-devel" ess-R-root-dir)
254 (file-name-all-completions "R-patched" ess-R-root-dir)
255 )) ;; this needs to rewritten to use (append '("rw") ess-r-versions)
256 (while rwxxyy
257 (setq rw (car rwxxyy))
258 (setq rwxxyy (cdr rwxxyy))
259 (setq Rterm (cons (concat ess-R-root-dir rw "bin/Rterm.exe") Rterm)))
260 Rterm))
262 (defun ess-rterm-versions-create ()
263 "Generate the `M-x rwxxyy' functions for starting other versions of R.
264 See `ess-rterm-versions' for strings that determine which functions
265 are created.
267 The result `ess-rterm-versions-created' will store a list of the new
268 Rterm defuns, if any, that were created. The defuns will normally be
269 placed on the menubar upon ESS initialisation."
271 ;; This works by creating a temp buffer where the template function is
272 ;; edited so that R-X.Y is replaced by the version name
273 (let ((template "")
274 (beg)
275 (versions)
276 (version)
277 (version-root)
278 (eval-buf (get-buffer-create "*ess-temp-r-evals*"))
279 (ess-rterm-versions-created)
282 ;; This is the template function used for creating M-x R-X.Y.
283 (setq template "(defun R-X.Y (&optional start-args)
284 \"Call R-X.Y, i.e., the R version 'R-X.Y' using ESS.
285 This function was generated by `ess-rterm-versions-create'.\"
286 (interactive \"P\")
287 (let ((inferior-R-program-name \"Rterm-X.Y\"))
288 (R start-args)))
291 (save-excursion
292 (set-buffer eval-buf)
293 ;; clear the buffer.
294 (delete-region (point-min) (point-max))
296 ;; Find which versions of R we want. Remove the pathname, leaving just
297 ;; the name of the executable.
298 (setq versions ess-rterm-versions)
299 (ess-write-to-dribble-buffer
300 (format "(R): ess-rterm-versions-create making M-x defuns for %s"
301 (mapconcat 'identity versions " ")))
303 ;; Iterate over each string in VERSIONS, creating a new defun each time.
304 (while versions
305 (setq version (car versions)
306 versions (cdr versions)
307 version-root (file-name-nondirectory
308 (substring (file-name-directory
309 (substring
310 (file-name-directory version)
311 0 -1))
312 0 -1)))
313 (setq beg (point))
314 (insert template)
315 (goto-char beg)
316 (while (search-forward "R-X.Y" nil t)
317 (replace-match version-root t t))
318 (goto-char beg)
319 (while (search-forward "Rterm-X.Y" nil t)
320 (replace-match version t t))
321 (goto-char (point-max))
322 (setq ess-rterm-versions-created
323 (cons version-root ess-rterm-versions-created))
325 ;; buffer has now been created with defuns, so eval them!
326 (eval-buffer)
327 (kill-buffer eval-buf)
329 ess-rterm-versions-created))
331 ;;;### autoload
332 (defun Rnw-mode ()
333 "Major mode for editing Sweave(R) source.
334 See `noweb-mode' and `R-mode' for more help."
335 (interactive)
336 (require 'ess-noweb);; << probably someplace else
337 (noweb-mode 1); turn it on
338 (noweb-set-doc-mode 'latex-mode)
339 (noweb-set-code-mode 'R-mode))
342 (autoload 'ess-transcript-mode "ess-trns"
343 "Major mode for editing S transcript files." t)
345 (defun R-transcript-mode ()
346 "Does the right thing."
347 (interactive)
348 (ess-transcript-mode R-customize-alist))
350 (fset 'r-transcript-mode 'R-transcript-mode)
352 (defun R-fix-T-F (&optional from quietly)
353 "Fix T/F into TRUE and FALSE *cautiously*, i.e. not in comments and strings;
354 starting from the current position (point)."
355 (interactive "d\nP"); point and prefix (C-u)
356 (save-excursion
357 (goto-char from)
358 (ess-rep-regexp "\\(\\([][=,()]\\|<-\\|_\\) *\\)T\\>" "\\1TRUE"
359 'fixcase nil (not quietly))
360 (goto-char from)
361 (ess-rep-regexp "\\(\\([][=,()]\\|<-\\|_\\\) *\\)F\\>" "\\1FALSE"
362 'fixcase nil (not quietly))))
364 \f ; provides
366 (provide 'essd-r)
368 \f ; Local variables section
370 ;;; This file is automatically placed in Outline minor mode.
371 ;;; The file is structured as follows:
372 ;;; Chapters: ^L ;
373 ;;; Sections: ;;*;;
374 ;;; Subsections: ;;;*;;;
375 ;;; Components: defuns, defvars, defconsts
376 ;;; Random code beginning with a ;;;;* comment
378 ;;; Local variables:
379 ;;; mode: emacs-lisp
380 ;;; outline-minor-mode: nil
381 ;;; mode: outline-minor
382 ;;; outline-regexp: "\^L\\|\\`;\\|;;\\*\\|;;;\\*\\|(def[cvu]\\|(setq\\|;;;;\\*"
383 ;;; End:
385 ;;; essd-r.el ends here