forked from emacs-ess/ESS
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathess-rlib.el
246 lines (221 loc) · 8.23 KB
/
ess-rlib.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
;;; ess-rlib.el --- browse contents of R packages.
;; Stephen Eglen, GPL applies.
;;
;; Primitive browswing facilities for the list of packages, and
;; the functions within a package. Use RET or mouse-2 to click on a
;; link and see either contents of a package or the function.
;;
;; To use, simply start a R session, eval this buffer,
;; then, in the R buffer, do
;; source("ess-rlib.R")
;; to load the changes to the data() and print.libraryIQR() functions.
;;
;; Then do M-x
;; ess-rpackage or use C-x C-e at end of one of following lines:
;;
;; (ess-rpackage "ctest")
;; okay
;;
;; (ess-rpackage "foreign")
;; okay, but fails on "S3 read functions"
;;
;; (ess-rpackage "eda")
;; shows help for lib, but won't show individual files unless package
;; has been loaded. How to show help without loading the package first?
;; (ess-rpackage "ts")
;; not so good, due to regexp failure!
;; (ess-rpackage "base")
;; (ess-rpackage "mva")
;; one problem, near end of buffer.
;; Presumably, adding link markup to the output from library() command
;; would help here so that only functions will get converted into
;; links. This would be more robust than using regexps.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; (ess-rdata)
;; This command will browse the output of the data() command, using
;; the extra markup of data names. Output goes to the *ess-rdata*
;; buffer. It currently just converts the data names into links
;; (highlight with mouse; underline), but no action is made on the
;; links. Kurt suggested before making e.g. ? bring up help on that
;; data topic, and RET to load the package.
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defun ess-rpackage (package)
"View functions within the package named PACKAGE. The package must
have already been loaded; if the package is not loaded, the functions
in it can still be viewed, but the help for those functions cannot be
viewed. This function is therefore currently restricted to show
contents for loaded packages only. This calls an extra R funcition named
funs.for.package()."
(interactive (let ()
(list
(completing-read "Package name: "
(mapcar 'list
(ess-rpackage-list))))))
(let (beg str (all t))
(setq str (concat "funs.for.package('"
package
"')\n"))
(ess-execute str nil "ess-rlib")
(pop-to-buffer "*ess-rlib*")
(goto-char (point-min))
(while (re-search-forward "^[^ ]" nil t)
(beginning-of-line)
(setq beg (point))
(re-search-forward "\\s-")
(add-text-properties beg (1- (point))
'(face underline
mouse-face highlight
help-xref function))
))
;; End of mark up, so add some text to the top of buffer.
(goto-char (point-min))
(insert "Functions in package " package ":\n\n")
(goto-char (point-min))
(ess-rpackage-mode)
)
(defun ess-rpackage-list ()
"Return list of packages currently loaded."
(save-window-excursion
(ess-execute "cat(.packages(), '\\n')")
(pop-to-buffer "*ess-output*")
(cdr (reverse
(split-string (buffer-substring (point-min) (point-max)) " ")))))
(defun ess-rpackage-1 (lib)
"View help available for a topic. Lib should either be blank or
name of a package. It currently uses regexps to guess which parts of
the output are function and package names. This mostly works, but for
a classic failure, see output from viewing the base package.
Old version."
(interactive "sPackage name (leave blank for lib list): ")
;; todo: would it be worth getting completion for package list?
(let (beg str (all t))
(setq str
(if (equal lib "")
"library()"
(setq all nil)
(concat "library(help="
lib
")\n")))
(ess-execute str nil "ess-rlib")
(pop-to-buffer "*ess-rlib*")
(if all
(ess-markup-libnames)
(re-search-forward "^Index:")
(while (re-search-forward "^[^ ]+ " nil t)
(beginning-of-line)
(setq beg (point))
(re-search-forward "[ \t]")
(add-text-properties beg (1- (point))
'( face underline
mouse-face highlight
help-xref function))
(end-of-line)
))
;; end of mark up
(goto-char (point-min))
(ess-rpackage-mode)
)
)
(defun ess-markup-libnames ()
"Markup the output from library() command."
(goto-char (point-min))
(while (re-search-forward "^\\\\package{" nil t)
(delete-region (point) (progn (beginning-of-line) (point)))
(setq beg (point))
(search-forward "}")
(delete-backward-char 1)
(add-text-properties beg (point)
'(face underline
mouse-face highlight
help-xref library))
(end-of-line)))
(defun ess-markup-libnames-old ()
"Markup the output from library() command."
(goto-char (point-min))
(while (re-search-forward "^[^ ]+ " nil t)
(beginning-of-line)
(if (not (looking-at "Packages in library"))
(progn
(setq beg (point))
(re-search-forward "[ \t]")
(add-text-properties beg (1- (point))
'(face underline
mouse-face highlight
help-xref library))))
(end-of-line)
))
;;; Set up the major mode for viewing.
(define-derived-mode ess-rpackage-mode
text-mode "Rlib"
"Major mode for browsing package contents.
\\{ess-rpackage-mode-map}"
(setq case-fold-search nil))
;; define the keys.
(if (featurep 'xemacs)
(define-key ess-rpackage-mode-map [button2] 'ess-rpackage-mouse-view)
(define-key ess-rpackage-mode-map [mouse-2] 'ess-rpackage-mouse-view)
)
(define-key ess-rpackage-mode-map [return] 'ess-rpackage-show-help)
(define-key ess-rpackage-mode-map "\t" 'help-next-ref)
(if (featurep 'xemacs)
(define-key ess-rpackage-mode-map [iso-left-tab] 'help-previous-ref)
(define-key ess-rpackage-mode-map [<S-iso-lefttab>] 'help-previous-ref))
(defun ess-rpackage-show-help ()
"Show ESS help for item on current line."
(interactive)
(let
(beg fn type)
(save-excursion
(beginning-of-line)
(setq beg (point))
(if (looking-at "[ \t\n]")
(message "No function on this line.")
(setq type (get-text-property (point) 'help-xref))
(re-search-forward "\\s-")
(setq fn (buffer-substring-no-properties beg (1- (point))))
(if (equal type 'function)
(ess-display-help-on-object fn)
(ess-rpackage fn))))))
(defun ess-rpackage-mouse-view (event)
"In rdired, visit the object on the line you click on."
;; copied from ess-rdired.
(interactive "e")
(let (window pos)
(save-excursion
(if (featurep 'xemacs)
;; XEmacs
(setq window (event-window event)
pos (event-point event))
;; Emacs
(setq window (posn-window (event-end event))
pos (posn-point (event-end event))))
(if (not (windowp window))
(error "No file chosen"))
(set-buffer (window-buffer window))
(goto-char pos)
(ess-rpackage-show-help))))
(defun ess-rdata ()
"Show the data currently available. Currently the links are not
active -- nothing is set up to handle either pressing RET or mouse-2
over a data name. Kurt suggested maybe `?' on a data item lists its
help, and RET to load the data set?"
(interactive)
(let (beg str (all t))
(setq str "data()")
(ess-execute str nil "ess-rdata")
(pop-to-buffer "*ess-rdata*")
;; Now mark up the buffer.
(goto-char (point-min))
(while (re-search-forward "^\\\\data{" nil t)
(delete-region (point) (progn (beginning-of-line) (point)))
(setq beg (point))
(search-forward "}")
(delete-backward-char 1)
(add-text-properties beg (point)
'(face underline
mouse-face highlight
help-xref library))
(end-of-line)))
(goto-char (point-min))
)