Klimi's new dotfiles with stow.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

354 lines
14 KiB

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