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 '("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"
139 '("Alpha" "Gamma" "R" "S3method" "S4method" "acronym" "alpha" "beta"
140 "bold" "cite" "code" "command" "cr" "dQuote" "deqn" "dfn" "dontrun"
141 "dontshow" "dots" "email" "emph" "env" "epsilon" "eqn" "file" "ge"
142 "item" "kbd" "lambda" "ldots" "le" "left" "linkS4class" "link" "method" "mu"
143 "option" "pi" "pkg" "right" "sQuote" "samp" "sigma" "strong" "tab"
146 ;; Need to fix Rd-bold-face problem.
148 ;; (defvar Rd-bold-face 'bold)
149 ;(defvar Rd-bold-face nil)
150 ;(make-face Rd-bold-face "R documentation bold face")
151 ;(make-face-bold Rd-bold-face
153 (defvar Rd-font-lock-keywords
157 (mapconcat 'identity Rd-section-names
"\\|")
159 'font-lock-reference-face
) ; Rd-bold-face
162 (mapconcat 'identity Rd-keywords
"\\|")
164 'font-lock-keyword-face
)
165 '("^#\\(ifn?def\\)\\s-+\\(\\sw+\\)"
166 (1 font-lock-builtin-face
)
167 (2 font-lock-variable-name-face nil t
))
168 '("^#\\(endif\\)" 1 font-lock-builtin-face
))
169 "Additional Rd expressions to highlight.")
171 (defvar Rd-indent-level
2
172 "*Indentation of Rd code with respect to containing blocks.")
174 (defvar Rd-mode-map nil
175 "Keymap used in Rd mode.")
178 (let ((map (make-sparse-keymap)))
179 (define-key map
"\t" 'indent-according-to-mode
)
180 (define-key map
"\C-j" 'reindent-then-newline-and-indent
)
181 (define-key map
"\C-m" 'reindent-then-newline-and-indent
)
182 (define-key map
"\C-c\C-p" 'Rd-preview-help
)
183 (define-key map
"\C-c\C-j" 'Rd-mode-insert-item
)
184 (define-key map
"\C-c\C-e" 'Rd-mode-insert-skeleton
)
185 (define-key map
"\C-c\C-f" 'Rd-font
)
186 ;; ^C^F ^E : \emph{ . }
187 ;; ^C^F ^C : \code{ . }
188 ;; ^C^F ^L : \link{ . }
189 ;; ^C^F L : \code{\link{ . }} etc
190 (define-key map
"\C-c\C-s" 'Rd-mode-insert-section
)
191 (define-key map
"\C-c\C-n" 'ess-eval-line-and-step
)
192 (define-key map
"\C-c\C-r" 'ess-eval-region
)
193 (define-key map
"\C-c\C-c" 'ess-eval-function-or-paragraph-and-step
)
194 (define-key map
"\C-c\C-v" 'ess-display-help-on-object
)
195 (define-key map
"\C-c\C-w" 'ess-switch-process
); is on C-c C-s in ess-mode..
196 (define-key map
"\C-c\C-y" 'ess-switch-to-ESS
)
197 (define-key map
"\C-c\C-z" 'ess-switch-to-end-of-ESS
)
198 (setq Rd-mode-map map
)))
202 ["Markup [word]" Rd-font t
]
203 ["Insert Item" Rd-mode-insert-item t
]
204 ["Insert Section" Rd-mode-insert-section t
]
205 ["Insert Skeleton" Rd-mode-insert-skeleton t
]
207 ["Preview" Rd-preview-help t
]
209 ["Eval Line" ess-eval-line-and-step t
]
210 ["Eval Region" ess-eval-region t
]
211 ["Switch to ESS Process" ess-switch-to-ESS t
]
212 ["Switch the ESS Process" ess-switch-process t
]
213 ["Switch to end{ESS Pr}" ess-switch-to-end-of-ESS t
]
215 ["Toggle Abbrev Mode" abbrev-mode t
]
216 ["Toggle Auto-Fill Mode" auto-fill-mode t
]
218 ["Submit Bug Report" Rd-submit-bug-report t
]
220 ["Describe Rd Mode" Rd-describe-major-mode t
])
221 "Menu used in Rd mode.")
223 (defvar Rd-mode-hook nil
224 "*Hook to be run when Rd mode is entered.")
226 (defvar Rd-to-help-command
"R CMD Rd2txt"
227 "*Shell command for converting R documentation source to help text.")
231 '((?\C-b
"\\bold{" "}")
232 (?\C-c
"\\code{" "}")
233 (?\C-e
"\\emph{" "}")
234 (?\C-l
"\\link{" "}")
235 (?l
"\\code{\\link{" "}}")
236 (?\C-m
"\\email{" "}")
240 "List of ``fonts'' used by Rd-font.
242 Each entry is a list.
243 The first element is the key to activate the font.
244 The second element is the string to insert before point, and the third
245 element is the string to insert after point."
251 "Major mode for editing R documentation source files.
253 This mode makes it easier to write R documentation by helping with
254 indentation, doing some of the typing for you (with Abbrev mode) and by
255 showing keywords, strings, etc. in different faces (with Font Lock mode
256 on terminals that support it).
258 Type \\[list-abbrevs] to display the built-in abbrevs for Rd keywords.
265 Variables you can use to customize Rd mode
266 ==========================================
269 Indentation of Rd code with respect to containing blocks.
272 Turning on Rd mode runs the hook `Rd-mode-hook'.
274 To automatically turn on the abbrev and font-lock features, add the
275 following lines to your `.emacs' file:
277 (add-hook 'Rd-mode-hook
280 (if (eq window-system 'x)
281 (font-lock-mode 1))))"
285 (kill-all-local-variables)
286 (use-local-map Rd-mode-map
)
287 (setq mode-name
"Rd")
288 (setq major-mode
'Rd-mode
)
289 (setq local-abbrev-table Rd-mode-abbrev-table
)
290 (set-syntax-table Rd-mode-syntax-table
)
292 (set (make-local-variable 'indent-line-function
) 'Rd-mode-indent-line
)
293 (set (make-local-variable 'fill-column
) 72)
294 (set (make-local-variable 'comment-start-skip
) "\\s<+\\s-*")
295 (set (make-local-variable 'comment-start
) "% ")
296 (set (make-local-variable 'comment-end
) "")
297 (set (make-local-variable 'font-lock-defaults
)
298 '(Rd-font-lock-keywords nil nil
))
299 ;; (set (make-local-variable 'parse-sexp-ignore-comments) t)
302 (easy-menu-define Rd-mode-menu-map Rd-mode-map
303 "Menu keymap for Rd mode." Rd-mode-menu
)
304 (easy-menu-add Rd-mode-menu-map Rd-mode-map
)
307 (message "Rd mode version %s" essddr-version
)
308 (run-hooks 'Rd-mode-hook
))
310 ;; FIXME: The following should be moved to ess-utils.el, no? (MM thinks)
311 (defun ess-point (position)
312 "Returns the value of point at certain positions."
315 ((eq position
'bol
) (beginning-of-line))
316 ((eq position
'eol
) (end-of-line))
317 ((eq position
'boi
) (back-to-indentation))
318 ((eq position
'bonl
) (forward-line 1))
319 ((eq position
'bopl
) (forward-line -
1))
320 (t (error "unknown buffer position requested: %s" position
)))
323 (defun Rd-describe-major-mode ()
324 "Describe the current major mode."
326 (describe-function major-mode
))
328 (defun Rd-mode-in-verbatim-p ()
331 (if (and (re-search-backward
332 "\\\\\\(usage\\|examples\\|synopsis\\)" nil t
)
333 (re-search-forward "\\s(" nil t
))
341 (defun Rd-mode-in-preprocessor-line-p ()
344 (looking-at "[ \t]*#\\(ifdef\\|endif\\)")))
346 (defun Rd-mode-calculate-indent ()
347 "Return appropriate indentation for current line in Rd mode."
352 ((Rd-mode-in-verbatim-p)
353 ;; Don't do anything in verbatims
355 ((Rd-mode-in-preprocessor-line-p)
360 (re-search-forward "[ \t]*\\s)*" (ess-point 'eol
) t
)
362 (if (or (< (forward-line -
1) 0)
363 (Rd-mode-in-verbatim-p))
365 (set-syntax-table Rd-mode-parse-syntax-table
)
366 (while (and (or (looking-at "[ \t]*$")
367 (Rd-mode-in-preprocessor-line-p))
370 (re-search-forward "[ \t]*\\s)*" (ess-point 'eol
) t
)
372 (+ (current-indentation)
373 (* (car (parse-partial-sexp (point) p
))
375 (set-syntax-table Rd-mode-syntax-table
))))))))
377 (defun Rd-mode-indent-line ()
378 "Indent current line as Rd source."
380 (let ((ic (Rd-mode-calculate-indent))
381 (rp (- (current-column) (current-indentation))))
382 (if ic
; Not inside a verbatim
384 (error "Unmatched parenthesis")
387 (move-to-column (+ ic rp
)))))))
389 (defun Rd-mode-insert-item ()
391 (reindent-then-newline-and-indent)
395 (defun Rd-mode-insert-section ()
397 (let ((s (completing-read
399 (mapcar '(lambda (x) (cons x x
)) Rd-section-names
)
402 (progn (insert "\\section{}{") (backward-char 2))
403 (insert (format "\\%s{" s
)))))
405 (defun Rd-mode-insert-skeleton ()
407 ;; Hmm: in theory this should be kept in sync with prompt()
408 ;; --- maybe using prompt() [or promptClass()...] would be better anyway?!
409 (insert "\\name{}\n")
410 (insert "\\alias{}\n")
411 (insert "\\title{}\n")
412 (insert "\\description{\n}\n")
413 (insert "\\usage{\n}\n")
414 (insert "\\arguments{\n}\n")
415 (insert "\\value{\n}\n")
416 (insert "\\details{\n}\n")
417 (insert "\\references{\n}\n")
418 (insert "\\seealso{\n}\n")
419 (insert "\\examples{\n}\n")
420 (insert "\\author{}\n")
421 (insert "\\keyword{}\n"))
423 ;; This is an `easy' version of (defun TeX-font ..) in AUCtex's tex.el ;
424 ;; see TeX-font-list and also LaTeX-font-list in latex.el
426 (defun Rd-font (what)
427 "Insert template for font command.
428 WHAT determines the font to use, as specified by `Rd-font-list'."
430 ;;TeX had : (Rd-update-style)
431 (let* ((entry (assoc what Rd-font-list
))
432 (before (nth 1 entry
))
433 (after (nth 2 entry
)))
434 (cond ((null entry
) ;; help on possibilities :
437 "Rd Markup (available from C-c C-f):\n\n\t"
441 ;; A textual description of an ENTRY in TeX-font-list.
442 (concat (format "%11s "
444 (char-to-string (nth 0 entry
))))
446 (nth 1 entry
) (nth 2 entry
))))
447 Rd-font-list
"\n"))))
448 (with-output-to-temp-buffer "*Help*"
449 (set-buffer "*Help*")
454 (cond ((> (mark) (point))
468 (defun Rd-preview-help ()
471 (let ((sbuf buffer-file-name
)
472 (pbuf (get-buffer-create "R Help Preview")))
475 (shell-command (format "%s %s" Rd-to-help-command sbuf
) t
)
478 (if (not (get-buffer-window pbuf
'visible
))
479 (display-buffer pbuf t
))))
482 (defun Rd-submit-bug-report ()
483 "Submit a bug report on Rd mode via mail."
487 (y-or-n-p "Do you want to submit a bug report? ")
488 (reporter-submit-bug-report
489 essddr-maintainer-address
490 (concat "Emacs version " emacs-version
)
498 ;; essddr.el ends here