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