Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
2701 views
1
;;; ess-r-args.el --- Insert R function's arguments
2
3
;; Copyright (C) 2007 Sven Hartenstein <mail at svenhartenstein dot de>
4
;; Copyright (C) 2007 A.J. Rossini, Richard M. Heiberger, Martin
5
;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen.
6
7
;; This file is part of ESS
8
9
;; This file is free software; you can redistribute it and/or modify
10
;; it under the terms of the GNU General Public License as published by
11
;; the Free Software Foundation; either version 2, or (at your option)
12
;; any later version.
13
14
;; This file is distributed in the hope that it will be useful,
15
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
;; GNU General Public License for more details.
18
19
;; A copy of the GNU General Public License is available at
20
;; http://www.r-project.org/Licenses/
21
22
;; Last update: 2012-02-27
23
24
;;; Commentary:
25
26
;; == DOCUMENTATION ==
27
28
;; This file provides some functions that show or insert a
29
;; R-function's arguments (and their default values) by using R's
30
;; args() function. This code requires ESS (http://ess.r-project.org).
31
;; For screenshots as well as information on requirements,
32
;; installation, configuration and troubleshooting, please visit
33
;; http://www.svenhartenstein.de/emacs-ess.php
34
35
;; Users of XEmacs (or maybe non-GNU-Emacs users): The code below must
36
;; be slightly adapted in order to work in XEmacs (i.e. comment out
37
;; the delete-trailing-whitespace function call by putting a semicolon
38
;; at the beginning of the line). Furthermore, the tooltip option does
39
;; NOT work in XEmacs (yet) (and will probably only ever work if the
40
;; ESS-core team will adapt the code for XEmacs compatibility).
41
42
;; == Requirements ==
43
44
;; * ESS mode must be loaded and running.
45
;; * A R process must be running within ESS.
46
;; * For the tooltip option to work, Emacs must not run within a
47
;; terminal but (directly) under the X window system (in case of
48
;; GNU/Linux).
49
;; * The tooltip option currently requires GNU Emacs (i.e. not XEmacs
50
;; or a similar other derivate).
51
52
;; == Installation ==
53
54
;; To make Emacs aware of the functions defined in this file load it
55
;; into Emacs by including something like the following in your
56
;; ~/.emacs file (adapt "/PATH/TO"!).
57
;;
58
;; (add-hook 'ess-mode-hook (lambda () (load "/PATH/TO/ess-r-args.el")))
59
;;
60
;; This file is included with ESS; if you are reading this file as
61
;; part of the ESS distribution, then you do not need to add the above
62
;; line.
63
64
;; == Configuration ==
65
66
;; Configuration should be done by setting some variables in your
67
;; ~/.emacs file, the following is an example only, adjust it to your
68
;; needs.
69
70
;; ;; ess-r-args-noargsmsg is printed, if no argument information
71
;; ;; could be found. You could set it to an empty string ("") for no
72
;; ;; message.
73
;; (setq ess-r-args-noargsmsg "No args found.")
74
;;
75
;; ;; ess-r-args-show-as determines how (where) the information is
76
;; ;; displayed. Set it to 'tooltip little tooltip windows or to
77
;; ;; 'message (the default) which will use the echo area at the bottom of
78
;; ;; your Emacs frame.
79
;; (setq ess-r-args-show-as nil)
80
;;
81
;; ;; ess-r-args-show-prefix is a string that is printed in front of
82
;; ;; the arguments list. The default is "ARGS: ".
83
;; (setq ess-r-args-show-prefix "ARGS: ")
84
85
;; == Usage ==
86
87
;; The functions should be called when point (text cursor) is between
88
;; two parentheses of a R function call (see screenshots above). It
89
;; will then (invisibly) query R for which arguments the respective
90
;; function knows as well as their default values and show or insert
91
;; the result.
92
93
;; There are currently two functions: ess-r-args-show echoes the
94
;; arguments in the echo area or as tooltip, ess-r-args-insert prints
95
;; the arguments at point.
96
97
;; In order to not having to type the whole function name each time
98
;; you want to see the arguments list, you most probably want to bind
99
;; the functions to a key which again should be done in your ~/.emacs
100
;; file. You can also let Emacs call the function each time you insert
101
;; an opening parenthesis ("(").
102
103
;; -----> do this below
104
105
;; Again, the following is an example only:
106
107
;; bind ess-r-args-show to F2
108
;; (define-key ess-mode-map [f2] 'ess-r-args-show)
109
110
;; bind ess-r-args-insert to F3
111
;; (define-key ess-mode-map [f3] 'ess-r-args-insert)
112
113
;; == Setting the tooltip position ==
114
115
;; Unfortunately (?), tooltips are by default shown at the mouse
116
;; pointer's position, which is not necessarily where you are looking
117
;; at. If you use Emacs' mouse-avoidance-mode with option "banish"
118
;; then the mouse pointer will automatically be put at the upper right
119
;; corner of the Emacs window so that you know where to look for the
120
;; tooltip. Emacs also allows for setting the tooltip position
121
;; relative to the upper left corner of your screen. If you know how
122
;; to let Emacs determine the point (text cursor) position in pixels
123
;; from the upper left corner of the screen, please let me know. It
124
;; would then be possible to show the tooltip near the point, which I
125
;; would consider preferably.
126
;; SJE: see code at bottom 2009-01-30...
127
128
;; ;; Put mouse away when using keyboard
129
;; (mouse-avoidance-mode 'banish)
130
131
;; ;; Set the tooltip position in absolute pixels from the upper left
132
;; ;; corner of the screen
133
;; (setq tooltip-frame-parameters
134
;; '((name . "tooltip")
135
;; (left . 20)
136
;; (top . 20)))
137
138
;; == Changelog ==
139
140
;; * 2007-04-03: The function should now do nothing (instead of
141
;; irritating cursor movement) if the current ESS process is
142
;; anything but R.
143
;; * 2007-04-05: Function names changed. Much more modular. GPLed. New
144
;; prefix configuration variable. Minor changes.
145
;; * 2007-04-30: Error handling added. Bugfix: Emacs used to lock up
146
;; when function was called within parentheses following the "#"
147
;; character (Thanks to John Bullock for his bug report!).
148
149
;; == Troubleshooting ==
150
151
;; Before sending reports of problems, please check the following.
152
153
;; * Doublecheck the requirements section above.
154
;; * Please be sure you tried both the "tooltip" option and the "echo
155
;; area" option and tell me whether both failed or just one.
156
;; * Check whether it is a key binding problem. Run the function with
157
;; M-x ess-r-args-show RET. If it works but not the key binding, try
158
;; binding it to another key. Some window managers might not pass
159
;; the function key keystrokes to Emacs.
160
161
;; If you encounter problems, please send me detailed bug reports.
162
;; Please also indicate the ESS version you are running and the Emacs
163
;; type (GNU vs. X) and operating system. I will do my best to help
164
;; but please be aware that I'm everything but an emacs lisp expert.
165
166
;; == TODO ==
167
168
;; These are things that I would like to see improved. Please let me
169
;; know if you know how it could be done.
170
171
;; * As mentioned above, I would like to place the tooltip near the
172
;; point (text cursor) but I do not see how this could be done.
173
;; * Both the message in the echo area and the tooltip automatically
174
;; disappear as soon as a key is pressed. That is, you will need to
175
;; call the function again if you have entered the first
176
;; parameter(s) and wonder what additional parameters are possible.
177
;; I would prefer the information to be shown, say, five seconds or
178
;; so.
179
180
;;; Code:
181
182
(eval-and-compile
183
(require 'ess-custom))
184
185
(eval-when-compile
186
(if ess-has-tooltip
187
(require 'tooltip))); for tooltip-show
188
189
(require 'ess)
190
191
(defun ess-r-args-current-function ()
192
"Returns the name of the R function assuming point is currently
193
within the argument list or nil if no possible function name is
194
found."
195
(save-excursion
196
(condition-case nil (up-list -1)
197
(error (message "Can't find opening parenthesis.")))
198
(let ((posend (point)))
199
(backward-sexp 1)
200
(let ((rfunname (buffer-substring-no-properties posend (point))))
201
(if (posix-string-match "^[a-zA-Z0-9_\.]+$" rfunname)
202
rfunname nil)))))
203
204
(defun ess-r-args-get (&optional function trim)
205
"Returns string of arguments and their default values of R
206
function FUNCTION or nil if no possible function name
207
found. Calls ess-r-args-current-function if no argument given.
208
If TRIM is non-nill remove tabs and newlines and replace ' = '
209
with '=' (useful for display in minibuffer to avoid window and
210
buffer readjustments for multiline string)."
211
(if (null function)
212
(setq function (ess-r-args-current-function)))
213
(when (and function
214
(or ess-current-process-name
215
(interactive-p)))
216
(ess-force-buffer-current "R process to use: ")
217
;; ^^^^^^^^^^^^^^^ has own error handler
218
(cadr (ess-function-arguments function))
219
))
220
221
;; (let ((ess-nuke-trailing-whitespace-p t)
222
;; (args))
223
;; (ess-command (format "try({fun<-\"%s\"; fundef<-paste(fun, '.default',sep='')
224
;; if(exists(fundef, mode = \"function\")) args(fundef) else args(fun)}, silent=F)\n" function)
225
;; (get-buffer-create "*ess-r-args-tmp*"))
226
;; (with-current-buffer "*ess-r-args-tmp*"
227
;; (goto-char (point-min))
228
;; (if (null (search-forward "function" 20 t))
229
;; (message ess-r-args-noargsmsg)
230
;; (goto-char (point-min))
231
;; (search-forward "(" nil t)
232
;; (delete-region (point-min) (point))
233
;; (goto-char (point-max))
234
;; (search-backward ")" nil t)
235
;; (delete-region (point) (point-max))
236
;; (ess-nuke-trailing-whitespace); should also work in Xemacs
237
;; (setq args (buffer-string))
238
;; (if trim
239
;; (replace-regexp-in-string " = " "="
240
;; (replace-regexp-in-string "[\n \t]+" " " args))
241
;; args)
242
;; )))))
243
244
(defun ess-r-args-show (&optional function)
245
"Show arguments and their default values of R function. Calls
246
\\[ess-r-args-current-function] if called without argument."
247
(interactive "*")
248
(ess-message "(ess-r-args-show): start")
249
(if (null function)
250
(setq function (ess-r-args-current-function)))
251
(ess-message ".... function='%s'" function)
252
(when function
253
(let* ((tt (and (equal ess-r-args-show-as 'tooltip)
254
ess-has-tooltip))
255
(args (concat ess-r-args-show-prefix (ess-r-args-get function (not tt)))))
256
(ess-message "(ess-r-args-show): args='%s'" args)
257
(when args
258
(if (not tt)
259
(message args)
260
(require 'tooltip)
261
;; value of 30 in next call is just a guess,
262
;; should really be based
263
;; on something like pixel height of 1-2 vertical
264
;; lines of text
265
(ess-tooltip-show-at-point args 0 30))
266
))))
267
268
(defun ess-r-args-auto-show ()
269
"Typically assigned to \"(\": If there's an ess-process, automatically show arguments
270
and their default values of an R function. Built on \\[ess-r-args-show]."
271
(interactive)
272
(insert "("); (skeleton-pair-insert-maybe nil)
273
(if (and (not eldoc-mode)
274
ess-local-process-name ; has a process and it must still be running
275
(ess-get-process ess-local-process-name))
276
(ess-r-args-show)))
277
278
;; MM: I would strongly discourage use of the following:
279
;; it leads to clueless newbie-users who indeed
280
;; explicitly call a function with all its default arguments;
281
;; instead of only setting the required arguments
282
(defun ess-r-args-insert (&optional function)
283
"Insert arguments and their default values of function. Calls
284
ess-r-args-current-function if no argument given."
285
(interactive "*")
286
(if (null function)
287
(setq function (ess-r-args-current-function)))
288
(if function
289
(let ((args (ess-r-args-get function))
290
(pointpos (point)))
291
(insert args)
292
(goto-char pointpos))))
293
294
295
;; (defvar ess-r-object-tooltip-alist
296
;; '((numeric . "summary")
297
;; (integer . "summary")
298
;; (factor . "table")
299
;; (lm . "summary")
300
;; (other . "str"))
301
;; "List of (<class> . <R-function>) to be used in \\[ess-r-object-tooltip].
302
;; For example, when called while point is on a factor object, a table of that
303
;; factor will be shown in the tooltip.
304
;; The special key \"other\" in the alist defines which function to call when
305
;; the class is not mached in the alist. The default, str(), is a fairly useful
306
;; default for many, including data.frame and function objects.")
307
308
;; From Erik Iversion, slightly modified,
309
;; http://www.sigmafield.org/2009/10/01/r-object-tooltips-in-ess/
310
;; (defun ess-r-object-tooltip ()
311
;; "Get info for object at point, and display it in a tooltip."
312
;; (interactive)
313
;; (let ((proc (ess-get-process))
314
;; (objname (current-word))
315
;; (curbuf (current-buffer))
316
;; (tmpbuf (get-buffer-create " *ess-r-object-tooltip*"))
317
;; bs)
318
;; (when objname
319
;; (ess-write-to-dribble-buffer
320
;; (format "ess-r-object-tooltip: objname='%s'\n" objname))
321
;; (ess-command (concat "class(" objname ")\n") tmpbuf nil nil nil proc)
322
;; (with-current-buffer tmpbuf
323
;; (goto-char (point-min))
324
;; ;; CARE: The following can only work in an English language locale!
325
;; ;; .lang. <- Sys.getenv("LANGUAGE"); Sys.setenv(LANGUAGE="en")
326
;; ;; .lc. <- Sys.getlocale("LC_MESSAGES"); Sys.setlocale("LC_MESSAGES","en_US.utf-8")
327
;; ;; and *afterward* Sys.setenv(LANGUAGE=.lang.); Sys.setlocale("LC_MESSAGES", .lc.)
328
;; ;; but that fails sometimes, e.g., on Windows
329
;; (unless (re-search-forward "\(object .* not found\)\|unexpected" nil t)
330
;; (re-search-forward "\"\\(.*\\)\"" nil t)
331
;; (let* ((objcls (match-string 1))
332
;; (myfun (or (cdr (assoc-string objcls ess-r-object-tooltip-alist))
333
;; (cdr (assoc 'other ess-r-object-tooltip-alist)))))
334
;; (ess-command (concat myfun "(" objname ")\n") tmpbuf nil nil nil proc))
335
;; (setq bs (buffer-string)))))
336
;; (if bs
337
;; (ess-tooltip-show-at-point bs 0 30))))
338
339
;; Erik: my default key map
340
;;(define-key ess-mode-map "\C-c\C-g" 'ess-r-object-tooltip)
341
342
;; On http://www.sigmafield.org/2009/10/01/r-object-tooltips-in-ess/
343
;; in the comments, "Charlie" recommended
344
345
;; (custom-set-faces
346
;; '(tooltip ((t (:background "white" :foreground "blue" :foundry "fixed")))))
347
348
349
350
(provide 'ess-r-args)
351
352
;;; ess-r-args.el ends here
353
354