(?`): define the backquote (`) character to be in the quote character
[ess.git] / lisp / essd-r-args.el
blobf371e80186f76432af3879c235d8963a1b1e09d4
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)
12 ;; any later version.
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).
44 ;; == Requirements ==
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).
54 ;; == Installation ==
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 ;; == Configuration ==
64 ;; Configuration should be done by setting some variables in your
65 ;; ~/.emacs file, the following is an example only, adjust it to your
66 ;; needs.
68 ;; ;; ess-r-args-noargsmsg is printed, if no argument information
69 ;; ;; could be found. You could set it to an empty string ("") for no
70 ;; ;; message.
71 ;; (setq ess-r-args-noargsmsg "No args found.")
73 ;; ;; ess-r-args-show-as determines how (where) the information is
74 ;; ;; displayed. Set it to "tooltip" for little tooltip windows or to
75 ;; ;; nil (the default) which will use the echo area at the bottom of
76 ;; ;; your Emacs frame.
77 ;; (setq ess-r-args-show-as nil)
79 ;; ;; ess-r-args-show-prefix is a string that is printed in front of
80 ;; ;; the arguments list. The default ist "ARGS: ".
81 ;; (setq ess-r-args-show-prefix "ARGS: ")
83 ;; == Usage ==
85 ;; The functions should be called when point (text cursor) is between
86 ;; two parentheses of a R function call (see screenshots above). It
87 ;; will then (invisibly) query R for which arguments the respective
88 ;; function knows as well as their default values and show or insert
89 ;; the result.
91 ;; There are currently two functions: ess-r-args-show echoes the
92 ;; arguments in the echo area or as tooltip, ess-r-args-insert prints
93 ;; the arguments at point.
95 ;; In order to not having to type the whole function name each time
96 ;; you want to see the arguments list, you most probably want to bind
97 ;; the functions to a key which again should be done in your ~/.emacs
98 ;; file. You can also let Emacs call the function each time you insert
99 ;; an opening parenthesis ("(").
101 ;; -----> do this below
103 ;; Again, the following is an example only:
105 ;; bind ess-r-args-show to F2
106 ;; (define-key ess-mode-map [f2] 'ess-r-args-show)
108 ;; bind ess-r-args-insert to F3
109 ;; (define-key ess-mode-map [f3] 'ess-r-args-insert)
111 ;; == Setting the tooltip position ==
113 ;; Unfortunately (?), tooltips are by default shown at the mouse
114 ;; pointer's position, which is not necessarily where you are looking
115 ;; at. If you use Emacs' mouse-avoidance-mode with option "banish"
116 ;; then the mouse pointer will automatically be put at the upper right
117 ;; corner of the Emacs window so that you know where to look for the
118 ;; tooltip. Emacs also allows for setting the tooltip position
119 ;; relative to the upper left corner of your screen. If you know how
120 ;; to let Emacs determine the point (text cursor) position in pixels
121 ;; from the upper left corner of the screen, please let me know. It
122 ;; would then be possible to show the tooltip near the point, which I
123 ;; would consider preferably.
125 ;; ;; Put mouse away when using keyboard
126 ;; (mouse-avoidance-mode 'banish)
128 ;; ;; Set the tooltip position in absolute pixels from the upper left
129 ;; ;; corner of the screen
130 ;; (setq tooltip-frame-parameters
131 ;; '((name . "tooltip")
132 ;; (left . 20)
133 ;; (top . 20)))
135 ;; == Changelog ==
137 ;; * 2007-04-03: The function should now do nothing (instead of
138 ;; irritating cursor movement) if the current ESS process is
139 ;; anything but R.
140 ;; * 2007-04-05: Function names changed. Much more modular. GPLed. New
141 ;; prefix configuration variable. Minor changes.
142 ;; * 2007-04-30: Error handling added. Bugfix: Emacs used to lock up
143 ;; when function was called within parentheses following the "#"
144 ;; character (Thanks to John Bullock for his bug report!).
146 ;; == Troubleshooting ==
148 ;; Before sending reports of problems, please check the following.
150 ;; * Doublecheck the requirements section above.
151 ;; * Please be sure you tried both the "tooltip" option and the "echo
152 ;; area" option and tell me whether both failed or just one.
153 ;; * Check whether it is a key binding problem. Run the function with
154 ;; M-x ess-r-args-show RET. If it works but not the key binding, try
155 ;; binding it to another key. Some window managers might not pass
156 ;; the function key keystrokes to Emacs.
158 ;; If you encounter problems, please send me detailed bug reports.
159 ;; Please also indicate the ESS version you are running and the Emacs
160 ;; type (GNU vs. X) and operating system. I will do my best to help
161 ;; but please be aware that I'm everything but an emacs lisp expert.
163 ;; == TODO ==
165 ;; These are things that I would like to see improved. Please let me
166 ;; know if you know how it could be done.
168 ;; * As mentioned above, I would like to place the tooltip near the
169 ;; point (text cursor) but I do not see how this could be done.
170 ;; * Both the message in the echo area and the tooltip automatically
171 ;; disappear as soon as a key is pressed. That is, you will need to
172 ;; call the function again if you have entered the first
173 ;; parameter(s) and wonder what additional parameters are possible.
174 ;; I would prefer the information to be shown, say, five seconds or
175 ;; so.
177 ;; ==================================================
179 (eval-and-compile
180 (require 'ess-cust)
182 (eval-when-compile
183 (require 'tooltip); for tooltip-show
186 (require 'ess)
188 ;;; FIXME: These three should become customizable and move to ./ess-cust.el :
189 (defvar ess-r-args-noargsmsg "No args found."
190 "The message that is returned if ess-r-args-get does not find a list
191 of arguments.")
193 (defvar ess-r-args-show-as nil
194 "How ess-r-args-show should show the argument list. Possible values
195 are: 'message' (the default) or 'tooltip'.")
196 (defvar ess-r-args-show-prefix "ARGS: "
197 "A prefix string that is shown before the arguments list.")
200 (defun ess-r-args-current-function ()
201 "Returns the name of the R function assuming point is currently
202 within the argument list or nil if no possible function name is
203 found."
204 (interactive "*")
205 (save-excursion
206 (condition-case nil (up-list -1)
207 (error (message "Can't find opening paranthesis.")))
208 (let ((posend (point)))
209 (backward-sexp 1)
210 (let ((rfunname (buffer-substring-no-properties posend (point))))
211 (if (posix-string-match "^[a-zA-Z0-9_\.]+$" rfunname)
212 rfunname nil)))))
214 (defun ess-r-args-get (&optional function)
215 "Returns string of arguments and their default values of R function
216 FUNCTION or nil if no possible function name found. Calls
217 ess-r-args-current-function if no argument given."
218 (interactive "*")
220 (if (null function)
221 (setq function (ess-r-args-current-function)))
222 (when function
223 (ess-force-buffer-current "R process to use: ")
224 ;; (ess-make-buffer-current)
225 ;; This is not ok: could be "R-devel" or ...
226 ;; (if (not (equal ess-current-process-name "R"))
227 ;; ((lambda () (message "No R process running") nil))
228 (let ((ess-nuke-trailing-whitespace-p t)
229 (args))
230 (ess-command (concat "try(args(" function "), silent=TRUE)\n")
231 (get-buffer-create "*ess-r-args-tmp*"))
232 (with-current-buffer "*ess-r-args-tmp*"
233 (goto-char (point-min))
234 (if (null (search-forward "function" 10 t))
235 (message ess-r-args-noargsmsg)
236 (goto-char (point-min))
237 (zap-to-char 1 (string-to-char "("))
238 (goto-char (point-max))
239 (zap-to-char -1 (string-to-char ")"))
240 (ess-nuke-trailing-whitespace); should also work in Xemacs
241 (setq args (buffer-string))))
242 (kill-buffer "*ess-r-args-tmp*")
243 args)))
245 (defun ess-r-args-show (&optional function)
246 "Show arguments and their default values of R function. Calls
247 ess-r-args-current-function if no argument given."
248 (interactive "*")
249 (if (null function)
250 (setq function (ess-r-args-current-function)))
251 (when function
252 (let ((args (ess-r-args-get function)))
253 (unless (null args)
254 (if (equal ess-r-args-show-as "tooltip")
255 (progn (require 'tooltip)
256 (tooltip-show (concat ess-r-args-show-prefix args)))
257 (message (concat ess-r-args-show-prefix args)))))))
259 ;; MM: I would strongly discourage use of the following:
260 ;; it leads to clueless newbie-users who indeed
261 ;; explicitly call a function with all its default arguments;
262 ;; instead of only setting the required arguments
263 (defun ess-r-args-insert (&optional function)
264 "Insert arguments and their default values of function. Calls
265 ess-r-args-current-function if no argument given."
266 (interactive "*")
267 (if (null function)
268 (setq function (ess-r-args-current-function)))
269 (when function
270 (let ((args (ess-r-args-get function))
271 (pointpos (point)))
272 (insert args)
273 (goto-char pointpos))))
275 ;; MM: activate this for now --- FIXME: *not* unconditionally
276 ;; call ess-r-args-show automatically --- this should be optional
278 (add-hook 'ess-mode-hook
279 (lambda ()
280 (define-key ess-mode-map "("
281 '(lambda ()
282 (interactive)
283 (skeleton-pair-insert-maybe nil)
284 (ess-r-args-show)))))
286 (provide 'essd-r-args)