1
;; Copyright (C) 2007 Sven Hartenstein
2
;; e-mail: mail at svenhartenstein dot de
4
;; Copyright (C) 2007 A.J. Rossini, Rich M. Heiberger, Martin
5
;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen.
7
;; This file is part of ESS
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)
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.
19
;; You should have received a copy of the GNU General Public License
20
;; along with GNU Emacs; see the file COPYING. If not, write to the
21
;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22
;; Boston, MA 02111-1307, USA.
24
;; ==================================================
26
;; Last update: 2007-04-30
28
;; == DOCUMENTATION ==
30
;; This file provides some functions that show or insert a
31
;; R-function's arguments (and their default values) by using R's
32
;; args() function. This code requires ESS (http://ess.r-project.org).
33
;; For screenshots as well as information on requirements,
34
;; installation, configuration and troubleshooting, please visit
35
;; http://www.svenhartenstein.de/emacs-ess.php
37
;; Users of XEmacs (or maybe non-GNU-Emacs users): The code below must
38
;; be slightly adapted in order to work in XEmacs (i.e. comment out
39
;; the delete-trailing-whitespace function call by putting a semicolon
40
;; at the beginning of the line). Furthermore, the tooltip option does
41
;; NOT work in XEmacs (yet) (and will probably only ever work if the
42
;; ESS-core team will adapt the code for XEmacs compatibility).
46
;; * ESS mode must be loaded and running.
47
;; * A R process must be running within ESS.
48
;; * For the tooltip option to work, Emacs must not run within a
49
;; terminal but (directly) under the X window system (in case of
51
;; * The tooltip option currently requires GNU Emacs (i.e. not XEmacs
52
;; or a similar other derivate).
56
;; To make Emacs aware of the functions defined in this file load it
57
;; into Emacs by including something like the following in your
58
;; ~/.emacs file (adapt "/PATH/TO"!).
60
;; (add-hook 'ess-mode-hook '(lambda () (load "/PATH/TO/ess-r-args.el")))
62
;; This file is included with ESS; if you are reading this file as
63
;; part of the ESS distribution, then you do not need to add the above
66
;; == Configuration ==
68
;; Configuration should be done by setting some variables in your
69
;; ~/.emacs file, the following is an example only, adjust it to your
72
;; ;; ess-r-args-noargsmsg is printed, if no argument information
73
;; ;; could be found. You could set it to an empty string ("") for no
75
;; (setq ess-r-args-noargsmsg "No args found.")
77
;; ;; ess-r-args-show-as determines how (where) the information is
78
;; ;; displayed. Set it to 'tooltip little tooltip windows or to
79
;; ;; 'message (the default) which will use the echo area at the bottom of
80
;; ;; your Emacs frame.
81
;; (setq ess-r-args-show-as nil)
83
;; ;; ess-r-args-show-prefix is a string that is printed in front of
84
;; ;; the arguments list. The default is "ARGS: ".
85
;; (setq ess-r-args-show-prefix "ARGS: ")
89
;; The functions should be called when point (text cursor) is between
90
;; two parentheses of a R function call (see screenshots above). It
91
;; will then (invisibly) query R for which arguments the respective
92
;; function knows as well as their default values and show or insert
95
;; There are currently two functions: ess-r-args-show echoes the
96
;; arguments in the echo area or as tooltip, ess-r-args-insert prints
97
;; the arguments at point.
99
;; In order to not having to type the whole function name each time
100
;; you want to see the arguments list, you most probably want to bind
101
;; the functions to a key which again should be done in your ~/.emacs
102
;; file. You can also let Emacs call the function each time you insert
103
;; an opening parenthesis ("(").
105
;; -----> do this below
107
;; Again, the following is an example only:
109
;; bind ess-r-args-show to F2
110
;; (define-key ess-mode-map [f2] 'ess-r-args-show)
112
;; bind ess-r-args-insert to F3
113
;; (define-key ess-mode-map [f3] 'ess-r-args-insert)
115
;; == Setting the tooltip position ==
117
;; Unfortunately (?), tooltips are by default shown at the mouse
118
;; pointer's position, which is not necessarily where you are looking
119
;; at. If you use Emacs' mouse-avoidance-mode with option "banish"
120
;; then the mouse pointer will automatically be put at the upper right
121
;; corner of the Emacs window so that you know where to look for the
122
;; tooltip. Emacs also allows for setting the tooltip position
123
;; relative to the upper left corner of your screen. If you know how
124
;; to let Emacs determine the point (text cursor) position in pixels
125
;; from the upper left corner of the screen, please let me know. It
126
;; would then be possible to show the tooltip near the point, which I
127
;; would consider preferably.
128
;; SJE: see code at bottom 2009-01-30...
130
;; ;; Put mouse away when using keyboard
131
;; (mouse-avoidance-mode 'banish)
133
;; ;; Set the tooltip position in absolute pixels from the upper left
134
;; ;; corner of the screen
135
;; (setq tooltip-frame-parameters
136
;; '((name . "tooltip")
142
;; * 2007-04-03: The function should now do nothing (instead of
143
;; irritating cursor movement) if the current ESS process is
145
;; * 2007-04-05: Function names changed. Much more modular. GPLed. New
146
;; prefix configuration variable. Minor changes.
147
;; * 2007-04-30: Error handling added. Bugfix: Emacs used to lock up
148
;; when function was called within parentheses following the "#"
149
;; character (Thanks to John Bullock for his bug report!).
151
;; == Troubleshooting ==
153
;; Before sending reports of problems, please check the following.
155
;; * Doublecheck the requirements section above.
156
;; * Please be sure you tried both the "tooltip" option and the "echo
157
;; area" option and tell me whether both failed or just one.
158
;; * Check whether it is a key binding problem. Run the function with
159
;; M-x ess-r-args-show RET. If it works but not the key binding, try
160
;; binding it to another key. Some window managers might not pass
161
;; the function key keystrokes to Emacs.
163
;; If you encounter problems, please send me detailed bug reports.
164
;; Please also indicate the ESS version you are running and the Emacs
165
;; type (GNU vs. X) and operating system. I will do my best to help
166
;; but please be aware that I'm everything but an emacs lisp expert.
170
;; These are things that I would like to see improved. Please let me
171
;; know if you know how it could be done.
173
;; * As mentioned above, I would like to place the tooltip near the
174
;; point (text cursor) but I do not see how this could be done.
175
;; * Both the message in the echo area and the tooltip automatically
176
;; disappear as soon as a key is pressed. That is, you will need to
177
;; call the function again if you have entered the first
178
;; parameter(s) and wonder what additional parameters are possible.
179
;; I would prefer the information to be shown, say, five seconds or
182
;; ==================================================
185
(require 'ess-custom))
189
(require 'tooltip))); for tooltip-show
193
(defun ess-r-args-current-function ()
194
"Returns the name of the R function assuming point is currently
195
within the argument list or nil if no possible function name is
198
(condition-case nil (up-list -1)
199
(error (message "Can't find opening parenthesis.")))
200
(let ((posend (point)))
202
(let ((rfunname (buffer-substring-no-properties posend (point))))
203
(if (posix-string-match "^[a-zA-Z0-9_\.]+$" rfunname)
206
(defun ess-r-args-get (&optional function)
207
"Returns string of arguments and their default values of R function
208
FUNCTION or nil if no possible function name found. Calls
209
ess-r-args-current-function if no argument given."
211
(setq function (ess-r-args-current-function)))
213
(or ess-current-process-name
215
(ess-force-buffer-current "R process to use: ")
216
;; ^^^^^^^^^^^^^^^ has own error handler
217
(let ((ess-nuke-trailing-whitespace-p t)
219
(ess-command (concat "try(args(" function "), silent=TRUE)\n")
220
(get-buffer-create "*ess-r-args-tmp*"))
221
(with-current-buffer "*ess-r-args-tmp*"
222
(goto-char (point-min))
223
(if (null (search-forward "function" 10 t))
224
(message ess-r-args-noargsmsg)
225
(goto-char (point-min))
226
(search-forward "(" nil t)
227
(delete-region (point-min) (point))
228
(goto-char (point-max))
229
(search-backward ")" nil t)
230
(delete-region (point) (point-max))
231
(ess-nuke-trailing-whitespace); should also work in Xemacs
232
(setq args (buffer-string))))
233
(kill-buffer "*ess-r-args-tmp*")
236
(defun ess-r-args-show (&optional function)
237
"Show arguments and their default values of R function. Calls
238
\\[ess-r-args-current-function] if called without argument."
240
(ess-message "(ess-r-args-show): start")
242
(setq function (ess-r-args-current-function)))
243
(ess-message ".... function='%s'" function)
245
(let ((args (ess-r-args-get function)))
246
(ess-message "(ess-r-args-show): args='%s'" args)
248
(if (and (equal ess-r-args-show-as 'tooltip)
250
(progn (require 'tooltip)
251
;; value of 30 in next call is just a guess,
252
;; should really be based
253
;; on something like pixel height of 1-2 vertical
255
(tooltip-show-at-point
256
(concat ess-r-args-show-prefix args) 0 30))
257
(message (concat ess-r-args-show-prefix args)))))))
259
(defun ess-r-args-auto-show ()
260
"Typically assigned to \"(\": If there's an ess-process, automatically show arguments
261
and their default values of an R function. Built on \\[ess-r-args-show]."
263
(insert "("); (skeleton-pair-insert-maybe nil)
264
(if (and ess-local-process-name ; has a process and it must still be running
265
(get-ess-process ess-local-process-name))
268
;; MM: I would strongly discourage use of the following:
269
;; it leads to clueless newbie-users who indeed
270
;; explicitly call a function with all its default arguments;
271
;; instead of only setting the required arguments
272
(defun ess-r-args-insert (&optional function)
273
"Insert arguments and their default values of function. Calls
274
ess-r-args-current-function if no argument given."
277
(setq function (ess-r-args-current-function)))
279
(let ((args (ess-r-args-get function))
282
(goto-char pointpos))))
284
;; ;; call ess-r-args-show automatically --- this should be optional
285
;; now in ess-mode.el :
286
;; (if ess-r-args-electric-paren ; <<- in ./ess-custom.el -- default nil
287
;; (add-hook 'ess-mode-hook
289
;; (define-key ess-mode-map "(" 'ess-r-args-auto-show))))
292
;; SJE: 2009-01-30 -- this contribution from
293
;; Erik Iverson <iverson@biostat.wisc.edu>
294
(require 'assoc) ;needed for aput, below.
295
(defun tooltip-show-at-point (text xo yo)
296
"Show a tooltip displaying 'text' at (around) point, xo and yo are x-
297
and y-offsets for the toolbar from point."
299
(fx (frame-parameter nil 'left))
300
(fy (frame-parameter nil 'top))
301
(fw (frame-pixel-width))
302
(fh (frame-pixel-height))
303
frame-left frame-top)
305
;; The following comment was found before code looking much like that
306
;; of frame-left and frame-top below in the file
307
;; tooltip-help.el. I include it here for acknowledgement, and I did observe
308
;; the same behavior with the Emacs window maximized under Windows XP.
310
;; -----original comment--------
311
;; handles the case where (frame-parameter nil 'top) or
312
;; (frame-parameter nil 'left) return something like (+ -4).
313
;; This was the case where e.g. Emacs window is maximized, at
314
;; least on Windows XP. The handling code is "shamelessly
315
;; stolen" from cedet/speedbar/dframe.el
316
;; (contributed by Andrey Grigoriev)
318
(setq frame-left (if (not (consp fx))
321
(- (x-display-pixel-width) (car (cdr fx)) fw)
324
(setq frame-top (if (not (consp fy))
327
(- (x-display-pixel-height) (car (cdr fy)) fh)
330
;; calculate the offset from point, use xo and yo to adjust to preference
331
(setq my-x-offset (+ (car(window-inside-pixel-edges))
332
(car(posn-x-y (posn-at-point)))
335
(setq my-y-offset (+ (cadr(window-inside-pixel-edges))
336
(cdr(posn-x-y (posn-at-point)))
339
;; this clobbers current tooltip-frame-parameters 'top' and 'left',
340
;; which are not set by default. use push/pop instead of aput/adelete?
341
;; the problem with using aput again is that if top/left were nil, aput'ing
342
;; nil will have no effect.
344
(aput 'tooltip-frame-parameters 'top my-y-offset)
345
(aput 'tooltip-frame-parameters 'left my-x-offset)
349
;; remove parameters so that further tooltip-show calls aren't shown in
350
;; odd place (i.e., wherever point happened to be the last time this was
352
(adelete 'tooltip-frame-parameters 'top)
353
(adelete 'tooltip-frame-parameters 'left)
356
(provide 'ess-r-args)