Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
2701 views
1
;;; ess-r-d.el --- R customization
2
3
;; Copyright (C) 1997--2010 A.J. Rossini, Richard M. Heiberger, Martin
4
;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen.
5
;; Copyright (C) 2011--2012 A.J. Rossini, Richard M. Heiberger, Martin Maechler,
6
;; Kurt Hornik, Rodney Sparapani, Stephen Eglen and Vitalie Spinu.
7
8
;; Author: A.J. Rossini
9
;; Created: 12 Jun 1997
10
;; Maintainer: ESS-core <[email protected]>
11
12
;; Keywords: languages, statistics
13
14
;; This file is part of ESS.
15
16
;; This file is free software; you can redistribute it and/or modify
17
;; it under the terms of the GNU General Public License as published by
18
;; the Free Software Foundation; either version 2, or (at your option)
19
;; any later version.
20
21
;; This file is distributed in the hope that it will be useful,
22
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
23
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24
;; GNU General Public License for more details.
25
26
;; A copy of the GNU General Public License is available at
27
;; http://www.r-project.org/Licenses/
28
29
;;; Commentary:
30
31
;; This file defines all the R customizations for ESS. See ess-s-l.el
32
;; for general S language customizations.
33
34
;;; Code:
35
36
;;; Autoloads and Requires
37
38
(ess-message "[ess-r-d:] (require 'ess-s-l)")
39
(require 'ess-s-l)
40
(require 'eldoc)
41
(require 'ess-r-args); some. ~/.emacs rely ess-r-args-show .. replace by autoload !?
42
(require 'ess-developer)
43
(require 'ess-help)
44
(require 'ess-roxy)
45
(when (featurep 'emacs)
46
(require 'ess-tracebug))
47
(require 'compile); for compilation-* below
48
(require 'easymenu)
49
50
(autoload 'ess-help-underline "ess-help" "(Autoload)" t)
51
(autoload 'ess--flush-help-into-current-buffer "ess-help" "(Autoload)" t)
52
53
(defvar ess-dev-map
54
(let (ess-dev-map)
55
(define-prefix-command 'ess-dev-map)
56
;; Note: some of these comand are automatically redefined by those in
57
(define-key ess-dev-map "\C-t" 'ess-toggle-developer)
58
(define-key ess-dev-map "t" 'ess-toggle-developer)
59
;; (define-key ess-dev-map "\C-T" 'ess-toggle-tracebug)
60
(define-key ess-dev-map "T" 'ess-toggle-tracebug)
61
(define-key ess-dev-map "\C-a" 'ess-developer-add-package)
62
(define-key ess-dev-map "a" 'ess-developer-add-package)
63
(define-key ess-dev-map "\C-r" 'ess-developer-remove-package)
64
(define-key ess-dev-map "r" 'ess-developer-remove-package)
65
(define-key ess-dev-map "\C-l" 'ess-developer-load-package)
66
(define-key ess-dev-map "l" 'ess-developer-load-package)
67
(define-key ess-dev-map "`" 'ess-show-traceback)
68
(define-key ess-dev-map "~" 'ess-show-call-stack)
69
(define-key ess-dev-map "\C-w" 'ess-watch)
70
(define-key ess-dev-map "w" 'ess-watch)
71
(define-key ess-dev-map "\C-d" 'ess-debug-flag-for-debugging)
72
(define-key ess-dev-map "d" 'ess-debug-flag-for-debugging)
73
(define-key ess-dev-map "\C-u" 'ess-debug-unflag-for-debugging)
74
(define-key ess-dev-map "u" 'ess-debug-unflag-for-debugging)
75
(define-key ess-dev-map [(control ?D)] 'ess-debug-unflag-for-debugging)
76
(define-key ess-dev-map "\C-b" 'ess-bp-set)
77
(define-key ess-dev-map "b" 'ess-bp-set)
78
(define-key ess-dev-map [(control ?B)] 'ess-bp-set-conditional)
79
(define-key ess-dev-map "B" 'ess-bp-set-conditional)
80
(define-key ess-dev-map "\C-L" 'ess-bp-set-logger)
81
(define-key ess-dev-map "L" 'ess-bp-set-logger)
82
(define-key ess-dev-map "\C-o" 'ess-bp-toggle-state)
83
(define-key ess-dev-map "o" 'ess-bp-toggle-state)
84
(define-key ess-dev-map "\C-k" 'ess-bp-kill)
85
(define-key ess-dev-map "k" 'ess-bp-kill)
86
(define-key ess-dev-map "\C-K" 'ess-bp-kill-all)
87
(define-key ess-dev-map "K" 'ess-bp-kill-all)
88
(define-key ess-dev-map "\C-n" 'ess-bp-next)
89
(define-key ess-dev-map "n" 'ess-bp-next)
90
(define-key ess-dev-map "i" 'ess-debug-goto-input-event-marker)
91
(define-key ess-dev-map "I" 'ess-debug-goto-input-event-marker)
92
(define-key ess-dev-map "\C-p" 'ess-bp-previous)
93
(define-key ess-dev-map "p" 'ess-bp-previous)
94
(define-key ess-dev-map "\C-e" 'ess-debug-toggle-error-action)
95
(define-key ess-dev-map "e" 'ess-debug-toggle-error-action)
96
(define-key ess-dev-map "0" 'ess-electric-selection)
97
(define-key ess-dev-map "1" 'ess-electric-selection)
98
(define-key ess-dev-map "2" 'ess-electric-selection)
99
(define-key ess-dev-map "3" 'ess-electric-selection)
100
(define-key ess-dev-map "4" 'ess-electric-selection)
101
(define-key ess-dev-map "5" 'ess-electric-selection)
102
(define-key ess-dev-map "6" 'ess-electric-selection)
103
(define-key ess-dev-map "7" 'ess-electric-selection)
104
(define-key ess-dev-map "8" 'ess-electric-selection)
105
(define-key ess-dev-map "9" 'ess-electric-selection)
106
(define-key ess-dev-map "?" 'ess-tracebug-show-help)
107
ess-dev-map)
108
"Keymap for commands related to development and debugging.")
109
110
(easy-menu-define ess-roxygen-menu nil
111
"Roxygen submenu."
112
'("Roxygen"
113
:visible (and ess-dialect (string-match "^R" ess-dialect))
114
["Update/Generate Template" ess-roxy-update-entry t]
115
["Preview Rd" ess-roxy-preview-Rd t]
116
["Preview HTML" ess-roxy-preview-HTML t]
117
["Preview text" ess-roxy-preview-text t]
118
["Hide all" ess-roxy-hide-all t]
119
["Toggle Roxygen Prefix" ess-roxy-toggle-roxy-region t]))
120
121
(easy-menu-define ess-tracebug-menu nil
122
"Tracebug submenu."
123
'("Tracebug"
124
:visible (and ess-dialect (string-match "^R" ess-dialect))
125
;; :enable ess-local-process-name
126
["Active?" ess-toggle-tracebug
127
:style toggle
128
:selected (or (and (ess-process-live-p)
129
(ess-process-get 'tracebug))
130
ess-use-tracebug)]
131
["Show traceback" ess-show-traceback (ess-process-live-p)]
132
["Show call stack" ess-show-call-stack (ess-process-live-p)]
133
["Watch" ess-watch (and (ess-process-live-p)
134
(ess-process-get 'tracebug))]
135
["Error action cycle" ess-debug-toggle-error-action (and (ess-process-live-p)
136
(ess-process-get 'tracebug))]
137
"----"
138
["Flag for debugging" ess-debug-flag-for-debugging ess-local-process-name]
139
["Unflag for debugging" ess-debug-unflag-for-debugging ess-local-process-name]
140
"----"
141
["Set BP" ess-bp-set t]
142
["Set conditional BP" ess-bp-set-conditional t]
143
["Set logger BP" ess-bp-set-logger t]
144
["Kill BP" ess-bp-kill t]
145
["Kill all BPs" ess-bp-kill-all t]
146
["Next BP" ess-bp-next t]
147
["Previous BP" ess-bp-previous t]
148
"-----"
149
["About" ess-tracebug-show-help t]))
150
151
(easy-menu-define ess-developer-menu nil
152
"Developer submenu."
153
'("Developer"
154
:visible (and ess-dialect (string-match "^R" ess-dialect))
155
["Active?" ess-toggle-developer
156
:style toggle
157
:selected ess-developer]
158
["Add package" ess-developer-add-package t]
159
["Remove package" ess-developer-remove-package t]))
160
161
(easy-menu-add-item ess-mode-menu nil ess-roxygen-menu "end-dev")
162
(easy-menu-add-item ess-mode-menu nil ess-developer-menu "end-dev")
163
(easy-menu-add-item ess-mode-menu nil ess-tracebug-menu "end-dev")
164
165
(easy-menu-add-item inferior-ess-mode-menu nil ess-developer-menu "end-dev")
166
(easy-menu-add-item inferior-ess-mode-menu nil ess-tracebug-menu "end-dev")
167
168
169
;; modify S Syntax table:
170
(setq R-syntax-table S-syntax-table)
171
172
;; In R 2.x, back tick now is a quote character, so lets tell Emacs
173
;; that it is; the problem below for older R should no longer be a
174
;; serious issue.
175
;;R >= 1.8: back tick `string` -- unfortunately no *pair* checking:
176
;; breaks when things like `..' are used:
177
(modify-syntax-entry ?` "\"" R-syntax-table)
178
(modify-syntax-entry ?_ "_" R-syntax-table) ; foo_bar is symbol in R >=1.9
179
180
(ess-message "[ess-r-d:] (autoload ..) & (def** ..)")
181
182
;; (autoload 'inferior-ess "ess-inf" "Run an ESS process.")
183
;; (autoload 'ess-mode "ess-mode" "Edit an ESS process.")
184
185
(defvar R-customize-alist
186
(append
187
'((ess-local-customize-alist . 'R-customize-alist)
188
(ess-eldoc-function . 'ess-R-eldoc-function)
189
(ess-dialect . "R")
190
(ess-suffix . "R")
191
(ess-ac-sources . '(ac-source-R))
192
(ess-build-tags-command . "rtags('%s', recursive = TRUE, pattern = '\\\\.[RrSs](rw)?$',ofile = '%s')")
193
(ess-traceback-command . "local({cat(geterrmessage(), \"---------------------------------- \n\", fill=TRUE);try(traceback(), silent=TRUE)})\n")
194
(ess-call-stack-command . "traceback(1)\n")
195
(ess-eval-command . ".ess.eval(\"%s\", FALSE, FALSE, file=\"%f\")\n")
196
(ess-eval-visibly-command . ".ess.eval(\"%s\", TRUE, TRUE, 300, file=\"%f\")\n")
197
(ess-eval-visibly-noecho-command . ".ess.eval(\"%s\", FALSE, TRUE, 300, file=\"%f\")\n")
198
(ess-load-command . ".ess.source(\"%s\", FALSE, FALSE)\n")
199
(ess-load-visibly-command . ".ess.source(\"%s\", TRUE, TRUE, 300)\n")
200
(ess-load-visibly-noecho-command . ".ess.source(\"%s\", FALSE, TRUE, 300)\n")
201
(ess-dump-filename-template . (ess-replace-regexp-in-string
202
"S$" ess-suffix ; in the one from custom:
203
ess-dump-filename-template-proto))
204
(ess-help-web-search-command . 'ess-R-sos)
205
(ess-mode-syntax-table . R-syntax-table)
206
(ess-mode-editing-alist . R-editing-alist)
207
(ess-change-sp-regexp . ess-R-change-sp-regexp)
208
(ess-help-sec-regex . ess-help-R-sec-regex)
209
(ess-help-sec-keys-alist . ess-help-R-sec-keys-alist)
210
(ess-loop-timeout . ess-S-loop-timeout);fixme: dialect spec.
211
(ess-cmd-delay . ess-R-cmd-delay)
212
(ess-function-pattern . ess-R-function-pattern)
213
(ess-object-name-db-file . "ess-r-namedb.el" )
214
(ess-smart-operators . ess-R-smart-operators)
215
(inferior-ess-program . inferior-R-program-name)
216
(inferior-ess-objects-command . inferior-R-objects-command)
217
(inferior-ess-font-lock-keywords . 'inferior-R-font-lock-keywords)
218
(inferior-ess-search-list-command . "search()\n")
219
;;(inferior-ess-help-command . "help(\"%s\", htmlhelp=FALSE)\n")
220
(inferior-ess-help-command . inferior-ess-r-help-command)
221
(inferior-ess-help-filetype . nil)
222
(inferior-ess-exit-command . "q()")
223
(inferior-ess-exit-prompt . "Save workspace image? [y/n/c]: ")
224
;;harmful for shell-mode's C-a: -- but "necessary" for ESS-help?
225
(inferior-ess-start-file . nil) ;; "~/.ess-R"
226
(inferior-ess-start-args . "")
227
(ess-error-regexp-alist . ess-R-error-regexp-alist)
228
(ess-describe-object-at-point-commands . 'ess-R-describe-object-at-point-commands)
229
(ess-STERM . "iESS")
230
(ess-editor . R-editor)
231
(ess-pager . R-pager)
232
(prettify-symbols-alist . '(("<-" . ?←)
233
("<<-" . ?↞)
234
("->" . ?→)
235
("->>" . ?↠))))
236
S-common-cust-alist)
237
"Variables to customize for R -- set up later than emacs initialization.")
238
239
240
(defvar R-editing-alist
241
;; copy the S-alist and modify :
242
(let ((S-alist (copy-alist S-editing-alist)))
243
(setcdr (assoc 'ess-font-lock-defaults S-alist)
244
'(ess--extract-default-fl-keywords ess-R-font-lock-keywords))
245
(setcdr (assoc 'ess-font-lock-keywords S-alist)
246
(quote 'ess-R-font-lock-keywords))
247
S-alist)
248
"General options for editing R source files.")
249
250
251
(defvar ess-R-error-regexp-alist '(R R1 R2 R3 R4 R-recover)
252
"List of symbols which are looked up in `compilation-error-regexp-alist-alist'.")
253
254
;; takes precidence over R1 below in english locales, and allows spaces in file path
255
(add-to-list 'compilation-error-regexp-alist-alist
256
'(R "\\(at \\(.+\\)#\\([0-9]+\\)\\)" 2 3 nil 2 1))
257
258
(add-to-list 'compilation-error-regexp-alist-alist
259
'(R1 " \\([^ \t\n]+\\)#\\([0-9]+\\)[: ]" 1 2 nil 2))
260
261
(add-to-list 'compilation-error-regexp-alist-alist
262
'(R2 "(\\(\\w+ \\([^())\n]+\\)#\\([0-9]+\\)\\))" 2 3 nil 2 1))
263
264
;; (add-to-list 'compilation-error-regexp-alist-alist
265
;; '(R2 "\\(?:^ +\\(.*?\\):\\([0-9]+\\):\\([0-9]+\\):\\)" 1 2 nil 2 1))
266
;; (add-to-list 'compilation-error-regexp-alist-alist
267
;; '(R3 "\\(?:Error.*: .*\n? +\\)\\(.*\\):\\([0-9]+\\):\\([0-9]+\\):" 1 2 3 2 1))
268
269
;; precede R4 and allowes spaces in file path
270
(add-to-list 'compilation-error-regexp-alist-alist
271
;; start with bol,: but don't start with digit
272
'(R3 "\\(?:^ +\\|: +\\)\\([^-+[:digit:]\n]:?[^:\n]*\\):\\([0-9]+\\):\\([0-9]+\\):" 1 2 3 2 1))
273
274
(add-to-list 'compilation-error-regexp-alist-alist
275
;; don't start with digit, don't contain spaces
276
'(R4 "\\([^-+ [:digit:]][^: \t\n]+\\):\\([0-9]+\\):\\([0-9]+\\):" 1 2 3 2 1))
277
278
(add-to-list 'compilation-error-regexp-alist-alist
279
'(R-recover " *[0-9]+: +\\([^:\n\t]+?\\)#\\([0-9]+:\\)" 1 2 nil 2 1))
280
281
;; gnu C errors
282
;; (add-to-list 'compilation-error-regexp-alist-alist
283
;; '(R_C "^\\([^-+ [:digit:]][^: \t\n]+\\):\\([0-9]+\\):\\([0-9]+\\):" 2 3 nil 2 1))
284
285
(let ((r-ver '("R-1" "R-2" "R-3" "R-devel" "R-patched")))
286
(defvar ess-r-versions
287
(if (eq system-type 'darwin) (append r-ver '("R32" "R64")) r-ver)
288
"List of partial strings for versions of R to access within ESS.
289
Each string specifies the start of a filename. If a filename
290
beginning with one of these strings is found on `exec-path', a M-x
291
command for that version of R is made available. For example, if the
292
file \"R-1.8.1\" is found and this variable includes the string
293
\"R-1\", a function called `M-x R-1.8.1' will be available to run that
294
version of R.
295
If duplicate versions of the same program are found (which happens if
296
the same path is listed on `exec-path' more than once), they are
297
ignored by calling `ess-uniq-list'.
298
Set this variable to nil to disable searching for other versions of R.
299
If you set this variable, you need to restart Emacs (and set this variable
300
before ess-site is loaded) for it to take effect."))
301
302
(defvar ess-R-post-run-hook nil
303
"Functions run in process buffer after the initialization of R
304
process.")
305
306
(defun ess--R-load-ESSR ()
307
"Load/INSTALL/Update ESSR."
308
(let* ((ESSR-directory (expand-file-name "ESSR" ess-etc-directory))
309
(src-dir (expand-file-name "R" ESSR-directory)))
310
311
(if (not (or (and (boundp 'ess-remote) ess-remote)
312
(file-remote-p (ess-get-process-variable 'default-directory))))
313
(let ((cmd (format
314
"local({
315
source('%s/.load.R', local=TRUE) #define load.ESSR
316
load.ESSR('%s')})\n"
317
src-dir src-dir)))
318
(ess-write-to-dribble-buffer (format "load-ESSR cmd:\n%s\n" cmd))
319
(with-current-buffer (ess-command cmd)
320
(let ((msg (buffer-string)))
321
(when (> (length msg) 1)
322
(message (format "load ESSR: %s" msg))))))
323
;; else, remote
324
(let* ((verfile (expand-file-name "VERSION" ESSR-directory))
325
(loadremote (expand-file-name "LOADREMOTE" ESSR-directory))
326
(version (if (file-exists-p verfile)
327
(with-temp-buffer
328
(insert-file-contents verfile)
329
(buffer-string))
330
(error "Cannot find ESSR source code")))
331
(r-load-code (with-temp-buffer
332
(insert-file-contents loadremote)
333
(buffer-string))))
334
(ess-write-to-dribble-buffer (format "version file: %s\nloadremote file: %s\n"
335
verfile loadremote))
336
(unless (ess-boolean-command (format r-load-code version) nil 0.1)
337
(let ((errmsg (with-current-buffer " *ess-command-output*" (buffer-string)))
338
(files (directory-files src-dir t "\\.R$")))
339
(ess-write-to-dribble-buffer (format "error loading ESSR.rda: \n%s\n" errmsg))
340
;; should not happen, unless extrem conditions (ancient R or failed download))
341
(message "Failed to download ESSR.rda (see *ESS* buffer). Injecting ESSR code from local machine")
342
(ess-command (format ".ess.ESSRversion <- '%s'\n" version)) ; cannot do this at R level
343
(mapc #'ess--inject-code-from-file files)))))))
344
345
346
;;;### autoload
347
(defun R (&optional start-args)
348
"Call 'R', the 'GNU S' system from the R Foundation.
349
Optional prefix (C-u) allows to set command line arguments, such as
350
--vsize. This should be OS agnostic.
351
If you have certain command line arguments that should always be passed
352
to R, put them in the variable `inferior-R-args'."
353
(interactive "P")
354
(ess-write-to-dribble-buffer ;; for debugging only
355
(format
356
"\n(R): ess-dialect=%s, buf=%s, start-arg=%s\n current-prefix-arg=%s\n"
357
ess-dialect (current-buffer) start-args current-prefix-arg))
358
(let* ((r-always-arg
359
(if (or ess-microsoft-p (eq system-type 'cygwin))
360
"--ess "
361
;; else: "unix alike"
362
(if (not ess-R-readline) "--no-readline ")))
363
(r-start-args
364
(concat r-always-arg
365
inferior-R-args " " ; add space just in case
366
(if start-args
367
(read-string
368
(concat "Starting Args"
369
(if r-always-arg
370
(concat " [other than '" r-always-arg "']"))
371
" ? "))
372
nil)))
373
(cust-alist (copy-alist R-customize-alist))
374
(gdbp (string-match-p "gdb" r-start-args))
375
use-dialog-box)
376
377
(when gdbp
378
(setcdr (assoc 'inferior-ess-secondary-prompt cust-alist)
379
(format "\\(%s\\)\\|\\((gdb) \\)"
380
(cdr (assoc 'inferior-ess-secondary-prompt cust-alist)))))
381
382
(when (or ess-microsoft-p
383
(eq system-type 'cygwin))
384
(setq use-dialog-box nil)
385
(when ess-microsoft-p ;; default-process-coding-system would break UTF locales on Unix
386
(setq default-process-coding-system '(undecided-dos . undecided-dos))))
387
388
(inferior-ess r-start-args cust-alist gdbp)
389
390
(ess-process-put 'funargs-pre-cache ess-R--funargs-pre-cache)
391
;; We need to use callback, because R might start with a gdb process
392
(ess-process-put 'callbacks '(R-initialize-on-start))
393
;; trigger the callback
394
(process-send-string (get-process ess-local-process-name) "\n")
395
396
(remove-hook 'completion-at-point-functions 'ess-filename-completion 'local) ;; should be first
397
(add-hook 'completion-at-point-functions 'ess-R-object-completion nil 'local)
398
(add-hook 'completion-at-point-functions 'ess-filename-completion nil 'local)
399
(setq comint-input-sender 'inferior-R-input-sender)
400
401
(ess-write-to-dribble-buffer
402
(format "(R): inferior-ess-language-start=%s\n"
403
inferior-ess-language-start))))
404
405
(defun R-initialize-on-start (&optional proc string)
406
"This function is run after the first R prompt.
407
Executed in process buffer."
408
(interactive)
409
410
(when ess-can-eval-in-background
411
(ess-async-command-delayed
412
"invisible(installed.packages())\n" nil (get-process ess-local-process-name)
413
;; "invisible(Sys.sleep(10))\n" nil (get-process ess-local-process-name) ;; test only
414
(lambda (proc) (process-put proc 'packages-cached? t))))
415
416
(ess--R-load-ESSR)
417
418
(when inferior-ess-language-start
419
(ess-eval-linewise inferior-ess-language-start
420
nil nil nil 'wait-prompt))
421
422
(with-ess-process-buffer nil
423
(run-mode-hooks 'ess-R-post-run-hook)))
424
425
426
;; (defun ess--R-cache-installed-packages ()
427
;; "Run by `ess-delayed-init' in R process buffer.
428
;; Useses internal R caching of installed packages."
429
;; (ess-command "invisible(installed.packages())\n"
430
;; nil nil nil .2 nil 'redisplay)
431
;; (ess-process-put 'packages-cached? t)
432
;; )
433
434
;;;### autoload
435
(defun R-mode (&optional proc-name)
436
"Major mode for editing R source. See `ess-mode' for more help."
437
(interactive "P")
438
(setq ess-customize-alist R-customize-alist)
439
;;(setq imenu-generic-expression R-imenu-generic-expression)
440
(ess-mode R-customize-alist proc-name)
441
;; for emacs < 24
442
(add-hook 'comint-dynamic-complete-functions 'ess-complete-object-name t 'local)
443
;; for emacs >= 24
444
(remove-hook 'completion-at-point-functions 'ess-filename-completion 'local) ;; should be first
445
(add-hook 'completion-at-point-functions 'ess-R-object-completion nil 'local)
446
(add-hook 'completion-at-point-functions 'ess-filename-completion nil 'local)
447
448
(if (fboundp 'ess-add-toolbar) (ess-add-toolbar))
449
;; ECB needs seminatic stuff.
450
;; (if (featurep 'semantic)
451
;; (setq semantic-toplevel-bovine-table r-toplevel-bovine-table))
452
(when (and ess-imenu-use-S (require 'ess-menu))
453
(setq imenu-generic-expression ess-imenu-generic-expression)
454
(imenu-add-to-menubar "Imenu-R"))
455
456
;; useful for swankr/slime:
457
(set (make-local-variable 'beginning-of-defun-function)
458
(lambda (&optional arg)
459
(skip-chars-backward " \t\n")
460
(ess-beginning-of-function 'no-error)))
461
(set (make-local-variable 'end-of-defun-function)
462
'ess-end-of-function)
463
464
(ess-roxy-mode t)
465
(ad-activate 'mark-paragraph)
466
(ad-activate 'fill-paragraph)
467
(ad-activate 'move-beginning-of-line)
468
(ad-activate 'newline-and-indent)
469
(ad-activate 'ess-eval-line-and-step)
470
(if ess-roxy-hide-show-p
471
(ad-activate 'ess-indent-command))
472
473
(run-hooks 'R-mode-hook))
474
475
(fset 'r-mode 'R-mode)
476
477
(defun ess-R-arch-2-bit (arch)
478
"Translate R's architecture shortcuts/directory names to 'bits',
479
i.e., \"32\" or \"64\" (for now)."
480
(if (string= arch "i386") "32"
481
;; else:
482
"64"))
483
484
(defun ess-rterm-arch-version (long-path &optional give-cons)
485
"Find an architecture-specific name for LONG-PATH, an absolute (long name) path
486
to R on Windows. Returns either Name, a string, or a (Name . Path) cons, such as
487
(\"R-2.12.1-64bit\" . \"C:/Program Files/R/R-2.12.1/bin/x64/Rterm.exe\")
488
489
\"R-x.y.z/bin/Rterm.exe\" will return \"R-x.y.z\", for R-2.11.x and older.
490
\"R-x.y.z/bin/i386/Rterm.exe\" will return \"R-x.y.z-32bit\", for R-2.12.x and newer.
491
\"R-x.y.z/bin/x64/Rterm.exe\" will return \"R-x.y.z-64bit\", for R-2.12.x and newer."
492
(let* ((dir (directory-file-name (file-name-directory long-path)))
493
(dir2 (directory-file-name (file-name-directory dir)))
494
(v-1up (file-name-nondirectory dir));; one level up
495
(v-2up (file-name-nondirectory dir2));; two levels up; don't want "bin" ...
496
(v-3up (file-name-nondirectory ;; three levels up; no "bin" for i386, x64 ...
497
(directory-file-name (file-name-directory dir2))))
498
(val (if (string= v-2up "bin")
499
(concat v-3up "-" (ess-R-arch-2-bit v-1up) "bit")
500
;; pre R-2.12.x, or when there's no extra arch-specific sub directory:
501
v-2up)))
502
(if give-cons
503
(cons val long-path)
504
val)))
505
506
507
(defun ess-r-versions-create ()
508
"Generate the `M-x R-x.y.z' functions for starting other versions of R.
509
On MS Windows, this works using `ess-rterm-version-paths'; otherwise,
510
see `ess-r-versions' for strings that determine which functions are created.
511
512
The result is a list of the new R defuns, if any, that were created. The
513
defuns will normally be placed on the menubar and stored as
514
`ess-r-versions-created' upon ESS initialisation."
515
516
(if (not ess-r-versions)
517
nil ;nothing to return
518
;; else, if ess-r-versions is non-nil, let's try to find those R versions.
519
;; This works by creating a temp buffer where the template function is
520
;; edited so that X.Y is replaced by the version name
521
(let (versions
522
r-versions-created
523
(eval-buf (get-buffer-create "*ess-temp-r-evals*"))
524
(template
525
;; This is the template function used for creating M-x R-X.Y.
526
(concat
527
"(defun R-X.Y (&optional start-args)
528
\"Call the R version 'R-X.Y' using ESS.
529
This function was generated by `ess-r-versions-create'.\"
530
(interactive \"P\")
531
(let ((inferior-R-version \"R-X.Y\")
532
(inferior-R-program-name \""
533
(if ess-microsoft-p "Rterm" "R") "-X.Y\"))
534
(R start-args)))
535
"
536
) ))
537
538
(with-current-buffer eval-buf
539
;; clear the buffer.
540
(delete-region (point-min) (point-max))
541
542
;; Find which versions of R we want. Remove the pathname, leaving just
543
;; the name of the executable.
544
(setq versions
545
(if ess-microsoft-p
546
(mapcar (lambda(v) (ess-rterm-arch-version v 'give-cons))
547
ess-rterm-version-paths)
548
;; ^^^^^^^^^^^^^^^^^^^^^^^ from ./ess-site.el at start
549
;; else (non-MS):
550
(ess-uniq-list
551
(mapcar 'file-name-nondirectory
552
(apply 'nconc
553
(mapcar 'ess-find-exec-completions
554
ess-r-versions))))))
555
(setq r-versions-created ; also for returning at end.
556
(if ess-microsoft-p
557
(mapcar 'car versions)
558
versions))
559
(ess-write-to-dribble-buffer
560
(format "(R): ess-r-versions-create making M-x defuns for \n %s\n"
561
(mapconcat 'identity r-versions-created "\n ")))
562
563
;; Iterate over each string in VERSIONS, creating a new defun each time.
564
(while versions
565
(let* ((version (car versions))
566
(ver (if ess-microsoft-p (car version) version))
567
(beg (point)))
568
569
(setq versions (cdr versions))
570
(insert template)
571
(goto-char beg)
572
(while (search-forward "R-X.Y" nil t) ;; in all cases
573
(replace-match ver t t))
574
(when ess-microsoft-p
575
(goto-char beg)
576
(while (search-forward "Rterm-X.Y" nil t)
577
(replace-match (w32-short-file-name (cdr version)) t t)))
578
(goto-char (point-max)))
579
)
580
;; buffer has now been created with defuns, so eval them!
581
(eval-buffer))
582
(unless (and (boundp 'ess-debugging) ess-debugging)
583
(kill-buffer eval-buf))
584
585
r-versions-created)))
586
587
(defvar ess-newest-R nil
588
"Stores the newest version of R that has been found. Used as a cache,
589
within ess-find-newest-R. Do not use this value directly, but
590
instead call the function \\[ess-find-newest-R].")
591
592
(defun ess-find-newest-R ()
593
"Find the newest version of R on the system. Once the value is found,
594
cache it in the variable `ess-newest-R' for future use as finding the
595
newest version of R can be potentially time-consuming."
596
(or ess-newest-R
597
(progn (message "Finding all versions of R on your system...")
598
;;(sleep-for 3)
599
nil)
600
(setq ess-newest-R
601
(ess-newest-r
602
(if ess-microsoft-p
603
ess-rterm-version-paths
604
(add-to-list 'ess-r-versions-created
605
inferior-R-program-name))))))
606
607
(defun ess-check-R-program-name ()
608
"Check if `inferior-R-program-name' points to an executable version of R.
609
If not, try to find the newest version of R elsewhere on the system, and
610
update `inferior-R-program-name' accordingly."
611
(unless (executable-find inferior-R-program-name)
612
;; need to check if we can find another name.
613
(let ((newest (ess-find-newest-R)))
614
(if newest
615
(setq inferior-R-program-name newest)
616
(message "Sorry, no version of R could be found on your system.")))))
617
618
(defun R-newest (&optional start-args)
619
"Find the newest version of R available, and run it.
620
Subsequent calls to R-newest will run that version, rather than searching
621
again for the newest version. Providing an optional prefix arg (C-u) will
622
prompt for command line arguments."
623
(interactive "P")
624
(let ((rnewest (ess-find-newest-R)))
625
(if (not rnewest)
626
(error "No version of R could be found.")
627
;; Else: we have a working version of R.
628
;; Have to be careful to avoid recursion...
629
(message (concat "Newest version of R is " rnewest))
630
(fset 'R-newest
631
(intern
632
(if ess-microsoft-p
633
(ess-rterm-arch-version rnewest)
634
rnewest)))
635
;;(fset 'R-newest (intern rnewest))
636
(R-newest start-args))))
637
638
;; (ess-r-version-date "R-2.5.1") (ess-r-version-date "R-patched")
639
;; (ess-r-version-date "R-1.2.1") (ess-r-version-date "R-1.8.1")
640
;; Windows:
641
;; (ess-r-version-date "C:/Program Files (x86)/R/R-2.11.1/bin/Rterm.exe")
642
;; Note that for R-devel, ver-string is something like
643
;; R version 2.6.0 Under development (unstable) (2007-07-14 r42234)
644
;; Antique examples are 'R 1.0.1 (April 14, 2000)' or 'R 1.5.1 (2002-06-17).'
645
(defun ess-r-version-date (rver)
646
"Return the date of the version of R named RVER.
647
The date is returned as a date string. If the version of R could
648
not be found from the output of the RVER program, \"-1\" is
649
returned."
650
(let ((date "-1")
651
(ver-string (shell-command-to-string
652
;; here, MS Windows (shell-command) needs a short name:
653
(concat (if ess-microsoft-p (w32-short-file-name rver) rver)
654
" --version"))))
655
(when (string-match
656
"R \\(version \\)?[1-9][^\n]+ (\\(2[0-9-]+\\)\\( r[0-9]+\\)?)"
657
ver-string)
658
(setq date (match-string 2 ver-string)))
659
(cons date rver)))
660
661
(defun ess-current-R-version ()
662
"Get the version of R currently running in the ESS buffer as a string"
663
(ess-make-buffer-current)
664
(car (ess-get-words-from-vector "as.character(.ess.Rversion)\n")))
665
666
(defun ess-current-R-at-least (version)
667
"Is the version of R (in the ESS buffer) at least (\">=\") VERSION ?
668
Examples: (ess-current-R-at-least '2.7.0)
669
or (ess-current-R-at-least \"2.5.1\")"
670
(ess-make-buffer-current)
671
(string= "TRUE"
672
(car (ess-get-words-from-vector
673
(format "as.character(.ess.Rversion >= \"%s\")\n" version)))))
674
675
(defvar ess-temp-newest nil)
676
677
(defun ess-newest-r (rvers)
678
"Check all the versions of RVERS to see which is the newest.
679
Return the name of the newest version of R."
680
(let ((rtimes (mapcar 'ess-r-version-date rvers)))
681
;; SJE: 2007-07-13 -- following line is a temp var to check that
682
;; the newest version of R is found correctly.
683
;; (nowadays gives a compile warning)
684
(setq ess-temp-newest rtimes)
685
(ess-find-newest-date rtimes)))
686
687
;; Test case for following defun:
688
;; (setq a '( ("2003-10-04" . "R-1.7")
689
;; ("2006-11-19" . "R-2.2")
690
;; ("2007-07-01" . "R-dev")
691
;; ("-1" . "R-broken")
692
;; ("2005-12-30" . "R-2.0")))
693
;; (ess-find-newest-date a)
694
(defun ess-find-newest-date (rvers)
695
"Find the newest version of R given in the a-list RVERS.
696
Each element of RVERS is a dotted pair (date . R-version), where
697
date is given as e.g.\"2007-11-30\" so that we can compare dates
698
as strings. If a date is listed as \"-1\", that version of R
699
could not be found.
700
701
If the value returned is nil, no valid newest version of R could be found."
702
(let (new-r this-r
703
(new-time "0"))
704
(while rvers
705
(setq this-r (car rvers)
706
rvers (cdr rvers))
707
(when (string< new-time (car this-r))
708
(setq new-time (car this-r)
709
new-r (cdr this-r))))
710
new-r))
711
712
713
(defun ess-find-rterm (&optional ess-R-root-dir bin-Rterm-exe)
714
"Find the full path of all occurences of Rterm.exe under the ESS-R-ROOT-DIR.
715
If ESS-R-ROOT-DIR is nil, construct it by looking for an occurence of Rterm.exe
716
in the exec-path. If there are no occurences of Rterm.exe in the exec-path,
717
then use `ess-program-files' (which evaluates to something like \"c:/progra~1/R/\"
718
in English locales) which is the default location for the R distribution.
719
If BIN-RTERM-EXE is nil, then use \"bin/Rterm.exe\"."
720
(if (not ess-R-root-dir)
721
(let ((Rpath (executable-find "Rterm")))
722
(setq ess-R-root-dir
723
(expand-file-name
724
(if Rpath
725
(concat (file-name-directory Rpath) "../../")
726
(concat ess-program-files "/R/"))))
727
(ess-write-to-dribble-buffer
728
(format "(ess-find-rterm): ess-R-root-dir = '%s'\n" ess-R-root-dir))
729
))
730
731
(if (not bin-Rterm-exe) (setq bin-Rterm-exe "bin/Rterm.exe"))
732
733
(when (file-directory-p ess-R-root-dir) ; otherwise file-name-all-.. errors
734
(setq ess-R-root-dir
735
(ess-replace-regexp-in-string "[\\]" "/" ess-R-root-dir))
736
(let ((R-ver
737
(ess-drop-non-directories
738
(ess-flatten-list
739
(mapcar (lambda (r-prefix)
740
(file-name-all-completions r-prefix ess-R-root-dir))
741
(append '("rw") ess-r-versions))))))
742
(mapcar (lambda (dir)
743
(let ((R-path
744
(concat ess-R-root-dir
745
(ess-replace-regexp-in-string "[\\]" "/" dir)
746
bin-Rterm-exe)))
747
(if (file-exists-p R-path) R-path)))
748
R-ver))))
749
750
751
;;; eldoc
752
753
(defun ess-R-eldoc-function ()
754
"Return the doc string, or nil.
755
If an ESS process is not associated with the buffer, do not try
756
to look up any doc strings."
757
(interactive)
758
(let ((proc (ess-get-next-available-process)))
759
(when proc
760
(let ((funname (or (and ess-eldoc-show-on-symbol ;; aggressive completion
761
(thing-at-point 'symbol))
762
(car (ess--funname.start)))))
763
(when funname
764
(let* ((args (ess-function-arguments funname proc))
765
(bargs (cadr args))
766
(doc (mapconcat (lambda (el)
767
(if (equal (car el) "...")
768
"..."
769
(concat (car el) "=" (cdr el))))
770
bargs ", "))
771
(margs (nth 2 args))
772
(W (- (window-width (minibuffer-window)) (+ 4 (length funname))))
773
doc1)
774
(when doc
775
(setq doc (ess-eldoc-docstring-format funname doc))
776
(when (and margs (< (length doc1) W))
777
(setq doc1 (concat doc (propertize " || " 'face font-lock-function-name-face)))
778
(while (and margs (< (length doc1) W))
779
(let ((head (pop margs)))
780
(unless (assoc head bargs)
781
(setq doc doc1
782
doc1 (concat doc1 head "=, ")))))
783
(when (equal (substring doc -2) ", ")
784
(setq doc (substring doc 0 -2)))
785
(when (and margs (< (length doc) W))
786
(setq doc (concat doc " {--}"))))
787
doc)))))))
788
789
(defun ess-eldoc-docstring-format (funname doc)
790
(save-match-data
791
(let* (;; (name (symbol-name sym))
792
(truncate (or (not (eq t eldoc-echo-area-use-multiline-p))
793
(eq ess-eldoc-abbreviation-style 'aggressive)))
794
;; Subtract 1 from window width since will cause a wraparound and
795
;; resize of the echo area.
796
(W (1- (- (window-width (minibuffer-window))
797
(+ 2 (length funname)))))
798
newdoc
799
)
800
(setq doc
801
(if (or (<= (length doc) W)
802
(null ess-eldoc-abbreviation-style)
803
(eq 'none ess-eldoc-abbreviation-style))
804
doc
805
;;MILD filter
806
(setq doc (replace-regexp-in-string "TRUE" "T" doc))
807
(setq doc (replace-regexp-in-string "FALSE" "F" doc))
808
(if (or (<= (length doc) W)
809
(eq 'mild ess-eldoc-abbreviation-style))
810
doc
811
;;NORMAL filter (deal with long defaults)
812
(setq doc (replace-regexp-in-string
813
;; function calls inside default docs foo(xxxx{..})
814
"([^)]\\{8\\}\\([^)]\\{4,\\}\\))"
815
"{.}" doc nil nil 1))
816
(if (<= (length doc) W)
817
doc
818
(setq doc (replace-regexp-in-string
819
" +[^ \t=,\"\]+=[^ \t]\\{10\\}\\([^ \t]\\{4,\\}\\)\\(,\\|\\'\\)"
820
"{.}," doc nil nil 1))
821
(if (<= (length doc) W)
822
doc
823
(setq doc (replace-regexp-in-string
824
" +[^ \t=,\"]+=\\([^ \t]\\{10,\\}\\)\\(,\\|\\'\\)"
825
"{.}," doc nil nil 1))
826
(if (or (<= (length doc) W)
827
(eq 'normal ess-eldoc-abbreviation-style))
828
doc
829
;;STRONG filter (replace defaults)
830
(setq doc (replace-regexp-in-string
831
" *[^ \t=,\"\\]* = \\([^ \t]\\{4,\\}\\)\\(,\\|\\'\\)"
832
"{.}," doc nil nil 1))
833
(if (<= (length doc) W)
834
doc
835
(setq doc (replace-regexp-in-string
836
"\\(=[^FT0-9].+?\\)\\(, [^ =,\"\\]+=\\|\\'\\)"
837
"" doc nil nil 1))
838
(setq doc (replace-regexp-in-string
839
"\\(=[^FT0-9].+?\\)\\(, [^ =,\"\\]+,\\|\\'\\)"
840
"" doc nil nil 1))
841
(if (or (<= (length doc) W)
842
(eq 'strong ess-eldoc-abbreviation-style))
843
doc
844
;;AGGRESSIVE filter (truncate what is left)
845
(concat (substring doc 0 (- W 4)) "{--}")))))))))
846
(when (and truncate
847
(> (length doc) W))
848
(setq doc (concat (substring doc 0 (- W 4)) "{--}")))
849
(format "%s: %s" (propertize funname 'face 'font-lock-function-name-face) doc))))
850
851
;;; function argument completions
852
853
;; (defconst ess--funname-ignore '("else"))
854
;; (defvar ess-objects-never-recache '("print" "plot")
855
;; "List of functions of whose arguments to be cashed only once per session.")
856
857
858
(defvar ess-R--funargs-pre-cache
859
'(("plot"
860
(("graphics")
861
(("x" . "") ("y" . "NULL") ("type" . "p") ("xlim" . "NULL") ("ylim" . "NULL") ("log" . "") ("main" . "NULL") ("sub" . "NULL") ("xlab" . "NULL") ("ylab" . "NULL")
862
("ann" . "par(\"ann\")") ("axes" . "TRUE") ("frame.plot" . "axes") ("panel.first" . "NULL") ("panel.last" . "NULL") ("asp" . "NA") ("..." . ""))
863
("x" "y" "..." "ci" "type" "xlab" "ylab" "ylim" "main" "ci.col" "ci.type" "max.mfrow" "ask" "mar" "oma" "mgp" "xpd" "cex.main" "verbose" "scale" "xlim" "log" "sub" "ann" "axes" "frame.plot" "panel.first" "panel.last" "asp" "center" "edge.root" "nodePar" "edgePar" "leaflab" "dLeaf" "xaxt" "yaxt" "horiz" "zero.line" "verticals" "col.01line" "pch" "legend.text" "formula" "data" "subset" "to" "from" "newpage" "vp" "labels" "hang" "freq" "density" "angle" "col" "border" "lty" "add" "predicted.values" "intervals" "separator" "col.predicted" "col.intervals" "col.separator" "lty.predicted" "lty.intervals" "lty.separator" "plot.type" "main2" "par.fit" "grid" "panel" "cex" "dimen" "abbrev" "which" "caption" "sub.caption" "id.n" "labels.id" "cex.id" "qqline" "cook.levels" "add.smooth" "label.pos" "cex.caption" "rows" "levels" "conf" "absVal" "ci.lty" "xval" "do.points" "col.points" "cex.points" "col.hor" "col.vert" "lwd" "set.pars" "range.bars" "col.range" "xy.labels" "xy.lines" "nc" "yax.flip" "mar.multi" "oma.multi")))
864
("print"
865
(("base")
866
(("x" . "") ("digits" . "NULL") ("quote" . "TRUE") ("na.print" . "NULL") ("print.gap" . "NULL") ("right" . "FALSE") ("max" . "NULL") ("useSource" . "TRUE") ("..." . ""))
867
("x" "..." "digits" "signif.stars" "intercept" "tol" "se" "sort" "verbose" "indent" "style" ".bibstyle" "prefix" "vsep" "minlevel" "quote" "right" "row.names" "max" "na.print" "print.gap" "useSource" "diag" "upper" "justify" "title" "max.levels" "width" "steps" "showEnv" "newpage" "vp" "cutoff" "max.level" "give.attr" "units" "abbrCollate" "print.x" "deparse" "locale" "symbolic.cor" "loadings" "zero.print" "calendar")))
868
)
869
"Alist of cached arguments for very time consuming functions.")
870
871
872
;; (defun ess-get-object-at-point ()
873
;; "A very permissive version of symbol-at-point.
874
;; Suitable for R object's names."
875
;; (let ((delim "[-+ ,\"\t\n\\*/()%{}:]"))
876
;; (unless (and (looking-back delim)
877
;; (looking-at delim))
878
;; (save-excursion
879
;; (let ((beg (re-search-backward delim nil t)))
880
;; (setq beg (or (and beg (goto-char (1+ beg)))
881
;; (goto-char (point-min))))
882
;; (unless (re-search-forward delim nil t)
883
;; (goto-char (point-max)))
884
;; (buffer-substring-no-properties beg (1- (point))))
885
;; ))))
886
887
;;*;; Object name completion
888
889
;;;*;;; The user completion command
890
(defun ess-R-object-completion ()
891
"Return completions at point in a format required by `completion-at-point-functions'. "
892
(if (ess-make-buffer-current)
893
(let* ((funstart (cdr (ess--funname.start)))
894
(completions (ess-R-get-rcompletions funstart))
895
(token (pop completions)))
896
(when completions
897
(list (- (point) (length token)) (point) completions)))
898
(when (string-match "complete" (symbol-name last-command))
899
(message "No ESS process associated with current buffer")
900
nil)
901
))
902
903
(defun ess-complete-object-name ()
904
"Perform completion on `ess-language' object preceding point.
905
Uses \\[ess-R-complete-object-name] when `ess-use-R-completion' is non-nil,
906
or \\[ess-internal-complete-object-name] otherwise."
907
(interactive)
908
(if (ess-make-buffer-current)
909
(if ess-use-R-completion
910
(ess-R-complete-object-name)
911
(ess-internal-complete-object-name))
912
;; else give a message on second invocation
913
(when (string-match "complete" (symbol-name last-command))
914
(message "No ESS process associated with current buffer")
915
nil)
916
))
917
918
(defun ess-complete-object-name-deprecated ()
919
"Gives a deprecated message "
920
(interactive)
921
(ess-complete-object-name)
922
(message "C-c TAB is deprecated, completions has been moved to [M-TAB] (aka C-M-i)")
923
(sit-for 2 t)
924
)
925
926
;; This one is needed for R <= 2.6.x -- hence *not* obsoleting it
927
(defun ess-internal-complete-object-name ()
928
"Perform completion on `ess-language' object preceding point.
929
The object is compared against those objects known by
930
`ess-get-object-list' and any additional characters up to ambiguity are
931
inserted. Completion only works on globally-known objects (including
932
elements of attached data frames), and thus is most suitable for
933
interactive command-line entry, and not so much for function editing
934
since local objects (e.g. argument names) aren't known.
935
936
Use \\[ess-resynch] to re-read the names of the attached directories.
937
This is done automatically (and transparently) if a directory is
938
modified (S only!), so the most up-to-date list of object names is always
939
available. However attached dataframes are *not* updated, so this
940
command may be necessary if you modify an attached dataframe."
941
(interactive)
942
(ess-make-buffer-current)
943
(if (memq (char-syntax (preceding-char)) '(?w ?_))
944
(let* ((comint-completion-addsuffix nil)
945
(end (point))
946
(buffer-syntax (syntax-table))
947
(beg (unwind-protect
948
(save-excursion
949
(set-syntax-table ess-mode-syntax-table)
950
(backward-sexp 1)
951
(point))
952
(set-syntax-table buffer-syntax)))
953
(full-prefix (buffer-substring beg end))
954
(pattern full-prefix)
955
;; See if we're indexing a list with `$'
956
(listname (if (string-match "\\(.+\\)\\$\\(\\(\\sw\\|\\s_\\)*\\)$"
957
full-prefix)
958
(progn
959
(setq pattern
960
(if (not (match-beginning 2)) ""
961
(substring full-prefix
962
(match-beginning 2)
963
(match-end 2))))
964
(substring full-prefix (match-beginning 1)
965
(match-end 1)))))
966
;; are we trying to get a slot via `@' ?
967
(classname (if (string-match "\\(.+\\)@\\(\\(\\sw\\|\\s_\\)*\\)$"
968
full-prefix)
969
(progn
970
(setq pattern
971
(if (not (match-beginning 2)) ""
972
(substring full-prefix
973
(match-beginning 2)
974
(match-end 2))))
975
(ess-write-to-dribble-buffer
976
(format "(ess-C-O-Name : slots..) : patt=%s"
977
pattern))
978
(substring full-prefix (match-beginning 1)
979
(match-end 1)))))
980
(components (if listname
981
(ess-object-names listname)
982
(if classname
983
(ess-slot-names classname)
984
;; Default case: It hangs here when
985
;; options(error=recover) :
986
(ess-get-object-list ess-current-process-name)))))
987
;; always return a non-nil value to prevent history expansions
988
(or (comint-dynamic-simple-complete pattern components) 'none))))
989
990
;; *NOT* doing this, as it is needed for R <= 2.6.x
991
;;(make-obsolete 'ess-internal-complete-object-name nil "ESS 13.09")
992
993
(defun ess-R-get-rcompletions (&optional start end)
994
"Call R internal completion utilities (rcomp) for possible completions.
995
Needs version of R>2.7.0
996
997
Optional START and END delimit the entity to complete, default to bol and point.
998
999
First element of a returned list is the completion token.
1000
"
1001
(let* ((start (or start
1002
(save-excursion (comint-bol nil) (point))))
1003
(end (or end (point)))
1004
;; (opts1 (if no-args "op<-rc.options(args=FALSE)" ""))
1005
;; (opts2 (if no-args "rc.options(op)" ""))
1006
(comm (format ".ess_get_completions(\"%s\", %d)\n"
1007
(ess-quote-special-chars (buffer-substring start end))
1008
(- end start))))
1009
(ess-get-words-from-vector comm)))
1010
1011
1012
(defun ess-R-complete-object-name ()
1013
"Completion in R via R's completion utilities (formerly 'rcompgen').
1014
To be used instead of ESS' completion engine for R versions >= 2.7.0."
1015
(interactive)
1016
(let ((possible-completions (ess-R-get-rcompletions))
1017
token-string)
1018
;; If there are no possible-completions, should return nil, so
1019
;; that when this function is called from
1020
;; comint-dynamic-complete-functions, other functions can also be
1021
;; tried.
1022
(when possible-completions
1023
(setq token-string (pop possible-completions))
1024
(or (comint-dynamic-simple-complete token-string
1025
possible-completions)
1026
'none))))
1027
1028
;;; auto-complete integration http://cx4a.org/software/auto-complete/index.html
1029
(defvar ac-source-R
1030
'((prefix . ess-ac-start)
1031
;; (requires . 0) ::)
1032
(candidates . ess-ac-candidates)
1033
(document . ess-ac-help)
1034
;; (action . ess-ac-action-args) ;; interfere with ac-fallback mechanism on RET (which is extremely annoing in inferior buffers)
1035
)
1036
"Combined ad-completion source for R function arguments and R objects")
1037
1038
(defun ess-ac-start ()
1039
(when (and ess-local-process-name
1040
(get-process ess-local-process-name))
1041
(or (ess-ac-start-args)
1042
(ess-symbol-start))))
1043
1044
(defun ess-ac-candidates ()
1045
"OBJECTS + ARGS"
1046
(let ((args (ess-ac-args)))
1047
;; sort of intrusive but right
1048
(if (and ac-auto-start
1049
(< (length ac-prefix) ac-auto-start))
1050
args
1051
(if args
1052
(append args (ess-ac-objects t))
1053
(ess-ac-objects)))))
1054
1055
(defun ess-ac-help (sym)
1056
(if (string-match-p "= *\\'" sym)
1057
(ess-ac-help-arg sym)
1058
(ess-ac-help-object sym)))
1059
1060
;; OBJECTS
1061
(defvar ac-source-R-objects
1062
'((prefix . ess-symbol-start)
1063
;; (requires . 2)
1064
(candidates . ess-ac-objects)
1065
(document . ess-ac-help-object))
1066
"Auto-completion source for R objects")
1067
1068
(defun ess-ac-objects (&optional no-kill)
1069
"Get all cached objects"
1070
(let ((aprf ac-prefix))
1071
(when aprf
1072
(unless no-kill ;; workaround
1073
(kill-local-variable 'ac-use-comphist))
1074
(if (string-match-p "[]:$@[]" aprf)
1075
;; call proc for objects
1076
(cdr (ess-R-get-rcompletions ac-point))
1077
;; else, get the (maybe cached) list of objects
1078
(with-ess-process-buffer 'no-error ;; use proc buf alist
1079
(ess-when-new-input last-objlist-update
1080
(if (and ess-sl-modtime-alist
1081
(not (process-get *proc* 'sp-for-ac-changed?)))
1082
;; not changes, re-read .GlobalEnv
1083
(ess-extract-onames-from-alist ess-sl-modtime-alist 1 'force))
1084
;; reread all objects, but not rda, much faster and not needed anyways
1085
(ess-get-modtime-list)
1086
(process-put *proc* 'sp-for-ac-changed? nil))
1087
(apply 'append (mapcar 'cddr ess-sl-modtime-alist)))))))
1088
1089
(defun ess-ac-help-object (sym)
1090
"Help string for ac."
1091
(let ((buf (get-buffer-create " *ess-command-output*")))
1092
(when (string-match ":+\\(.*\\)" sym)
1093
(setq sym (match-string 1 sym)))
1094
(ess-with-current-buffer buf
1095
(ess--flush-help-into-current-buffer sym nil t))
1096
(with-current-buffer buf
1097
(ess-help-underline)
1098
(goto-char (point-min))
1099
(buffer-string))))
1100
1101
;; ARGS
1102
(defvar ac-source-R-args
1103
'((prefix . ess-ac-start-args)
1104
;; (requires . 0)
1105
(candidates . ess-ac-args)
1106
(document . ess-ac-help-arg)
1107
;; (action . ess-ac-action-args)
1108
)
1109
"Auto-completion source for R function arguments")
1110
1111
(defun ess-ac-start-args ()
1112
"Get initial position for args completion"
1113
(when (and ess-local-process-name
1114
(not (eq (get-text-property (point) 'face) 'font-lock-string-face)))
1115
(when (ess--funname.start)
1116
(if (looking-back "[(,]+[ \t\n]*")
1117
(point)
1118
(ess-symbol-start)))))
1119
1120
(defun ess-ac-args ()
1121
"Get the args of the function when inside parentheses."
1122
(when ess--funname.start ;; stored by a coll to ess-ac-start-args
1123
(let ((args (nth 2 (ess-function-arguments (car ess--funname.start))))
1124
(len (length ac-prefix)))
1125
(if args
1126
(set (make-local-variable 'ac-use-comphist) nil)
1127
(kill-local-variable 'ac-use-comphist))
1128
(delete "..." args)
1129
(mapcar (lambda (a) (concat a ess-ac-R-argument-suffix))
1130
args))))
1131
1132
(defun ess-ac-help-arg (sym)
1133
"Help string for ac."
1134
(setq sym (replace-regexp-in-string " *= *\\'" "" sym))
1135
(let ((fun (car ess--funname.start)))
1136
(with-current-buffer (ess-command (format ess--ac-help-arg-command sym fun))
1137
(goto-char (point-min))
1138
(forward-line)
1139
(buffer-substring-no-properties (point) (point-max)))))
1140
1141
1142
(defvar ess--ac-help-arg-command
1143
"
1144
getArgHelp <- function(arg, func=NULL){
1145
olderr <- getOption('error')
1146
options(error=NULL)
1147
on.exit(options(error=olderr))
1148
fguess <-
1149
if(is.null(func)) get('fguess', envir=utils:::.CompletionEnv)
1150
else func
1151
findArgHelp <- function(fun, arg){
1152
file <- help(fun, try.all.packages=FALSE)[[1]]
1153
hlp <- utils:::.getHelpFile(file)
1154
id <- grep('arguments', tools:::RdTags(hlp), fixed=TRUE)
1155
if(length(id)){
1156
arg_section <- hlp[[id[[1L]]]]
1157
items <- grep('item', tools:::RdTags(arg_section), fixed=TRUE)
1158
## cat('items:', items, fill=TRUE)
1159
if(length(items)){
1160
arg_section <- arg_section[items]
1161
args <- unlist(lapply(arg_section,
1162
function(el) paste(unlist(el[[1]][[1]], TRUE, FALSE), collapse='')))
1163
fits <- grep(arg, args, fixed=TRUE)
1164
## cat('args', args, 'fits', fill=TRUE)
1165
if(length(fits))
1166
paste(unlist(arg_section[[fits[1L]]][[2]], TRUE, FALSE), collapse='')
1167
}
1168
}
1169
}
1170
funcs <- c(fguess, tryCatch(methods(fguess),
1171
warning=function(w) {NULL},
1172
error=function(e) {NULL}))
1173
if(length(funcs) > 1 && length(pos <- grep('default', funcs))){
1174
funcs <- c(funcs[[pos[[1L]]]], funcs[-pos[[1L]]])
1175
}
1176
i <- 1L; found <- FALSE
1177
out <- 'No help found'
1178
while(i <= length(funcs) && is.null(out <-
1179
tryCatch(findArgHelp(funcs[[i]], arg),
1180
warning=function(w) {NULL},
1181
error=function(e) {NULL})
1182
))
1183
i <- i + 1L
1184
cat(' \n\n', as.character(out), '\n\n')
1185
}; getArgHelp('%s','%s')
1186
")
1187
1188
1189
;;;### autoload
1190
(defun Rnw-mode ()
1191
"Major mode for editing Sweave(R) source.
1192
See `ess-noweb-mode' and `R-mode' for more help."
1193
(interactive)
1194
(require 'ess-noweb);; << probably someplace else
1195
(setq ess--make-local-vars-permenent t)
1196
(ess-noweb-mode 1); turn it on
1197
(ess-noweb-set-doc-mode 'latex-mode)
1198
(ess-noweb-set-code-mode 'R-mode)
1199
(setq ess--local-handy-commands
1200
(append '(("weave" . ess-swv-weave)
1201
("tangle" . ess-swv-tangle))
1202
ess-handy-commands)
1203
ess-dialect "R"
1204
ess-language "S")
1205
(put 'ess--local-handy-commands 'permanent-local t)
1206
(run-hooks 'Rnw-mode-hook))
1207
1208
(fset 'Snw-mode 'Rnw-mode); just a synonym (for now or ever)
1209
1210
(autoload 'ess-transcript-mode "ess-trns"
1211
"Major mode for editing S transcript files." t)
1212
1213
(defun R-transcript-mode ()
1214
"Does the right thing."
1215
(interactive)
1216
(ess-transcript-mode R-customize-alist))
1217
1218
(fset 'r-transcript-mode 'R-transcript-mode)
1219
1220
(defun R-fix-T-F (&optional from quietly)
1221
"Fix T/F into TRUE and FALSE *cautiously*, i.e. not in comments and strings;
1222
starting from the current position (point)."
1223
(interactive "d\nP"); point and prefix (C-u)
1224
(save-excursion
1225
(goto-char from)
1226
(ess-rep-regexp "\\(\\([][=,()]\\|<-\\) *\\)T\\>" "\\1TRUE"
1227
'fixcase nil (not quietly))
1228
(goto-char from)
1229
(ess-rep-regexp "\\(\\([][=,()]\\|<-\\) *\\)F\\>" "\\1FALSE"
1230
'fixcase nil (not quietly))))
1231
1232
;; From: Sebastian Luque <[email protected]>
1233
;; To: [email protected]
1234
;; Date: Mon, 01 May 2006 19:17:49 -0500
1235
1236
;; Without knowing how to tell R to use w3m from within Emacs, and after
1237
;; switching to Konqueror's window for the millionth time, I wrote the
1238
;; following function:
1239
1240
;; This emulates some of the functionality of RSiteSearch() and tests ok in
1241
;; my system GNU Emacs 22.0.50.1 (i486-pc-linux-gnu, X toolkit, Xaw3d scroll
1242
;; bars) of 2006-04-27 on pacem, modified by Debian. This has the benefit of
1243
;; displaying results with whatever you've told browse-url to use; in my
1244
;; case, w3m with the emacs-w3m package.
1245
1246
;; My elisp skills are rather poor, so comments and suggestions for
1247
;; improvement are welcome.
1248
;; --
1249
;; Seb
1250
1251
1252
;; MM _FIXME_: This only works correctly for Emacs 22.0.50 (alpha)
1253
;; for 21.x it has problems in the (completing-read-multiple .)
1254
;; at the end
1255
(defun R-site-search (string)
1256
"Search the R archives for STRING, using default criteria. If
1257
called with a prefix, options are available for
1258
1) matches per page,
1259
2) sections of the archives to search (separated by value of `crm-default-separator'),
1260
3) for displaying results in long or short formats, and
1261
4) for sorting by any given field.
1262
Completion is available for supplying options."
1263
(interactive "sSearch string: ")
1264
(let ((site "http://search.r-project.org/cgi-bin/namazu.cgi?query=")
1265
(okstring (replace-regexp-in-string " +" "+" string)))
1266
(if current-prefix-arg
1267
(let ((mpp (concat
1268
"&max="
1269
(completing-read
1270
"Matches per page: "
1271
'(("20" 1) ("30" 2) ("40" 3) ("50" 4) ("100" 5)))))
1272
(format (concat
1273
"&result="
1274
(completing-read
1275
"Format: " '("normal" "short")
1276
nil t "normal" nil "normal")))
1277
(sortby (concat
1278
"&sort="
1279
(completing-read
1280
"Sort by: "
1281
'(("score" 1) ("date:late" 2) ("date:early" 3)
1282
("field:subject:ascending" 4)
1283
("field:subject:decending" 5)
1284
("field:from:ascending" 6) ("field:from:decending" 7)
1285
("field:size:ascending" 8) ("field:size:decending" 9))
1286
nil t "score" nil "score")))
1287
(restrict (concat
1288
"&idxname="
1289
(mapconcat
1290
'identity
1291
(completing-read-multiple
1292
"Limit search to: "
1293
'(("Rhelp02a" 1) ("functions" 2) ("docs" 3)
1294
("Rhelp01" 4))
1295
nil t "Rhelp02a,functions,docs" nil
1296
"Rhelp02a,functions,docs") "&idxname="))))
1297
(browse-url (concat site okstring mpp format sortby restrict)))
1298
;; else: without prefix use defaults:
1299
(browse-url (concat site okstring "&max=20&result=normal&sort=score"
1300
"&idxname=Rhelp02a&idxname=functions&idxname=docs")))))
1301
1302
(defvar ess--packages-cache nil
1303
"Cache var to store package names. Used by
1304
`ess-install.packages'.")
1305
1306
(defun ess-R-install.packages (&optional update pack)
1307
"Prompt and install R package. With argument, update cached packages list."
1308
(interactive "P")
1309
(when (equal "@CRAN@" (car (ess-get-words-from-vector "getOption('repos')[['CRAN']]\n")))
1310
(ess-setCRANMiror)
1311
(ess-wait-for-process (get-process ess-current-process-name))
1312
(unless pack (setq update t)))
1313
(when (or update
1314
(not ess--packages-cache))
1315
(message "Fetching R packages ... ")
1316
(setq ess--packages-cache
1317
(ess-get-words-from-vector "print(rownames(available.packages()), max=1e6)\n")))
1318
(let* ((ess-eval-visibly-p t)
1319
(pack (or pack
1320
(ess-completing-read "Package to install" ess--packages-cache))))
1321
(process-send-string (get-process ess-current-process-name)
1322
(format "install.packages('%s')\n" pack))
1323
(display-buffer (buffer-name (process-buffer (get-process ess-current-process-name))))
1324
))
1325
1326
(define-obsolete-function-alias 'ess-install.packages 'ess-R-install.packages "ESS[12.09-1]")
1327
1328
(defun ess-install-library ()
1329
"Install library/package for current dialect.
1330
Currently works only for R."
1331
(interactive)
1332
(if (not (string-match "^R" ess-dialect))
1333
(message "Sorry, not available for %s" ess-dialect)
1334
(ess-R-install.packages)))
1335
1336
1337
(defun ess-setRepositories ()
1338
"Call setRepositories()"
1339
(interactive)
1340
(if (not (string-match "^R" ess-dialect))
1341
(message "Sorry, not available for %s" ess-dialect)
1342
(ess-eval-linewise "setRepositories(FALSE)\n")
1343
))
1344
1345
(defun ess-setCRANMiror ()
1346
"Set cran mirror"
1347
(interactive)
1348
(let* ((M1 (ess-get-words-from-vector "local({out <- getCRANmirrors(local.only=TRUE); print(paste(out$Name,'[',out$URL,']', sep=''))})\n"))
1349
(M2 (mapcar (lambda (el)
1350
(string-match "\\(.*\\)\\[\\(.*\\)\\]$" el)
1351
(propertize (match-string 1 el) 'URL (match-string 2 el)))
1352
M1))
1353
(opt (ess-completing-read "Choose CRAN mirror" M2 nil t)))
1354
(when opt
1355
(setq opt (get-text-property 0 'URL opt))
1356
(ess-command
1357
(format "local({r <- getOption('repos'); r['CRAN'] <- '%s';options(repos=r)})\n" opt))
1358
(message "New CHRAN mirror: %s" (car (ess-get-words-from-vector "getOption('repos')[['CRAN']]\n")))
1359
)))
1360
1361
(defun ess-R-sos (cmd)
1362
"Interface to findFn in the library sos."
1363
;(interactive (list (read-from-minibuffer "Web search for:" nil nil t nil (current-word))))
1364
(interactive "sfindFn: ")
1365
(unless (equal "TRUE" (car (ess-get-words-from-vector "as.character(suppressPackageStartupMessages(require(sos)))\n")))
1366
(if (y-or-n-p "Library 'sos' is not installed. Install? ")
1367
(progn (ess-eval-linewise "install.packages('sos')\n")
1368
(ess-eval-linewise "library(sos)\n"))
1369
(signal 'quit nil)))
1370
(message nil)
1371
(ess-eval-linewise (format "findFn(\"%s\", maxPages=10)" cmd))
1372
)
1373
1374
(define-obsolete-function-alias 'ess-sos 'ess-R-sos "ESS[12.09-1]")
1375
1376
1377
(defun ess-load-library ()
1378
"Prompt and load dialect specific library/package/module.
1379
1380
Note that add-ons in R are called 'packages' and the name of this
1381
function has nothing to do with R package mechanism, but it
1382
rather serves a generic, dialect independent purpose. It is also
1383
similar to `load-library' emacs function."
1384
(interactive)
1385
(if (not (string-match "^R" ess-dialect))
1386
(message "Sorry, not available for %s" ess-dialect)
1387
(let ((ess-eval-visibly-p t)
1388
(packs (ess-get-words-from-vector "print(.packages(T), max=1e6)\n"))
1389
pack)
1390
(setq pack (ess-completing-read "Load" packs))
1391
(ess-eval-linewise (format "library('%s')\n" pack))
1392
(ess--mark-search-list-as-changed)
1393
(display-buffer (buffer-name (process-buffer (get-process ess-current-process-name))))
1394
)))
1395
1396
(define-obsolete-function-alias 'ess-library 'ess-load-library "ESS[12.09-1]")
1397
1398
; provides
1399
1400
(provide 'ess-r-d)
1401
1402
; Local variables section
1403
1404
;;; This file is automatically placed in Outline minor mode.
1405
;;; The file is structured as follows:
1406
;;; Chapters: ^L ;
1407
;;; Sections: ;;*;;
1408
;;; Subsections: ;;;*;;;
1409
;;; Components: defuns, defvars, defconsts
1410
;;; Random code beginning with a ;;;;* comment
1411
1412
;;; Local variables:
1413
;;; mode: emacs-lisp
1414
;;; outline-minor-mode: nil
1415
;;; mode: outline-minor
1416
;;; outline-regexp: "\^L\\|\\`;\\|;;\\*\\|;;;\\*\\|(def[cvu]\\|(setq\\|;;;;\\*"
1417
;;; End:
1418
1419
;;; ess-r-d.el ends here
1420
1421