(sh-font-lock-keywords): Don't crash for an unrecognized shell.
[bpt/emacs.git] / lisp / man.el
CommitLineData
effdc6a2 1;;; man.el --- browse UNIX manual pages
6594deb0 2
00ed33e7 3;; Copyright (C) 1993, 1994, 1996, 1997 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
00ed33e7
RS
101(defgroup man nil
102 "Browse UNIX manual pages."
103 :prefix "Man-"
104 :group 'help)
105
106
d0aede3f
FP
107(defvar Man-notify)
108(defvar Man-current-page)
109(defvar Man-page-list)
00ed33e7 110(defcustom Man-filter-list nil
58ffb6ae
RS
111 "*Manpage cleaning filter command phrases.
112This variable contains a list of the following form:
113
114'((command-string phrase-string*)*)
115
116Each phrase-string is concatenated onto the command-string to form a
117command filter. The (standard) output (and standard error) of the Un*x
118man command is piped through each command filter in the order the
119commands appear in the association list. The final output is placed in
00ed33e7
RS
120the manpage buffer."
121 :type '(repeat (list (string :tag "Command String")
122 (repeat :inline t
123 (string :tag "Phrase String"))))
124 :group 'man)
58ffb6ae 125
d0aede3f
FP
126(defvar Man-original-frame)
127(defvar Man-arguments)
d0aede3f
FP
128(defvar Man-sections-alist)
129(defvar Man-refpages-alist)
58ffb6ae
RS
130(defvar Man-uses-untabify-flag t
131 "When non-nil use `untabify' instead of Man-untabify-command.")
d0aede3f 132(defvar Man-page-mode-string)
58ffb6ae
RS
133(defvar Man-sed-script nil
134 "Script for sed to nuke backspaces and ANSI codes from manpages.")
d0aede3f 135
effdc6a2
RS
136;; vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
137;; user variables
138
00ed33e7
RS
139(defcustom Man-fontify-manpage-flag t
140 "*Make up the manpage with fonts."
141 :type 'boolean
142 :group 'man)
6e7e47f6 143
00ed33e7
RS
144(defcustom Man-overstrike-face 'bold
145 "*Face to use when fontifying overstrike."
146 :type 'face
147 :group 'man)
6e7e47f6 148
00ed33e7
RS
149(defcustom Man-underline-face 'underline
150 "*Face to use when fontifying underlining."
151 :type 'face
152 :group 'man)
2788b7c9 153
b3435a2f 154;; Use the value of the obsolete user option Man-notify, if set.
00ed33e7 155(defcustom Man-notify-method (if (boundp 'Man-notify) Man-notify 'friendly)
effdc6a2 156 "*Selects the behavior when manpage is ready.
b3435a2f
FP
157This variable may have one of the following values, where (sf) means
158that the frames are switched, so the manpage is displayed in the frame
159where the man command was called from:
effdc6a2 160
b51aeeff 161newframe -- put the manpage in its own frame (see `Man-frame-parameters')
b3435a2f
FP
162pushy -- make the manpage the current buffer in the current window
163bully -- make the manpage the current buffer and only window (sf)
164aggressive -- make the manpage the current buffer in the other window (sf)
165friendly -- display manpage in the other window but don't make current (sf)
166polite -- don't display manpage, but prints message and beep when ready
effdc6a2 167quiet -- like `polite', but don't beep
b3435a2f 168meek -- make no indication that the manpage is ready
effdc6a2 169
00ed33e7
RS
170Any other value of `Man-notify-method' is equivalent to `meek'."
171 :type '(radio (const newframe) (const pushy) (const bully)
172 (const aggressive) (const friendly)
173 (const polite) (const quiet) (const meek))
174 :group 'man)
effdc6a2 175
00ed33e7
RS
176(defcustom Man-frame-parameters nil
177 "*Frame parameter list for creating a new frame for a manual page."
178 :type 'sexp
179 :group 'man)
b51aeeff 180
00ed33e7 181(defcustom Man-downcase-section-letters-flag t
effdc6a2
RS
182 "*Letters in sections are converted to lower case.
183Some Un*x man commands can't handle uppercase letters in sections, for
184example \"man 2V chmod\", but they are often displayed in the manpage
c3343fcf 185with the upper case letter. When this variable is t, the section
effdc6a2 186letter (e.g., \"2V\") is converted to lowercase (e.g., \"2v\") before
00ed33e7
RS
187being sent to the man background process."
188 :type 'boolean
189 :group 'man)
effdc6a2 190
00ed33e7
RS
191(defcustom Man-circular-pages-flag t
192 "*If t, the manpage list is treated as circular for traversal."
193 :type 'boolean
194 :group 'man)
effdc6a2 195
00ed33e7 196(defcustom Man-section-translations-alist
b3435a2f
FP
197 (list
198 '("3C++" . "3")
199 ;; Some systems have a real 3x man section, so let's comment this.
200 ;; '("3X" . "3") ; Xlib man pages
201 '("3X11" . "3")
202 '("1-UCB" . ""))
effdc6a2
RS
203 "*Association list of bogus sections to real section numbers.
204Some manpages (e.g. the Sun C++ 2.1 manpages) have section numbers in
c3343fcf 205their references which Un*x `man' does not recognize. This
eb8c3be9 206association list is used to translate those sections, when found, to
00ed33e7
RS
207the associated section number."
208 :type '(repeat (cons (string :tag "Bogus Section")
209 (string :tag "Real Section")))
210 :group 'man)
effdc6a2 211
6e7e47f6
FP
212(defvar manual-program "man"
213 "The name of the program that produces man pages.")
214
b3435a2f 215(defvar Man-untabify-command "pr"
6e7e47f6 216 "Command used for untabifying.")
b3435a2f
FP
217
218(defvar Man-untabify-command-args (list "-t" "-e")
6e7e47f6 219 "List of arguments to be passed to Man-untabify-command (which see).")
b3435a2f
FP
220
221(defvar Man-sed-command "sed"
6e7e47f6 222 "Command used for processing sed scripts.")
b3435a2f
FP
223
224(defvar Man-awk-command "awk"
6e7e47f6 225 "Command used for processing awk scripts.")
effdc6a2
RS
226
227(defvar Man-mode-line-format
6f72f1c2
AS
228 '("-"
229 mode-line-mule-info
230 mode-line-modified
231 mode-line-frame-identification
232 mode-line-buffer-identification " "
233 global-mode-string
234 " " Man-page-mode-string
235 " %[(" mode-name mode-line-process minor-mode-alist "%n)%]--"
236 (line-number-mode "L%l--")
237 (column-number-mode "C%c--")
238 (-3 . "%p") "-%-")
6e7e47f6 239 "Mode line format for manual mode buffer.")
effdc6a2
RS
240
241(defvar Man-mode-map nil
6e7e47f6 242 "Keymap for Man mode.")
effdc6a2 243
e660d0db 244(defvar Man-mode-hook nil
6e7e47f6 245 "Hook run when Man mode is enabled.")
effdc6a2 246
c2d606f4 247(defvar Man-cooked-hook nil
6e7e47f6 248 "Hook run after removing backspaces but before Man-mode processing.")
b3435a2f
FP
249
250(defvar Man-name-regexp "[-a-zA-Z0-9_][-a-zA-Z0-9_.]*"
6e7e47f6 251 "Regular expression describing the name of a manpage (without section).")
c2d606f4 252
f5f76002 253(defvar Man-section-regexp "[0-9][a-zA-Z+]*\\|[LNln]"
6e7e47f6 254 "Regular expression describing a manpage section within parentheses.")
effdc6a2 255
b3435a2f
FP
256(defvar Man-page-header-regexp
257 (concat "^[ \t]*\\(" Man-name-regexp
258 "(\\(" Man-section-regexp "\\))\\).*\\1")
6e7e47f6 259 "Regular expression describing the heading of a page.")
b3435a2f
FP
260
261(defvar Man-heading-regexp "^\\([A-Z][A-Z ]+\\)$"
6e7e47f6 262 "Regular expression describing a manpage heading entry.")
effdc6a2
RS
263
264(defvar Man-see-also-regexp "SEE ALSO"
6e7e47f6 265 "Regular expression for SEE ALSO heading (or your equivalent).
effdc6a2
RS
266This regexp should not start with a `^' character.")
267
2cd4790e 268(defvar Man-first-heading-regexp "^[ \t]*NAME$\\|^[ \t]*No manual entry fo.*$"
6e7e47f6 269 "Regular expression describing first heading on a manpage.
effdc6a2
RS
270This regular expression should start with a `^' character.")
271
3eedeb85 272(defvar Man-reference-regexp
b3435a2f 273 (concat "\\(" Man-name-regexp "\\)(\\(" Man-section-regexp "\\))")
6e7e47f6 274 "Regular expression describing a reference in the SEE ALSO section.")
effdc6a2 275
733155db 276(defvar Man-switches ""
6e7e47f6 277 "Switches passed to the man command, as a single string.")
effdc6a2 278
e660d0db
RS
279(defvar Man-specified-section-option
280 (if (string-match "-solaris[0-9.]*$" system-configuration)
281 "-s"
282 "")
6e7e47f6 283 "Option that indicates a specified a manual section name.")
9de0760c 284
effdc6a2
RS
285;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
286;; end user variables
effdc6a2
RS
287\f
288;; other variables and keymap initializations
289(make-variable-buffer-local 'Man-sections-alist)
290(make-variable-buffer-local 'Man-refpages-alist)
291(make-variable-buffer-local 'Man-page-list)
292(make-variable-buffer-local 'Man-current-page)
293(make-variable-buffer-local 'Man-page-mode-string)
75db9a64 294(make-variable-buffer-local 'Man-original-frame)
b3435a2f 295(make-variable-buffer-local 'Man-arguments)
effdc6a2
RS
296
297(setq-default Man-sections-alist nil)
298(setq-default Man-refpages-alist nil)
299(setq-default Man-page-list nil)
300(setq-default Man-current-page 0)
b3435a2f 301(setq-default Man-page-mode-string "1 of 1")
effdc6a2 302
6e7e47f6
FP
303(defconst Man-sysv-sed-script "\
304/\b/ { s/_\b//g
305 s/\b_//g
306 s/o\b+/o/g
f90531cc 307 s/+\bo/o/g
6e7e47f6
FP
308 :ovstrk
309 s/\\(.\\)\b\\1/\\1/g
310 t ovstrk
311 }
312/\e\\[[0-9][0-9]*m/ s///g"
313 "Script for sysV-like sed to nuke backspaces and ANSI codes from manpages.")
314
315(defconst Man-berkeley-sed-script "\
316/\b/ { s/_\b//g\\
317 s/\b_//g\\
318 s/o\b+/o/g\\
f90531cc 319 s/+\bo/o/g\\
6e7e47f6
FP
320 :ovstrk\\
321 s/\\(.\\)\b\\1/\\1/g\\
322 t ovstrk\\
323 }\\
324/\e\\[[0-9][0-9]*m/ s///g"
325 "Script for berkeley-like sed to nuke backspaces and ANSI codes from manpages.")
326
f655106b
KH
327(defvar man-mode-syntax-table
328 (let ((table (copy-syntax-table (standard-syntax-table))))
329 (modify-syntax-entry ?. "w" table)
330 (modify-syntax-entry ?_ "w" table)
331 table)
332 "Syntax table used in Man mode buffers.")
333
effdc6a2
RS
334(if Man-mode-map
335 nil
336 (setq Man-mode-map (make-keymap))
337 (suppress-keymap Man-mode-map)
338 (define-key Man-mode-map " " 'scroll-up)
339 (define-key Man-mode-map "\177" 'scroll-down)
340 (define-key Man-mode-map "n" 'Man-next-section)
341 (define-key Man-mode-map "p" 'Man-previous-section)
342 (define-key Man-mode-map "\en" 'Man-next-manpage)
343 (define-key Man-mode-map "\ep" 'Man-previous-manpage)
b3435a2f
FP
344 (define-key Man-mode-map ">" 'end-of-buffer)
345 (define-key Man-mode-map "<" 'beginning-of-buffer)
346 (define-key Man-mode-map "." 'beginning-of-buffer)
effdc6a2 347 (define-key Man-mode-map "r" 'Man-follow-manual-reference)
effdc6a2
RS
348 (define-key Man-mode-map "g" 'Man-goto-section)
349 (define-key Man-mode-map "s" 'Man-goto-see-also-section)
b3435a2f 350 (define-key Man-mode-map "k" 'Man-kill)
effdc6a2 351 (define-key Man-mode-map "q" 'Man-quit)
b3435a2f 352 (define-key Man-mode-map "m" 'man)
e7bf8d10 353 (define-key Man-mode-map "\r" 'man-follow)
effdc6a2
RS
354 (define-key Man-mode-map "?" 'describe-mode)
355 )
356
357\f
358;; ======================================================================
359;; utilities
360
58ffb6ae 361(defun Man-init-defvars ()
b3435a2f
FP
362 "Used for initialising variables based on the value of window-system.
363This is necessary if one wants to dump man.el with emacs."
364
b3435a2f
FP
365 ;; The following is necessary until fonts are implemented on
366 ;; terminals.
367 (setq Man-fontify-manpage-flag (and Man-fontify-manpage-flag
368 window-system))
369
fd5733a9
KH
370 ;; Avoid possible error in call-process by using a directory that must exist.
371 (let ((default-directory "/"))
372 (setq Man-sed-script
373 (cond
374 (Man-fontify-manpage-flag
375 nil)
376 ((= 0 (call-process Man-sed-command nil nil nil Man-sysv-sed-script))
377 Man-sysv-sed-script)
378 ((= 0 (call-process Man-sed-command nil nil nil Man-berkeley-sed-script))
379 Man-berkeley-sed-script)
380 (t
381 nil))))
58ffb6ae
RS
382
383 (setq Man-filter-list
1ac26bf5
AS
384 ;; Avoid trailing nil which confuses customize.
385 (apply 'list
b3435a2f 386 (cons
58ffb6ae
RS
387 Man-sed-command
388 (list
389 (if Man-sed-script
390 (concat "-e '" Man-sed-script "'")
391 "")
392 "-e '/^[\001-\032][\001-\032]*$/d'"
393 "-e '/\e[789]/s///g'"
394 "-e '/Reformatting page. Wait/d'"
395 "-e '/Reformatting entry. Wait/d'"
396 "-e '/^[ \t]*Hewlett-Packard[ \t]Company[ \t]*-[ \t][0-9]*[ \t]-/d'"
397 "-e '/^[ \t]*Hewlett-Packard[ \t]*-[ \t][0-9]*[ \t]-.*$/d'"
398 "-e '/^[ \t][ \t]*-[ \t][0-9]*[ \t]-[ \t]*Formatted:.*[0-9]$/d'"
399 "-e '/^[ \t]*Page[ \t][0-9]*.*(printed[ \t][0-9\\/]*)$/d'"
400 "-e '/^Printed[ \t][0-9].*[0-9]$/d'"
401 "-e '/^[ \t]*X[ \t]Version[ \t]1[01].*Release[ \t][0-9]/d'"
008d825a 402 "-e '/^[A-Za-z].*Last[ \t]change:/d'"
58ffb6ae
RS
403 "-e '/^Sun[ \t]Release[ \t][0-9].*[0-9]$/d'"
404 "-e '/[ \t]*Copyright [0-9]* UNIX System Laboratories, Inc.$/d'"
405 "-e '/^[ \t]*Rev\\..*Page [0-9][0-9]*$/d'"
406 ))
407 (cons
408 Man-awk-command
409 (list
410 "'\n"
411 "BEGIN { blankline=0; anonblank=0; }\n"
412 "/^$/ { if (anonblank==0) next; }\n"
413 "{ anonblank=1; }\n"
414 "/^$/ { blankline++; next; }\n"
415 "{ if (blankline>0) { print \"\"; blankline=0; } print $0; }\n"
416 "'"
417 ))
418 (if (not Man-uses-untabify-flag)
1ac26bf5
AS
419 ;; The outer list will be stripped off by apply.
420 (list (cons
421 Man-untabify-command
422 Man-untabify-command-args))
58ffb6ae 423 )))
b3435a2f 424)
effdc6a2 425
d0aede3f
FP
426(defsubst Man-match-substring (&optional n string)
427 "Return the substring matched by the last search.
428Optional arg N means return the substring matched by the Nth paren
429grouping. Optional second arg STRING means return a substring from
430that string instead of from the current buffer."
431 (if (null n) (setq n 0))
432 (if string
433 (substring string (match-beginning n) (match-end n))
434 (buffer-substring (match-beginning n) (match-end n))))
435
b3435a2f
FP
436(defsubst Man-make-page-mode-string ()
437 "Formats part of the mode line for Man mode."
438 (format "%s page %d of %d"
439 (or (nth 2 (nth (1- Man-current-page) Man-page-list))
440 "")
441 Man-current-page
442 (length Man-page-list)))
443
444(defsubst Man-build-man-command ()
effdc6a2 445 "Builds the entire background manpage and cleaning command."
0020dbcd
EZ
446 (let ((command (concat manual-program " " Man-switches
447 ; Stock MS-DOS shells cannot redirect stderr;
448 ; `call-process' below sends it to /dev/null,
449 ; so we don't need `2>' even with DOS shells
450 ; which do support stderr redirection.
451 (if (not (fboundp 'start-process))
452 " %s"
453 " %s 2>/dev/null")))
effdc6a2 454 (flist Man-filter-list))
b3435a2f 455 (while (and flist (car flist))
effdc6a2 456 (let ((pcom (car (car flist)))
b3435a2f
FP
457 (pargs (cdr (car flist))))
458 (setq command
459 (concat command " | " pcom " "
460 (mapconcat '(lambda (phrase)
461 (if (not (stringp phrase))
462 (error "Malformed Man-filter-list"))
463 phrase)
464 pargs " ")))
465 (setq flist (cdr flist))))
effdc6a2
RS
466 command))
467
effdc6a2 468(defun Man-translate-references (ref)
b3435a2f
FP
469 "Translates REF from \"chmod(2V)\" to \"2v chmod\" style.
470Leave it as is if already in that style. Possibly downcase and
471translate the section (see the Man-downcase-section-letters-flag
2f2228c0 472and the Man-section-translations-alist variables)."
b3435a2f
FP
473 (let ((name "")
474 (section "")
475 (slist Man-section-translations-alist))
effdc6a2 476 (cond
b3435a2f 477 ;; "chmod(2V)" case ?
2f2228c0 478 ((string-match (concat "^" Man-reference-regexp "$") ref)
b3435a2f
FP
479 (setq name (Man-match-substring 1 ref)
480 section (Man-match-substring 2 ref)))
481 ;; "2v chmod" case ?
2f2228c0 482 ((string-match (concat "^\\(" Man-section-regexp
b3435a2f
FP
483 "\\) +\\(" Man-name-regexp "\\)$") ref)
484 (setq name (Man-match-substring 2 ref)
485 section (Man-match-substring 1 ref))))
486 (if (string= name "")
487 ref ; Return the reference as is
488 (if Man-downcase-section-letters-flag
489 (setq section (downcase section)))
490 (while slist
491 (let ((s1 (car (car slist)))
492 (s2 (cdr (car slist))))
493 (setq slist (cdr slist))
494 (if Man-downcase-section-letters-flag
495 (setq s1 (downcase s1)))
496 (if (not (string= s1 section)) nil
497 (setq section (if Man-downcase-section-letters-flag
498 (downcase s2)
499 s2)
500 slist nil))))
501 (concat Man-specified-section-option section " " name))))
502
effdc6a2
RS
503\f
504;; ======================================================================
b3435a2f 505;; default man entry: get word under point
effdc6a2 506
b3435a2f 507(defsubst Man-default-man-entry ()
effdc6a2
RS
508 "Make a guess at a default manual entry.
509This guess is based on the text surrounding the cursor, and the
c3343fcf 510default section number is selected from `Man-auto-section-alist'."
f655106b 511 (let (word)
1a20f48d 512 (save-excursion
b3435a2f 513 ;; Default man entry title is any word the cursor is on, or if
f655106b
KH
514 ;; cursor not on a word, then nearest preceding word.
515 (setq word (current-word))
516 (if (string-match "[._]+$" word)
517 (setq word (substring word 0 (match-beginning 0))))
b3435a2f 518 ;; If looking at something like ioctl(2) or brc(1M), include the
c448c134 519 ;; section number in the returned value. Remove text properties.
f655106b
KH
520 (forward-word 1)
521 ;; Use `format' here to clear any text props from `word'.
522 (format "%s%s"
523 word
524 (if (looking-at
525 (concat "[ \t]*([ \t]*\\(" Man-section-regexp "\\)[ \t]*)"))
526 (format "(%s)" (Man-match-substring 1))
527 "")))))
b3435a2f 528
effdc6a2
RS
529\f
530;; ======================================================================
b3435a2f 531;; Top level command and background process sentinel
1a20f48d 532
b3435a2f 533;; For compatibility with older versions.
cac0b95d 534;;;###autoload
b3435a2f 535(defalias 'manual-entry 'man)
cac0b95d 536
effdc6a2 537;;;###autoload
98fd7017 538(defun man (man-args)
effdc6a2 539 "Get a Un*x manual page and put it in a buffer.
c3343fcf 540This command is the top-level command in the man package. It runs a Un*x
effdc6a2 541command to retrieve and clean a manpage in the background and places the
c3343fcf 542results in a Man mode (manpage browsing) buffer. See variable
799ac634 543`Man-notify-method' for what happens when the buffer is ready.
98fd7017 544If a buffer already exists for this man page, it will display immediately."
b3435a2f 545 (interactive
98fd7017
FP
546 (list (let* ((default-entry (Man-default-man-entry))
547 (input (read-string
548 (format "Manual entry%s: "
549 (if (string= default-entry "")
550 ""
551 (format " (default %s)" default-entry))))))
552 (if (string= input "")
553 (if (string= default-entry "")
554 (error "No man args given")
555 default-entry)
556 input))))
b3435a2f 557
b3435a2f
FP
558 ;; Possibly translate the "subject(section)" syntax into the
559 ;; "section subject" syntax and possibly downcase the section.
560 (setq man-args (Man-translate-references man-args))
561
98fd7017 562 (Man-getpage-in-background man-args))
b3435a2f 563
e7bf8d10
KH
564;;;###autoload
565(defun man-follow (man-args)
566 "Get a Un*x manual page of the item under point and put it in a buffer."
567 (interactive (list (Man-default-man-entry)))
568 (if (or (not man-args)
569 (string= man-args ""))
570 (error "No item under point")
571 (man man-args)))
aa228418 572
98fd7017
FP
573(defun Man-getpage-in-background (topic)
574 "Uses TOPIC to build and fire off the manpage and cleaning command."
e660d0db 575 (let* ((man-args topic)
d0aede3f 576 (bufname (concat "*Man " man-args "*"))
effdc6a2 577 (buffer (get-buffer bufname)))
98fd7017 578 (if buffer
effdc6a2 579 (Man-notify-when-ready buffer)
eaf1946c 580 (require 'env)
b3435a2f 581 (message "Invoking %s %s in the background" manual-program man-args)
effdc6a2 582 (setq buffer (generate-new-buffer bufname))
75db9a64
KH
583 (save-excursion
584 (set-buffer buffer)
b3435a2f
FP
585 (setq Man-original-frame (selected-frame))
586 (setq Man-arguments man-args))
fd5733a9 587 (let ((process-environment (copy-sequence process-environment))
cd3b7f95
RS
588 ;; The following is so Awk script gets \n intact
589 ;; But don't prevent decoding of the outside.
590 (coding-system-for-write 'raw-text-unix)
fd5733a9
KH
591 ;; Avoid possible error by using a directory that always exists.
592 (default-directory "/"))
82c9fe8e
RS
593 ;; Prevent any attempt to use display terminal fanciness.
594 (setenv "TERM" "dumb")
0020dbcd
EZ
595 (if (fboundp 'start-process)
596 (set-process-sentinel
597 (start-process manual-program buffer "sh" "-c"
598 (format (Man-build-man-command) man-args))
599 'Man-bgproc-sentinel)
600 (progn
601 (let ((exit-status
602 (call-process shell-file-name nil (list buffer nil) nil "-c"
603 (format (Man-build-man-command) man-args)))
604 (msg ""))
605 (or (and (numberp exit-status)
606 (= exit-status 0))
607 (and (numberp exit-status)
608 (setq msg
609 (format "exited abnormally with code %d"
610 exit-status)))
611 (setq msg exit-status))
612 (Man-bgproc-sentinel bufname msg))))))))
effdc6a2
RS
613
614(defun Man-notify-when-ready (man-buffer)
615 "Notify the user when MAN-BUFFER is ready.
799ac634 616See the variable `Man-notify-method' for the different notification behaviors."
c9bf42f9
RS
617 (let ((saved-frame (save-excursion
618 (set-buffer man-buffer)
619 Man-original-frame)))
620 (cond
799ac634 621 ((eq Man-notify-method 'newframe)
b3435a2f
FP
622 ;; Since we run asynchronously, perhaps while Emacs is waiting
623 ;; for input, we must not leave a different buffer current. We
624 ;; can't rely on the editor command loop to reselect the
625 ;; selected window's buffer.
c9bf42f9 626 (save-excursion
42a9dc84
RS
627 (let ((frame (make-frame Man-frame-parameters)))
628 (set-window-buffer (frame-selected-window frame) man-buffer)
629 (set-window-dedicated-p (frame-selected-window frame) t))))
799ac634 630 ((eq Man-notify-method 'pushy)
b3435a2f 631 (switch-to-buffer man-buffer))
799ac634 632 ((eq Man-notify-method 'bully)
c9bf42f9
RS
633 (and window-system
634 (frame-live-p saved-frame)
635 (select-frame saved-frame))
636 (pop-to-buffer man-buffer)
637 (delete-other-windows))
799ac634 638 ((eq Man-notify-method 'aggressive)
c9bf42f9
RS
639 (and window-system
640 (frame-live-p saved-frame)
641 (select-frame saved-frame))
642 (pop-to-buffer man-buffer))
799ac634 643 ((eq Man-notify-method 'friendly)
c9bf42f9
RS
644 (and window-system
645 (frame-live-p saved-frame)
646 (select-frame saved-frame))
647 (display-buffer man-buffer 'not-this-window))
799ac634 648 ((eq Man-notify-method 'polite)
c9bf42f9 649 (beep)
b3435a2f 650 (message "Manual buffer %s is ready" (buffer-name man-buffer)))
799ac634 651 ((eq Man-notify-method 'quiet)
b3435a2f 652 (message "Manual buffer %s is ready" (buffer-name man-buffer)))
799ac634 653 ((or (eq Man-notify-method 'meek)
c9bf42f9
RS
654 t)
655 (message ""))
656 )))
effdc6a2 657
6cb92c3a
KH
658(defun Man-softhyphen-to-minus ()
659 ;; \255 is some kind of dash in Latin-1.
660 (goto-char (point-min))
661 (if enable-multibyte-characters
662 (while (search-forward "\255" nil t)
663 (if (= (preceding-char) ?\255)
664 (replace-match "-")))
665 (while (search-forward "\255" nil t) (replace-match "-"))))
666
b3435a2f
FP
667(defun Man-fontify-manpage ()
668 "Convert overstriking and underlining to the correct fonts.
669Same for the ANSI bold and normal escape sequences."
670 (interactive)
671 (message "Please wait: making up the %s man page..." Man-arguments)
c3343fcf 672 (goto-char (point-min))
b3435a2f
FP
673 (while (search-forward "\e[1m" nil t)
674 (delete-backward-char 4)
675 (put-text-property (point)
676 (progn (if (search-forward "\e[0m" nil 'move)
677 (delete-backward-char 4))
678 (point))
6e7e47f6 679 'face Man-overstrike-face))
b3435a2f
FP
680 (goto-char (point-min))
681 (while (search-forward "_\b" nil t)
682 (backward-delete-char 2)
6e7e47f6 683 (put-text-property (point) (1+ (point)) 'face Man-underline-face))
b3435a2f
FP
684 (goto-char (point-min))
685 (while (search-forward "\b_" nil t)
686 (backward-delete-char 2)
6e7e47f6 687 (put-text-property (1- (point)) (point) 'face Man-underline-face))
b3435a2f 688 (goto-char (point-min))
6024daef
FP
689 (while (re-search-forward "\\(.\\)\\(\b\\1\\)+" nil t)
690 (replace-match "\\1")
6e7e47f6 691 (put-text-property (1- (point)) (point) 'face Man-overstrike-face))
6024daef 692 (goto-char (point-min))
f90531cc
FP
693 (while (re-search-forward "o\b\\+\\|\\+\bo" nil t)
694 (replace-match "o")
b3435a2f
FP
695 (put-text-property (1- (point)) (point) 'face 'bold))
696 (goto-char (point-min))
f7046d47 697 (while (re-search-forward "[-|]\\(\b[-|]\\)+" nil t)
6024daef 698 (replace-match "+")
b3435a2f 699 (put-text-property (1- (point)) (point) 'face 'bold))
6cb92c3a 700 (Man-softhyphen-to-minus)
b3435a2f
FP
701 (message "%s man page made up" Man-arguments))
702
703(defun Man-cleanup-manpage ()
704 "Remove overstriking and underlining from the current buffer."
705 (interactive)
f7046d47
FP
706 (message "Please wait: cleaning up the %s man page..."
707 Man-arguments)
9931e1ba 708 (if (or (interactive-p) (not Man-sed-script))
f7046d47
FP
709 (progn
710 (goto-char (point-min))
711 (while (search-forward "_\b" nil t) (backward-delete-char 2))
712 (goto-char (point-min))
713 (while (search-forward "\b_" nil t) (backward-delete-char 2))
714 (goto-char (point-min))
715 (while (re-search-forward "\\(.\\)\\(\b\\1\\)+" nil t)
716 (replace-match "\\1"))
717 (goto-char (point-min))
718 (while (re-search-forward "\e\\[[0-9]+m" nil t) (replace-match ""))
719 (goto-char (point-min))
f90531cc 720 (while (re-search-forward "o\b\\+\\|\\+\bo" nil t) (replace-match "o"))
f7046d47 721 ))
6024daef 722 (goto-char (point-min))
f7046d47 723 (while (re-search-forward "[-|]\\(\b[-|]\\)+" nil t) (replace-match "+"))
6cb92c3a 724 (Man-softhyphen-to-minus)
b3435a2f 725 (message "%s man page cleaned up" Man-arguments))
c3343fcf 726
effdc6a2 727(defun Man-bgproc-sentinel (process msg)
0020dbcd
EZ
728 "Manpage background process sentinel.
729When manpage command is run asynchronously, PROCESS is the process
730object for the manpage command; when manpage command is run
731synchronously, PROCESS is the name of the buffer where the manpage
732command is run. Second argument MSG is the exit message of the
733manpage command."
734 (let ((Man-buffer (if (stringp process) (get-buffer process)
735 (process-buffer process)))
effdc6a2 736 (delete-buff nil)
8c79b392 737 (err-mess nil))
b3435a2f 738
effdc6a2 739 (if (null (buffer-name Man-buffer)) ;; deleted buffer
0020dbcd
EZ
740 (or (stringp process)
741 (set-process-buffer process nil))
b3435a2f
FP
742
743 (save-excursion
744 (set-buffer Man-buffer)
1d56cc39
RS
745 (let ((case-fold-search nil))
746 (goto-char (point-min))
747 (cond ((or (looking-at "No \\(manual \\)*entry for")
748 (looking-at "[^\n]*: nothing appropriate$"))
749 (setq err-mess (buffer-substring (point)
750 (progn
751 (end-of-line) (point)))
752 delete-buff t))
0020dbcd
EZ
753 ((or (stringp process)
754 (not (and (eq (process-status process) 'exit)
755 (= (process-exit-status process) 0))))
756 (or (zerop (length msg))
757 (progn
758 (setq err-mess
759 (concat (buffer-name Man-buffer)
760 ": process "
761 (let ((eos (1- (length msg))))
762 (if (= (aref msg eos) ?\n)
763 (substring msg 0 eos) msg))))
764 (goto-char (point-max))
765 (insert (format "\nprocess %s" msg))))
766 ))
1223b6c4
RS
767 (if delete-buff
768 (kill-buffer Man-buffer)
769 (if Man-fontify-manpage-flag
770 (Man-fontify-manpage)
771 (Man-cleanup-manpage))
772 (run-hooks 'Man-cooked-hook)
773 (Man-mode)
774 (set-buffer-modified-p nil)
0020dbcd 775 ))
1d56cc39
RS
776 ;; Restore case-fold-search before calling
777 ;; Man-notify-when-ready because it may switch buffers.
778
779 (if (not delete-buff)
780 (Man-notify-when-ready Man-buffer))
781
782 (if err-mess
783 (error err-mess))
784 ))))
effdc6a2
RS
785
786\f
787;; ======================================================================
788;; set up manual mode in buffer and build alists
789
790(defun Man-mode ()
c3343fcf 791 "A mode for browsing Un*x manual pages.
effdc6a2
RS
792
793The following man commands are available in the buffer. Try
794\"\\[describe-key] <key> RET\" for more information:
aa228418 795
b3435a2f 796\\[man] Prompt to retrieve a new manpage.
effdc6a2
RS
797\\[Man-follow-manual-reference] Retrieve reference in SEE ALSO section.
798\\[Man-next-manpage] Jump to next manpage in circular list.
799\\[Man-previous-manpage] Jump to previous manpage in circular list.
800\\[Man-next-section] Jump to next manpage section.
801\\[Man-previous-section] Jump to previous manpage section.
802\\[Man-goto-section] Go to a manpage section.
803\\[Man-goto-see-also-section] Jumps to the SEE ALSO manpage section.
b3435a2f
FP
804\\[Man-quit] Deletes the manpage window, bury its buffer.
805\\[Man-kill] Deletes the manpage window, kill its buffer.
effdc6a2
RS
806\\[describe-mode] Prints this help text.
807
808The following variables may be of some use. Try
809\"\\[describe-variable] <variable-name> RET\" for more information:
810
799ac634 811Man-notify-method What happens when manpage formatting is done.
b3435a2f
FP
812Man-downcase-section-letters-flag Force section letters to lower case.
813Man-circular-pages-flag Treat multiple manpage list as circular.
effdc6a2
RS
814Man-auto-section-alist List of major modes and their section numbers.
815Man-section-translations-alist List of section numbers and their Un*x equiv.
816Man-filter-list Background manpage filter command.
e660d0db
RS
817Man-mode-line-format Mode line format for Man mode buffers.
818Man-mode-map Keymap bindings for Man mode buffers.
819Man-mode-hook Normal hook run on entry to Man mode.
effdc6a2
RS
820Man-section-regexp Regexp describing manpage section letters.
821Man-heading-regexp Regexp describing section headers.
822Man-see-also-regexp Regexp for SEE ALSO section (or your equiv).
823Man-first-heading-regexp Regexp for first heading on a manpage.
824Man-reference-regexp Regexp matching a references in SEE ALSO.
733155db 825Man-switches Background `man' command switches.
effdc6a2
RS
826
827The following key bindings are currently in effect in the buffer:
828\\{Man-mode-map}"
829 (interactive)
830 (setq major-mode 'Man-mode
c3343fcf 831 mode-name "Man"
effdc6a2
RS
832 buffer-auto-save-file-name nil
833 mode-line-format Man-mode-line-format
834 truncate-lines t
835 buffer-read-only t)
836 (buffer-disable-undo (current-buffer))
837 (auto-fill-mode -1)
838 (use-local-map Man-mode-map)
f655106b 839 (set-syntax-table man-mode-syntax-table)
effdc6a2 840 (Man-build-page-list)
b3435a2f
FP
841 (Man-strip-page-headers)
842 (Man-unindent)
526504b8
RS
843 (Man-goto-page 1)
844 (run-hooks 'Man-mode-hook))
1a20f48d 845
b3435a2f 846(defsubst Man-build-section-alist ()
effdc6a2
RS
847 "Build the association list of manpage sections."
848 (setq Man-sections-alist nil)
1a20f48d 849 (goto-char (point-min))
2cd4790e
KH
850 (let ((case-fold-search nil))
851 (while (re-search-forward Man-heading-regexp (point-max) t)
b3435a2f 852 (aput 'Man-sections-alist (Man-match-substring 1))
2cd4790e 853 (forward-line 1))))
effdc6a2 854
b3435a2f 855(defsubst Man-build-references-alist ()
effdc6a2
RS
856 "Build the association list of references (in the SEE ALSO section)."
857 (setq Man-refpages-alist nil)
858 (save-excursion
859 (if (Man-find-section Man-see-also-regexp)
860 (let ((start (progn (forward-line 1) (point)))
861 (end (progn
862 (Man-next-section 1)
863 (point)))
864 hyphenated
865 (runningpoint -1))
2cd4790e
KH
866 (save-restriction
867 (narrow-to-region start end)
868 (goto-char (point-min))
869 (back-to-indentation)
870 (while (and (not (eobp)) (/= (point) runningpoint))
871 (setq runningpoint (point))
b3435a2f
FP
872 (if (re-search-forward Man-reference-regexp end t)
873 (let* ((word (Man-match-substring 0))
874 (len (1- (length word))))
875 (if hyphenated
876 (setq word (concat hyphenated word)
877 hyphenated nil))
878 (if (= (aref word len) ?-)
879 (setq hyphenated (substring word 0 len))
880 (aput 'Man-refpages-alist word))))
2cd4790e 881 (skip-chars-forward " \t\n,")))))))
effdc6a2 882
d0aede3f 883(defun Man-build-page-list ()
effdc6a2
RS
884 "Build the list of separate manpages in the buffer."
885 (setq Man-page-list nil)
b3435a2f
FP
886 (let ((page-start (point-min))
887 (page-end (point-max))
888 (header ""))
889 (goto-char page-start)
890 ;; (switch-to-buffer (current-buffer))(debug)
891 (while (not (eobp))
892 (setq header
893 (if (looking-at Man-page-header-regexp)
894 (Man-match-substring 1)
895 nil))
896 ;; Go past both the current and the next Man-first-heading-regexp
897 (if (re-search-forward Man-first-heading-regexp nil 'move 2)
898 (let ((p (progn (beginning-of-line) (point))))
899 ;; We assume that the page header is delimited by blank
900 ;; lines and that it contains at most one blank line. So
901 ;; if we back by three blank lines we will be sure to be
902 ;; before the page header but not before the possible
903 ;; previous page header.
904 (search-backward "\n\n" nil t 3)
905 (if (re-search-forward Man-page-header-regexp p 'move)
906 (beginning-of-line))))
907 (setq page-end (point))
908 (setq Man-page-list (append Man-page-list
909 (list (list (copy-marker page-start)
910 (copy-marker page-end)
911 header))))
912 (setq page-start page-end)
913 )))
914
d0aede3f 915(defun Man-strip-page-headers ()
b3435a2f
FP
916 "Strip all the page headers but the first from the manpage."
917 (let ((buffer-read-only nil)
918 (case-fold-search nil)
919 (page-list Man-page-list)
920 (page ())
921 (header ""))
922 (while page-list
923 (setq page (car page-list))
924 (and (nth 2 page)
925 (goto-char (car page))
926 (re-search-forward Man-first-heading-regexp nil t)
927 (setq header (buffer-substring (car page) (match-beginning 0)))
928 ;; Since the awk script collapses all successive blank
929 ;; lines into one, and since we don't want to get rid of
930 ;; the fast awk script, one must choose between adding
931 ;; spare blank lines between pages when there were none and
932 ;; deleting blank lines at page boundaries when there were
933 ;; some. We choose the first, so we comment the following
934 ;; line.
935 ;; (setq header (concat "\n" header)))
936 (while (search-forward header (nth 1 page) t)
937 (replace-match "")))
938 (setq page-list (cdr page-list)))))
939
d0aede3f 940(defun Man-unindent ()
b3435a2f
FP
941 "Delete the leading spaces that indent the manpage."
942 (let ((buffer-read-only nil)
943 (case-fold-search nil)
944 (page-list Man-page-list))
945 (while page-list
946 (let ((page (car page-list))
947 (indent "")
948 (nindent 0))
949 (narrow-to-region (car page) (car (cdr page)))
950 (if Man-uses-untabify-flag
951 (untabify (point-min) (point-max)))
952 (if (catch 'unindent
953 (goto-char (point-min))
954 (if (not (re-search-forward Man-first-heading-regexp nil t))
955 (throw 'unindent nil))
956 (beginning-of-line)
957 (setq indent (buffer-substring (point)
958 (progn
959 (skip-chars-forward " ")
960 (point))))
961 (setq nindent (length indent))
962 (if (zerop nindent)
963 (throw 'unindent nil))
964 (setq indent (concat indent "\\|$"))
965 (goto-char (point-min))
966 (while (not (eobp))
967 (if (looking-at indent)
968 (forward-line 1)
969 (throw 'unindent nil)))
970 (goto-char (point-min)))
971 (while (not (eobp))
972 (or (eolp)
973 (delete-char nindent))
974 (forward-line 1)))
975 (setq page-list (cdr page-list))
2cd4790e 976 ))))
effdc6a2
RS
977
978\f
979;; ======================================================================
e660d0db 980;; Man mode commands
effdc6a2
RS
981
982(defun Man-next-section (n)
983 "Move point to Nth next section (default 1)."
984 (interactive "p")
2cd4790e
KH
985 (let ((case-fold-search nil))
986 (if (looking-at Man-heading-regexp)
987 (forward-line 1))
988 (if (re-search-forward Man-heading-regexp (point-max) t n)
989 (beginning-of-line)
990 (goto-char (point-max)))))
effdc6a2
RS
991
992(defun Man-previous-section (n)
993 "Move point to Nth previous section (default 1)."
994 (interactive "p")
2cd4790e
KH
995 (let ((case-fold-search nil))
996 (if (looking-at Man-heading-regexp)
997 (forward-line -1))
998 (if (re-search-backward Man-heading-regexp (point-min) t n)
999 (beginning-of-line)
1000 (goto-char (point-min)))))
effdc6a2
RS
1001
1002(defun Man-find-section (section)
1003 "Move point to SECTION if it exists, otherwise don't move point.
1004Returns t if section is found, nil otherwise."
2cd4790e
KH
1005 (let ((curpos (point))
1006 (case-fold-search nil))
effdc6a2 1007 (goto-char (point-min))
b3435a2f 1008 (if (re-search-forward (concat "^" section) (point-max) t)
effdc6a2
RS
1009 (progn (beginning-of-line) t)
1010 (goto-char curpos)
1011 nil)
1012 ))
1013
1014(defun Man-goto-section ()
1015 "Query for section to move point to."
1016 (interactive)
1017 (aput 'Man-sections-alist
1018 (let* ((default (aheadsym Man-sections-alist))
1019 (completion-ignore-case t)
1020 chosen
1021 (prompt (concat "Go to section: (default " default ") ")))
1022 (setq chosen (completing-read prompt Man-sections-alist))
1023 (if (or (not chosen)
1024 (string= chosen ""))
1025 default
1026 chosen)))
1027 (Man-find-section (aheadsym Man-sections-alist)))
1028
1029(defun Man-goto-see-also-section ()
1030 "Move point the the \"SEE ALSO\" section.
c3343fcf 1031Actually the section moved to is described by `Man-see-also-regexp'."
effdc6a2
RS
1032 (interactive)
1033 (if (not (Man-find-section Man-see-also-regexp))
1034 (error (concat "No " Man-see-also-regexp
b3435a2f 1035 " section found in the current manpage"))))
effdc6a2 1036
2151a1cf 1037(defun Man-follow-manual-reference (reference)
effdc6a2 1038 "Get one of the manpages referred to in the \"SEE ALSO\" section.
2151a1cf 1039Specify which reference to use; default is based on word at point."
e660d0db
RS
1040 (interactive
1041 (if (not Man-refpages-alist)
b3435a2f 1042 (error "There are no references in the current man page")
2151a1cf 1043 (list (let* ((default (or
e660d0db
RS
1044 (car (all-completions
1045 (save-excursion
1046 (skip-syntax-backward "w()")
1047 (skip-chars-forward " \t")
1048 (let ((word (current-word)))
1049 ;; strip a trailing '-':
1050 (if (string-match "-$" word)
2cd4790e
KH
1051 (substring word 0
1052 (match-beginning 0))
e660d0db
RS
1053 word)))
1054 Man-refpages-alist))
1055 (aheadsym Man-refpages-alist)))
1056 chosen
1057 (prompt (concat "Refer to: (default " default ") ")))
1058 (setq chosen (completing-read prompt Man-refpages-alist nil t))
1059 (if (or (not chosen)
1060 (string= chosen ""))
1061 default
1062 chosen)))))
effdc6a2 1063 (if (not Man-refpages-alist)
b3435a2f 1064 (error "Can't find any references in the current manpage")
e660d0db 1065 (aput 'Man-refpages-alist reference)
effdc6a2 1066 (Man-getpage-in-background
2151a1cf 1067 (Man-translate-references (aheadsym Man-refpages-alist)))))
effdc6a2 1068
b3435a2f 1069(defun Man-kill ()
effdc6a2
RS
1070 "Kill the buffer containing the manpage."
1071 (interactive)
06cab243 1072 (quit-window t))
b3435a2f
FP
1073
1074(defun Man-quit ()
1075 "Bury the buffer containing the manpage."
1076 (interactive)
06cab243 1077 (quit-window))
effdc6a2
RS
1078
1079(defun Man-goto-page (page)
1080 "Go to the manual page on page PAGE."
1081 (interactive
b3435a2f
FP
1082 (if (not Man-page-list)
1083 (let ((args Man-arguments))
1084 (kill-buffer (current-buffer))
1085 (error "Can't find the %s manpage" args))
1086 (if (= (length Man-page-list) 1)
1087 (error "You're looking at the only manpage in the buffer")
1088 (list (read-minibuffer (format "Go to manpage [1-%d]: "
1089 (length Man-page-list)))))))
1090 (if (not Man-page-list)
1091 (let ((args Man-arguments))
1092 (kill-buffer (current-buffer))
1093 (error "Can't find the %s manpage" args)))
effdc6a2
RS
1094 (if (or (< page 1)
1095 (> page (length Man-page-list)))
1096 (error "No manpage %d found" page))
1097 (let* ((page-range (nth (1- page) Man-page-list))
1098 (page-start (car page-range))
b3435a2f 1099 (page-end (car (cdr page-range))))
effdc6a2 1100 (setq Man-current-page page
b3435a2f 1101 Man-page-mode-string (Man-make-page-mode-string))
effdc6a2
RS
1102 (widen)
1103 (goto-char page-start)
1104 (narrow-to-region page-start page-end)
1105 (Man-build-section-alist)
b3435a2f 1106 (Man-build-references-alist)
effdc6a2
RS
1107 (goto-char (point-min))))
1108
1109
1110(defun Man-next-manpage ()
1111 "Find the next manpage entry in the buffer."
1112 (interactive)
1113 (if (= (length Man-page-list) 1)
9f2863b2 1114 (error "This is the only manpage in the buffer"))
effdc6a2
RS
1115 (if (< Man-current-page (length Man-page-list))
1116 (Man-goto-page (1+ Man-current-page))
b3435a2f 1117 (if Man-circular-pages-flag
effdc6a2 1118 (Man-goto-page 1)
9f2863b2 1119 (error "You're looking at the last manpage in the buffer"))))
effdc6a2
RS
1120
1121(defun Man-previous-manpage ()
1122 "Find the previous manpage entry in the buffer."
1123 (interactive)
1124 (if (= (length Man-page-list) 1)
9f2863b2 1125 (error "This is the only manpage in the buffer"))
effdc6a2
RS
1126 (if (> Man-current-page 1)
1127 (Man-goto-page (1- Man-current-page))
b3435a2f 1128 (if Man-circular-pages-flag
effdc6a2 1129 (Man-goto-page (length Man-page-list))
9f2863b2 1130 (error "You're looking at the first manpage in the buffer"))))
733155db 1131\f
58ffb6ae
RS
1132;; Init the man package variables, if not already done.
1133(Man-init-defvars)
1134
733155db
JB
1135(provide 'man)
1136
6594deb0 1137;;; man.el ends here