Mercurial > hg > xemacs-beta
comparison lisp/packages/man.el @ 8:4b173ad71786 r19-15b5
Import from CVS: tag r19-15b5
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:47:35 +0200 |
parents | b82b59fe008d |
children | 49a24b4fd526 |
comparison
equal
deleted
inserted
replaced
7:c153ca296910 | 8:4b173ad71786 |
---|---|
1 ;;; man.el --- browse UNIX manual pages | 1 ;;; man.el --- browse UNIX manual pages |
2 | 2 ;; Keywords: help |
3 ;; Copyright (C) 1993, 1994, 1996 Free Software Foundation, Inc. | 3 |
4 | 4 ;; Copyright (C) 1985, 1993, 1994 Free Software Foundation, Inc. |
5 ;; Author: Barry A. Warsaw <bwarsaw@cen.com> | 5 ;; |
6 ;; Keywords: help | |
7 ;; Adapted-By: ESR, pot | |
8 | |
9 ;; This file is part of XEmacs. | 6 ;; This file is part of XEmacs. |
10 | 7 |
11 ;; XEmacs is free software; you can redistribute it and/or modify it | 8 ;; XEmacs is free software; you can redistribute it and/or modify it |
12 ;; under the terms of the GNU General Public License as published by | 9 ;; under the terms of the GNU General Public License as published by |
13 ;; the Free Software Foundation; either version 2, or (at your option) | 10 ;; the Free Software Foundation; either version 2, or (at your option) |
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
19 ;; General Public License for more details. | 16 ;; General Public License for more details. |
20 | 17 |
21 ;; You should have received a copy of the GNU General Public License | 18 ;; You should have received a copy of the GNU General Public License |
22 ;; along with XEmacs; see the file COPYING. If not, write to the Free | 19 ;; along with XEmacs; see the file COPYING. If not, write to the Free |
23 ;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | 20 ;; Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. |
24 ;; 02111-1307, USA. | 21 |
25 | 22 ;; Mostly rewritten by Alan K. Stebbens <aks@hub.ucsb.edu> 11-apr-90. |
26 ;;; Synched up with: FSF 19.34. | 23 ;; |
27 | 24 ;; o Match multiple man pages using TOPIC as a simple pattern |
28 ;;; Commentary: | 25 ;; o Search unformatted pages, even when formatted matches are found |
29 | 26 ;; o Query the user as to which pages are desired |
30 ;; This code provides a function, `man', with which you can browse | 27 ;; o Use of the prefix arg to toggle/bypass the above features |
31 ;; UNIX manual pages. Formatting is done in background so that you | 28 ;; o Buffers named by the first topic in the buffer |
32 ;; can continue to use your Emacs while processing is going on. | 29 ;; o Automatic uncompress for compressed man pages (.Z, .z, and .gz) |
33 ;; | 30 ;; o View the resulting buffer using M-x view mode |
34 ;; The mode also supports hypertext-like following of manual page SEE | 31 ;; |
35 ;; ALSO references, and other features. See below or do `?' in a | 32 ;; Modified 16-mar-91 by Jamie Zawinski <jwz@lucid.com> to default the |
36 ;; manual page buffer for details. | 33 ;; manual topic to the symbol at point, just like find-tag does. |
37 | 34 ;; |
38 ;; ========== Credits and History ========== | 35 ;; Modified 22-mar-93 by jwz to use multiple fonts and follow xrefs with mouse. |
39 ;; In mid 1991, several people posted some interesting improvements to | 36 ;; |
40 ;; man.el from the standard emacs 18.57 distribution. I liked many of | 37 ;; Modified 16-apr-93 by Dave Gillespie <daveg@synaptics.com> to make |
41 ;; these, but wanted everything in one single package, so I decided | 38 ;; apropos work nicely; work correctly when bold or italic is unavailable; |
42 ;; to incorporate them into a single manual browsing mode. While | 39 ;; reuse old buffer if topic is re-selected (in Manual-topic-buffer mode). |
43 ;; much of the code here has been rewritten, and some features added, | 40 ;; |
44 ;; these folks deserve lots of credit for providing the initial | 41 ;; Modified 4-apr-94 by jwz: merged in Tibor Polgar's code for manpath.conf. |
45 ;; excellent packages on which this one is based. | 42 ;; |
46 | 43 ;; Modified 19-apr-94 by Tibor Polgar <tlp00@spg.amdahl.com> to add support for |
47 ;; Nick Duffek <duffek@chaos.cs.brandeis.edu>, posted a very nice | 44 ;; $PAGER variable to be emacsclient and properly process man pages (assuming |
48 ;; improvement which retrieved and cleaned the manpages in a | 45 ;; the man pages were built by man in /tmp. also fixed bug with man list being |
49 ;; background process, and which correctly deciphered such options as | 46 ;; backwards. |
50 ;; man -k. | 47 ;; |
51 | 48 ;; Modified 23-aug-94 by Tibor Polgar <tlp00@spg.amdahl.com> to add support for |
52 ;; Eric Rose <erose@jessica.stanford.edu>, submitted manual.el which | 49 ;; displaying only one instance of a man page (Manual-unique-man-sections-only) |
53 ;; provided a very nice manual browsing mode. | 50 ;; Fixed some more man page ordering bugs, bug with Manual-query-multiple-pages. |
54 | 51 ;; |
55 ;; This package was available as `superman.el' from the LCD package | 52 ;; Modified 29-nov-94 by Ben Wing <wing@spg.amdahl.com>: small fixes |
56 ;; for some time before it was accepted into Emacs 19. The entry | 53 ;; that should hopefully make things work under HPUX and IRIX.; |
57 ;; point and some other names have been changed to make it a drop-in | 54 ;; |
58 ;; replacement for the old man.el package. | 55 ;; Modified 15-jul-95 by Dale Atems <atems@physics.wayne.edu>: |
59 | 56 ;; some extensive rewriting to make things work right (more or less) |
60 ;; Francesco Potorti` <pot@cnuce.cnr.it> cleaned it up thoroughly, | 57 ;; under IRIX. |
61 ;; making it faster, more robust and more tolerant of different | 58 ;; |
62 ;; systems' man idiosyncrasies. | 59 ;; This file defines "manual-entry", and the remaining definitions all |
63 | 60 ;; begin with "Manual-". This makes the autocompletion on "M-x man" work. |
64 ;; ========== Features ========== | 61 ;; |
65 ;; + Runs "man" in the background and pipes the results through a | 62 ;; Variables of interest: |
66 ;; series of sed and awk scripts so that all retrieving and cleaning | 63 ;; |
67 ;; is done in the background. The cleaning commands are configurable. | 64 ;; Manual-program |
68 ;; + Syntax is the same as Un*x man | 65 ;; Manual-topic-buffer |
69 ;; + Functionality is the same as Un*x man, including "man -k" and | 66 ;; Manual-buffer-view-mode |
70 ;; "man <section>", etc. | 67 ;; Manual-directory-list |
71 ;; + Provides a manual browsing mode with keybindings for traversing | 68 ;; Manual-formatted-directory-list |
72 ;; the sections of a manpage, following references in the SEE ALSO | 69 ;; Manual-match-topic-exactly |
73 ;; section, and more. | 70 ;; Manual-query-multiple-pages |
74 ;; + Multiple manpages created with the same man command are put into | 71 ;; Manual-page-history |
75 ;; a narrowed buffer circular list. | 72 ;; Manual-subdirectory-list |
76 | 73 ;; Manual-man-page-section-ids |
77 ;; ============= TODO =========== | 74 ;; Manual-formatted-page-prefix |
78 ;; - Add a command for printing. | 75 ;; Manual-unformatted-page-prefix |
79 ;; - The awk script deletes multiple blank lines. This behaviour does | 76 ;; Manual-use-full-section-ids |
80 ;; not allow to understand if there was indeed a blank line at the | 77 |
81 ;; end or beginning of a page (after the header, or before the | 78 (defvar Manual-program "man" "\ |
82 ;; footer). A different algorithm should be used. It is easy to | 79 *Name of the program to invoke in order to format the source man pages.") |
83 ;; compute how many blank lines there are before and after the page | 80 |
84 ;; headers, and after the page footer. But it is possible to compute | 81 (defvar Manual-section-switch (if (eq system-type 'usg-unix-v) "-s" nil) |
85 ;; the number of blank lines before the page footer by euristhics | 82 "SysV needs this to work right.") |
86 ;; only. Is it worth doing? | 83 |
87 ;; - Allow a user option to mean that all the manpages should go in | 84 (defvar Manual-topic-buffer t "\ |
88 ;; the same buffer, where they can be browsed with M-n and M-p. | 85 *Non-nil means \\[Manual-entry] should output the manual entry for TOPIC into |
89 ;; - Allow completion on the manpage name when calling man. This | 86 a buffer named *man TOPIC*, otherwise, it should name the buffer |
90 ;; requires a reliable list of places where manpages can be found. The | 87 *Manual Entry*.") |
91 ;; drawback would be that if the list is not complete, the user might | 88 |
92 ;; be led to believe that the manpages in the missing directories do | 89 (defvar Manual-buffer-view-mode t "\ |
93 ;; not exist. | 90 *Whether manual buffers should be placed in view-mode. |
94 | 91 nil means leave the buffer in fundamental-mode in another window. |
95 | 92 t means use `view-buffer' to display the man page in the current window. |
96 ;;; Code: | 93 Any other value means use `view-buffer-other-window'.") |
97 | 94 |
98 (require 'assoc) | 95 (defvar Manual-match-topic-exactly t "\ |
99 | 96 *Non-nil means that \\[manual-entry] will match the given TOPIC exactly, rather |
100 ;; vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv | 97 apply it as a pattern. When this is nil, and \"Manual-query-multiple-pages\" |
101 ;; empty defvars (keep the compiler quiet) | 98 is non-nil, then \\[manual-entry] will query you for all matching TOPICs. |
102 | 99 This variable only has affect on the preformatted man pages (the \"cat\" files), |
103 (defvar Man-notify) | 100 since the \"man\" command always does exact topic matches.") |
104 (defvar Man-current-page) | 101 |
105 (defvar Man-page-list) | 102 (defvar Manual-query-multiple-pages nil "\ |
106 (defvar Man-filter-list nil | 103 *Non-nil means that \\[manual-entry] will query the user about multiple man |
107 "*Manpage cleaning filter command phrases. | 104 pages which match the given topic. The query is done using the function |
108 This variable contains a list of the following form: | 105 \"y-or-n-p\". If this variable is nil, all man pages with topics matching the |
109 | 106 topic given to \\[manual-entry] will be inserted into the temporary buffer. |
110 '((command-string phrase-string*)*) | 107 See the variable \"Manual-match-topic-exactly\" to control the matching.") |
111 | 108 |
112 Each phrase-string is concatenated onto the command-string to form a | 109 (defvar Manual-unique-man-sections-only nil |
113 command filter. The (standard) output (and standard error) of the Un*x | 110 "*Only present one man page per section. This variable is useful if the same or |
114 man command is piped through each command filter in the order the | 111 up/down level man pages for the same entry are present in mulitple man paths. |
115 commands appear in the association list. The final output is placed in | 112 When set to t, only the first entry found in a section is displayed, the others |
116 the manpage buffer.") | 113 are ignored without any messages or warnings. Note that duplicates can occur if |
117 | 114 the system has both formatted and unformatted version of the same page.") |
118 (defvar Man-original-frame) | 115 |
119 (defvar Man-arguments) | 116 (defvar Manual-mode-hook nil |
120 (defvar Man-sections-alist) | 117 "Function or functions run on entry to Manual-mode.") |
121 (defvar Man-refpages-alist) | 118 |
122 (defvar Man-uses-untabify-flag t | 119 (defvar Manual-directory-list nil "\ |
123 "When non-nil use `untabify' instead of Man-untabify-command.") | 120 *A list of directories used with the \"man\" command, where each directory |
124 (defvar Man-page-mode-string) | 121 contains a set of \"man?\" and \"cat?\" subdirectories. If this variable is nil, |
125 (defvar Man-sed-script nil | 122 it is initialized by \\[Manual-directory-list-init].") |
126 "Script for sed to nuke backspaces and ANSI codes from manpages.") | 123 |
127 | 124 (defvar Manual-formatted-directory-list nil "\ |
128 ;; vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv | 125 A list of directories containing formatted man pages. Initialized by |
129 ;; user variables | 126 \\[Manual-directory-list-init].") |
130 | 127 |
131 (defvar Man-fontify-manpage-flag t | 128 (defvar Manual-unformatted-directory-list nil "\ |
132 "*Make up the manpage with fonts.") | 129 A list of directories containing the unformatted (source) man pages. |
133 | 130 Initialized by \\[Manual-directory-list-init].") |
134 (defvar Man-overstrike-face 'bold | 131 |
135 "*Face to use when fontifying overstrike.") | 132 (defvar Manual-page-history nil "\ |
136 | 133 A list of names of previously visited man page buffers.") |
137 (defvar Man-underline-face 'underline | 134 |
138 "*Face to use when fontifying underlining.") | 135 (defvar Manual-manpath-config-file "/usr/lib/manpath.config" |
139 | 136 "*Location of the manpath.config file, if any.") |
140 ;; Use the value of the obsolete user option Man-notify, if set. | 137 |
141 (defvar Man-notify-method (if (boundp 'Man-notify) Man-notify 'friendly) | 138 (defvar Manual-apropos-switch "-k" |
142 "*Selects the behavior when manpage is ready. | 139 "*Man apropos switch") |
143 This variable may have one of the following values, where (sf) means | 140 |
144 that the frames are switched, so the manpage is displayed in the frame | 141 ;; New variables. |
145 where the man command was called from: | 142 |
146 | 143 (defvar Manual-subdirectory-list nil "\ |
147 newframe -- put the manpage in its own frame (see `Man-frame-parameters') | 144 A list of all the subdirectories in which man pages may be found. |
148 pushy -- make the manpage the current buffer in the current window | 145 Iniialized by Manual-directory-list-init.") |
149 bully -- make the manpage the current buffer and only window (sf) | 146 |
150 aggressive -- make the manpage the current buffer in the other window (sf) | 147 ;; This is for SGI systems; don't know what it should be otherwise. |
151 friendly -- display manpage in the other window but don't make current (sf) | 148 (defvar Manual-man-page-section-ids "1nl6823457poD" "\ |
152 polite -- don't display manpage, but prints message and beep when ready | 149 String containing all suffix characters for \"cat\" and \"man\" |
153 quiet -- like `polite', but don't beep | 150 that identify valid sections of the Un*x manual.") |
154 meek -- make no indication that the manpage is ready | 151 |
155 | 152 (defvar Manual-formatted-page-prefix "cat" "\ |
156 Any other value of `Man-notify-method' is equivalent to `meek'.") | 153 Prefix for directories where formatted man pages are to be found. |
157 | 154 Defaults to \"cat\".") |
158 (defvar Man-frame-parameters nil | 155 |
159 "*Frame parameter list for creating a new frame for a manual page.") | 156 (defvar Manual-unformatted-page-prefix "man" "\ |
160 | 157 Prefix for directories where unformatted man pages are to be found. |
161 (defvar Man-downcase-section-letters-flag t | 158 Defaults to \"man\".") |
162 "*Letters in sections are converted to lower case. | 159 |
163 Some Un*x man commands can't handle uppercase letters in sections, for | 160 (defvar Manual-leaf-signature "" "\ |
164 example \"man 2V chmod\", but they are often displayed in the manpage | 161 Regexp for identifying \"leaf\" subdirectories in the search path. |
165 with the upper case letter. When this variable is t, the section | 162 If empty, initialized by Manual-directory-list-init.") |
166 letter (e.g., \"2V\") is converted to lowercase (e.g., \"2v\") before | 163 |
167 being sent to the man background process.") | 164 (defvar Manual-use-full-section-ids t "\ |
168 | 165 If non-nil, pass full section ids to Manual-program, otherwise pass |
169 (defvar Man-circular-pages-flag t | 166 only the first character. Defaults to 't'.") |
170 "*If t, the manpage list is treated as circular for traversal.") | 167 |
171 | 168 (defvar Manual-use-subdirectory-list (eq system-type 'irix) "\ |
172 (defvar Man-section-translations-alist | 169 This makes manual-entry work correctly on SGI machines but it |
173 (list | 170 imposes a large startup cost which is why it is not simply on by |
174 '("3C++" . "3") | 171 default on all systems.") |
175 ;; Some systems have a real 3x man section, so let's comment this. | 172 |
176 ;; '("3X" . "3") ; Xlib man pages | 173 (make-face 'man-italic) |
177 '("3X11" . "3") | 174 (or (face-differs-from-default-p 'man-italic) |
178 '("1-UCB" . "")) | 175 (copy-face 'italic 'man-italic)) |
179 "*Association list of bogus sections to real section numbers. | 176 ;; XEmacs (from Darrell Kindred): underlining is annoying due to |
180 Some manpages (e.g. the Sun C++ 2.1 manpages) have section numbers in | 177 ;; large blank spaces in this face. |
181 their references which Un*x `man' does not recognize. This | 178 ;; (or (face-differs-from-default-p 'man-italic) |
182 association list is used to translate those sections, when found, to | 179 ;; (set-face-underline-p 'man-italic t)) |
183 the associated section number.") | 180 |
184 | 181 (make-face 'man-bold) |
185 (defvar manual-program "man" | 182 (or (face-differs-from-default-p 'man-bold) |
186 "The name of the program that produces man pages.") | 183 (copy-face 'bold 'man-bold)) |
187 | 184 (or (face-differs-from-default-p 'man-bold) |
188 (defvar Man-untabify-command "pr" | 185 (copy-face 'man-italic 'man-bold)) |
189 "Command used for untabifying.") | 186 |
190 | 187 (make-face 'man-heading) |
191 (defvar Man-untabify-command-args (list "-t" "-e") | 188 (or (face-differs-from-default-p 'man-heading) |
192 "List of arguments to be passed to Man-untabify-command (which see).") | 189 (copy-face 'man-bold 'man-heading)) |
193 | 190 |
194 (defvar Man-sed-command "sed" | 191 (make-face 'man-xref) |
195 "Command used for processing sed scripts.") | 192 (or (face-differs-from-default-p 'man-xref) |
196 | 193 (set-face-underline-p 'man-xref t)) |
197 (defvar Man-awk-command "awk" | 194 |
198 "Command used for processing awk scripts.") | 195 ;; Manual-directory-list-init |
199 | 196 ;; Initialize the directory lists. |
200 (defvar Man-mode-line-format | 197 |
201 '("" mode-line-modified | 198 (defun Manual-directory-list-init (&optional arg) |
202 mode-line-buffer-identification " " | 199 "Initialize the Manual-directory-list variable from $MANPATH |
203 global-mode-string | 200 if it is not already set, or if a prefix argument is provided." |
204 " " Man-page-mode-string | 201 (interactive "P") |
205 " %[(" mode-name mode-line-process minor-mode-alist ")%]----" | 202 (if arg (setq Manual-directory-list nil)) |
206 (-3 . "%p") "-%-") | 203 (if (null Manual-directory-list) |
207 "Mode line format for manual mode buffer.") | 204 (let ((manpath (getenv "MANPATH")) |
208 | 205 (global (Manual-manpath-config-contents)) |
209 (defvar Man-mode-map nil | 206 (dirlist nil) |
210 "Keymap for Man mode.") | 207 dir) |
211 | 208 (cond ((and manpath global) |
212 (defvar Man-mode-hook nil | 209 (setq manpath (concat manpath ":" global))) |
213 "Hook run when Man mode is enabled.") | 210 (global |
214 | 211 (setq manpath global)) |
215 (defvar Man-cooked-hook nil | 212 ((not manpath) |
216 "Hook run after removing backspaces but before Man-mode processing.") | 213 ;; XEmacs - (bpw/stig) Unix-specifix hack for lusers w/ no manpath |
217 | 214 (setq manpath "/usr/local/man:/usr/share/man:/usr/contrib/man:/usr/X11/man:/usr/man:/usr/catman"))) |
218 (defvar Man-name-regexp "[-a-zA-Z0-9_][-a-zA-Z0-9_.]*" | 215 ;; Make sure that any changes we've made internally are seen by man. |
219 "Regular expression describing the name of a manpage (without section).") | 216 (setenv "MANPATH" manpath) |
220 | 217 (while (string-match "\\`:*\\([^:]+\\)" manpath) |
221 (defvar Man-section-regexp "[0-9][a-zA-Z+]*\\|[LNln]" | 218 (setq dir (substring manpath (match-beginning 1) (match-end 1))) |
222 "Regular expression describing a manpage section within parentheses.") | 219 (and (not (member dir dirlist)) |
223 | 220 (setq dirlist (cons dir dirlist))) |
224 (defvar Man-page-header-regexp | 221 (setq manpath (substring manpath (match-end 0)))) |
225 (concat "^[ \t]*\\(" Man-name-regexp | 222 (setq dirlist (nreverse dirlist)) |
226 "(\\(" Man-section-regexp "\\))\\).*\\1") | 223 (setq Manual-directory-list dirlist) |
227 "Regular expression describing the heading of a page.") | 224 (setq Manual-subdirectory-list nil) |
228 | 225 (setq Manual-formatted-directory-list nil) |
229 (defvar Man-heading-regexp "^\\([A-Z][A-Z ]+\\)$" | 226 (setq Manual-unformatted-directory-list nil))) |
230 "Regular expression describing a manpage heading entry.") | 227 (if (string-equal Manual-leaf-signature "") |
231 | 228 (setq Manual-leaf-signature |
232 (defvar Man-see-also-regexp "SEE ALSO" | 229 (concat "/\\(" |
233 "Regular expression for SEE ALSO heading (or your equivalent). | 230 Manual-formatted-page-prefix |
234 This regexp should not start with a `^' character.") | 231 "\\|" Manual-unformatted-page-prefix |
235 | 232 "\\)" |
236 (defvar Man-first-heading-regexp "^[ \t]*NAME$\\|^[ \t]*No manual entry fo.*$" | 233 "[" Manual-man-page-section-ids |
237 "Regular expression describing first heading on a manpage. | 234 "].?/."))) |
238 This regular expression should start with a `^' character.") | 235 (if Manual-use-subdirectory-list |
239 | 236 (progn |
240 (defvar Man-reference-regexp | 237 (if (null Manual-subdirectory-list) |
241 (concat "\\(" Man-name-regexp "\\)(\\(" Man-section-regexp "\\))") | 238 (setq Manual-subdirectory-list |
242 "Regular expression describing a reference in the SEE ALSO section.") | 239 (Manual-all-subdirectories Manual-directory-list |
243 | 240 Manual-leaf-signature nil))) |
244 (defvar Man-switches "" | 241 (if (null Manual-formatted-directory-list) |
245 "Switches passed to the man command, as a single string.") | 242 (setq Manual-formatted-directory-list |
246 | 243 (Manual-filter-subdirectories Manual-subdirectory-list |
247 (defvar Man-specified-section-option | 244 Manual-formatted-page-prefix))) |
248 (if (string-match "-solaris[0-9.]*$" system-configuration) | 245 (if (null Manual-unformatted-directory-list) |
249 "-s" | 246 (setq Manual-unformatted-directory-list |
250 "") | 247 (Manual-filter-subdirectories Manual-subdirectory-list |
251 "Option that indicates a specified a manual section name.") | 248 Manual-unformatted-page-prefix)))) |
252 | 249 (if (null Manual-formatted-directory-list) |
253 ;; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | 250 (setq Manual-formatted-directory-list |
254 ;; end user variables | 251 (Manual-select-subdirectories Manual-directory-list |
255 | 252 Manual-formatted-page-prefix))) |
256 ;; other variables and keymap initializations | 253 (if (null Manual-unformatted-directory-list) |
257 (make-variable-buffer-local 'Man-sections-alist) | 254 (setq Manual-unformatted-directory-list |
258 (make-variable-buffer-local 'Man-refpages-alist) | 255 (Manual-select-subdirectories Manual-directory-list |
259 (make-variable-buffer-local 'Man-page-list) | 256 Manual-unformatted-page-prefix))))) |
260 (make-variable-buffer-local 'Man-current-page) | 257 |
261 (make-variable-buffer-local 'Man-page-mode-string) | 258 |
262 (make-variable-buffer-local 'Man-original-frame) | 259 (defun Manual-manpath-config-contents () |
263 (make-variable-buffer-local 'Man-arguments) | 260 "Parse the `Manual-manpath-config-file' file, if any. |
264 | 261 Returns a string like in $MANPATH." |
265 (setq-default Man-sections-alist nil) | 262 (if (and Manual-manpath-config-file |
266 (setq-default Man-refpages-alist nil) | 263 (file-readable-p Manual-manpath-config-file)) |
267 (setq-default Man-page-list nil) | 264 (let ((buf (get-buffer-create " *Manual-config*")) |
268 (setq-default Man-current-page 0) | 265 path) |
269 (setq-default Man-page-mode-string "1 of 1") | 266 (set-buffer buf) |
270 | 267 (buffer-disable-undo buf) |
271 (defconst Man-sysv-sed-script "\ | 268 (erase-buffer) |
272 /\b/ { s/_\b//g | 269 (insert-file-contents Manual-manpath-config-file) |
273 s/\b_//g | 270 (while (re-search-forward "^\\(MANDATORY_MANPATH\\|MANPATH_MAP\\)" |
274 s/o\b+/o/g | 271 nil t) |
275 s/+\bo/o/g | 272 (and (re-search-forward "\\(/[^ \t\n]+\\)[ \t]*$") |
276 :ovstrk | 273 (setq path (concat path (buffer-substring (match-beginning 1) |
277 s/\\(.\\)\b\\1/\\1/g | 274 (match-end 1)) |
278 t ovstrk | 275 ":")))) |
279 } | 276 (kill-buffer buf) |
280 /\e\\[[0-9][0-9]*m/ s///g" | 277 path))) |
281 "Script for sysV-like sed to nuke backspaces and ANSI codes from manpages.") | 278 ;; |
282 | 279 ;; manual-entry -- The "main" user function |
283 (defconst Man-berkeley-sed-script "\ | 280 ;; |
284 /\b/ { s/_\b//g\\ | 281 |
285 s/\b_//g\\ | |
286 s/o\b+/o/g\\ | |
287 s/+\bo/o/g\\ | |
288 :ovstrk\\ | |
289 s/\\(.\\)\b\\1/\\1/g\\ | |
290 t ovstrk\\ | |
291 }\\ | |
292 /\e\\[[0-9][0-9]*m/ s///g" | |
293 "Script for berkeley-like sed to nuke backspaces and ANSI codes from manpages.") | |
294 | |
295 (if Man-mode-map | |
296 nil | |
297 (setq Man-mode-map (make-keymap)) | |
298 (suppress-keymap Man-mode-map) | |
299 (define-key Man-mode-map " " 'scroll-up) | |
300 (define-key Man-mode-map "\177" 'scroll-down) | |
301 (define-key Man-mode-map "n" 'Man-next-section) | |
302 (define-key Man-mode-map "p" 'Man-previous-section) | |
303 (define-key Man-mode-map "\en" 'Man-next-manpage) | |
304 (define-key Man-mode-map "\ep" 'Man-previous-manpage) | |
305 (define-key Man-mode-map ">" 'end-of-buffer) | |
306 (define-key Man-mode-map "<" 'beginning-of-buffer) | |
307 (define-key Man-mode-map "." 'beginning-of-buffer) | |
308 (define-key Man-mode-map "r" 'Man-follow-manual-reference) | |
309 (define-key Man-mode-map "g" 'Man-goto-section) | |
310 (define-key Man-mode-map "s" 'Man-goto-see-also-section) | |
311 (define-key Man-mode-map "k" 'Man-kill) | |
312 (define-key Man-mode-map "q" 'Man-quit) | |
313 (define-key Man-mode-map "m" 'man) | |
314 (define-key Man-mode-map "?" 'describe-mode) | |
315 ) | |
316 | |
317 | |
318 ;; ====================================================================== | |
319 ;; utilities | |
320 | |
321 (defun Man-init-defvars () | |
322 "Used for initialising variables based on the value of window-system. | |
323 This is necessary if one wants to dump man.el with emacs." | |
324 | |
325 ;; The following is necessary until fonts are implemented on | |
326 ;; terminals. | |
327 (setq Man-fontify-manpage-flag (and Man-fontify-manpage-flag | |
328 window-system)) | |
329 | |
330 (setq Man-sed-script | |
331 (cond | |
332 (Man-fontify-manpage-flag | |
333 nil) | |
334 ((= 0 (call-process Man-sed-command nil nil nil Man-sysv-sed-script)) | |
335 Man-sysv-sed-script) | |
336 ((= 0 (call-process Man-sed-command nil nil nil Man-berkeley-sed-script)) | |
337 Man-berkeley-sed-script) | |
338 (t | |
339 nil))) | |
340 | |
341 (setq Man-filter-list | |
342 (list | |
343 (cons | |
344 Man-sed-command | |
345 (list | |
346 (if Man-sed-script | |
347 (concat "-e '" Man-sed-script "'") | |
348 "") | |
349 "-e '/^[\001-\032][\001-\032]*$/d'" | |
350 "-e '/\e[789]/s///g'" | |
351 "-e '/Reformatting page. Wait/d'" | |
352 "-e '/Reformatting entry. Wait/d'" | |
353 "-e '/^[ \t]*Hewlett-Packard[ \t]Company[ \t]*-[ \t][0-9]*[ \t]-/d'" | |
354 "-e '/^[ \t]*Hewlett-Packard[ \t]*-[ \t][0-9]*[ \t]-.*$/d'" | |
355 "-e '/^[ \t][ \t]*-[ \t][0-9]*[ \t]-[ \t]*Formatted:.*[0-9]$/d'" | |
356 "-e '/^[ \t]*Page[ \t][0-9]*.*(printed[ \t][0-9\\/]*)$/d'" | |
357 "-e '/^Printed[ \t][0-9].*[0-9]$/d'" | |
358 "-e '/^[ \t]*X[ \t]Version[ \t]1[01].*Release[ \t][0-9]/d'" | |
359 "-e '/^[A-za-z].*Last[ \t]change:/d'" | |
360 "-e '/^Sun[ \t]Release[ \t][0-9].*[0-9]$/d'" | |
361 "-e '/[ \t]*Copyright [0-9]* UNIX System Laboratories, Inc.$/d'" | |
362 "-e '/^[ \t]*Rev\\..*Page [0-9][0-9]*$/d'" | |
363 )) | |
364 (cons | |
365 Man-awk-command | |
366 (list | |
367 "'\n" | |
368 "BEGIN { blankline=0; anonblank=0; }\n" | |
369 "/^$/ { if (anonblank==0) next; }\n" | |
370 "{ anonblank=1; }\n" | |
371 "/^$/ { blankline++; next; }\n" | |
372 "{ if (blankline>0) { print \"\"; blankline=0; } print $0; }\n" | |
373 "'" | |
374 )) | |
375 (if (not Man-uses-untabify-flag) | |
376 (cons | |
377 Man-untabify-command | |
378 Man-untabify-command-args) | |
379 ))) | |
380 ) | |
381 | |
382 (defsubst Man-match-substring (&optional n string) | |
383 "Return the substring matched by the last search. | |
384 Optional arg N means return the substring matched by the Nth paren | |
385 grouping. Optional second arg STRING means return a substring from | |
386 that string instead of from the current buffer." | |
387 (if (null n) (setq n 0)) | |
388 (if string | |
389 (substring string (match-beginning n) (match-end n)) | |
390 (buffer-substring (match-beginning n) (match-end n)))) | |
391 | |
392 (defsubst Man-make-page-mode-string () | |
393 "Formats part of the mode line for Man mode." | |
394 (format "%s page %d of %d" | |
395 (or (nth 2 (nth (1- Man-current-page) Man-page-list)) | |
396 "") | |
397 Man-current-page | |
398 (length Man-page-list))) | |
399 | |
400 (defsubst Man-build-man-command () | |
401 "Builds the entire background manpage and cleaning command." | |
402 (let ((command (concat manual-program " " Man-switches " %s 2>/dev/null")) | |
403 (flist Man-filter-list)) | |
404 (while (and flist (car flist)) | |
405 (let ((pcom (car (car flist))) | |
406 (pargs (cdr (car flist)))) | |
407 (setq command | |
408 (concat command " | " pcom " " | |
409 (mapconcat '(lambda (phrase) | |
410 (if (not (stringp phrase)) | |
411 (error "Malformed Man-filter-list")) | |
412 phrase) | |
413 pargs " "))) | |
414 (setq flist (cdr flist)))) | |
415 command)) | |
416 | |
417 (defun Man-translate-references (ref) | |
418 "Translates REF from \"chmod(2V)\" to \"2v chmod\" style. | |
419 Leave it as is if already in that style. Possibly downcase and | |
420 translate the section (see the Man-downcase-section-letters-flag | |
421 and the Man-section-translations-alist variables)." | |
422 (let ((name "") | |
423 (section "") | |
424 (slist Man-section-translations-alist)) | |
425 (cond | |
426 ;; "chmod(2V)" case ? | |
427 ((string-match (concat "^" Man-reference-regexp "$") ref) | |
428 (setq name (Man-match-substring 1 ref) | |
429 section (Man-match-substring 2 ref))) | |
430 ;; "2v chmod" case ? | |
431 ((string-match (concat "^\\(" Man-section-regexp | |
432 "\\) +\\(" Man-name-regexp "\\)$") ref) | |
433 (setq name (Man-match-substring 2 ref) | |
434 section (Man-match-substring 1 ref)))) | |
435 (if (string= name "") | |
436 ref ; Return the reference as is | |
437 (if Man-downcase-section-letters-flag | |
438 (setq section (downcase section))) | |
439 (while slist | |
440 (let ((s1 (car (car slist))) | |
441 (s2 (cdr (car slist)))) | |
442 (setq slist (cdr slist)) | |
443 (if Man-downcase-section-letters-flag | |
444 (setq s1 (downcase s1))) | |
445 (if (not (string= s1 section)) nil | |
446 (setq section (if Man-downcase-section-letters-flag | |
447 (downcase s2) | |
448 s2) | |
449 slist nil)))) | |
450 (concat Man-specified-section-option section " " name)))) | |
451 | |
452 | |
453 ;; ====================================================================== | |
454 ;; default man entry: get word under point | |
455 | |
456 (defsubst Man-default-man-entry () | |
457 "Make a guess at a default manual entry. | |
458 This guess is based on the text surrounding the cursor, and the | |
459 default section number is selected from `Man-auto-section-alist'." | |
460 (let (default-title) | |
461 (save-excursion | |
462 | |
463 ;; Default man entry title is any word the cursor is on, or if | |
464 ;; cursor not on a word, then nearest preceding word. Cannot | |
465 ;; use the current-word function because it skips the dots. | |
466 (if (not (looking-at "[-a-zA-Z_.]")) | |
467 (skip-chars-backward "^a-zA-Z")) | |
468 (skip-chars-backward "-(a-zA-Z_0-9_.") | |
469 (if (looking-at "(") (forward-char 1)) | |
470 (setq default-title | |
471 (buffer-substring | |
472 (point) | |
473 (progn (skip-chars-forward "-a-zA-Z0-9_.") (point)))) | |
474 | |
475 ;; If looking at something like ioctl(2) or brc(1M), include the | |
476 ;; section number in the returned value. Remove text properties. | |
477 (let ((result (concat | |
478 default-title | |
479 (if (looking-at | |
480 (concat "[ \t]*([ \t]*\\(" | |
481 Man-section-regexp "\\)[ \t]*)")) | |
482 (format "(%s)" (Man-match-substring 1)))))) | |
483 (set-text-properties 0 (length result) nil result) | |
484 result)))) | |
485 | |
486 | |
487 ;; ====================================================================== | |
488 ;; Top level command and background process sentinel | |
489 | |
490 ;; For compatibility with older versions. | |
491 ;;;###autoload | 282 ;;;###autoload |
492 (defalias 'manual-entry 'man) | 283 (defun manual-entry (topic &optional arg silent) |
493 | 284 "Display the Unix manual entry (or entries) for TOPIC. |
494 ;;;###autoload | 285 If prefix arg is given, modify the search according to the value: |
495 (defun man (man-args) | 286 2 = complement default exact matching of the TOPIC name; |
496 "Get a Un*x manual page and put it in a buffer. | 287 exact matching default is specified by `Manual-match-topic-exactly' |
497 This command is the top-level command in the man package. It runs a Un*x | 288 3 = force a search of the unformatted man directories |
498 command to retrieve and clean a manpage in the background and places the | 289 4 = both 2 and 3 |
499 results in a Man mode (manpage browsing) buffer. See variable | 290 The manual entries are searched according to the variable |
500 `Man-notify-method' for what happens when the buffer is ready. | 291 Manual-directory-list, which should be a list of directories. If |
501 If a buffer already exists for this man page, it will display immediately." | 292 Manual-directory-list is nil, \\[Manual-directory-list-init] is |
293 invoked to create this list from the MANPATH environment variable. | |
294 See the variable Manual-topic-buffer which controls how the buffer | |
295 is named. See also the variables Manual-match-topic-exactly, | |
296 Manual-query-multiple-pages, and Manual-buffer-view-mode." | |
502 (interactive | 297 (interactive |
503 (list (let* ((default-entry (Man-default-man-entry)) | 298 (list (let* ((fmh "-A-Za-z0-9_.") |
504 (input (read-string | 299 (default (save-excursion |
505 (format "Manual entry%s: " | 300 (buffer-substring |
506 (if (string= default-entry "") | 301 (progn |
507 "" | 302 (re-search-backward "\\sw" nil t) |
508 (format " (default %s)" default-entry)))))) | 303 (skip-chars-backward fmh) (point)) |
509 (if (string= input "") | 304 (progn (skip-chars-forward fmh) (point))))) |
510 (if (string= default-entry "") | 305 (thing (read-string |
511 (error "No man args given") | 306 (if (equal default "") "Manual entry: " |
512 default-entry) | 307 (concat "Manual entry: (default " default ") "))))) |
513 input)))) | 308 (if (equal thing "") default thing)) |
514 | 309 (prefix-numeric-value current-prefix-arg))) |
515 ;; Possibly translate the "subject(section)" syntax into the | 310 ;;(interactive "sManual entry (topic): \np") |
516 ;; "section subject" syntax and possibly downcase the section. | 311 (or arg (setq arg 1)) |
517 (setq man-args (Man-translate-references man-args)) | 312 (Manual-directory-list-init nil) |
518 | 313 (let ((exact (if (or (= arg 2) (= arg 4)) |
519 (Man-getpage-in-background man-args)) | 314 (not Manual-match-topic-exactly) |
520 | 315 Manual-match-topic-exactly)) |
521 | 316 (force (if (>= arg 3) |
522 (defun Man-getpage-in-background (topic) | 317 t |
523 "Uses TOPIC to build and fire off the manpage and cleaning command." | 318 nil)) |
524 (let* ((man-args topic) | 319 section fmtlist manlist apropos-mode) |
525 (bufname (concat "*Man " man-args "*")) | 320 (let ((case-fold-search nil)) |
526 (buffer (get-buffer bufname))) | 321 (if (and (null section) |
527 (if buffer | 322 (string-match |
528 (Man-notify-when-ready buffer) | 323 "\\`[ \t]*\\([^( \t]+\\)[ \t]*(\\(.+\\))[ \t]*\\'" topic)) |
529 (require 'env) | 324 (setq section (substring topic (match-beginning 2) |
530 (message "Invoking %s %s in the background" manual-program man-args) | 325 (match-end 2)) |
531 (setq buffer (generate-new-buffer bufname)) | 326 topic (substring topic (match-beginning 1) |
327 (match-end 1))) | |
328 (if (string-match "\\`[ \t]*-k[ \t]+\\([^ \t]+\\)\\'" topic) | |
329 (setq section "-k" | |
330 topic (substring topic (match-beginning 1)))))) | |
331 (if (equal section "-k") | |
332 (setq apropos-mode t) | |
333 (or silent | |
334 (message "Looking for formatted entry for %s%s..." | |
335 topic (if section (concat "(" section ")") ""))) | |
336 (setq fmtlist (Manual-select-man-pages | |
337 Manual-formatted-directory-list | |
338 topic section exact '())) | |
339 (if (or force (not section) (null fmtlist)) | |
340 (progn | |
341 (or silent | |
342 (message "%sooking for unformatted entry for %s%s..." | |
343 (if fmtlist "L" "No formatted entry, l") | |
344 topic (if section (concat "(" section ")") ""))) | |
345 (setq manlist (Manual-select-man-pages | |
346 Manual-unformatted-directory-list | |
347 topic section exact (if force '() fmtlist)))))) | |
348 | |
349 ;; Delete duplicate man pages (a file of the same name in multiple | |
350 ;; directories.) | |
351 (or nil ;force | |
352 (let ((rest (append fmtlist manlist))) | |
353 (while rest | |
354 (let ((rest2 (cdr rest))) | |
355 (while rest2 | |
356 (if (equal (file-name-nondirectory (car rest)) | |
357 (file-name-nondirectory (car rest2))) | |
358 (setq fmtlist (delq (car rest2) fmtlist) | |
359 manlist (delq (car rest2) manlist))) | |
360 (setq rest2 (cdr rest2)))) | |
361 (setq rest (cdr rest))))) | |
362 | |
363 (if (not (or fmtlist manlist apropos-mode)) | |
364 (progn | |
365 (message "No entries found for %s%s" topic | |
366 (if section (concat "(" section ")") "")) | |
367 nil) | |
368 (let ((bufname (cond ((not Manual-topic-buffer) | |
369 ;; What's the point of retaining this? | |
370 (if apropos-mode | |
371 "*Manual Apropos*" | |
372 "*Manual Entry*")) | |
373 (apropos-mode | |
374 (concat "*man apropos " topic "*")) | |
375 (t | |
376 (concat "*man " | |
377 (cond (exact | |
378 (if section | |
379 (concat topic "." section) | |
380 topic)) | |
381 ((or (cdr fmtlist) (cdr manlist) | |
382 (and fmtlist manlist)) | |
383 ;; more than one entry found | |
384 (concat topic "...")) | |
385 (t | |
386 (file-name-nondirectory | |
387 (car (or fmtlist manlist))))) | |
388 "*")))) | |
389 (temp-buffer-show-function | |
390 (cond ((eq 't Manual-buffer-view-mode) 'view-buffer) | |
391 ((eq 'nil Manual-buffer-view-mode) | |
392 temp-buffer-show-function) | |
393 (t 'view-buffer-other-window)))) | |
394 | |
395 (if apropos-mode | |
396 (setq manlist (list (format "%s.%s" topic section)))) | |
397 | |
398 (cond | |
399 ((and Manual-topic-buffer (get-buffer bufname)) | |
400 ;; reselect an old man page buffer if it exists already. | |
401 (save-excursion | |
402 (set-buffer (get-buffer bufname)) | |
403 (Manual-mode)) | |
404 (if temp-buffer-show-function | |
405 (funcall temp-buffer-show-function (get-buffer bufname)) | |
406 (display-buffer bufname))) | |
407 (t | |
408 (with-output-to-temp-buffer bufname | |
409 (buffer-disable-undo standard-output) | |
410 (save-excursion | |
411 (set-buffer standard-output) | |
412 (setq buffer-read-only nil) | |
413 (erase-buffer) | |
414 (Manual-insert-pages fmtlist manlist apropos-mode) | |
415 (set-buffer-modified-p nil) | |
416 (Manual-mode) | |
417 )))) | |
418 (setq Manual-page-history | |
419 (cons (buffer-name) | |
420 (delete (buffer-name) Manual-page-history))) | |
421 (message nil) | |
422 t)))) | |
423 | |
424 (defun Manpage-apropos (topic &optional arg silent) | |
425 "Apropos on Unix manual pages for TOPIC. | |
426 It calls the function `manual-entry'. Look at this function for | |
427 further description. Look also at the variable `Manual-apropos-switch', | |
428 if this function doesn't work on your system." | |
429 (interactive | |
430 (list (let* ((fmh "-A-Za-z0-9_.") | |
431 (default (save-excursion | |
432 (buffer-substring | |
433 (progn | |
434 (re-search-backward "\\sw" nil t) | |
435 (skip-chars-backward fmh) (point)) | |
436 (progn (skip-chars-forward fmh) (point))))) | |
437 (thing (read-string | |
438 (if (equal default "") "Manual entry: " | |
439 (concat "Manual entry: (default " default ") "))))) | |
440 (if (equal thing "") default thing)) | |
441 (prefix-numeric-value current-prefix-arg))) | |
442 (manual-entry (concat Manual-apropos-switch " " topic) arg silent)) | |
443 | |
444 (defun Manual-insert-pages (fmtlist manlist apropos-mode) | |
445 (let ((sep (make-string 65 ?-)) | |
446 name start end topic section) | |
447 (while fmtlist ; insert any formatted files | |
448 (setq name (car fmtlist)) | |
449 (goto-char (point-max)) | |
450 (setq start (point)) | |
451 ;; In case the file can't be read or uncompressed or | |
452 ;; something like that. | |
453 (condition-case () | |
454 (Manual-insert-man-file name) | |
455 (file-error nil)) | |
456 (goto-char (point-max)) | |
457 (setq end (point)) | |
532 (save-excursion | 458 (save-excursion |
533 (set-buffer buffer) | 459 (save-restriction |
534 (setq Man-original-frame (selected-frame)) | 460 (message "Cleaning manual entry for %s..." |
535 (setq Man-arguments man-args)) | 461 (file-name-nondirectory name)) |
536 (let ((process-environment (copy-sequence process-environment))) | 462 (narrow-to-region start end) |
537 ;; Prevent any attempt to use display terminal fanciness. | 463 (Manual-nuke-nroff-bs) |
538 (setenv "TERM" "dumb") | 464 (goto-char (point-min)) |
539 (set-process-sentinel | 465 (insert "File: " name "\n") |
540 (start-process manual-program buffer "sh" "-c" | 466 (goto-char (point-max)) |
541 (format (Man-build-man-command) man-args)) | 467 )) |
542 'Man-bgproc-sentinel))))) | 468 (if (or (cdr fmtlist) manlist) |
543 | 469 (insert "\n\n" sep "\n")) |
544 (defun Man-notify-when-ready (man-buffer) | 470 (setq fmtlist (cdr fmtlist))) |
545 "Notify the user when MAN-BUFFER is ready. | 471 |
546 See the variable `Man-notify-method' for the different notification behaviors." | 472 (while manlist ; process any unformatted files |
547 (let ((saved-frame (save-excursion | 473 (setq name (car manlist)) |
548 (set-buffer man-buffer) | 474 (or (string-match "\\([^/]+\\)\\.\\([^./]+\\)\\(\\.gz\\'\\)" name) |
549 Man-original-frame))) | 475 (string-match "\\([^/]+\\)\\.\\([^./]+\\)\\'" name)) |
550 (cond | 476 (setq topic (substring name (match-beginning 1) (match-end 1))) |
551 ((eq Man-notify-method 'newframe) | 477 (setq section (substring name (match-beginning 2) (match-end 2))) |
552 ;; Since we run asynchronously, perhaps while Emacs is waiting | 478 ;; This won't work under IRIX, because SGI man accepts only the |
553 ;; for input, we must not leave a different buffer current. We | 479 ;; "main" (one-character) section id, not full section ids |
554 ;; can't rely on the editor command loop to reselect the | 480 ;; like 1M, 3X, etc. Put (setq Manual-use-full-section-ids nil) |
555 ;; selected window's buffer. | 481 ;; in your .emacs to work around this problem. |
482 (if (not (or Manual-use-full-section-ids (string-equal section ""))) | |
483 (setq section (substring section 0 1))) | |
484 (message "Invoking man %s%s %s..." | |
485 (if Manual-section-switch | |
486 (concat Manual-section-switch " ") | |
487 "") | |
488 section topic) | |
489 (setq start (point)) | |
490 (Manual-run-formatter name topic section) | |
491 (setq end (point)) | |
556 (save-excursion | 492 (save-excursion |
557 (set-buffer man-buffer) | 493 (save-restriction |
558 (make-frame Man-frame-parameters))) | 494 (message "Cleaning manual entry for %s(%s)..." topic section) |
559 ((eq Man-notify-method 'pushy) | 495 (narrow-to-region start end) |
560 (switch-to-buffer man-buffer)) | 496 (Manual-nuke-nroff-bs apropos-mode) |
561 ((eq Man-notify-method 'bully) | 497 (goto-char (point-min)) |
562 (and window-system | 498 (insert "File: " name "\n") |
563 (frame-live-p saved-frame) | 499 (goto-char (point-max)) |
564 (select-frame saved-frame)) | 500 )) |
565 (pop-to-buffer man-buffer) | 501 (if (cdr manlist) |
566 (delete-other-windows)) | 502 (insert "\n\n" sep "\n")) |
567 ((eq Man-notify-method 'aggressive) | 503 (setq manlist (cdr manlist)))) |
568 (and window-system | 504 (if (< (buffer-size) 200) |
569 (frame-live-p saved-frame) | 505 (progn |
570 (select-frame saved-frame)) | 506 (goto-char (point-min)) |
571 (pop-to-buffer man-buffer)) | 507 (if (looking-at "^File: ") |
572 ((eq Man-notify-method 'friendly) | 508 (forward-line 1)) |
573 (and window-system | 509 (error (buffer-substring (point) (progn (end-of-line) (point)))))) |
574 (frame-live-p saved-frame) | 510 nil) |
575 (select-frame saved-frame)) | 511 |
576 (display-buffer man-buffer 'not-this-window)) | 512 |
577 ((eq Man-notify-method 'polite) | 513 (defun Manual-run-formatter (name topic section) |
578 (beep) | 514 (cond ((string-match "roff\\'" Manual-program) |
579 (message "Manual buffer %s is ready" (buffer-name man-buffer))) | 515 ;; kludge kludge |
580 ((eq Man-notify-method 'quiet) | 516 (call-process Manual-program nil t nil "-Tman" "-man" name)) |
581 (message "Manual buffer %s is ready" (buffer-name man-buffer))) | 517 (Manual-section-switch |
582 ((or (eq Man-notify-method 'meek) | 518 (call-process Manual-program nil t nil Manual-section-switch |
583 t) | 519 section topic)) |
584 (message "")) | 520 (t |
585 ))) | 521 (call-process Manual-program nil t nil section topic)))) |
586 | 522 |
587 (defun Man-fontify-manpage () | 523 |
588 "Convert overstriking and underlining to the correct fonts. | 524 (defvar Manual-mode-map |
589 Same for the ANSI bold and normal escape sequences." | 525 (let ((m (make-sparse-keymap))) |
526 (set-keymap-name m 'Manual-mode-map) | |
527 (define-key m "l" 'Manual-last-page) | |
528 (define-key m 'button2 'Manual-follow-xref) | |
529 (define-key m 'button3 'Manual-popup-menu) | |
530 m)) | |
531 | |
532 (defun Manual-mode () | |
533 (kill-all-local-variables) | |
534 (setq buffer-read-only t) | |
535 (use-local-map Manual-mode-map) | |
536 (setq major-mode 'Manual-mode | |
537 mode-name "Manual") | |
538 ;; man pages with long lines are buggy! | |
539 ;; This looks slightly better if they only | |
540 ;; overran by a couple of chars. | |
541 (setq truncate-lines t) | |
542 ;; turn off horizontal scrollbars in this buffer | |
543 (set-specifier scrollbar-height (cons (current-buffer) 0)) | |
544 (run-hooks 'Manual-mode-hook)) | |
545 | |
546 (defun Manual-last-page () | |
590 (interactive) | 547 (interactive) |
591 (message "Please wait: making up the %s man page..." Man-arguments) | 548 (while (or (not (get-buffer (car (or Manual-page-history |
592 (goto-char (point-min)) | 549 (error "No more history."))))) |
593 (while (search-forward "\e[1m" nil t) | 550 (eq (get-buffer (car Manual-page-history)) (current-buffer))) |
594 (delete-backward-char 4) | 551 (setq Manual-page-history (cdr Manual-page-history))) |
595 (put-text-property (point) | 552 (switch-to-buffer (car Manual-page-history))) |
596 (progn (if (search-forward "\e[0m" nil 'move) | 553 |
597 (delete-backward-char 4)) | 554 |
598 (point)) | 555 ;; Manual-select-subdirectories |
599 'face Man-overstrike-face)) | 556 ;; Given a DIRLIST and a SUBDIR name, return all subdirectories of the former which |
557 ;; match the latter. | |
558 | |
559 (defun Manual-select-subdirectories (dirlist subdir) | |
560 (let ((dirs '()) | |
561 (case-fold-search nil) | |
562 (match (concat "\\`" (regexp-quote subdir))) | |
563 d) | |
564 (while dirlist | |
565 (setq d (car dirlist) dirlist (cdr dirlist)) | |
566 (if (file-directory-p d) | |
567 (let ((files (directory-files d t match nil 'dirs-only)) | |
568 (dir-temp '())) | |
569 (while files | |
570 (if (file-executable-p (car files)) | |
571 (setq dir-temp (cons (file-name-as-directory (car files)) | |
572 dir-temp))) | |
573 (setq files (cdr files))) | |
574 (and dir-temp | |
575 (setq dirs (append dirs (nreverse dir-temp))))))) | |
576 dirs)) | |
577 | |
578 | |
579 ;; Manual-filter-subdirectories | |
580 ;; Given a DIRLIST and a SUBDIR name, return all members of the former | |
581 ;; which match the latter. | |
582 | |
583 (defun Manual-filter-subdirectories (dirlist subdir) | |
584 (let ((match (concat | |
585 "/" | |
586 (regexp-quote subdir) | |
587 "[" Manual-man-page-section-ids "]")) | |
588 slist dir) | |
589 (while dirlist | |
590 (setq dir (car dirlist) dirlist (cdr dirlist)) | |
591 (if (and (file-executable-p dir) (string-match match dir)) | |
592 (setq slist (cons dir slist)))) | |
593 (nreverse slist))) | |
594 | |
595 | |
596 (defun Manual-all-subdirectories (dirlist leaf-signature dirs &optional silent) "\ | |
597 Given a DIRLIST, return a backward-sorted list of all subdirectories | |
598 thereof, prepended to DIRS if non-nil. This function calls itself | |
599 recursively until subdirectories matching LEAF-SIGNATURE are reached, | |
600 or the hierarchy has been thoroughly searched. This code is a modified | |
601 version of a function written by Tim Bradshaw (tfb@ed.ac.uk)." | |
602 (Manual-all-subdirectories-noloop dirlist leaf-signature dirs nil silent)) | |
603 | |
604 (defun Manual-all-subdirectories-noloop (dirlist leaf-signature dirs been &optional silent) "\ | |
605 Does the job of manual-all-subdirectories and keeps track of where it | |
606 has been to avoid loops." | |
607 (let (dir) | |
608 (while dirlist | |
609 (setq dir (car dirlist) dirlist (cdr dirlist)) | |
610 (if (file-directory-p dir) | |
611 (let ((dir-temp (cons (file-name-as-directory dir) dirs))) | |
612 ;; Without feedback the user might wonder about the delay! | |
613 (or silent (message | |
614 "Building list of search directories... %s" | |
615 (car dir-temp))) | |
616 (if (member (file-truename dir) been) | |
617 () ; Ignore. We have been here before | |
618 (setq been (cons (file-truename dir) been)) | |
619 (setq dirs | |
620 (if (string-match leaf-signature dir) | |
621 dir-temp | |
622 (Manual-all-subdirectories-noloop | |
623 (directory-files dir t "[^.]$" nil 'dirs-only) | |
624 leaf-signature dir-temp been silent)))))))) | |
625 dirs) | |
626 | |
627 | |
628 (defvar Manual-bogus-file-pattern "\\.\\(lpr\\|ps\\|PS\\)\\'" | |
629 "Some systems have files in the man/man*/ directories which aren't man pages. | |
630 This pattern is used to prune those files.") | |
631 | |
632 ;; Manual-select-man-pages | |
633 ;; | |
634 ;; Given a DIRLIST, discover all filenames which complete given the TOPIC | |
635 ;; and SECTION. | |
636 | |
637 ;; ## Note: BSD man looks for .../man1/foo.1 and .../man1/$MACHINE/foo.1 | |
638 | |
639 ;; ## Fixed for SGI IRIX 5.x on Sat Jul 15 1995 by Dale Atems | |
640 ;; (atems@physics.wayne.edu). | |
641 | |
642 (defun Manual-select-man-pages (dirlist topic section exact shadow) | |
643 (let ((case-fold-search nil)) | |
644 (and section | |
645 (let ((l '()) | |
646 ;;(match (concat (substring section 0 1) "/?\\'")) | |
647 ;; ^^^ | |
648 ;; We'll lose any pages inside subdirectories of the "standard" | |
649 ;; ones if we insist on this! The following regexp should | |
650 ;; match any directory ending with the full section id or | |
651 ;; its first character, or any direct subdirectory thereof: | |
652 (match (concat "\\(" | |
653 (regexp-quote section) | |
654 "\\|" | |
655 (substring section 0 1) | |
656 "\\)/?")) | |
657 d) | |
658 (while dirlist | |
659 (setq d (car dirlist) dirlist (cdr dirlist)) | |
660 (if (string-match match d) | |
661 (setq l (cons d l)))) | |
662 (setq dirlist l))) | |
663 (if shadow | |
664 (setq shadow (concat "/\\(" | |
665 (mapconcat #'(lambda (n) | |
666 (regexp-quote | |
667 (file-name-nondirectory n))) | |
668 shadow | |
669 "\\|") | |
670 "\\)\\'"))) | |
671 (let ((manlist '()) | |
672 (match (concat "\\`" | |
673 (regexp-quote topic) | |
674 ;; **Note: on IRIX the preformatted pages | |
675 ;; are packed, so they end with ".z". This | |
676 ;; way you miss them if you specify a | |
677 ;; section. I don't see any point to it here | |
678 ;; even on BSD systems since we're looking | |
679 ;; one level down already, but I can't test | |
680 ;; this. More thought needed (???) | |
681 | |
682 (cond ((and section | |
683 (not Manual-use-subdirectory-list)) | |
684 (concat "\\." (regexp-quote section))) | |
685 (exact | |
686 ;; If Manual-match-topic-exactly is | |
687 ;; set, then we must make sure the | |
688 ;; completions are exact, except for | |
689 ;; trailing weird characters after | |
690 ;; the section. | |
691 "\\.") | |
692 (t | |
693 "")))) | |
694 dir) | |
695 (while dirlist | |
696 (setq dir (car dirlist) dirlist (cdr dirlist)) | |
697 (if (not (file-directory-p dir)) | |
698 (progn | |
699 (message "warning: %s is not a directory" dir) | |
700 ;;(sit-for 1) | |
701 ) | |
702 (let ((files (directory-files dir t match nil t)) | |
703 f) | |
704 (while files | |
705 (setq f (car files) files (cdr files)) | |
706 (cond ((string-match Manual-bogus-file-pattern f) | |
707 ;(message "Bogus fule %s" f) (sit-for 2) | |
708 ) | |
709 ((and shadow (string-match shadow f)) | |
710 ;(message "Shadowed %s" f) (sit-for 2) | |
711 ) | |
712 ((not (file-readable-p f)) | |
713 ;(message "Losing with %s" f) (sit-for 2) | |
714 ) | |
715 (t | |
716 (setq manlist (cons f manlist)))))))) | |
717 (setq manlist (nreverse manlist)) | |
718 (and Manual-unique-man-sections-only | |
719 (setq manlist (Manual-clean-to-unique-pages-only manlist))) | |
720 (if (and manlist Manual-query-multiple-pages) | |
721 (apply #'append | |
722 (mapcar #'(lambda (page) | |
723 (and page | |
724 (y-or-n-p (format "Read %s? " page)) | |
725 (list page))) | |
726 manlist)) | |
727 manlist)))) | |
728 | |
729 (defun Manual-clean-to-unique-pages-only (manlist) | |
730 "Prune the current list of pages down to a unique set." | |
731 (let (page-name unique-pages) | |
732 (apply 'append | |
733 (mapcar '(lambda (page) | |
734 (cond (page | |
735 (and (string-match ".*/\\(.*\\)" page) | |
736 (setq page-name (substring page (match-beginning 1) | |
737 (match-end 1))) | |
738 ;; try to clip off .Z, .gz suffixes | |
739 (and (string-match "\\(.*\\)\\.\\(.+\\)\\.\\(.+\\)" | |
740 page-name) | |
741 (setq page-name | |
742 (substring page-name (match-beginning 1) | |
743 (match-end 2))))) | |
744 ;; add Manual-unique-pages if it isn't there | |
745 ;; and return file | |
746 (if (and unique-pages | |
747 page-name | |
748 (string-match (concat "\\b" page-name "\\b") | |
749 unique-pages)) | |
750 nil | |
751 (setq unique-pages (concat unique-pages | |
752 page-name | |
753 " ")) | |
754 (list page))))) | |
755 manlist)))) | |
756 | |
757 | |
758 | |
759 (defun Manual-insert-man-file (name) | |
760 ;; Insert manual file (unpacked as necessary) into buffer | |
761 (cond ((equal (substring name -3) ".gz") | |
762 (call-process "gunzip" nil t nil "--stdout" name)) | |
763 ((or (equal (substring name -2) ".Z") | |
764 ;; HPUX uses directory names that end in .Z and compressed | |
765 ;; files that don't. How gratuitously random. | |
766 (let ((case-fold-search nil)) | |
767 (string-match "\\.Z/" name))) | |
768 (call-process "zcat" name t nil)) ;; XEmacs change for HPUX | |
769 ((equal (substring name -2) ".z") | |
770 (call-process "pcat" nil t nil name)) | |
771 (t | |
772 (insert-file-contents name)))) | |
773 | |
774 (defmacro Manual-delete-char (n) | |
775 ;; in v19, delete-char is compiled as a function call, but delete-region | |
776 ;; is byte-coded, so it's much faster. (We were spending 40% of our time | |
777 ;; in delete-char alone.) | |
778 (list 'delete-region '(point) (list '+ '(point) n))) | |
779 | |
780 ;; Hint: BS stands form more things than "back space" | |
781 (defun Manual-nuke-nroff-bs (&optional apropos-mode) | |
782 (interactive "*") | |
783 ;; | |
784 ;; turn underlining into italics | |
785 ;; | |
600 (goto-char (point-min)) | 786 (goto-char (point-min)) |
601 (while (search-forward "_\b" nil t) | 787 (while (search-forward "_\b" nil t) |
602 (backward-delete-char 2) | 788 ;; searching for underscore-backspace and then comparing the following |
603 (put-text-property (point) (1+ (point)) 'face Man-underline-face)) | 789 ;; chars until the sequence ends turns out to be much faster than searching |
790 ;; for a regexp which matches the whole sequence. | |
791 (let ((s (match-beginning 0))) | |
792 (goto-char s) | |
793 (while (and (= (following-char) ?_) | |
794 (= (char-after (1+ (point))) ?\b)) | |
795 (Manual-delete-char 2) | |
796 (forward-char 1)) | |
797 (set-extent-face (make-extent s (point)) 'man-italic))) | |
798 ;; | |
799 ;; turn overstriking into bold | |
800 ;; | |
604 (goto-char (point-min)) | 801 (goto-char (point-min)) |
605 (while (search-forward "\b_" nil t) | 802 (while (re-search-forward "\\([^\n]\\)\\(\b\\1\\)" nil t) |
606 (backward-delete-char 2) | 803 ;; Surprisingly, searching for the above regexp is faster than searching |
607 (put-text-property (1- (point)) (point) 'face Man-underline-face)) | 804 ;; for a backspace and then comparing the preceding and following chars, |
805 ;; I presume because there are many false matches, meaning more funcalls | |
806 ;; to re-search-forward. | |
807 (let ((s (match-beginning 0))) | |
808 (goto-char s) | |
809 ;; Some systems (SGI) overstrike multiple times, eg, "M\bM\bM\bM". | |
810 (while (looking-at "\\([^\n]\\)\\(\b\\1\\)+") | |
811 (delete-region (+ (point) 1) (match-end 0)) | |
812 (forward-char 1)) | |
813 (set-extent-face (make-extent s (point)) 'man-bold))) | |
814 ;; | |
815 ;; hack bullets: o^H+ --> + | |
608 (goto-char (point-min)) | 816 (goto-char (point-min)) |
609 (while (re-search-forward "\\(.\\)\\(\b\\1\\)+" nil t) | 817 (while (search-forward "\b" nil t) |
610 (replace-match "\\1") | 818 (Manual-delete-char -2)) |
611 (put-text-property (1- (point)) (point) 'face Man-overstrike-face)) | 819 |
820 (if (> (buffer-size) 100) ; minor kludge | |
821 (Manual-nuke-nroff-bs-footers)) | |
822 ;; | |
823 ;; turn subsection header lines into bold | |
824 ;; | |
612 (goto-char (point-min)) | 825 (goto-char (point-min)) |
613 (while (re-search-forward "o\b\\+\\|\\+\bo" nil t) | 826 (if apropos-mode |
614 (replace-match "o") | 827 (while (re-search-forward "[a-zA-Z0-9] ([0-9]" nil t) |
615 (put-text-property (1- (point)) (point) 'face 'bold)) | 828 (forward-char -2) |
829 (delete-backward-char 1)) | |
830 | |
831 ;; (while (re-search-forward "^[^ \t\n]" nil t) | |
832 ;; (set-extent-face (make-extent (match-beginning 0) | |
833 ;; (progn (end-of-line) (point))) | |
834 ;; 'man-heading)) | |
835 | |
836 ;; boldface the first line | |
837 (if (looking-at "[^ \t\n].*$") | |
838 (set-extent-face (make-extent (match-beginning 0) (match-end 0)) | |
839 'man-bold)) | |
840 | |
841 ;; boldface subsequent title lines | |
842 ;; Regexp to match section headers changed to match a non-indented | |
843 ;; line preceded by a blank line and followed by an indented line. | |
844 ;; This seems to work ok for manual pages but gives better results | |
845 ;; with other nroff'd files | |
846 (while (re-search-forward "\n\n\\([^ \t\n].*\\)\n[ \t]+[^ \t\n]" nil t) | |
847 (goto-char (match-end 1)) | |
848 (set-extent-face (make-extent (match-beginning 1) (match-end 1)) | |
849 'man-heading) | |
850 (forward-line 1)) | |
851 ) | |
852 | |
853 ;; Zap ESC7, ESC8, and ESC9 | |
854 ;; This is for Sun man pages like "man 1 csh" | |
616 (goto-char (point-min)) | 855 (goto-char (point-min)) |
617 (while (re-search-forward "[-|]\\(\b[-|]\\)+" nil t) | 856 (while (re-search-forward "\e[789]" nil t) |
618 (replace-match "+") | 857 (replace-match "")) |
619 (put-text-property (1- (point)) (point) 'face 'bold)) | 858 |
620 ;; \255 is some kind of dash in Latin-1. | 859 ;; Nuke blanks lines at start. |
860 ;; (goto-char (point-min)) | |
861 ;; (skip-chars-forward "\n") | |
862 ;; (delete-region (point-min) (point)) | |
863 | |
864 (Manual-mouseify-xrefs) | |
865 ) | |
866 | |
867 (fset 'nuke-nroff-bs 'Manual-nuke-nroff-bs) ; use old name | |
868 | |
869 | |
870 (defun Manual-nuke-nroff-bs-footers () | |
871 ;; Nuke headers and footers. | |
872 ;; | |
873 ;; nroff assumes pages are 66 lines high. We assume that, and that the | |
874 ;; first and last line on each page is expendible. There is no way to | |
875 ;; tell the difference between a page break in the middle of a paragraph | |
876 ;; and a page break between paragraphs (the amount of extra whitespace | |
877 ;; that nroff inserts is the same in both cases) so this might strip out | |
878 ;; a blank line were one should remain. I think that's better than | |
879 ;; leaving in a blank line where there shouldn't be one. (Need I say | |
880 ;; it: FMH.) | |
881 ;; | |
882 ;; Note that if nroff spits out error messages, pages will be more than | |
883 ;; 66 lines high, and we'll lose badly. That's ok because standard | |
884 ;; nroff doesn't do any diagnostics, and the "gnroff" wrapper for groff | |
885 ;; turns off error messages for compatibility. (At least, it's supposed | |
886 ;; to.) | |
887 ;; | |
621 (goto-char (point-min)) | 888 (goto-char (point-min)) |
622 (while (search-forward "\255" nil t) (replace-match "-")) | 889 ;; first lose the status output |
623 (message "%s man page made up" Man-arguments)) | 890 (let ((case-fold-search t)) |
624 | 891 (if (and (not (looking-at "[^\n]*warning")) |
625 (defun Man-cleanup-manpage () | 892 (looking-at "Reformatting.*\n")) |
626 "Remove overstriking and underlining from the current buffer." | 893 (delete-region (match-beginning 0) (match-end 0)))) |
627 (interactive) | 894 |
628 (message "Please wait: cleaning up the %s man page..." | 895 ;; kludge around a groff bug where it won't keep quiet about some |
629 Man-arguments) | 896 ;; warnings even with -Wall or -Ww. |
630 (if (or (interactive-p) (not Man-sed-script)) | 897 (cond ((looking-at "grotty:") |
631 (progn | 898 (while (looking-at "grotty:") |
632 (goto-char (point-min)) | 899 (delete-region (point) (progn (forward-line 1) (point)))) |
633 (while (search-forward "_\b" nil t) (backward-delete-char 2)) | 900 (if (looking-at " *done\n") |
634 (goto-char (point-min)) | 901 (delete-region (point) (match-end 0))))) |
635 (while (search-forward "\b_" nil t) (backward-delete-char 2)) | 902 |
636 (goto-char (point-min)) | 903 (let ((pages '()) |
637 (while (re-search-forward "\\(.\\)\\(\b\\1\\)+" nil t) | 904 p) |
638 (replace-match "\\1")) | 905 ;; collect the page boundary markers before we start deleting, to make |
639 (goto-char (point-min)) | 906 ;; it easier to strip things out without changing the page sizes. |
640 (while (re-search-forward "\e\\[[0-9]+m" nil t) (replace-match "")) | 907 (while (not (eobp)) |
641 (goto-char (point-min)) | 908 (forward-line 66) |
642 (while (re-search-forward "o\b\\+\\|\\+\bo" nil t) (replace-match "o")) | 909 (setq pages (cons (point-marker) pages))) |
643 )) | 910 (setq pages (nreverse pages)) |
911 (while pages | |
912 (goto-char (car pages)) | |
913 (set-marker (car pages) nil) | |
914 ;; | |
915 ;; The lines are: 3 blank; footer; 6 blank; header; 3 blank. | |
916 ;; We're in between the previous footer and the following header, | |
917 ;; | |
918 ;; First lose 3 blank lines, the header, and then 3 more. | |
919 ;; | |
920 (setq p (point)) | |
921 (skip-chars-forward "\n") | |
922 (delete-region p (point)) | |
923 (and (looking-at "[^\n]+\n\n?\n?\n?") | |
924 (delete-region (match-beginning 0) (match-end 0))) | |
925 ;; | |
926 ;; Next lose the footer, and the 3 blank lines after, and before it. | |
927 ;; But don't lose the last footer of the manual entry; that contains | |
928 ;; the "last change" date, so it's not completely uninteresting. | |
929 ;; (Actually lose all blank lines before it; sh(1) needs this.) | |
930 ;; | |
931 (skip-chars-backward "\n") | |
932 (beginning-of-line) | |
933 (if (null (cdr pages)) | |
934 nil | |
935 (and (looking-at "[^\n]+\n\n?\n?\n?") | |
936 (delete-region (match-beginning 0) (match-end 0)))) | |
937 (setq p (point)) | |
938 (skip-chars-backward "\n") | |
939 (if (> (- p (point)) 4) | |
940 (delete-region (+ 2 (point)) p) | |
941 (delete-region (1+ (point)) p)) | |
942 ; (and (looking-at "\n\n?\n?") | |
943 ; (delete-region (match-beginning 0) (match-end 0))) | |
944 | |
945 (setq pages (cdr pages))) | |
946 ;; | |
947 ;; Now nuke the extra blank lines at the beginning and end. | |
948 (goto-char (point-min)) | |
949 (if (looking-at "\n+") | |
950 (delete-region (match-beginning 0) (match-end 0))) | |
951 (forward-line 1) | |
952 (if (looking-at "\n\n+") | |
953 (delete-region (1+ (match-beginning 0)) (match-end 0))) | |
954 (goto-char (point-max)) | |
955 (skip-chars-backward "\n") | |
956 (delete-region (point) (point-max)) | |
957 (beginning-of-line) | |
958 (forward-char -1) | |
959 (setq p (point)) | |
960 (skip-chars-backward "\n") | |
961 (if (= ?\n (following-char)) (forward-char 1)) | |
962 (if (> (point) (1+ p)) | |
963 (delete-region (point) p)) | |
964 )) | |
965 | |
966 ;(defun Manual-nuke-nroff-bs-footers () | |
967 ; ;; Nuke headers: "MORE(1) UNIX Programmer's Manual MORE(1)" | |
968 ; (goto-char (point-min)) | |
969 ; (while (re-search-forward "^ *\\([A-Za-z][-_A-Za-z0-9]*([0-9A-Za-z]+)\\).*\\1$" nil t) | |
970 ; (replace-match "")) | |
971 ; | |
972 ; ;; | |
973 ; ;; it would appear that we have a choice between sometimes introducing | |
974 ; ;; an extra blank line when a paragraph was broken by a footer, and | |
975 ; ;; sometimes not putting in a blank line between two paragraphs when | |
976 ; ;; a footer appeared right between them. FMH; I choose the latter. | |
977 ; ;; | |
978 ; | |
979 ; ;; Nuke footers: "Printed 12/3/85 27 April 1981 1" | |
980 ; ;; Sun appear to be on drugz: | |
981 ; ;; "Sun Release 3.0B Last change: 1 February 1985 1" | |
982 ; ;; HP are even worse! | |
983 ; ;; " Hewlett-Packard -1- (printed 12/31/99)" FMHWA12ID!! | |
984 ; ;; System V (well WICATs anyway): | |
985 ; ;; "Page 1 (printed 7/24/85)" | |
986 ; ;; Who is administering PCP to these corporate bozos? | |
987 ; (goto-char (point-min)) | |
988 ; (while (re-search-forward | |
989 ; (cond | |
990 ; ((eq system-type 'hpux) | |
991 ; "\n\n?[ \t]*Hewlett-Packard\\(\\| Company\\)[ \t]*- [0-9]* -.*\n") | |
992 ; ((eq system-type 'dgux-unix) | |
993 ; "\n\n?[ \t]*Licensed material--.*Page [0-9]*\n") | |
994 ; ((eq system-type 'usg-unix-v) | |
995 ; "\n\n? *Page [0-9]*.*(printed [0-9/]*)\n") | |
996 ; (t | |
997 ; "\n\n?\\(Printed\\|Sun Release\\) [0-9].*[0-9]\n")) | |
998 ; nil t) | |
999 ; (replace-match "")) | |
1000 ; | |
1001 ; ;; Also, hack X footers: | |
1002 ; ;; "X Version 11 Last change: Release 5 1" | |
1003 ; (goto-char (point-min)) | |
1004 ; (while (re-search-forward "\n\n?X Version [^\n]+\n" nil t) | |
1005 ; (replace-match "")) | |
1006 ; | |
1007 ; ;; Crunch blank lines | |
1008 ; (goto-char (point-min)) | |
1009 ; (while (re-search-forward "\n\n\n\n*" nil t) | |
1010 ; (replace-match "\n\n")) | |
1011 ; ) | |
1012 | |
1013 (defun Manual-mouseify-xrefs () | |
644 (goto-char (point-min)) | 1014 (goto-char (point-min)) |
645 (while (re-search-forward "[-|]\\(\b[-|]\\)+" nil t) (replace-match "+")) | 1015 (forward-line 1) |
646 ;; \255 is some kind of dash in Latin-1. | 1016 (let ((case-fold-search nil) |
647 (goto-char (point-min)) | 1017 s e name extent) |
648 (while (search-forward "\255" nil t) (replace-match "-")) | 1018 ;; possibly it would be faster to rewrite this expression to search for |
649 (message "%s man page cleaned up" Man-arguments)) | 1019 ;; a less common sequence first (like "([0-9]") and then back up to see |
650 | 1020 ;; if it's really a match. This function is 15% of the total time, 13% |
651 (defun Man-bgproc-sentinel (process msg) | 1021 ;; of which is this call to re-search-forward. |
652 "Manpage background process sentinel." | 1022 (while (re-search-forward "[a-zA-Z_][-a-zA-Z0-9_.]*([0-9][a-zA-Z0-9]*)" |
653 (let ((Man-buffer (process-buffer process)) | 1023 nil t) |
654 (delete-buff nil) | 1024 (setq s (match-beginning 0) |
655 (err-mess nil)) | 1025 e (match-end 0) |
656 | 1026 name (buffer-substring s e)) |
657 (if (null (buffer-name Man-buffer)) ;; deleted buffer | 1027 (goto-char s) |
658 (set-process-buffer process nil) | 1028 (skip-chars-backward " \t") |
659 | 1029 (if (and (bolp) |
660 (save-excursion | 1030 (progn (backward-char 1) (= (preceding-char) ?-))) |
661 (set-buffer Man-buffer) | 1031 (progn |
662 (let ((case-fold-search nil)) | 1032 (setq s (point)) |
663 (goto-char (point-min)) | 1033 (skip-chars-backward "-a-zA-Z0-9_.") |
664 (cond ((or (looking-at "No \\(manual \\)*entry for") | 1034 (setq name (concat (buffer-substring (point) (1- s)) name)) |
665 (looking-at "[^\n]*: nothing appropriate$")) | 1035 (setq s (point)))) |
666 (setq err-mess (buffer-substring (point) | 1036 ;; if there are upper case letters in the section, downcase them. |
667 (progn | 1037 (if (string-match "(.*[A-Z]+.*)$" name) |
668 (end-of-line) (point))) | 1038 (setq name (concat (substring name 0 (match-beginning 0)) |
669 delete-buff t)) | 1039 (downcase (substring name (match-beginning 0)))))) |
670 ((not (and (eq (process-status process) 'exit) | 1040 ;; (setq already-fontified (extent-at s)) |
671 (= (process-exit-status process) 0))) | 1041 (setq extent (make-extent s e)) |
672 (setq err-mess | 1042 (set-extent-property extent 'man (list 'Manual-follow-xref name)) |
673 (concat (buffer-name Man-buffer) | 1043 (set-extent-property extent 'highlight t) |
674 ": process " | 1044 ;; (if (not already-fontified)... |
675 (let ((eos (1- (length msg)))) | 1045 (set-extent-face extent 'man-xref) |
676 (if (= (aref msg eos) ?\n) | 1046 (goto-char e)))) |
677 (substring msg 0 eos) msg)))) | 1047 |
678 (goto-char (point-max)) | 1048 (defun Manual-follow-xref (&optional name-or-event) |
679 (insert (format "\nprocess %s" msg)) | 1049 "Invoke `manual-entry' on the cross-reference under the mouse. |
680 )) | 1050 When invoked noninteractively, the arg may be an xref string to parse instead." |
681 (if delete-buff | 1051 (interactive "e") |
682 (kill-buffer Man-buffer) | 1052 (if (eventp name-or-event) |
683 (if Man-fontify-manpage-flag | 1053 (let* ((p (event-point name-or-event)) |
684 (Man-fontify-manpage) | 1054 (extent (and p (extent-at p |
685 (Man-cleanup-manpage)) | 1055 (event-buffer name-or-event) |
686 (run-hooks 'Man-cooked-hook) | 1056 'highlight))) |
687 (Man-mode) | 1057 (data (and extent (extent-property extent 'man)))) |
688 (set-buffer-modified-p nil) | 1058 (if (eq (car-safe data) 'Manual-follow-xref) |
689 )) | 1059 (eval data) |
690 ;; Restore case-fold-search before calling | 1060 (error "no manual cross-reference there."))) |
691 ;; Man-notify-when-ready because it may switch buffers. | 1061 (let ((Manual-match-topic-exactly t) |
692 | 1062 (Manual-query-multiple-pages nil)) |
693 (if (not delete-buff) | 1063 (or (manual-entry name-or-event) |
694 (Man-notify-when-ready Man-buffer)) | 1064 ;; If that didn't work, maybe it's in a different section than the |
695 | 1065 ;; man page writer expected. For example, man pages tend assume |
696 (if err-mess | 1066 ;; that all user programs are in section 1, but X tends to generate |
697 (error err-mess)) | 1067 ;; makefiles that put things in section "n" instead... |
698 )))) | 1068 (and (string-match "[ \t]*([^)]+)\\'" name-or-event) |
699 | 1069 (progn |
700 | 1070 (message "No entries found for %s; checking other sections..." |
701 ;; ====================================================================== | 1071 name-or-event) |
702 ;; set up manual mode in buffer and build alists | 1072 (manual-entry |
703 | 1073 (substring name-or-event 0 (match-beginning 0)) |
704 (defun Man-mode () | 1074 nil t))))))) |
705 "A mode for browsing Un*x manual pages. | 1075 |
706 | 1076 (defun Manual-popup-menu (&optional event) |
707 The following man commands are available in the buffer. Try | 1077 "Pops up a menu of cross-references in this manual page. |
708 \"\\[describe-key] <key> RET\" for more information: | 1078 If there is a cross-reference under the mouse button which invoked this |
709 | 1079 command, it will be the first item on the menu. Otherwise, they are |
710 \\[man] Prompt to retrieve a new manpage. | 1080 on the menu in the order in which they appear in the buffer." |
711 \\[Man-follow-manual-reference] Retrieve reference in SEE ALSO section. | 1081 (interactive "e") |
712 \\[Man-next-manpage] Jump to next manpage in circular list. | 1082 (let ((buffer (current-buffer)) |
713 \\[Man-previous-manpage] Jump to previous manpage in circular list. | 1083 (sep "---") |
714 \\[Man-next-section] Jump to next manpage section. | 1084 (prefix "Show Manual Page for ") |
715 \\[Man-previous-section] Jump to previous manpage section. | 1085 xref items) |
716 \\[Man-goto-section] Go to a manpage section. | 1086 (cond (event |
717 \\[Man-goto-see-also-section] Jumps to the SEE ALSO manpage section. | 1087 (setq buffer (event-buffer event)) |
718 \\[Man-quit] Deletes the manpage window, bury its buffer. | 1088 (let* ((p (event-point event)) |
719 \\[Man-kill] Deletes the manpage window, kill its buffer. | 1089 (extent (and p (extent-at p buffer 'highlight))) |
720 \\[describe-mode] Prints this help text. | 1090 (data (and extent (extent-property extent 'man)))) |
721 | 1091 (if (eq (car-safe data) 'Manual-follow-xref) |
722 The following variables may be of some use. Try | 1092 (setq xref (nth 1 data)))))) |
723 \"\\[describe-variable] <variable-name> RET\" for more information: | 1093 (if xref (setq items (list sep xref))) |
724 | 1094 (map-extents #'(lambda (extent ignore) |
725 Man-notify-method What happens when manpage formatting is done. | 1095 (let ((data (extent-property extent 'man))) |
726 Man-downcase-section-letters-flag Force section letters to lower case. | 1096 (if (and (eq (car-safe data) 'Manual-follow-xref) |
727 Man-circular-pages-flag Treat multiple manpage list as circular. | 1097 (not (member (nth 1 data) items))) |
728 Man-auto-section-alist List of major modes and their section numbers. | 1098 (setq items (cons (nth 1 data) items))) |
729 Man-section-translations-alist List of section numbers and their Un*x equiv. | 1099 nil)) |
730 Man-filter-list Background manpage filter command. | 1100 buffer) |
731 Man-mode-line-format Mode line format for Man mode buffers. | 1101 (if (eq sep (car items)) (setq items (cdr items))) |
732 Man-mode-map Keymap bindings for Man mode buffers. | 1102 (let ((popup-menu-titles nil)) |
733 Man-mode-hook Normal hook run on entry to Man mode. | 1103 (popup-menu |
734 Man-section-regexp Regexp describing manpage section letters. | 1104 (cons "Manual Entry" |
735 Man-heading-regexp Regexp describing section headers. | 1105 (mapcar #'(lambda (item) |
736 Man-see-also-regexp Regexp for SEE ALSO section (or your equiv). | 1106 (if (eq item sep) |
737 Man-first-heading-regexp Regexp for first heading on a manpage. | 1107 item |
738 Man-reference-regexp Regexp matching a references in SEE ALSO. | 1108 (vector (concat prefix item) |
739 Man-switches Background `man' command switches. | 1109 (list 'Manual-follow-xref item) t))) |
740 | 1110 (nreverse items))))))) |
741 The following key bindings are currently in effect in the buffer: | 1111 |
742 \\{Man-mode-map}" | 1112 (defun pager-cleanup-hook () |
743 (interactive) | 1113 "cleanup man page if called via $PAGER" |
744 (setq major-mode 'Man-mode | 1114 (let ((buf-name (or buffer-file-name (buffer-name)))) |
745 mode-name "Man" | 1115 (if (and (or (string-match "^/tmp/man[0-9]+" buf-name) |
746 buffer-auto-save-file-name nil | 1116 (string-match ".*/man/\\(man\\|cat\\)[1-9a-z]/" buf-name)) |
747 mode-line-format Man-mode-line-format | 1117 (not (string-match Manual-bogus-file-pattern buf-name))) |
748 truncate-lines t | 1118 (let (buffer manpage) |
749 buffer-read-only t) | 1119 (require 'man) |
750 (buffer-disable-undo (current-buffer)) | |
751 (auto-fill-mode -1) | |
752 (use-local-map Man-mode-map) | |
753 (Man-build-page-list) | |
754 (Man-strip-page-headers) | |
755 (Man-unindent) | |
756 (Man-goto-page 1) | |
757 (run-hooks 'Man-mode-hook)) | |
758 | |
759 (defsubst Man-build-section-alist () | |
760 "Build the association list of manpage sections." | |
761 (setq Man-sections-alist nil) | |
762 (goto-char (point-min)) | |
763 (let ((case-fold-search nil)) | |
764 (while (re-search-forward Man-heading-regexp (point-max) t) | |
765 (aput 'Man-sections-alist (Man-match-substring 1)) | |
766 (forward-line 1)))) | |
767 | |
768 (defsubst Man-build-references-alist () | |
769 "Build the association list of references (in the SEE ALSO section)." | |
770 (setq Man-refpages-alist nil) | |
771 (save-excursion | |
772 (if (Man-find-section Man-see-also-regexp) | |
773 (let ((start (progn (forward-line 1) (point))) | |
774 (end (progn | |
775 (Man-next-section 1) | |
776 (point))) | |
777 hyphenated | |
778 (runningpoint -1)) | |
779 (save-restriction | |
780 (narrow-to-region start end) | |
781 (goto-char (point-min)) | |
782 (back-to-indentation) | |
783 (while (and (not (eobp)) (/= (point) runningpoint)) | |
784 (setq runningpoint (point)) | |
785 (if (re-search-forward Man-reference-regexp end t) | |
786 (let* ((word (Man-match-substring 0)) | |
787 (len (1- (length word)))) | |
788 (if hyphenated | |
789 (setq word (concat hyphenated word) | |
790 hyphenated nil)) | |
791 (if (= (aref word len) ?-) | |
792 (setq hyphenated (substring word 0 len)) | |
793 (aput 'Man-refpages-alist word)))) | |
794 (skip-chars-forward " \t\n,"))))))) | |
795 | |
796 (defun Man-build-page-list () | |
797 "Build the list of separate manpages in the buffer." | |
798 (setq Man-page-list nil) | |
799 (let ((page-start (point-min)) | |
800 (page-end (point-max)) | |
801 (header "")) | |
802 (goto-char page-start) | |
803 ;; (switch-to-buffer (current-buffer))(debug) | |
804 (while (not (eobp)) | |
805 (setq header | |
806 (if (looking-at Man-page-header-regexp) | |
807 (Man-match-substring 1) | |
808 nil)) | |
809 ;; Go past both the current and the next Man-first-heading-regexp | |
810 (if (re-search-forward Man-first-heading-regexp nil 'move 2) | |
811 (let ((p (progn (beginning-of-line) (point)))) | |
812 ;; We assume that the page header is delimited by blank | |
813 ;; lines and that it contains at most one blank line. So | |
814 ;; if we back by three blank lines we will be sure to be | |
815 ;; before the page header but not before the possible | |
816 ;; previous page header. | |
817 (search-backward "\n\n" nil t 3) | |
818 (if (re-search-forward Man-page-header-regexp p 'move) | |
819 (beginning-of-line)))) | |
820 (setq page-end (point)) | |
821 (setq Man-page-list (append Man-page-list | |
822 (list (list (copy-marker page-start) | |
823 (copy-marker page-end) | |
824 header)))) | |
825 (setq page-start page-end) | |
826 ))) | |
827 | |
828 (defun Man-strip-page-headers () | |
829 "Strip all the page headers but the first from the manpage." | |
830 (let ((buffer-read-only nil) | |
831 (case-fold-search nil) | |
832 (page-list Man-page-list) | |
833 (page ()) | |
834 (header "")) | |
835 (while page-list | |
836 (setq page (car page-list)) | |
837 (and (nth 2 page) | |
838 (goto-char (car page)) | |
839 (re-search-forward Man-first-heading-regexp nil t) | |
840 (setq header (buffer-substring (car page) (match-beginning 0))) | |
841 ;; Since the awk script collapses all successive blank | |
842 ;; lines into one, and since we don't want to get rid of | |
843 ;; the fast awk script, one must choose between adding | |
844 ;; spare blank lines between pages when there were none and | |
845 ;; deleting blank lines at page boundaries when there were | |
846 ;; some. We choose the first, so we comment the following | |
847 ;; line. | |
848 ;; (setq header (concat "\n" header))) | |
849 (while (search-forward header (nth 1 page) t) | |
850 (replace-match ""))) | |
851 (setq page-list (cdr page-list))))) | |
852 | |
853 (defun Man-unindent () | |
854 "Delete the leading spaces that indent the manpage." | |
855 (let ((buffer-read-only nil) | |
856 (case-fold-search nil) | |
857 (page-list Man-page-list)) | |
858 (while page-list | |
859 (let ((page (car page-list)) | |
860 (indent "") | |
861 (nindent 0)) | |
862 (narrow-to-region (car page) (car (cdr page))) | |
863 (if Man-uses-untabify-flag | |
864 (untabify (point-min) (point-max))) | |
865 (if (catch 'unindent | |
866 (goto-char (point-min)) | 1120 (goto-char (point-min)) |
867 (if (not (re-search-forward Man-first-heading-regexp nil t)) | 1121 (setq buffer-read-only nil) |
868 (throw 'unindent nil)) | 1122 (Manual-nuke-nroff-bs) |
869 (beginning-of-line) | |
870 (setq indent (buffer-substring (point) | |
871 (progn | |
872 (skip-chars-forward " ") | |
873 (point)))) | |
874 (setq nindent (length indent)) | |
875 (if (zerop nindent) | |
876 (throw 'unindent nil)) | |
877 (setq indent (concat indent "\\|$")) | |
878 (goto-char (point-min)) | 1123 (goto-char (point-min)) |
879 (while (not (eobp)) | 1124 (if (re-search-forward "[^ \t]") |
880 (if (looking-at indent) | 1125 (goto-char (- (point) 1))) |
881 (forward-line 1) | 1126 (if (looking-at "\\([a-zA-Z0-9]+\\)[ \t]*(") |
882 (throw 'unindent nil))) | 1127 (setq manpage (buffer-substring (match-beginning 1) (match-end 1))) |
883 (goto-char (point-min))) | 1128 (setq manpage "???")) |
884 (while (not (eobp)) | 1129 (setq buffer |
885 (or (eolp) | 1130 (rename-buffer |
886 (delete-char nindent)) | 1131 (generate-new-buffer-name (concat "*man " manpage "*")))) |
887 (forward-line 1))) | 1132 (setq buffer-file-name nil) |
888 (setq page-list (cdr page-list)) | 1133 (goto-char (point-min)) |
889 )))) | 1134 (insert (format "%s\n" buf-name)) |
890 | 1135 (goto-char (point-min)) |
891 | 1136 (buffer-disable-undo buffer) |
892 ;; ====================================================================== | 1137 (set-buffer-modified-p nil) |
893 ;; Man mode commands | 1138 (Manual-mode) |
894 | 1139 )))) |
895 (defun Man-next-section (n) | 1140 |
896 "Move point to Nth next section (default 1)." | 1141 (add-hook 'server-visit-hook 'pager-cleanup-hook) |
897 (interactive "p") | |
898 (let ((case-fold-search nil)) | |
899 (if (looking-at Man-heading-regexp) | |
900 (forward-line 1)) | |
901 (if (re-search-forward Man-heading-regexp (point-max) t n) | |
902 (beginning-of-line) | |
903 (goto-char (point-max))))) | |
904 | |
905 (defun Man-previous-section (n) | |
906 "Move point to Nth previous section (default 1)." | |
907 (interactive "p") | |
908 (let ((case-fold-search nil)) | |
909 (if (looking-at Man-heading-regexp) | |
910 (forward-line -1)) | |
911 (if (re-search-backward Man-heading-regexp (point-min) t n) | |
912 (beginning-of-line) | |
913 (goto-char (point-min))))) | |
914 | |
915 (defun Man-find-section (section) | |
916 "Move point to SECTION if it exists, otherwise don't move point. | |
917 Returns t if section is found, nil otherwise." | |
918 (let ((curpos (point)) | |
919 (case-fold-search nil)) | |
920 (goto-char (point-min)) | |
921 (if (re-search-forward (concat "^" section) (point-max) t) | |
922 (progn (beginning-of-line) t) | |
923 (goto-char curpos) | |
924 nil) | |
925 )) | |
926 | |
927 (defun Man-goto-section () | |
928 "Query for section to move point to." | |
929 (interactive) | |
930 (aput 'Man-sections-alist | |
931 (let* ((default (aheadsym Man-sections-alist)) | |
932 (completion-ignore-case t) | |
933 chosen | |
934 (prompt (concat "Go to section: (default " default ") "))) | |
935 (setq chosen (completing-read prompt Man-sections-alist)) | |
936 (if (or (not chosen) | |
937 (string= chosen "")) | |
938 default | |
939 chosen))) | |
940 (Man-find-section (aheadsym Man-sections-alist))) | |
941 | |
942 (defun Man-goto-see-also-section () | |
943 "Move point the the \"SEE ALSO\" section. | |
944 Actually the section moved to is described by `Man-see-also-regexp'." | |
945 (interactive) | |
946 (if (not (Man-find-section Man-see-also-regexp)) | |
947 (error (concat "No " Man-see-also-regexp | |
948 " section found in the current manpage")))) | |
949 | |
950 (defun Man-follow-manual-reference (reference) | |
951 "Get one of the manpages referred to in the \"SEE ALSO\" section. | |
952 Specify which reference to use; default is based on word at point." | |
953 (interactive | |
954 (if (not Man-refpages-alist) | |
955 (error "There are no references in the current man page") | |
956 (list (let* ((default (or | |
957 (car (all-completions | |
958 (save-excursion | |
959 (skip-syntax-backward "w()") | |
960 (skip-chars-forward " \t") | |
961 (let ((word (current-word))) | |
962 ;; strip a trailing '-': | |
963 (if (string-match "-$" word) | |
964 (substring word 0 | |
965 (match-beginning 0)) | |
966 word))) | |
967 Man-refpages-alist)) | |
968 (aheadsym Man-refpages-alist))) | |
969 chosen | |
970 (prompt (concat "Refer to: (default " default ") "))) | |
971 (setq chosen (completing-read prompt Man-refpages-alist nil t)) | |
972 (if (or (not chosen) | |
973 (string= chosen "")) | |
974 default | |
975 chosen))))) | |
976 (if (not Man-refpages-alist) | |
977 (error "Can't find any references in the current manpage") | |
978 (aput 'Man-refpages-alist reference) | |
979 (Man-getpage-in-background | |
980 (Man-translate-references (aheadsym Man-refpages-alist))))) | |
981 | |
982 (defun Man-kill () | |
983 "Kill the buffer containing the manpage." | |
984 (interactive) | |
985 (let ((buff (current-buffer))) | |
986 (delete-windows-on buff) | |
987 (kill-buffer buff)) | |
988 (if (and window-system | |
989 (or (eq Man-notify-method 'newframe) | |
990 (and pop-up-frames | |
991 (eq Man-notify-method 'bully)))) | |
992 (delete-frame))) | |
993 | |
994 (defun Man-quit () | |
995 "Bury the buffer containing the manpage." | |
996 (interactive) | |
997 (let ((buff (current-buffer))) | |
998 (delete-windows-on buff) | |
999 (bury-buffer buff)) | |
1000 (if (and window-system | |
1001 (or (eq Man-notify-method 'newframe) | |
1002 (and pop-up-frames | |
1003 (eq Man-notify-method 'bully)))) | |
1004 (delete-frame))) | |
1005 | |
1006 (defun Man-goto-page (page) | |
1007 "Go to the manual page on page PAGE." | |
1008 (interactive | |
1009 (if (not Man-page-list) | |
1010 (let ((args Man-arguments)) | |
1011 (kill-buffer (current-buffer)) | |
1012 (error "Can't find the %s manpage" args)) | |
1013 (if (= (length Man-page-list) 1) | |
1014 (error "You're looking at the only manpage in the buffer") | |
1015 (list (read-minibuffer (format "Go to manpage [1-%d]: " | |
1016 (length Man-page-list))))))) | |
1017 (if (not Man-page-list) | |
1018 (let ((args Man-arguments)) | |
1019 (kill-buffer (current-buffer)) | |
1020 (error "Can't find the %s manpage" args))) | |
1021 (if (or (< page 1) | |
1022 (> page (length Man-page-list))) | |
1023 (error "No manpage %d found" page)) | |
1024 (let* ((page-range (nth (1- page) Man-page-list)) | |
1025 (page-start (car page-range)) | |
1026 (page-end (car (cdr page-range)))) | |
1027 (setq Man-current-page page | |
1028 Man-page-mode-string (Man-make-page-mode-string)) | |
1029 (widen) | |
1030 (goto-char page-start) | |
1031 (narrow-to-region page-start page-end) | |
1032 (Man-build-section-alist) | |
1033 (Man-build-references-alist) | |
1034 (goto-char (point-min)))) | |
1035 | |
1036 | |
1037 (defun Man-next-manpage () | |
1038 "Find the next manpage entry in the buffer." | |
1039 (interactive) | |
1040 (if (= (length Man-page-list) 1) | |
1041 (error "This is the only manpage in the buffer")) | |
1042 (if (< Man-current-page (length Man-page-list)) | |
1043 (Man-goto-page (1+ Man-current-page)) | |
1044 (if Man-circular-pages-flag | |
1045 (Man-goto-page 1) | |
1046 (error "You're looking at the last manpage in the buffer")))) | |
1047 | |
1048 (defun Man-previous-manpage () | |
1049 "Find the previous manpage entry in the buffer." | |
1050 (interactive) | |
1051 (if (= (length Man-page-list) 1) | |
1052 (error "This is the only manpage in the buffer")) | |
1053 (if (> Man-current-page 1) | |
1054 (Man-goto-page (1- Man-current-page)) | |
1055 (if Man-circular-pages-flag | |
1056 (Man-goto-page (length Man-page-list)) | |
1057 (error "You're looking at the first manpage in the buffer")))) | |
1058 | |
1059 ;; Init the man package variables, if not already done. | |
1060 (Man-init-defvars) | |
1061 | |
1062 (provide 'man) | 1142 (provide 'man) |
1063 | |
1064 ;;; man.el ends here |