Test for lazy-lock-mode before swapping hooks.
[bpt/emacs.git] / lisp / man.el
CommitLineData
effdc6a2 1;;; man.el --- browse UNIX manual pages
6594deb0 2
f5632218 3;; Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc.
9750e079 4
effdc6a2 5;; Author: Barry A. Warsaw <bwarsaw@cen.com>
effdc6a2 6;; Keywords: help
b3435a2f 7;; Adapted-By: ESR, pot
e5167999 8
1a20f48d
JA
9;; This file is part of GNU Emacs.
10
11;; GNU Emacs is free software; you can redistribute it and/or modify
12;; it under the terms of the GNU General Public License as published by
e5167999 13;; the Free Software Foundation; either version 2, or (at your option)
1a20f48d
JA
14;; any later version.
15
16;; GNU Emacs is distributed in the hope that it will be useful,
17;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19;; GNU General Public License for more details.
20
21;; You should have received a copy of the GNU General Public License
b578f267
EN
22;; along with GNU Emacs; see the file COPYING. If not, write to the
23;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24;; Boston, MA 02111-1307, USA.
1a20f48d 25
edbd2f74
ER
26;;; Commentary:
27
b3435a2f
FP
28;; This code provides a function, `man', with which you can browse
29;; UNIX manual pages. Formatting is done in background so that you
30;; can continue to use your Emacs while processing is going on.
effdc6a2
RS
31;;
32;; The mode also supports hypertext-like following of manual page SEE
33;; ALSO references, and other features. See below or do `?' in a
34;; manual page buffer for details.
35
36;; ========== Credits and History ==========
37;; In mid 1991, several people posted some interesting improvements to
38;; man.el from the standard emacs 18.57 distribution. I liked many of
a7acbbe4 39;; these, but wanted everything in one single package, so I decided
b3435a2f 40;; to incorporate them into a single manual browsing mode. While
effdc6a2
RS
41;; much of the code here has been rewritten, and some features added,
42;; these folks deserve lots of credit for providing the initial
43;; excellent packages on which this one is based.
44
45;; Nick Duffek <duffek@chaos.cs.brandeis.edu>, posted a very nice
46;; improvement which retrieved and cleaned the manpages in a
47;; background process, and which correctly deciphered such options as
48;; man -k.
49
50;; Eric Rose <erose@jessica.stanford.edu>, submitted manual.el which
51;; provided a very nice manual browsing mode.
52
eb8c3be9 53;; This package was available as `superman.el' from the LCD package
effdc6a2
RS
54;; for some time before it was accepted into Emacs 19. The entry
55;; point and some other names have been changed to make it a drop-in
56;; replacement for the old man.el package.
57
b3435a2f
FP
58;; Francesco Potorti` <pot@cnuce.cnr.it> cleaned it up thoroughly,
59;; making it faster, more robust and more tolerant of different
a7acbbe4 60;; systems' man idiosyncrasies.
b3435a2f 61
effdc6a2
RS
62;; ========== Features ==========
63;; + Runs "man" in the background and pipes the results through a
64;; series of sed and awk scripts so that all retrieving and cleaning
65;; is done in the background. The cleaning commands are configurable.
66;; + Syntax is the same as Un*x man
67;; + Functionality is the same as Un*x man, including "man -k" and
c3343fcf 68;; "man <section>", etc.
effdc6a2
RS
69;; + Provides a manual browsing mode with keybindings for traversing
70;; the sections of a manpage, following references in the SEE ALSO
71;; section, and more.
72;; + Multiple manpages created with the same man command are put into
73;; a narrowed buffer circular list.
edbd2f74 74
b3435a2f
FP
75;; ============= TODO ===========
76;; - Add a command for printing.
77;; - The awk script deletes multiple blank lines. This behaviour does
78;; not allow to understand if there was indeed a blank line at the
79;; end or beginning of a page (after the header, or before the
80;; footer). A different algorithm should be used. It is easy to
81;; compute how many blank lines there are before and after the page
82;; headers, and after the page footer. But it is possible to compute
83;; the number of blank lines before the page footer by euristhics
84;; only. Is it worth doing?
98fd7017
FP
85;; - Allow a user option to mean that all the manpages should go in
86;; the same buffer, where they can be browsed with M-n and M-p.
b3435a2f
FP
87;; - Allow completion on the manpage name when calling man. This
88;; requires a reliable list of places where manpages can be found. The
89;; drawback would be that if the list is not complete, the user might
90;; be led to believe that the manpages in the missing directories do
91;; not exist.
92
d0aede3f 93\f
e5167999
ER
94;;; Code:
95
effdc6a2 96(require 'assoc)
effdc6a2 97
d0aede3f
FP
98;; vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
99;; empty defvars (keep the compiler quiet)
100
101(defvar Man-notify)
102(defvar Man-current-page)
103(defvar Man-page-list)
58ffb6ae
RS
104(defvar Man-filter-list nil
105 "*Manpage cleaning filter command phrases.
106This variable contains a list of the following form:
107
108'((command-string phrase-string*)*)
109
110Each phrase-string is concatenated onto the command-string to form a
111command filter. The (standard) output (and standard error) of the Un*x
112man command is piped through each command filter in the order the
113commands appear in the association list. The final output is placed in
114the manpage buffer.")
115
d0aede3f
FP
116(defvar Man-original-frame)
117(defvar Man-arguments)
d0aede3f
FP
118(defvar Man-sections-alist)
119(defvar Man-refpages-alist)
58ffb6ae
RS
120(defvar Man-uses-untabify-flag t
121 "When non-nil use `untabify' instead of Man-untabify-command.")
d0aede3f 122(defvar Man-page-mode-string)
58ffb6ae
RS
123(defvar Man-sed-script nil
124 "Script for sed to nuke backspaces and ANSI codes from manpages.")
d0aede3f 125
effdc6a2
RS
126;; vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
127;; user variables
128
6e7e47f6
FP
129(defvar Man-fontify-manpage-flag t
130 "*Make up the manpage with fonts.")
131
132(defvar Man-overstrike-face 'bold
133 "*Face to use when fontifying overstrike.")
134
135(defvar Man-underline-face 'underline
b0d77652 136 "*Face to use when fontifying underlining.")
2788b7c9 137
b3435a2f 138;; Use the value of the obsolete user option Man-notify, if set.
799ac634 139(defvar Man-notify-method (if (boundp 'Man-notify) Man-notify 'friendly)
effdc6a2 140 "*Selects the behavior when manpage is ready.
b3435a2f
FP
141This variable may have one of the following values, where (sf) means
142that the frames are switched, so the manpage is displayed in the frame
143where the man command was called from:
effdc6a2 144
b51aeeff 145newframe -- put the manpage in its own frame (see `Man-frame-parameters')
b3435a2f
FP
146pushy -- make the manpage the current buffer in the current window
147bully -- make the manpage the current buffer and only window (sf)
148aggressive -- make the manpage the current buffer in the other window (sf)
149friendly -- display manpage in the other window but don't make current (sf)
150polite -- don't display manpage, but prints message and beep when ready
effdc6a2 151quiet -- like `polite', but don't beep
b3435a2f 152meek -- make no indication that the manpage is ready
effdc6a2 153
799ac634 154Any other value of `Man-notify-method' is equivalent to `meek'.")
effdc6a2 155
b51aeeff
RS
156(defvar Man-frame-parameters nil
157 "*Frame parameter list for creating a new frame for a manual page.")
158
b3435a2f 159(defvar Man-downcase-section-letters-flag t
effdc6a2
RS
160 "*Letters in sections are converted to lower case.
161Some Un*x man commands can't handle uppercase letters in sections, for
162example \"man 2V chmod\", but they are often displayed in the manpage
c3343fcf 163with the upper case letter. When this variable is t, the section
effdc6a2
RS
164letter (e.g., \"2V\") is converted to lowercase (e.g., \"2v\") before
165being sent to the man background process.")
166
b3435a2f 167(defvar Man-circular-pages-flag t
effdc6a2
RS
168 "*If t, the manpage list is treated as circular for traversal.")
169
effdc6a2 170(defvar Man-section-translations-alist
b3435a2f
FP
171 (list
172 '("3C++" . "3")
173 ;; Some systems have a real 3x man section, so let's comment this.
174 ;; '("3X" . "3") ; Xlib man pages
175 '("3X11" . "3")
176 '("1-UCB" . ""))
effdc6a2
RS
177 "*Association list of bogus sections to real section numbers.
178Some manpages (e.g. the Sun C++ 2.1 manpages) have section numbers in
c3343fcf 179their references which Un*x `man' does not recognize. This
eb8c3be9 180association list is used to translate those sections, when found, to
effdc6a2
RS
181the associated section number.")
182
6e7e47f6
FP
183(defvar manual-program "man"
184 "The name of the program that produces man pages.")
185
b3435a2f 186(defvar Man-untabify-command "pr"
6e7e47f6 187 "Command used for untabifying.")
b3435a2f
FP
188
189(defvar Man-untabify-command-args (list "-t" "-e")
6e7e47f6 190 "List of arguments to be passed to Man-untabify-command (which see).")
b3435a2f
FP
191
192(defvar Man-sed-command "sed"
6e7e47f6 193 "Command used for processing sed scripts.")
b3435a2f
FP
194
195(defvar Man-awk-command "awk"
6e7e47f6 196 "Command used for processing awk scripts.")
effdc6a2
RS
197
198(defvar Man-mode-line-format
199 '("" mode-line-modified
b3435a2f 200 mode-line-buffer-identification " "
effdc6a2 201 global-mode-string
056a5ef3 202 " " Man-page-mode-string
b3435a2f 203 " %[(" mode-name mode-line-process minor-mode-alist ")%]----"
effdc6a2 204 (-3 . "%p") "-%-")
6e7e47f6 205 "Mode line format for manual mode buffer.")
effdc6a2
RS
206
207(defvar Man-mode-map nil
6e7e47f6 208 "Keymap for Man mode.")
effdc6a2 209
e660d0db 210(defvar Man-mode-hook nil
6e7e47f6 211 "Hook run when Man mode is enabled.")
effdc6a2 212
c2d606f4 213(defvar Man-cooked-hook nil
6e7e47f6 214 "Hook run after removing backspaces but before Man-mode processing.")
b3435a2f
FP
215
216(defvar Man-name-regexp "[-a-zA-Z0-9_][-a-zA-Z0-9_.]*"
6e7e47f6 217 "Regular expression describing the name of a manpage (without section).")
c2d606f4 218
f5f76002 219(defvar Man-section-regexp "[0-9][a-zA-Z+]*\\|[LNln]"
6e7e47f6 220 "Regular expression describing a manpage section within parentheses.")
effdc6a2 221
b3435a2f
FP
222(defvar Man-page-header-regexp
223 (concat "^[ \t]*\\(" Man-name-regexp
224 "(\\(" Man-section-regexp "\\))\\).*\\1")
6e7e47f6 225 "Regular expression describing the heading of a page.")
b3435a2f
FP
226
227(defvar Man-heading-regexp "^\\([A-Z][A-Z ]+\\)$"
6e7e47f6 228 "Regular expression describing a manpage heading entry.")
effdc6a2
RS
229
230(defvar Man-see-also-regexp "SEE ALSO"
6e7e47f6 231 "Regular expression for SEE ALSO heading (or your equivalent).
effdc6a2
RS
232This regexp should not start with a `^' character.")
233
2cd4790e 234(defvar Man-first-heading-regexp "^[ \t]*NAME$\\|^[ \t]*No manual entry fo.*$"
6e7e47f6 235 "Regular expression describing first heading on a manpage.
effdc6a2
RS
236This regular expression should start with a `^' character.")
237
3eedeb85 238(defvar Man-reference-regexp
b3435a2f 239 (concat "\\(" Man-name-regexp "\\)(\\(" Man-section-regexp "\\))")
6e7e47f6 240 "Regular expression describing a reference in the SEE ALSO section.")
effdc6a2 241
733155db 242(defvar Man-switches ""
6e7e47f6 243 "Switches passed to the man command, as a single string.")
effdc6a2 244
e660d0db
RS
245(defvar Man-specified-section-option
246 (if (string-match "-solaris[0-9.]*$" system-configuration)
247 "-s"
248 "")
6e7e47f6 249 "Option that indicates a specified a manual section name.")
9de0760c 250
effdc6a2
RS
251;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
252;; end user variables
effdc6a2
RS
253\f
254;; other variables and keymap initializations
255(make-variable-buffer-local 'Man-sections-alist)
256(make-variable-buffer-local 'Man-refpages-alist)
257(make-variable-buffer-local 'Man-page-list)
258(make-variable-buffer-local 'Man-current-page)
259(make-variable-buffer-local 'Man-page-mode-string)
75db9a64 260(make-variable-buffer-local 'Man-original-frame)
b3435a2f 261(make-variable-buffer-local 'Man-arguments)
effdc6a2
RS
262
263(setq-default Man-sections-alist nil)
264(setq-default Man-refpages-alist nil)
265(setq-default Man-page-list nil)
266(setq-default Man-current-page 0)
b3435a2f 267(setq-default Man-page-mode-string "1 of 1")
effdc6a2 268
6e7e47f6
FP
269(defconst Man-sysv-sed-script "\
270/\b/ { s/_\b//g
271 s/\b_//g
272 s/o\b+/o/g
f90531cc 273 s/+\bo/o/g
6e7e47f6
FP
274 :ovstrk
275 s/\\(.\\)\b\\1/\\1/g
276 t ovstrk
277 }
278/\e\\[[0-9][0-9]*m/ s///g"
279 "Script for sysV-like sed to nuke backspaces and ANSI codes from manpages.")
280
281(defconst Man-berkeley-sed-script "\
282/\b/ { s/_\b//g\\
283 s/\b_//g\\
284 s/o\b+/o/g\\
f90531cc 285 s/+\bo/o/g\\
6e7e47f6
FP
286 :ovstrk\\
287 s/\\(.\\)\b\\1/\\1/g\\
288 t ovstrk\\
289 }\\
290/\e\\[[0-9][0-9]*m/ s///g"
291 "Script for berkeley-like sed to nuke backspaces and ANSI codes from manpages.")
292
effdc6a2
RS
293(if Man-mode-map
294 nil
295 (setq Man-mode-map (make-keymap))
296 (suppress-keymap Man-mode-map)
297 (define-key Man-mode-map " " 'scroll-up)
298 (define-key Man-mode-map "\177" 'scroll-down)
299 (define-key Man-mode-map "n" 'Man-next-section)
300 (define-key Man-mode-map "p" 'Man-previous-section)
301 (define-key Man-mode-map "\en" 'Man-next-manpage)
302 (define-key Man-mode-map "\ep" 'Man-previous-manpage)
b3435a2f
FP
303 (define-key Man-mode-map ">" 'end-of-buffer)
304 (define-key Man-mode-map "<" 'beginning-of-buffer)
305 (define-key Man-mode-map "." 'beginning-of-buffer)
effdc6a2 306 (define-key Man-mode-map "r" 'Man-follow-manual-reference)
effdc6a2
RS
307 (define-key Man-mode-map "g" 'Man-goto-section)
308 (define-key Man-mode-map "s" 'Man-goto-see-also-section)
b3435a2f 309 (define-key Man-mode-map "k" 'Man-kill)
effdc6a2 310 (define-key Man-mode-map "q" 'Man-quit)
b3435a2f 311 (define-key Man-mode-map "m" 'man)
effdc6a2
RS
312 (define-key Man-mode-map "?" 'describe-mode)
313 )
314
315\f
316;; ======================================================================
317;; utilities
318
58ffb6ae 319(defun Man-init-defvars ()
b3435a2f
FP
320 "Used for initialising variables based on the value of window-system.
321This is necessary if one wants to dump man.el with emacs."
322
b3435a2f
FP
323 ;; The following is necessary until fonts are implemented on
324 ;; terminals.
325 (setq Man-fontify-manpage-flag (and Man-fontify-manpage-flag
326 window-system))
327
58ffb6ae
RS
328 (setq Man-sed-script
329 (cond
330 (Man-fontify-manpage-flag
331 nil)
332 ((= 0 (call-process Man-sed-command nil nil nil Man-sysv-sed-script))
333 Man-sysv-sed-script)
334 ((= 0 (call-process Man-sed-command nil nil nil Man-berkeley-sed-script))
335 Man-berkeley-sed-script)
336 (t
337 nil)))
338
339 (setq Man-filter-list
340 (list
b3435a2f 341 (cons
58ffb6ae
RS
342 Man-sed-command
343 (list
344 (if Man-sed-script
345 (concat "-e '" Man-sed-script "'")
346 "")
347 "-e '/^[\001-\032][\001-\032]*$/d'"
348 "-e '/\e[789]/s///g'"
349 "-e '/Reformatting page. Wait/d'"
350 "-e '/Reformatting entry. Wait/d'"
351 "-e '/^[ \t]*Hewlett-Packard[ \t]Company[ \t]*-[ \t][0-9]*[ \t]-/d'"
352 "-e '/^[ \t]*Hewlett-Packard[ \t]*-[ \t][0-9]*[ \t]-.*$/d'"
353 "-e '/^[ \t][ \t]*-[ \t][0-9]*[ \t]-[ \t]*Formatted:.*[0-9]$/d'"
354 "-e '/^[ \t]*Page[ \t][0-9]*.*(printed[ \t][0-9\\/]*)$/d'"
355 "-e '/^Printed[ \t][0-9].*[0-9]$/d'"
356 "-e '/^[ \t]*X[ \t]Version[ \t]1[01].*Release[ \t][0-9]/d'"
357 "-e '/^[A-za-z].*Last[ \t]change:/d'"
358 "-e '/^Sun[ \t]Release[ \t][0-9].*[0-9]$/d'"
359 "-e '/[ \t]*Copyright [0-9]* UNIX System Laboratories, Inc.$/d'"
360 "-e '/^[ \t]*Rev\\..*Page [0-9][0-9]*$/d'"
361 ))
362 (cons
363 Man-awk-command
364 (list
365 "'\n"
366 "BEGIN { blankline=0; anonblank=0; }\n"
367 "/^$/ { if (anonblank==0) next; }\n"
368 "{ anonblank=1; }\n"
369 "/^$/ { blankline++; next; }\n"
370 "{ if (blankline>0) { print \"\"; blankline=0; } print $0; }\n"
371 "'"
372 ))
373 (if (not Man-uses-untabify-flag)
374 (cons
375 Man-untabify-command
376 Man-untabify-command-args)
377 )))
b3435a2f 378)
effdc6a2 379
d0aede3f
FP
380(defsubst Man-match-substring (&optional n string)
381 "Return the substring matched by the last search.
382Optional arg N means return the substring matched by the Nth paren
383grouping. Optional second arg STRING means return a substring from
384that string instead of from the current buffer."
385 (if (null n) (setq n 0))
386 (if string
387 (substring string (match-beginning n) (match-end n))
388 (buffer-substring (match-beginning n) (match-end n))))
389
b3435a2f
FP
390(defsubst Man-make-page-mode-string ()
391 "Formats part of the mode line for Man mode."
392 (format "%s page %d of %d"
393 (or (nth 2 (nth (1- Man-current-page) Man-page-list))
394 "")
395 Man-current-page
396 (length Man-page-list)))
397
398(defsubst Man-build-man-command ()
effdc6a2 399 "Builds the entire background manpage and cleaning command."
17077ab3 400 (let ((command (concat manual-program " " Man-switches " %s 2>/dev/null"))
effdc6a2 401 (flist Man-filter-list))
b3435a2f 402 (while (and flist (car flist))
effdc6a2 403 (let ((pcom (car (car flist)))
b3435a2f
FP
404 (pargs (cdr (car flist))))
405 (setq command
406 (concat command " | " pcom " "
407 (mapconcat '(lambda (phrase)
408 (if (not (stringp phrase))
409 (error "Malformed Man-filter-list"))
410 phrase)
411 pargs " ")))
412 (setq flist (cdr flist))))
effdc6a2
RS
413 command))
414
effdc6a2 415(defun Man-translate-references (ref)
b3435a2f
FP
416 "Translates REF from \"chmod(2V)\" to \"2v chmod\" style.
417Leave it as is if already in that style. Possibly downcase and
418translate the section (see the Man-downcase-section-letters-flag
2f2228c0 419and the Man-section-translations-alist variables)."
b3435a2f
FP
420 (let ((name "")
421 (section "")
422 (slist Man-section-translations-alist))
effdc6a2 423 (cond
b3435a2f 424 ;; "chmod(2V)" case ?
2f2228c0 425 ((string-match (concat "^" Man-reference-regexp "$") ref)
b3435a2f
FP
426 (setq name (Man-match-substring 1 ref)
427 section (Man-match-substring 2 ref)))
428 ;; "2v chmod" case ?
2f2228c0 429 ((string-match (concat "^\\(" Man-section-regexp
b3435a2f
FP
430 "\\) +\\(" Man-name-regexp "\\)$") ref)
431 (setq name (Man-match-substring 2 ref)
432 section (Man-match-substring 1 ref))))
433 (if (string= name "")
434 ref ; Return the reference as is
435 (if Man-downcase-section-letters-flag
436 (setq section (downcase section)))
437 (while slist
438 (let ((s1 (car (car slist)))
439 (s2 (cdr (car slist))))
440 (setq slist (cdr slist))
441 (if Man-downcase-section-letters-flag
442 (setq s1 (downcase s1)))
443 (if (not (string= s1 section)) nil
444 (setq section (if Man-downcase-section-letters-flag
445 (downcase s2)
446 s2)
447 slist nil))))
448 (concat Man-specified-section-option section " " name))))
449
effdc6a2
RS
450\f
451;; ======================================================================
b3435a2f 452;; default man entry: get word under point
effdc6a2 453
b3435a2f 454(defsubst Man-default-man-entry ()
effdc6a2
RS
455 "Make a guess at a default manual entry.
456This guess is based on the text surrounding the cursor, and the
c3343fcf 457default section number is selected from `Man-auto-section-alist'."
d902a611 458 (let (default-title)
1a20f48d 459 (save-excursion
effdc6a2 460
b3435a2f
FP
461 ;; Default man entry title is any word the cursor is on, or if
462 ;; cursor not on a word, then nearest preceding word. Cannot
463 ;; use the current-word function because it skips the dots.
464 (if (not (looking-at "[-a-zA-Z_.]"))
465 (skip-chars-backward "^a-zA-Z"))
466 (skip-chars-backward "-(a-zA-Z_0-9_.")
467 (if (looking-at "(") (forward-char 1))
effdc6a2
RS
468 (setq default-title
469 (buffer-substring
470 (point)
b3435a2f 471 (progn (skip-chars-forward "-a-zA-Z0-9_.") (point))))
effdc6a2 472
b3435a2f 473 ;; If looking at something like ioctl(2) or brc(1M), include the
c448c134
FP
474 ;; section number in the returned value. Remove text properties.
475 (let ((result (concat
476 default-title
477 (if (looking-at
478 (concat "[ \t]*([ \t]*\\("
479 Man-section-regexp "\\)[ \t]*)"))
480 (format "(%s)" (Man-match-substring 1))))))
481 (set-text-properties 0 (length result) nil result)
0006272a 482 result))))
b3435a2f 483
effdc6a2
RS
484\f
485;; ======================================================================
b3435a2f 486;; Top level command and background process sentinel
1a20f48d 487
b3435a2f 488;; For compatibility with older versions.
cac0b95d 489;;;###autoload
b3435a2f 490(defalias 'manual-entry 'man)
cac0b95d 491
effdc6a2 492;;;###autoload
98fd7017 493(defun man (man-args)
effdc6a2 494 "Get a Un*x manual page and put it in a buffer.
c3343fcf 495This command is the top-level command in the man package. It runs a Un*x
effdc6a2 496command to retrieve and clean a manpage in the background and places the
c3343fcf 497results in a Man mode (manpage browsing) buffer. See variable
799ac634 498`Man-notify-method' for what happens when the buffer is ready.
98fd7017 499If a buffer already exists for this man page, it will display immediately."
b3435a2f 500 (interactive
98fd7017
FP
501 (list (let* ((default-entry (Man-default-man-entry))
502 (input (read-string
503 (format "Manual entry%s: "
504 (if (string= default-entry "")
505 ""
506 (format " (default %s)" default-entry))))))
507 (if (string= input "")
508 (if (string= default-entry "")
509 (error "No man args given")
510 default-entry)
511 input))))
b3435a2f 512
b3435a2f
FP
513 ;; Possibly translate the "subject(section)" syntax into the
514 ;; "section subject" syntax and possibly downcase the section.
515 (setq man-args (Man-translate-references man-args))
516
98fd7017 517 (Man-getpage-in-background man-args))
b3435a2f 518
aa228418 519
98fd7017
FP
520(defun Man-getpage-in-background (topic)
521 "Uses TOPIC to build and fire off the manpage and cleaning command."
e660d0db 522 (let* ((man-args topic)
d0aede3f 523 (bufname (concat "*Man " man-args "*"))
effdc6a2 524 (buffer (get-buffer bufname)))
98fd7017 525 (if buffer
effdc6a2 526 (Man-notify-when-ready buffer)
eaf1946c 527 (require 'env)
b3435a2f 528 (message "Invoking %s %s in the background" manual-program man-args)
effdc6a2 529 (setq buffer (generate-new-buffer bufname))
75db9a64
KH
530 (save-excursion
531 (set-buffer buffer)
b3435a2f
FP
532 (setq Man-original-frame (selected-frame))
533 (setq Man-arguments man-args))
0322056b 534 (let ((process-environment (copy-sequence process-environment)))
82c9fe8e
RS
535 ;; Prevent any attempt to use display terminal fanciness.
536 (setenv "TERM" "dumb")
537 (set-process-sentinel
2788b7c9 538 (start-process manual-program buffer "sh" "-c"
13628415 539 (format (Man-build-man-command) man-args))
98fd7017 540 'Man-bgproc-sentinel)))))
effdc6a2
RS
541
542(defun Man-notify-when-ready (man-buffer)
543 "Notify the user when MAN-BUFFER is ready.
799ac634 544See the variable `Man-notify-method' for the different notification behaviors."
c9bf42f9
RS
545 (let ((saved-frame (save-excursion
546 (set-buffer man-buffer)
547 Man-original-frame)))
548 (cond
799ac634 549 ((eq Man-notify-method 'newframe)
b3435a2f
FP
550 ;; Since we run asynchronously, perhaps while Emacs is waiting
551 ;; for input, we must not leave a different buffer current. We
552 ;; can't rely on the editor command loop to reselect the
553 ;; selected window's buffer.
c9bf42f9
RS
554 (save-excursion
555 (set-buffer man-buffer)
556 (make-frame Man-frame-parameters)))
799ac634 557 ((eq Man-notify-method 'pushy)
b3435a2f 558 (switch-to-buffer man-buffer))
799ac634 559 ((eq Man-notify-method 'bully)
c9bf42f9
RS
560 (and window-system
561 (frame-live-p saved-frame)
562 (select-frame saved-frame))
563 (pop-to-buffer man-buffer)
564 (delete-other-windows))
799ac634 565 ((eq Man-notify-method 'aggressive)
c9bf42f9
RS
566 (and window-system
567 (frame-live-p saved-frame)
568 (select-frame saved-frame))
569 (pop-to-buffer man-buffer))
799ac634 570 ((eq Man-notify-method 'friendly)
c9bf42f9
RS
571 (and window-system
572 (frame-live-p saved-frame)
573 (select-frame saved-frame))
574 (display-buffer man-buffer 'not-this-window))
799ac634 575 ((eq Man-notify-method 'polite)
c9bf42f9 576 (beep)
b3435a2f 577 (message "Manual buffer %s is ready" (buffer-name man-buffer)))
799ac634 578 ((eq Man-notify-method 'quiet)
b3435a2f 579 (message "Manual buffer %s is ready" (buffer-name man-buffer)))
799ac634 580 ((or (eq Man-notify-method 'meek)
c9bf42f9
RS
581 t)
582 (message ""))
583 )))
effdc6a2 584
b3435a2f
FP
585(defun Man-fontify-manpage ()
586 "Convert overstriking and underlining to the correct fonts.
587Same for the ANSI bold and normal escape sequences."
588 (interactive)
589 (message "Please wait: making up the %s man page..." Man-arguments)
c3343fcf 590 (goto-char (point-min))
b3435a2f
FP
591 (while (search-forward "\e[1m" nil t)
592 (delete-backward-char 4)
593 (put-text-property (point)
594 (progn (if (search-forward "\e[0m" nil 'move)
595 (delete-backward-char 4))
596 (point))
6e7e47f6 597 'face Man-overstrike-face))
b3435a2f
FP
598 (goto-char (point-min))
599 (while (search-forward "_\b" nil t)
600 (backward-delete-char 2)
6e7e47f6 601 (put-text-property (point) (1+ (point)) 'face Man-underline-face))
b3435a2f
FP
602 (goto-char (point-min))
603 (while (search-forward "\b_" nil t)
604 (backward-delete-char 2)
6e7e47f6 605 (put-text-property (1- (point)) (point) 'face Man-underline-face))
b3435a2f 606 (goto-char (point-min))
6024daef
FP
607 (while (re-search-forward "\\(.\\)\\(\b\\1\\)+" nil t)
608 (replace-match "\\1")
6e7e47f6 609 (put-text-property (1- (point)) (point) 'face Man-overstrike-face))
6024daef 610 (goto-char (point-min))
f90531cc
FP
611 (while (re-search-forward "o\b\\+\\|\\+\bo" nil t)
612 (replace-match "o")
b3435a2f
FP
613 (put-text-property (1- (point)) (point) 'face 'bold))
614 (goto-char (point-min))
f7046d47 615 (while (re-search-forward "[-|]\\(\b[-|]\\)+" nil t)
6024daef 616 (replace-match "+")
b3435a2f 617 (put-text-property (1- (point)) (point) 'face 'bold))
86884919
RS
618 ;; \255 is some kind of dash in Latin-1.
619 (goto-char (point-min))
620 (while (search-forward "\255" nil t) (replace-match "-"))
b3435a2f
FP
621 (message "%s man page made up" Man-arguments))
622
623(defun Man-cleanup-manpage ()
624 "Remove overstriking and underlining from the current buffer."
625 (interactive)
f7046d47
FP
626 (message "Please wait: cleaning up the %s man page..."
627 Man-arguments)
9931e1ba 628 (if (or (interactive-p) (not Man-sed-script))
f7046d47
FP
629 (progn
630 (goto-char (point-min))
631 (while (search-forward "_\b" nil t) (backward-delete-char 2))
632 (goto-char (point-min))
633 (while (search-forward "\b_" nil t) (backward-delete-char 2))
634 (goto-char (point-min))
635 (while (re-search-forward "\\(.\\)\\(\b\\1\\)+" nil t)
636 (replace-match "\\1"))
637 (goto-char (point-min))
638 (while (re-search-forward "\e\\[[0-9]+m" nil t) (replace-match ""))
639 (goto-char (point-min))
f90531cc 640 (while (re-search-forward "o\b\\+\\|\\+\bo" nil t) (replace-match "o"))
f7046d47 641 ))
6024daef 642 (goto-char (point-min))
f7046d47 643 (while (re-search-forward "[-|]\\(\b[-|]\\)+" nil t) (replace-match "+"))
86884919
RS
644 ;; \255 is some kind of dash in Latin-1.
645 (goto-char (point-min))
646 (while (search-forward "\255" nil t) (replace-match "-"))
b3435a2f 647 (message "%s man page cleaned up" Man-arguments))
c3343fcf 648
effdc6a2
RS
649(defun Man-bgproc-sentinel (process msg)
650 "Manpage background process sentinel."
651 (let ((Man-buffer (process-buffer process))
652 (delete-buff nil)
8c79b392 653 (err-mess nil))
b3435a2f 654
effdc6a2
RS
655 (if (null (buffer-name Man-buffer)) ;; deleted buffer
656 (set-process-buffer process nil)
b3435a2f
FP
657
658 (save-excursion
659 (set-buffer Man-buffer)
1d56cc39
RS
660 (let ((case-fold-search nil))
661 (goto-char (point-min))
662 (cond ((or (looking-at "No \\(manual \\)*entry for")
663 (looking-at "[^\n]*: nothing appropriate$"))
664 (setq err-mess (buffer-substring (point)
665 (progn
666 (end-of-line) (point)))
667 delete-buff t))
668 ((not (and (eq (process-status process) 'exit)
669 (= (process-exit-status process) 0)))
670 (setq err-mess
671 (concat (buffer-name Man-buffer)
672 ": process "
673 (let ((eos (1- (length msg))))
674 (if (= (aref msg eos) ?\n)
675 (substring msg 0 eos) msg))))
676 (goto-char (point-max))
677 (insert (format "\nprocess %s" msg))
678 ))
679 (if delete-buff
680 (kill-buffer Man-buffer)
681 (if Man-fontify-manpage-flag
682 (Man-fontify-manpage)
683 (Man-cleanup-manpage))
684 (run-hooks 'Man-cooked-hook)
685 (Man-mode)
686 (set-buffer-modified-p nil)
687 ))
688 ;; Restore case-fold-search before calling
689 ;; Man-notify-when-ready because it may switch buffers.
690
691 (if (not delete-buff)
692 (Man-notify-when-ready Man-buffer))
693
694 (if err-mess
695 (error err-mess))
696 ))))
effdc6a2
RS
697
698\f
699;; ======================================================================
700;; set up manual mode in buffer and build alists
701
702(defun Man-mode ()
c3343fcf 703 "A mode for browsing Un*x manual pages.
effdc6a2
RS
704
705The following man commands are available in the buffer. Try
706\"\\[describe-key] <key> RET\" for more information:
aa228418 707
b3435a2f 708\\[man] Prompt to retrieve a new manpage.
effdc6a2
RS
709\\[Man-follow-manual-reference] Retrieve reference in SEE ALSO section.
710\\[Man-next-manpage] Jump to next manpage in circular list.
711\\[Man-previous-manpage] Jump to previous manpage in circular list.
712\\[Man-next-section] Jump to next manpage section.
713\\[Man-previous-section] Jump to previous manpage section.
714\\[Man-goto-section] Go to a manpage section.
715\\[Man-goto-see-also-section] Jumps to the SEE ALSO manpage section.
b3435a2f
FP
716\\[Man-quit] Deletes the manpage window, bury its buffer.
717\\[Man-kill] Deletes the manpage window, kill its buffer.
effdc6a2
RS
718\\[describe-mode] Prints this help text.
719
720The following variables may be of some use. Try
721\"\\[describe-variable] <variable-name> RET\" for more information:
722
799ac634 723Man-notify-method What happens when manpage formatting is done.
b3435a2f
FP
724Man-downcase-section-letters-flag Force section letters to lower case.
725Man-circular-pages-flag Treat multiple manpage list as circular.
effdc6a2
RS
726Man-auto-section-alist List of major modes and their section numbers.
727Man-section-translations-alist List of section numbers and their Un*x equiv.
728Man-filter-list Background manpage filter command.
e660d0db
RS
729Man-mode-line-format Mode line format for Man mode buffers.
730Man-mode-map Keymap bindings for Man mode buffers.
731Man-mode-hook Normal hook run on entry to Man mode.
effdc6a2
RS
732Man-section-regexp Regexp describing manpage section letters.
733Man-heading-regexp Regexp describing section headers.
734Man-see-also-regexp Regexp for SEE ALSO section (or your equiv).
735Man-first-heading-regexp Regexp for first heading on a manpage.
736Man-reference-regexp Regexp matching a references in SEE ALSO.
733155db 737Man-switches Background `man' command switches.
effdc6a2
RS
738
739The following key bindings are currently in effect in the buffer:
740\\{Man-mode-map}"
741 (interactive)
742 (setq major-mode 'Man-mode
c3343fcf 743 mode-name "Man"
effdc6a2
RS
744 buffer-auto-save-file-name nil
745 mode-line-format Man-mode-line-format
746 truncate-lines t
747 buffer-read-only t)
748 (buffer-disable-undo (current-buffer))
749 (auto-fill-mode -1)
750 (use-local-map Man-mode-map)
effdc6a2 751 (Man-build-page-list)
b3435a2f
FP
752 (Man-strip-page-headers)
753 (Man-unindent)
526504b8
RS
754 (Man-goto-page 1)
755 (run-hooks 'Man-mode-hook))
1a20f48d 756
b3435a2f 757(defsubst Man-build-section-alist ()
effdc6a2
RS
758 "Build the association list of manpage sections."
759 (setq Man-sections-alist nil)
1a20f48d 760 (goto-char (point-min))
2cd4790e
KH
761 (let ((case-fold-search nil))
762 (while (re-search-forward Man-heading-regexp (point-max) t)
b3435a2f 763 (aput 'Man-sections-alist (Man-match-substring 1))
2cd4790e 764 (forward-line 1))))
effdc6a2 765
b3435a2f 766(defsubst Man-build-references-alist ()
effdc6a2
RS
767 "Build the association list of references (in the SEE ALSO section)."
768 (setq Man-refpages-alist nil)
769 (save-excursion
770 (if (Man-find-section Man-see-also-regexp)
771 (let ((start (progn (forward-line 1) (point)))
772 (end (progn
773 (Man-next-section 1)
774 (point)))
775 hyphenated
776 (runningpoint -1))
2cd4790e
KH
777 (save-restriction
778 (narrow-to-region start end)
779 (goto-char (point-min))
780 (back-to-indentation)
781 (while (and (not (eobp)) (/= (point) runningpoint))
782 (setq runningpoint (point))
b3435a2f
FP
783 (if (re-search-forward Man-reference-regexp end t)
784 (let* ((word (Man-match-substring 0))
785 (len (1- (length word))))
786 (if hyphenated
787 (setq word (concat hyphenated word)
788 hyphenated nil))
789 (if (= (aref word len) ?-)
790 (setq hyphenated (substring word 0 len))
791 (aput 'Man-refpages-alist word))))
2cd4790e 792 (skip-chars-forward " \t\n,")))))))
effdc6a2 793
d0aede3f 794(defun Man-build-page-list ()
effdc6a2
RS
795 "Build the list of separate manpages in the buffer."
796 (setq Man-page-list nil)
b3435a2f
FP
797 (let ((page-start (point-min))
798 (page-end (point-max))
799 (header ""))
800 (goto-char page-start)
801 ;; (switch-to-buffer (current-buffer))(debug)
802 (while (not (eobp))
803 (setq header
804 (if (looking-at Man-page-header-regexp)
805 (Man-match-substring 1)
806 nil))
807 ;; Go past both the current and the next Man-first-heading-regexp
808 (if (re-search-forward Man-first-heading-regexp nil 'move 2)
809 (let ((p (progn (beginning-of-line) (point))))
810 ;; We assume that the page header is delimited by blank
811 ;; lines and that it contains at most one blank line. So
812 ;; if we back by three blank lines we will be sure to be
813 ;; before the page header but not before the possible
814 ;; previous page header.
815 (search-backward "\n\n" nil t 3)
816 (if (re-search-forward Man-page-header-regexp p 'move)
817 (beginning-of-line))))
818 (setq page-end (point))
819 (setq Man-page-list (append Man-page-list
820 (list (list (copy-marker page-start)
821 (copy-marker page-end)
822 header))))
823 (setq page-start page-end)
824 )))
825
d0aede3f 826(defun Man-strip-page-headers ()
b3435a2f
FP
827 "Strip all the page headers but the first from the manpage."
828 (let ((buffer-read-only nil)
829 (case-fold-search nil)
830 (page-list Man-page-list)
831 (page ())
832 (header ""))
833 (while page-list
834 (setq page (car page-list))
835 (and (nth 2 page)
836 (goto-char (car page))
837 (re-search-forward Man-first-heading-regexp nil t)
838 (setq header (buffer-substring (car page) (match-beginning 0)))
839 ;; Since the awk script collapses all successive blank
840 ;; lines into one, and since we don't want to get rid of
841 ;; the fast awk script, one must choose between adding
842 ;; spare blank lines between pages when there were none and
843 ;; deleting blank lines at page boundaries when there were
844 ;; some. We choose the first, so we comment the following
845 ;; line.
846 ;; (setq header (concat "\n" header)))
847 (while (search-forward header (nth 1 page) t)
848 (replace-match "")))
849 (setq page-list (cdr page-list)))))
850
d0aede3f 851(defun Man-unindent ()
b3435a2f
FP
852 "Delete the leading spaces that indent the manpage."
853 (let ((buffer-read-only nil)
854 (case-fold-search nil)
855 (page-list Man-page-list))
856 (while page-list
857 (let ((page (car page-list))
858 (indent "")
859 (nindent 0))
860 (narrow-to-region (car page) (car (cdr page)))
861 (if Man-uses-untabify-flag
862 (untabify (point-min) (point-max)))
863 (if (catch 'unindent
864 (goto-char (point-min))
865 (if (not (re-search-forward Man-first-heading-regexp nil t))
866 (throw 'unindent nil))
867 (beginning-of-line)
868 (setq indent (buffer-substring (point)
869 (progn
870 (skip-chars-forward " ")
871 (point))))
872 (setq nindent (length indent))
873 (if (zerop nindent)
874 (throw 'unindent nil))
875 (setq indent (concat indent "\\|$"))
876 (goto-char (point-min))
877 (while (not (eobp))
878 (if (looking-at indent)
879 (forward-line 1)
880 (throw 'unindent nil)))
881 (goto-char (point-min)))
882 (while (not (eobp))
883 (or (eolp)
884 (delete-char nindent))
885 (forward-line 1)))
886 (setq page-list (cdr page-list))
2cd4790e 887 ))))
effdc6a2
RS
888
889\f
890;; ======================================================================
e660d0db 891;; Man mode commands
effdc6a2
RS
892
893(defun Man-next-section (n)
894 "Move point to Nth next section (default 1)."
895 (interactive "p")
2cd4790e
KH
896 (let ((case-fold-search nil))
897 (if (looking-at Man-heading-regexp)
898 (forward-line 1))
899 (if (re-search-forward Man-heading-regexp (point-max) t n)
900 (beginning-of-line)
901 (goto-char (point-max)))))
effdc6a2
RS
902
903(defun Man-previous-section (n)
904 "Move point to Nth previous section (default 1)."
905 (interactive "p")
2cd4790e
KH
906 (let ((case-fold-search nil))
907 (if (looking-at Man-heading-regexp)
908 (forward-line -1))
909 (if (re-search-backward Man-heading-regexp (point-min) t n)
910 (beginning-of-line)
911 (goto-char (point-min)))))
effdc6a2
RS
912
913(defun Man-find-section (section)
914 "Move point to SECTION if it exists, otherwise don't move point.
915Returns t if section is found, nil otherwise."
2cd4790e
KH
916 (let ((curpos (point))
917 (case-fold-search nil))
effdc6a2 918 (goto-char (point-min))
b3435a2f 919 (if (re-search-forward (concat "^" section) (point-max) t)
effdc6a2
RS
920 (progn (beginning-of-line) t)
921 (goto-char curpos)
922 nil)
923 ))
924
925(defun Man-goto-section ()
926 "Query for section to move point to."
927 (interactive)
928 (aput 'Man-sections-alist
929 (let* ((default (aheadsym Man-sections-alist))
930 (completion-ignore-case t)
931 chosen
932 (prompt (concat "Go to section: (default " default ") ")))
933 (setq chosen (completing-read prompt Man-sections-alist))
934 (if (or (not chosen)
935 (string= chosen ""))
936 default
937 chosen)))
938 (Man-find-section (aheadsym Man-sections-alist)))
939
940(defun Man-goto-see-also-section ()
941 "Move point the the \"SEE ALSO\" section.
c3343fcf 942Actually the section moved to is described by `Man-see-also-regexp'."
effdc6a2
RS
943 (interactive)
944 (if (not (Man-find-section Man-see-also-regexp))
945 (error (concat "No " Man-see-also-regexp
b3435a2f 946 " section found in the current manpage"))))
effdc6a2 947
2151a1cf 948(defun Man-follow-manual-reference (reference)
effdc6a2 949 "Get one of the manpages referred to in the \"SEE ALSO\" section.
2151a1cf 950Specify which reference to use; default is based on word at point."
e660d0db
RS
951 (interactive
952 (if (not Man-refpages-alist)
b3435a2f 953 (error "There are no references in the current man page")
2151a1cf 954 (list (let* ((default (or
e660d0db
RS
955 (car (all-completions
956 (save-excursion
957 (skip-syntax-backward "w()")
958 (skip-chars-forward " \t")
959 (let ((word (current-word)))
960 ;; strip a trailing '-':
961 (if (string-match "-$" word)
2cd4790e
KH
962 (substring word 0
963 (match-beginning 0))
e660d0db
RS
964 word)))
965 Man-refpages-alist))
966 (aheadsym Man-refpages-alist)))
967 chosen
968 (prompt (concat "Refer to: (default " default ") ")))
969 (setq chosen (completing-read prompt Man-refpages-alist nil t))
970 (if (or (not chosen)
971 (string= chosen ""))
972 default
973 chosen)))))
effdc6a2 974 (if (not Man-refpages-alist)
b3435a2f 975 (error "Can't find any references in the current manpage")
e660d0db 976 (aput 'Man-refpages-alist reference)
effdc6a2 977 (Man-getpage-in-background
2151a1cf 978 (Man-translate-references (aheadsym Man-refpages-alist)))))
effdc6a2 979
b3435a2f 980(defun Man-kill ()
effdc6a2
RS
981 "Kill the buffer containing the manpage."
982 (interactive)
983 (let ((buff (current-buffer)))
984 (delete-windows-on buff)
b3435a2f
FP
985 (kill-buffer buff))
986 (if (and window-system
799ac634 987 (or (eq Man-notify-method 'newframe)
b3435a2f 988 (and pop-up-frames
799ac634 989 (eq Man-notify-method 'bully))))
b3435a2f
FP
990 (delete-frame)))
991
992(defun Man-quit ()
993 "Bury the buffer containing the manpage."
994 (interactive)
995 (let ((buff (current-buffer)))
996 (delete-windows-on buff)
997 (bury-buffer buff))
998 (if (and window-system
799ac634 999 (or (eq Man-notify-method 'newframe)
b3435a2f 1000 (and pop-up-frames
799ac634 1001 (eq Man-notify-method 'bully))))
b3435a2f 1002 (delete-frame)))
effdc6a2
RS
1003
1004(defun Man-goto-page (page)
1005 "Go to the manual page on page PAGE."
1006 (interactive
b3435a2f
FP
1007 (if (not Man-page-list)
1008 (let ((args Man-arguments))
1009 (kill-buffer (current-buffer))
1010 (error "Can't find the %s manpage" args))
1011 (if (= (length Man-page-list) 1)
1012 (error "You're looking at the only manpage in the buffer")
1013 (list (read-minibuffer (format "Go to manpage [1-%d]: "
1014 (length Man-page-list)))))))
1015 (if (not Man-page-list)
1016 (let ((args Man-arguments))
1017 (kill-buffer (current-buffer))
1018 (error "Can't find the %s manpage" args)))
effdc6a2
RS
1019 (if (or (< page 1)
1020 (> page (length Man-page-list)))
1021 (error "No manpage %d found" page))
1022 (let* ((page-range (nth (1- page) Man-page-list))
1023 (page-start (car page-range))
b3435a2f 1024 (page-end (car (cdr page-range))))
effdc6a2 1025 (setq Man-current-page page
b3435a2f 1026 Man-page-mode-string (Man-make-page-mode-string))
effdc6a2
RS
1027 (widen)
1028 (goto-char page-start)
1029 (narrow-to-region page-start page-end)
1030 (Man-build-section-alist)
b3435a2f 1031 (Man-build-references-alist)
effdc6a2
RS
1032 (goto-char (point-min))))
1033
1034
1035(defun Man-next-manpage ()
1036 "Find the next manpage entry in the buffer."
1037 (interactive)
1038 (if (= (length Man-page-list) 1)
9f2863b2 1039 (error "This is the only manpage in the buffer"))
effdc6a2
RS
1040 (if (< Man-current-page (length Man-page-list))
1041 (Man-goto-page (1+ Man-current-page))
b3435a2f 1042 (if Man-circular-pages-flag
effdc6a2 1043 (Man-goto-page 1)
9f2863b2 1044 (error "You're looking at the last manpage in the buffer"))))
effdc6a2
RS
1045
1046(defun Man-previous-manpage ()
1047 "Find the previous manpage entry in the buffer."
1048 (interactive)
1049 (if (= (length Man-page-list) 1)
9f2863b2 1050 (error "This is the only manpage in the buffer"))
effdc6a2
RS
1051 (if (> Man-current-page 1)
1052 (Man-goto-page (1- Man-current-page))
b3435a2f 1053 (if Man-circular-pages-flag
effdc6a2 1054 (Man-goto-page (length Man-page-list))
9f2863b2 1055 (error "You're looking at the first manpage in the buffer"))))
733155db 1056\f
58ffb6ae
RS
1057;; Init the man package variables, if not already done.
1058(Man-init-defvars)
1059
733155db
JB
1060(provide 'man)
1061
6594deb0 1062;;; man.el ends here