~ubuntu-branches/ubuntu/precise/ess/precise

« back to all changes in this revision

Viewing changes to lisp/ess-r-args.el

  • Committer: Bazaar Package Importer
  • Author(s): Dirk Eddelbuettel
  • Date: 2010-03-03 06:25:04 UTC
  • mfrom: (1.2.13 upstream) (3.1.13 sid)
  • Revision ID: james.westby@ubuntu.com-20100303062504-rtei3p11s1gmcj4r
Tags: 5.8-1
New upstream version released this morning

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
;; Copyright (C) 2007 Sven Hartenstein
 
2
;; e-mail: mail at svenhartenstein dot de
 
3
 
 
4
;; Copyright (C) 2007 A.J. Rossini, Rich 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
;; 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.
 
23
 
 
24
;; ==================================================
 
25
 
 
26
;; Last update: 2007-04-30
 
27
 
 
28
;; == DOCUMENTATION ==
 
29
 
 
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
 
36
 
 
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).
 
43
 
 
44
;; == Requirements ==
 
45
 
 
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
 
50
;;   GNU/Linux).
 
51
;; * The tooltip option currently requires GNU Emacs (i.e. not XEmacs
 
52
;;   or a similar other derivate).
 
53
 
 
54
;; == Installation ==
 
55
 
 
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"!).
 
59
;;
 
60
;; (add-hook 'ess-mode-hook '(lambda () (load "/PATH/TO/ess-r-args.el")))
 
61
;;
 
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
 
64
;; line.
 
65
 
 
66
;; == Configuration ==
 
67
 
 
68
;; Configuration should be done by setting some variables in your
 
69
;; ~/.emacs file, the following is an example only, adjust it to your
 
70
;; needs.
 
71
 
 
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
 
74
;; ;; message.
 
75
;; (setq ess-r-args-noargsmsg "No args found.")
 
76
;;
 
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)
 
82
;;
 
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: ")
 
86
 
 
87
;; == Usage ==
 
88
 
 
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
 
93
;; the result.
 
94
 
 
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.
 
98
 
 
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 ("(").
 
104
 
 
105
;; -----> do this below
 
106
 
 
107
;; Again, the following is an example only:
 
108
 
 
109
;; bind ess-r-args-show to F2
 
110
;; (define-key ess-mode-map [f2] 'ess-r-args-show)
 
111
 
 
112
;; bind ess-r-args-insert to F3
 
113
;; (define-key ess-mode-map [f3] 'ess-r-args-insert)
 
114
 
 
115
;; == Setting the tooltip position ==
 
116
 
 
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...
 
129
 
 
130
;; ;; Put mouse away when using keyboard
 
131
;; (mouse-avoidance-mode 'banish)
 
132
 
 
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")
 
137
;;   (left . 20)
 
138
;;   (top . 20)))
 
139
 
 
140
;; == Changelog ==
 
141
 
 
142
;; * 2007-04-03: The function should now do nothing (instead of
 
143
;;   irritating cursor movement) if the current ESS process is
 
144
;;   anything but R.
 
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!).
 
150
 
 
151
;; == Troubleshooting ==
 
152
 
 
153
;; Before sending reports of problems, please check the following.
 
154
 
 
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.
 
162
 
 
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.
 
167
 
 
168
;; == TODO ==
 
169
 
 
170
;; These are things that I would like to see improved. Please let me
 
171
;; know if you know how it could be done.
 
172
 
 
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
 
180
;;   so.
 
181
 
 
182
;; ==================================================
 
183
 
 
184
(eval-and-compile
 
185
  (require 'ess-custom))
 
186
 
 
187
(eval-when-compile
 
188
  (if ess-has-tooltip
 
189
    (require 'tooltip))); for tooltip-show
 
190
 
 
191
(require 'ess)
 
192
 
 
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
 
196
found."
 
197
  (save-excursion
 
198
    (condition-case nil (up-list -1)
 
199
      (error (message "Can't find opening parenthesis.")))
 
200
    (let ((posend (point)))
 
201
      (backward-sexp 1)
 
202
      (let ((rfunname (buffer-substring-no-properties posend (point))))
 
203
        (if (posix-string-match "^[a-zA-Z0-9_\.]+$" rfunname)
 
204
            rfunname nil)))))
 
205
 
 
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."
 
210
  (if (null function)
 
211
      (setq function (ess-r-args-current-function)))
 
212
  (when (and function
 
213
             (or ess-current-process-name
 
214
                 (interactive-p)))
 
215
    (ess-force-buffer-current "R process to use: ")
 
216
    ;; ^^^^^^^^^^^^^^^ has own error handler
 
217
    (let ((ess-nuke-trailing-whitespace-p t)
 
218
          (args))
 
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*")
 
234
      args)))
 
235
 
 
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."
 
239
  (interactive "*")
 
240
  (ess-message "(ess-r-args-show): start")
 
241
  (if (null function)
 
242
      (setq function (ess-r-args-current-function)))
 
243
  (ess-message ".... function='%s'" function)
 
244
  (if function
 
245
    (let ((args (ess-r-args-get function)))
 
246
      (ess-message "(ess-r-args-show): args='%s'" args)
 
247
      (unless (null args)
 
248
        (if (and (equal ess-r-args-show-as 'tooltip)
 
249
                 ess-has-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 
 
254
                   ;; lines of text
 
255
                   (tooltip-show-at-point 
 
256
                    (concat ess-r-args-show-prefix args) 0 30))
 
257
          (message (concat ess-r-args-show-prefix args)))))))
 
258
 
 
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]."
 
262
  (interactive)
 
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))
 
266
      (ess-r-args-show)))
 
267
 
 
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."
 
275
  (interactive "*")
 
276
  (if (null function)
 
277
      (setq function (ess-r-args-current-function)))
 
278
  (if function
 
279
    (let ((args (ess-r-args-get function))
 
280
          (pointpos (point)))
 
281
      (insert args)
 
282
      (goto-char pointpos))))
 
283
 
 
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
 
288
;;            (lambda ()
 
289
;;              (define-key ess-mode-map "(" 'ess-r-args-auto-show))))
 
290
 
 
291
 
 
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."
 
298
  (let (
 
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)
 
304
 
 
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. 
 
309
    
 
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)
 
317
    
 
318
    (setq frame-left (if (not (consp fx))
 
319
                         fx
 
320
                       (if (eq (car fx) '-)
 
321
                           (- (x-display-pixel-width) (car (cdr fx)) fw)
 
322
                         (car (cdr fx)))))
 
323
    
 
324
    (setq frame-top (if (not (consp fy))
 
325
                        fy
 
326
                      (if (eq (car fy) '-)
 
327
                          (- (x-display-pixel-height) (car (cdr fy)) fh)
 
328
                        (car (cdr fy)))))
 
329
    
 
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)))
 
333
                         frame-left xo))
 
334
    
 
335
    (setq my-y-offset (+ (cadr(window-inside-pixel-edges))
 
336
                         (cdr(posn-x-y (posn-at-point)))
 
337
                         frame-top yo))
 
338
    
 
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. 
 
343
    
 
344
    (aput 'tooltip-frame-parameters 'top my-y-offset)
 
345
    (aput 'tooltip-frame-parameters 'left my-x-offset)
 
346
    
 
347
    (tooltip-show text)
 
348
    
 
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 
 
351
    ;; called
 
352
    (adelete 'tooltip-frame-parameters 'top)
 
353
    (adelete 'tooltip-frame-parameters 'left)
 
354
    ))
 
355
 
 
356
(provide 'ess-r-args)