Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
2701 views
1
;; ess-rd.el --- Support for editing R documentation (Rd) source
2
3
;; Copyright (C) 1997--2005 A.J. Rossini, Richard M. Heiberger, Martin
4
;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen.
5
6
;; Author: KH <[email protected]>
7
;; Created: 25 July 1997
8
;; Maintainer: ESS-core <[email protected]>
9
10
;; This file is part of ESS (Emacs Speaks Statistics).
11
12
;; This file is free software; you may redistribute it and/or modify it
13
;; under the terms of the GNU General Public License as published by the
14
;; Free Software Foundation; either version 2, or (at your option) any
15
;; later version.
16
;;
17
;; This is distributed in the hope that it will be useful, but WITHOUT
18
;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19
;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20
;; for more details.
21
;;
22
;; A copy of the GNU General Public License is available on the World
23
;; Wide Web at http://www.gnu.org/copyleft/gpl.html. You can also
24
;; obtain it by writing to the Free Software Foundation, Inc., 675 Mass
25
;; Ave, Cambridge, MA 02139, USA.
26
27
;;; Code:
28
29
;; To stave off byte compiler errors
30
(eval-when-compile (require 'ess-help))
31
32
(defvar essddr-version "0.9-1"
33
"Current version of ess-rd.el.")
34
35
(defvar essddr-maintainer-address
36
"ESS Core Team <[email protected]>"
37
"Current maintainer of ess-rd.el.")
38
39
(defun Rd-active-mark () nil) ;silence compiler.
40
(if (featurep 'xemacs)
41
;; Special support for XEmacs (curtesy of auctex):
42
(defun Rd-active-mark ()
43
(and zmacs-regions (mark)))
44
45
;; else: special support for GNU Emacs
46
(defun Rd-active-mark ()
47
(and transient-mark-mode mark-active))
48
)
49
50
(autoload 'ess-eval-region "ess-inf" "[autoload]" t)
51
(autoload 'ess-eval-line-and-step "ess-inf" "[autoload]" t)
52
(autoload 'ess-switch-process "ess-inf" "[autoload]" t)
53
(autoload 'ess-switch-to-ESS "ess-inf" "[autoload]" t)
54
(autoload 'ess-switch-to-end-of-ESS "ess-inf" "[autoload]" t)
55
56
(autoload 'ess-help-mode "ess-help" "[autoload]" t)
57
(autoload 'ess-nuke-help-bs "ess-help" "[autoload]" t)
58
59
(defvar Rd-mode-abbrev-table nil
60
"Abbrev table for R documentation keywords.
61
All Rd mode abbrevs start with a grave accent (`).")
62
(if Rd-mode-abbrev-table
63
()
64
(define-abbrev-table 'Rd-mode-abbrev-table ())
65
(define-abbrev Rd-mode-abbrev-table "`ag" "\\arguments")
66
(define-abbrev Rd-mode-abbrev-table "`al" "\\alias")
67
(define-abbrev Rd-mode-abbrev-table "`au" "\\author")
68
(define-abbrev Rd-mode-abbrev-table "`bf" "\\bold")
69
(define-abbrev Rd-mode-abbrev-table "`co" "\\code")
70
(define-abbrev Rd-mode-abbrev-table "`de" "\\describe")
71
(define-abbrev Rd-mode-abbrev-table "`dn" "\\description")
72
(define-abbrev Rd-mode-abbrev-table "`dt" "\\details")
73
(define-abbrev Rd-mode-abbrev-table "`em" "\\emph")
74
(define-abbrev Rd-mode-abbrev-table "`en" "\\enumerate")
75
(define-abbrev Rd-mode-abbrev-table "`ex" "\\examples")
76
(define-abbrev Rd-mode-abbrev-table "`fi" "\\file")
77
(define-abbrev Rd-mode-abbrev-table "`fo" "\\format")
78
(define-abbrev Rd-mode-abbrev-table "`it" "\\item")
79
(define-abbrev Rd-mode-abbrev-table "`iz" "\\itemize")
80
(define-abbrev Rd-mode-abbrev-table "`kw" "\\keyword")
81
(define-abbrev Rd-mode-abbrev-table "`li" "\\link")
82
(define-abbrev Rd-mode-abbrev-table "`me" "\\method")
83
(define-abbrev Rd-mode-abbrev-table "`na" "\\name")
84
(define-abbrev Rd-mode-abbrev-table "`no" "\\note")
85
(define-abbrev Rd-mode-abbrev-table "`re" "\\references")
86
(define-abbrev Rd-mode-abbrev-table "`sa" "\\seealso")
87
(define-abbrev Rd-mode-abbrev-table "`se" "\\section")
88
(define-abbrev Rd-mode-abbrev-table "`so" "\\source")
89
(define-abbrev Rd-mode-abbrev-table "`ss" "\\subsection")
90
(define-abbrev Rd-mode-abbrev-table "`sy" "\\synopsis")
91
(define-abbrev Rd-mode-abbrev-table "`ta" "\\tabular")
92
(define-abbrev Rd-mode-abbrev-table "`ti" "\\title")
93
(define-abbrev Rd-mode-abbrev-table "`us" "\\usage")
94
(define-abbrev Rd-mode-abbrev-table "`va" "\\value"))
95
96
(defvar Rd-mode-syntax-table nil
97
"Syntax table for Rd mode.")
98
(if Rd-mode-syntax-table
99
()
100
(setq Rd-mode-syntax-table (copy-syntax-table text-mode-syntax-table))
101
(modify-syntax-entry ?\\ "\\" Rd-mode-syntax-table)
102
(modify-syntax-entry ?\{ "(}" Rd-mode-syntax-table)
103
(modify-syntax-entry ?\} "){" Rd-mode-syntax-table)
104
;; Nice for editing, not for parsing ...
105
(modify-syntax-entry ?\( "()" Rd-mode-syntax-table)
106
(modify-syntax-entry ?\) ")(" Rd-mode-syntax-table)
107
(modify-syntax-entry ?\[ "(]" Rd-mode-syntax-table)
108
(modify-syntax-entry ?\] ")[" Rd-mode-syntax-table)
109
;; To get strings right
110
;; (modify-syntax-entry ?\' "\"" Rd-mode-syntax-table)
111
(modify-syntax-entry ?\" "\"" Rd-mode-syntax-table)
112
;; To make abbrevs starting with a grave accent work ...
113
(modify-syntax-entry ?\` "w" Rd-mode-syntax-table)
114
;; Comments
115
(modify-syntax-entry ?\% "<" Rd-mode-syntax-table)
116
(modify-syntax-entry ?\n ">" Rd-mode-syntax-table))
117
118
(defvar Rd-mode-parse-syntax-table nil
119
"Syntax table for parsing Rd mode.")
120
(if Rd-mode-parse-syntax-table
121
()
122
(setq Rd-mode-parse-syntax-table
123
(copy-syntax-table Rd-mode-syntax-table))
124
;; To make parse-partial-sexps do the thing we want for computing
125
;; indentations
126
(modify-syntax-entry ?\( "_" Rd-mode-parse-syntax-table)
127
(modify-syntax-entry ?\) "_" Rd-mode-parse-syntax-table)
128
(modify-syntax-entry ?\[ "_" Rd-mode-parse-syntax-table)
129
(modify-syntax-entry ?\] "_" Rd-mode-parse-syntax-table))
130
131
(defvar Rd-section-names
132
'("Rdversion" "arguments" "alias" "author" "concept" "describe" "description"
133
"details" "docType" "encoding" "enumerate" "examples" "format"
134
"itemize" "keyword" "name" "note" "preformatted" "references"
135
"seealso" "section" "source" "subsection" "synopsis"
136
"tabular" "title" "usage"
137
"value"))
138
139
(defvar Rd-keywords
140
'(
141
;; the next two lines: only valid in R <= 2.8.1
142
;; commented out on 2011-01-14 for ESS version 5.13:
143
;; "Alpha" "Gamma" "alpha" "beta" "epsilon" "lambda" "mu" "pi" "sigma"
144
;; "ge" "le" "left" "right"
145
;;
146
"CRANpkg" "R" "RdOpts" "S3method" "S4method" "Sexpr" "acronym"
147
"bold" "cite" "code" "command" "cr" "dQuote" "deqn" "dfn" "dontrun"
148
"dontshow" "donttest" "dots" "email" "emph" "enc" "env" "eqn" "figure" "file"
149
"href" "if" "ifelse"
150
"item" "kbd" "ldots" "linkS4class" "link" "method"
151
"newcommand" "option" "out"
152
"pkg" "sQuote" "renewcommand"
153
"samp" "strong" "tab" "url" "var" "verb"
154
))
155
156
;; Need to fix Rd-bold-face problem.
157
;;
158
;; (defvar Rd-bold-face 'bold)
159
;(defvar Rd-bold-face nil)
160
;(make-face Rd-bold-face "R documentation bold face")
161
;(make-face-bold Rd-bold-face
162
163
(defvar Rd-font-lock-keywords
164
(list
165
(cons
166
(concat "\\\\\\("
167
(mapconcat 'identity Rd-section-names "\\|")
168
"\\>\\)")
169
'font-lock-reference-face) ; Rd-bold-face
170
(cons
171
(concat "\\\\\\("
172
(mapconcat 'identity Rd-keywords "\\|")
173
"\\>\\)")
174
'font-lock-keyword-face)
175
'("^#\\(ifn?def\\)\\s-+\\(\\sw+\\)"
176
(1 font-lock-builtin-face)
177
(2 font-lock-variable-name-face nil t))
178
'("^#\\(endif\\)" 1 font-lock-builtin-face))
179
"Additional Rd expressions to highlight.")
180
181
(defvar Rd-indent-level 2
182
"*Indentation of Rd code with respect to containing blocks.")
183
184
(defvar Rd-mode-map
185
(let ((map (make-sparse-keymap)))
186
(define-key map "\t" 'indent-according-to-mode)
187
(define-key map "\C-j" 'reindent-then-newline-and-indent)
188
(define-key map "\C-m" 'reindent-then-newline-and-indent)
189
(define-key map "\C-c\C-p" 'Rd-preview-help)
190
(define-key map "\C-c\C-j" 'Rd-mode-insert-item)
191
(define-key map "\C-c\C-e" 'Rd-mode-insert-skeleton)
192
(define-key map "\C-c\C-f" 'Rd-font)
193
;; ^C^F ^E : \emph{ . }
194
;; ^C^F ^C : \code{ . }
195
;; ^C^F ^L : \link{ . }
196
;; ^C^F L : \code{\link{ . }} etc
197
(define-key map "\C-c\C-s" 'Rd-mode-insert-section)
198
(define-key map "\C-ch" 'ess-handy-commands)
199
(define-key map "\C-c\C-n" 'ess-eval-line-and-step)
200
(define-key map "\C-c\C-r" 'ess-eval-region)
201
(define-key map "\C-c\C-c" 'ess-eval-region-or-function-or-paragraph-and-step)
202
(define-key map "\C-\M-x" 'ess-eval-region-or-function-or-paragraph)
203
(define-key map "\C-c\C-v" 'ess-display-help-on-object)
204
(define-key map "\C-c\C-w" 'ess-switch-process); is on C-c C-s in ess-mode..
205
(define-key map "\C-c\C-y" 'ess-switch-to-ESS)
206
(define-key map "\C-c\C-z" 'ess-switch-to-end-of-ESS)
207
map)
208
"Keymap used in Rd mode.")
209
210
(defvar Rd-mode-menu
211
(list "Rd"
212
["Markup [word]" Rd-font t]
213
["Insert Item" Rd-mode-insert-item t]
214
["Insert Section" Rd-mode-insert-section t]
215
["Insert Skeleton" Rd-mode-insert-skeleton t]
216
"-"
217
["Preview" Rd-preview-help t]
218
"-"
219
["Eval Line" ess-eval-line-and-step t]
220
["Eval Region" ess-eval-region t]
221
["Switch to ESS Process" ess-switch-to-ESS t]
222
["Switch the ESS Process" ess-switch-process t]
223
["Switch to end{ESS Pr}" ess-switch-to-end-of-ESS t]
224
"-"
225
["Toggle Abbrev Mode" abbrev-mode t]
226
["Toggle Auto-Fill Mode" auto-fill-mode t]
227
"-"
228
["Submit Bug Report" Rd-submit-bug-report t]
229
"-"
230
["Describe Rd Mode" Rd-describe-major-mode t])
231
"Menu used in Rd mode.")
232
233
(defvar Rd-mode-hook nil
234
"*Hook to be run when Rd mode is entered.")
235
236
(defvar Rd-to-help-command "R CMD Rd2txt"
237
"*Shell command for converting R documentation source to help text.")
238
239
240
(defvar Rd-font-list
241
'((?\C-b "\\bold{" "}")
242
(?\C-c "\\code{" "}")
243
(?\C-e "\\emph{" "}")
244
(?\C-l "\\link{" "}")
245
(?l "\\code{\\link{" "}}")
246
(?\C-m "\\email{" "}")
247
(?\C-q "\\eqn{" "}")
248
(?\C-u "\\url{" "}")
249
)
250
"List of ``fonts'' used by Rd-font.
251
252
Each entry is a list.
253
The first element is the key to activate the font.
254
The second element is the string to insert before point, and the third
255
element is the string to insert after point."
256
)
257
258
259
;;;###autoload
260
(defun Rd-mode ()
261
"Major mode for editing R documentation source files.
262
263
This mode makes it easier to write R documentation by helping with
264
indentation, doing some of the typing for you (with Abbrev mode) and by
265
showing keywords, strings, etc. in different faces (with Font Lock mode
266
on terminals that support it).
267
268
Type \\[list-abbrevs] to display the built-in abbrevs for Rd keywords.
269
270
Keybindings
271
===========
272
273
\\{Rd-mode-map}
274
275
Variables you can use to customize Rd mode
276
==========================================
277
278
`Rd-indent-level'
279
Indentation of Rd code with respect to containing blocks.
280
Default is 2.
281
282
Turning on Rd mode runs the hook `Rd-mode-hook'.
283
284
To automatically turn on the abbrev(iate) features, add the
285
following lines to your `.emacs' file:
286
287
(add-hook 'Rd-mode-hook
288
(lambda ()
289
(abbrev-mode 1)))
290
"
291
292
(interactive)
293
(text-mode)
294
(kill-all-local-variables)
295
(ess-setq-vars-local R-customize-alist) ;same functionality is availabe as in R buffers
296
(use-local-map Rd-mode-map)
297
(setq mode-name "Rd")
298
(setq major-mode 'Rd-mode)
299
(setq local-abbrev-table Rd-mode-abbrev-table)
300
(set-syntax-table Rd-mode-syntax-table)
301
302
(set (make-local-variable 'indent-line-function) 'Rd-mode-indent-line)
303
(set (make-local-variable 'fill-column) 72)
304
(set (make-local-variable 'comment-start-skip) "\\s<+\\s-*")
305
(set (make-local-variable 'comment-start) "% ")
306
(set (make-local-variable 'comment-end) "")
307
(set (make-local-variable 'font-lock-defaults)
308
'(Rd-font-lock-keywords nil nil))
309
;; (set (make-local-variable 'parse-sexp-ignore-comments) t)
310
311
(require 'easymenu)
312
(easy-menu-define Rd-mode-menu-map Rd-mode-map
313
"Menu keymap for Rd mode." Rd-mode-menu)
314
(easy-menu-add Rd-mode-menu-map Rd-mode-map)
315
316
(turn-on-auto-fill)
317
(message "Rd mode version %s" essddr-version)
318
(setq ess-language "S" ess-dialect "R"); (buffer local)
319
(run-hooks 'Rd-mode-hook))
320
321
;; FIXME: The following should be moved to ess-utils.el, no? (MM thinks)
322
(defun ess-point (position)
323
"Returns the value of point at certain positions."
324
(save-excursion
325
(cond
326
((eq position 'bol) (beginning-of-line))
327
((eq position 'eol) (end-of-line))
328
((eq position 'boi) (back-to-indentation))
329
((eq position 'bonl) (forward-line 1))
330
((eq position 'bopl) (forward-line -1))
331
(t (error "unknown buffer position requested: %s" position)))
332
(point)))
333
334
(defun Rd-describe-major-mode ()
335
"Describe the current major mode."
336
(interactive)
337
(describe-function major-mode))
338
339
(defun Rd-mode-in-verbatim-p ()
340
(let ((pos (point)))
341
(save-excursion
342
(if (and (re-search-backward
343
"\\\\\\(usage\\|examples\\|synopsis\\)" nil t)
344
(re-search-forward "\\s(" nil t))
345
(condition-case ()
346
(progn
347
(up-list 1)
348
(< pos (point)))
349
(error t))
350
nil))))
351
352
(defun Rd-mode-in-preprocessor-line-p ()
353
(save-excursion
354
(beginning-of-line)
355
(looking-at "[ \t]*#\\(ifdef\\|endif\\)")))
356
357
(defun Rd-mode-calculate-indent ()
358
"Return appropriate indentation for current line in Rd mode."
359
(interactive)
360
(save-excursion
361
(beginning-of-line)
362
(cond
363
((Rd-mode-in-verbatim-p)
364
;; Don't do anything in verbatims
365
nil)
366
((Rd-mode-in-preprocessor-line-p)
367
;; Indent to 0
368
0)
369
(t
370
(let ((p (progn
371
(re-search-forward "[ \t]*\\s)*" (ess-point 'eol) t)
372
(point))))
373
(if (or (< (forward-line -1) 0)
374
(Rd-mode-in-verbatim-p))
375
0
376
(set-syntax-table Rd-mode-parse-syntax-table)
377
(while (and (or (looking-at "[ \t]*$")
378
(Rd-mode-in-preprocessor-line-p))
379
(not (bobp)))
380
(forward-line -1))
381
(re-search-forward "[ \t]*\\s)*" (ess-point 'eol) t)
382
(prog1
383
(+ (current-indentation)
384
(* (car (parse-partial-sexp (point) p))
385
Rd-indent-level))
386
(set-syntax-table Rd-mode-syntax-table))))))))
387
388
(defun Rd-mode-indent-line ()
389
"Indent current line as Rd source."
390
(interactive)
391
(let ((ic (Rd-mode-calculate-indent))
392
(rp (- (current-column) (current-indentation))))
393
(if ic ; Not inside a verbatim
394
(if (< ic 0)
395
(error "Unmatched parenthesis")
396
(indent-line-to ic)
397
(if (> rp 0)
398
(move-to-column (+ ic rp)))))))
399
400
(defun Rd-mode-insert-item ()
401
(interactive)
402
(reindent-then-newline-and-indent)
403
(insert "\\item{")
404
)
405
406
(defun Rd-mode-insert-section ()
407
(interactive)
408
(let ((s (ess-completing-read
409
"Insert section: "
410
(mapcar (lambda (x) (cons x x)) Rd-section-names)
411
nil t)))
412
(if (string= s "")
413
(progn (insert "\\section{}{") (backward-char 2))
414
(insert (format "\\%s{" s)))))
415
416
(defun Rd-mode-insert-skeleton ()
417
(interactive)
418
;; Hmm: in theory this should be kept in sync with prompt()
419
;; --- maybe using prompt() [or promptClass()...] would be better anyway?!
420
(insert "\\name{}\n")
421
(insert "\\alias{}\n")
422
(insert "\\title{}\n")
423
(insert "\\description{\n}\n")
424
(insert "\\usage{\n}\n")
425
(insert "\\arguments{\n}\n")
426
(insert "\\value{\n}\n")
427
(insert "\\details{\n}\n")
428
(insert "\\references{\n}\n")
429
(insert "\\seealso{\n}\n")
430
(insert "\\examples{\n}\n")
431
(insert "\\author{}\n")
432
(insert "\\keyword{}\n"))
433
434
;; This is an `easy' version of (defun TeX-font ..) in AUCtex's tex.el ;
435
;; see TeX-font-list and also LaTeX-font-list in latex.el
436
437
(defun Rd-font (what)
438
"Insert template for font command.
439
WHAT determines the font to use, as specified by `Rd-font-list'."
440
(interactive "c")
441
;;TeX had : (Rd-update-style)
442
(let* ((entry (assoc what Rd-font-list))
443
(before (nth 1 entry))
444
(after (nth 2 entry)))
445
(cond ((null entry) ;; help on possibilities :
446
(let ((help
447
(concat
448
"Rd Markup (available from C-c C-f):\n\n\t"
449
"KEY Rd-Markup\n\n"
450
(mapconcat
451
(lambda (entry)
452
;; A textual description of an ENTRY in TeX-font-list.
453
(concat (format "%11s "
454
(key-description
455
(char-to-string (nth 0 entry))))
456
(format "%14s %-3s"
457
(nth 1 entry) (nth 2 entry))))
458
Rd-font-list "\n"))))
459
(with-output-to-temp-buffer "*Help*"
460
(set-buffer "*Help*")
461
(insert help))))
462
463
((Rd-active-mark)
464
(save-excursion
465
(cond ((> (mark) (point))
466
(insert before)
467
(goto-char (mark))
468
(insert after))
469
(t
470
(insert after)
471
(goto-char (mark))
472
(insert before)))))
473
(t
474
(insert before)
475
(save-excursion
476
(insert after))))))
477
478
(defun Rd-preview-help ()
479
"Preview the current buffer contents using `Rd-to-help-command'.
480
If the current buffer is not associated with a file, create a
481
temporary one in `temporary-file-directory'.
482
"
483
(interactive)
484
(require 'ess-help)
485
(let ((file buffer-file-name)
486
(pbuf (get-buffer-create "R Help Preview"))
487
del-p shcmd)
488
(unless file
489
(setq file (make-temp-file "RD_" nil ".Rd"))
490
(write-region (point-min) (point-max) file)
491
(setq del-p t))
492
(setq shcmd (format "%s '%s'" Rd-to-help-command file))
493
(set-buffer pbuf)
494
(erase-buffer)
495
(ess-write-to-dribble-buffer
496
(format "Rd-preview-help: (shell-command |%s| t)" shcmd))
497
(shell-command shcmd t)
498
(ess-setq-vars-local R-customize-alist)
499
(setq ess-help-sec-regex ess-help-R-sec-regex
500
ess-help-sec-keys-alist ess-help-R-sec-keys-alist)
501
(ess-nuke-help-bs)
502
(ess-help-mode)
503
(when del-p (delete-file file))
504
(unless (get-buffer-window pbuf 'visible)
505
(display-buffer pbuf t))))
506
507
;; Bug reporting
508
(defun Rd-submit-bug-report ()
509
"Submit a bug report on Rd mode via mail."
510
(interactive)
511
(require 'reporter)
512
(and
513
(y-or-n-p "Do you want to submit a bug report? ")
514
(reporter-submit-bug-report
515
essddr-maintainer-address
516
(concat "Emacs version " emacs-version)
517
(list
518
'essddr-version
519
'Rd-indent-level))))
520
521
522
;; Provide ourself
523
(provide 'essddr)
524
525
;; ess-rd.el ends here
526
527