1
;; essddr.el --- Support for editing R documentation (Rd) source
3
;; Copyright (C) 1997--2005 A.J. Rossini, Rich M. Heiberger, Martin
4
;; Maechler, Kurt Hornik, Rodney Sparapani, and Stephen Eglen.
6
;; Original Author: KH <Kurt.Hornik@ci.tuwien.ac.at>
7
;; Created: 25 July 1997
8
;; Maintainers: ESS-core <ESS-core@stat.math.ethz.ch>
10
;; This file is part of ESS (Emacs Speaks Statistics).
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
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
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.
29
;; To stave off byte compiler errors
30
(eval-when-compile (require 'ess-help))
32
(defvar essddr-version "0.9-1"
33
"Current version of essddr.el.")
35
(defvar essddr-maintainer-address
36
"Kurt Hornik <Kurt.Hornik@R-project.org>"
37
"Current maintainer of essddr.el.")
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)))
45
;; else: special support for GNU Emacs
46
(defun Rd-active-mark ()
47
(and transient-mark-mode mark-active))
51
(autoload 'ess-eval-region "ess-inf" "[autoload]" t)
52
(autoload 'ess-eval-line-and-step "ess-inf" "[autoload]" t)
53
(autoload 'ess-switch-process "ess-inf" "[autoload]" t)
54
(autoload 'ess-switch-to-ESS "ess-inf" "[autoload]" t)
55
(autoload 'ess-switch-to-end-of-ESS "ess-inf" "[autoload]" t)
57
(autoload 'ess-help-mode "ess-help" "[autoload]" t)
58
(autoload 'ess-nuke-help-bs "ess-help" "[autoload]" t)
60
(defvar Rd-mode-abbrev-table nil
61
"Abbrev table for R documentation keywords.
62
All Rd mode abbrevs start with a grave accent (`).")
63
(if Rd-mode-abbrev-table
65
(define-abbrev-table 'Rd-mode-abbrev-table ())
66
(define-abbrev Rd-mode-abbrev-table "`ag" "\\arguments")
67
(define-abbrev Rd-mode-abbrev-table "`al" "\\alias")
68
(define-abbrev Rd-mode-abbrev-table "`au" "\\author")
69
(define-abbrev Rd-mode-abbrev-table "`bf" "\\bold")
70
(define-abbrev Rd-mode-abbrev-table "`co" "\\code")
71
(define-abbrev Rd-mode-abbrev-table "`de" "\\describe")
72
(define-abbrev Rd-mode-abbrev-table "`dn" "\\description")
73
(define-abbrev Rd-mode-abbrev-table "`dt" "\\details")
74
(define-abbrev Rd-mode-abbrev-table "`em" "\\emph")
75
(define-abbrev Rd-mode-abbrev-table "`en" "\\enumerate")
76
(define-abbrev Rd-mode-abbrev-table "`ex" "\\examples")
77
(define-abbrev Rd-mode-abbrev-table "`fi" "\\file")
78
(define-abbrev Rd-mode-abbrev-table "`fo" "\\format")
79
(define-abbrev Rd-mode-abbrev-table "`it" "\\item")
80
(define-abbrev Rd-mode-abbrev-table "`iz" "\\itemize")
81
(define-abbrev Rd-mode-abbrev-table "`kw" "\\keyword")
82
(define-abbrev Rd-mode-abbrev-table "`li" "\\link")
83
(define-abbrev Rd-mode-abbrev-table "`me" "\\method")
84
(define-abbrev Rd-mode-abbrev-table "`na" "\\name")
85
(define-abbrev Rd-mode-abbrev-table "`no" "\\note")
86
(define-abbrev Rd-mode-abbrev-table "`re" "\\references")
87
(define-abbrev Rd-mode-abbrev-table "`sa" "\\seealso")
88
(define-abbrev Rd-mode-abbrev-table "`se" "\\section")
89
(define-abbrev Rd-mode-abbrev-table "`so" "\\source")
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"))
96
(defvar Rd-mode-syntax-table nil
97
"Syntax table for Rd mode.")
98
(if Rd-mode-syntax-table
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)
115
(modify-syntax-entry ?\% "<" Rd-mode-syntax-table)
116
(modify-syntax-entry ?\n ">" Rd-mode-syntax-table))
118
(defvar Rd-mode-parse-syntax-table nil
119
"Syntax table for parsing Rd mode.")
120
(if Rd-mode-parse-syntax-table
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
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))
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" "synopsis" "tabular" "title" "usage"
140
;; the next two lines: only valid in R <= 2.8.1
141
"Alpha" "Gamma" "alpha" "beta" "epsilon" "lambda" "mu" "pi" "sigma"
142
"ge" "le" "left" "right"
144
"R" "S3method" "S4method" "acronym"
145
"bold" "cite" "code" "command" "cr" "dQuote" "deqn" "dfn" "dontrun"
146
"dontshow" "dots" "email" "emph" "env" "eqn" "file"
147
"item" "kbd" "ldots" "linkS4class" "link" "method"
148
"option" "pkg" "sQuote" "samp" "strong" "tab" "url" "var" ;;maybe? "verb"
151
;; Need to fix Rd-bold-face problem.
153
;; (defvar Rd-bold-face 'bold)
154
;(defvar Rd-bold-face nil)
155
;(make-face Rd-bold-face "R documentation bold face")
156
;(make-face-bold Rd-bold-face
158
(defvar Rd-font-lock-keywords
162
(mapconcat 'identity Rd-section-names "\\|")
164
'font-lock-reference-face) ; Rd-bold-face
167
(mapconcat 'identity Rd-keywords "\\|")
169
'font-lock-keyword-face)
170
'("^#\\(ifn?def\\)\\s-+\\(\\sw+\\)"
171
(1 font-lock-builtin-face)
172
(2 font-lock-variable-name-face nil t))
173
'("^#\\(endif\\)" 1 font-lock-builtin-face))
174
"Additional Rd expressions to highlight.")
176
(defvar Rd-indent-level 2
177
"*Indentation of Rd code with respect to containing blocks.")
179
(defvar Rd-mode-map nil
180
"Keymap used in Rd mode.")
183
(let ((map (make-sparse-keymap)))
184
(define-key map "\t" 'indent-according-to-mode)
185
(define-key map "\C-j" 'reindent-then-newline-and-indent)
186
(define-key map "\C-m" 'reindent-then-newline-and-indent)
187
(define-key map "\C-c\C-p" 'Rd-preview-help)
188
(define-key map "\C-c\C-j" 'Rd-mode-insert-item)
189
(define-key map "\C-c\C-e" 'Rd-mode-insert-skeleton)
190
(define-key map "\C-c\C-f" 'Rd-font)
191
;; ^C^F ^E : \emph{ . }
192
;; ^C^F ^C : \code{ . }
193
;; ^C^F ^L : \link{ . }
194
;; ^C^F L : \code{\link{ . }} etc
195
(define-key map "\C-c\C-s" 'Rd-mode-insert-section)
196
(define-key map "\C-c\C-n" 'ess-eval-line-and-step)
197
(define-key map "\C-c\C-r" 'ess-eval-region)
198
(define-key map "\C-c\C-c" 'ess-eval-function-or-paragraph-and-step)
199
(define-key map "\C-c\C-v" 'ess-display-help-on-object)
200
(define-key map "\C-c\C-w" 'ess-switch-process); is on C-c C-s in ess-mode..
201
(define-key map "\C-c\C-y" 'ess-switch-to-ESS)
202
(define-key map "\C-c\C-z" 'ess-switch-to-end-of-ESS)
203
(setq Rd-mode-map map)))
207
["Markup [word]" Rd-font t]
208
["Insert Item" Rd-mode-insert-item t]
209
["Insert Section" Rd-mode-insert-section t]
210
["Insert Skeleton" Rd-mode-insert-skeleton t]
212
["Preview" Rd-preview-help t]
214
["Eval Line" ess-eval-line-and-step t]
215
["Eval Region" ess-eval-region t]
216
["Switch to ESS Process" ess-switch-to-ESS t]
217
["Switch the ESS Process" ess-switch-process t]
218
["Switch to end{ESS Pr}" ess-switch-to-end-of-ESS t]
220
["Toggle Abbrev Mode" abbrev-mode t]
221
["Toggle Auto-Fill Mode" auto-fill-mode t]
223
["Submit Bug Report" Rd-submit-bug-report t]
225
["Describe Rd Mode" Rd-describe-major-mode t])
226
"Menu used in Rd mode.")
228
(defvar Rd-mode-hook nil
229
"*Hook to be run when Rd mode is entered.")
231
(defvar Rd-to-help-command "R CMD Rd2txt"
232
"*Shell command for converting R documentation source to help text.")
236
'((?\C-b "\\bold{" "}")
237
(?\C-c "\\code{" "}")
238
(?\C-e "\\emph{" "}")
239
(?\C-l "\\link{" "}")
240
(?l "\\code{\\link{" "}}")
241
(?\C-m "\\email{" "}")
245
"List of ``fonts'' used by Rd-font.
247
Each entry is a list.
248
The first element is the key to activate the font.
249
The second element is the string to insert before point, and the third
250
element is the string to insert after point."
256
"Major mode for editing R documentation source files.
258
This mode makes it easier to write R documentation by helping with
259
indentation, doing some of the typing for you (with Abbrev mode) and by
260
showing keywords, strings, etc. in different faces (with Font Lock mode
261
on terminals that support it).
263
Type \\[list-abbrevs] to display the built-in abbrevs for Rd keywords.
270
Variables you can use to customize Rd mode
271
==========================================
274
Indentation of Rd code with respect to containing blocks.
277
Turning on Rd mode runs the hook `Rd-mode-hook'.
279
To automatically turn on the abbrev and font-lock features, add the
280
following lines to your `.emacs' file:
282
(add-hook 'Rd-mode-hook
285
(if (eq window-system 'x)
286
(font-lock-mode 1))))"
290
(kill-all-local-variables)
291
(use-local-map Rd-mode-map)
292
(setq mode-name "Rd")
293
(setq major-mode 'Rd-mode)
294
(setq local-abbrev-table Rd-mode-abbrev-table)
295
(set-syntax-table Rd-mode-syntax-table)
297
(set (make-local-variable 'indent-line-function) 'Rd-mode-indent-line)
298
(set (make-local-variable 'fill-column) 72)
299
(set (make-local-variable 'comment-start-skip) "\\s<+\\s-*")
300
(set (make-local-variable 'comment-start) "% ")
301
(set (make-local-variable 'comment-end) "")
302
(set (make-local-variable 'font-lock-defaults)
303
'(Rd-font-lock-keywords nil nil))
304
;; (set (make-local-variable 'parse-sexp-ignore-comments) t)
307
(easy-menu-define Rd-mode-menu-map Rd-mode-map
308
"Menu keymap for Rd mode." Rd-mode-menu)
309
(easy-menu-add Rd-mode-menu-map Rd-mode-map)
312
(message "Rd mode version %s" essddr-version)
313
(run-hooks 'Rd-mode-hook))
315
;; FIXME: The following should be moved to ess-utils.el, no? (MM thinks)
316
(defun ess-point (position)
317
"Returns the value of point at certain positions."
320
((eq position 'bol) (beginning-of-line))
321
((eq position 'eol) (end-of-line))
322
((eq position 'boi) (back-to-indentation))
323
((eq position 'bonl) (forward-line 1))
324
((eq position 'bopl) (forward-line -1))
325
(t (error "unknown buffer position requested: %s" position)))
328
(defun Rd-describe-major-mode ()
329
"Describe the current major mode."
331
(describe-function major-mode))
333
(defun Rd-mode-in-verbatim-p ()
336
(if (and (re-search-backward
337
"\\\\\\(usage\\|examples\\|synopsis\\)" nil t)
338
(re-search-forward "\\s(" nil t))
346
(defun Rd-mode-in-preprocessor-line-p ()
349
(looking-at "[ \t]*#\\(ifdef\\|endif\\)")))
351
(defun Rd-mode-calculate-indent ()
352
"Return appropriate indentation for current line in Rd mode."
357
((Rd-mode-in-verbatim-p)
358
;; Don't do anything in verbatims
360
((Rd-mode-in-preprocessor-line-p)
365
(re-search-forward "[ \t]*\\s)*" (ess-point 'eol) t)
367
(if (or (< (forward-line -1) 0)
368
(Rd-mode-in-verbatim-p))
370
(set-syntax-table Rd-mode-parse-syntax-table)
371
(while (and (or (looking-at "[ \t]*$")
372
(Rd-mode-in-preprocessor-line-p))
375
(re-search-forward "[ \t]*\\s)*" (ess-point 'eol) t)
377
(+ (current-indentation)
378
(* (car (parse-partial-sexp (point) p))
380
(set-syntax-table Rd-mode-syntax-table))))))))
382
(defun Rd-mode-indent-line ()
383
"Indent current line as Rd source."
385
(let ((ic (Rd-mode-calculate-indent))
386
(rp (- (current-column) (current-indentation))))
387
(if ic ; Not inside a verbatim
389
(error "Unmatched parenthesis")
392
(move-to-column (+ ic rp)))))))
394
(defun Rd-mode-insert-item ()
396
(reindent-then-newline-and-indent)
400
(defun Rd-mode-insert-section ()
402
(let ((s (completing-read
404
(mapcar '(lambda (x) (cons x x)) Rd-section-names)
407
(progn (insert "\\section{}{") (backward-char 2))
408
(insert (format "\\%s{" s)))))
410
(defun Rd-mode-insert-skeleton ()
412
;; Hmm: in theory this should be kept in sync with prompt()
413
;; --- maybe using prompt() [or promptClass()...] would be better anyway?!
414
(insert "\\name{}\n")
415
(insert "\\alias{}\n")
416
(insert "\\title{}\n")
417
(insert "\\description{\n}\n")
418
(insert "\\usage{\n}\n")
419
(insert "\\arguments{\n}\n")
420
(insert "\\value{\n}\n")
421
(insert "\\details{\n}\n")
422
(insert "\\references{\n}\n")
423
(insert "\\seealso{\n}\n")
424
(insert "\\examples{\n}\n")
425
(insert "\\author{}\n")
426
(insert "\\keyword{}\n"))
428
;; This is an `easy' version of (defun TeX-font ..) in AUCtex's tex.el ;
429
;; see TeX-font-list and also LaTeX-font-list in latex.el
431
(defun Rd-font (what)
432
"Insert template for font command.
433
WHAT determines the font to use, as specified by `Rd-font-list'."
435
;;TeX had : (Rd-update-style)
436
(let* ((entry (assoc what Rd-font-list))
437
(before (nth 1 entry))
438
(after (nth 2 entry)))
439
(cond ((null entry) ;; help on possibilities :
442
"Rd Markup (available from C-c C-f):\n\n\t"
446
;; A textual description of an ENTRY in TeX-font-list.
447
(concat (format "%11s "
449
(char-to-string (nth 0 entry))))
451
(nth 1 entry) (nth 2 entry))))
452
Rd-font-list "\n"))))
453
(with-output-to-temp-buffer "*Help*"
454
(set-buffer "*Help*")
459
(cond ((> (mark) (point))
473
(defun Rd-preview-help ()
476
(let ((sbuf buffer-file-name)
477
(pbuf (get-buffer-create "R Help Preview")))
480
(shell-command (format "%s %s" Rd-to-help-command sbuf) t)
483
(if (not (get-buffer-window pbuf 'visible))
484
(display-buffer pbuf t))))
487
(defun Rd-submit-bug-report ()
488
"Submit a bug report on Rd mode via mail."
492
(y-or-n-p "Do you want to submit a bug report? ")
493
(reporter-submit-bug-report
494
essddr-maintainer-address
495
(concat "Emacs version " emacs-version)
503
;; essddr.el ends here