1 |
;;; woman.el --- browse UN*X manual pages `wo (without) man' |
;;; woman.el --- browse UN*X manual pages `wo (without) man' |
2 |
|
|
3 |
;; Copyright (C) 2000 Free Software Foundation, Inc. |
;; Copyright (C) 2000, 2002 Free Software Foundation, Inc. |
4 |
|
|
5 |
;; Author: Francis J. Wright <F.J.Wright@Maths.QMW.ac.uk> |
;; Author: Francis J. Wright <F.J.Wright@qmul.ac.uk> |
6 |
;; Maintainer: Francis J. Wright <F.J.Wright@Maths.QMW.ac.uk> |
;; Maintainer: Francis J. Wright <F.J.Wright@qmul.ac.uk> |
7 |
;; Keywords: help, man, UN*X, manual |
;; Keywords: help, unix |
8 |
;; Adapted-By: Eli Zaretskii <eliz@is.elta.co.il> |
;; Adapted-By: Eli Zaretskii <eliz@is.elta.co.il> |
9 |
;; Version: see `woman-version' |
;; Version: see `woman-version' |
10 |
;; URL: http://centaur.maths.qmw.ac.uk/Emacs/WoMan/ |
;; URL: http://centaur.maths.qmul.ac.uk/Emacs/WoMan/ |
11 |
|
|
12 |
;; This file is part of GNU Emacs. |
;; This file is part of GNU Emacs. |
13 |
|
|
337 |
;; Allow general delimiter in `\v', cf. `\h'. |
;; Allow general delimiter in `\v', cf. `\h'. |
338 |
;; Improve major-mode documentation. |
;; Improve major-mode documentation. |
339 |
;; Pre-process conditionals in macro bodies if possible for speed? |
;; Pre-process conditionals in macro bodies if possible for speed? |
340 |
;; Emulate some preprocessor support for tbl (.TS/.TE) and eqn (.EQ/.EN) |
;; Emulate more complete preprocessor support for tbl (.TS/.TE) |
341 |
|
;; Emulate some preprocessor support for eqn (.EQ/.EN) |
342 |
;; Re-write filling and adjusting code! |
;; Re-write filling and adjusting code! |
343 |
;; Allow word wrap at comma (for long option lists)? |
;; Allow word wrap at comma (for long option lists)? |
344 |
;; Buffer list handling not quite right. |
;; Buffer list handling not quite right. |
387 |
;; Juanma Barranquero <barranquero@laley-actualidad.es> |
;; Juanma Barranquero <barranquero@laley-actualidad.es> |
388 |
;; Karl Berry <kb@cs.umb.edu> |
;; Karl Berry <kb@cs.umb.edu> |
389 |
;; Jim Chapman <jchapman@netcomuk.co.uk> |
;; Jim Chapman <jchapman@netcomuk.co.uk> |
390 |
|
;; Kin Cho <kin@neoscale.com> |
391 |
;; Frederic Corne <frederic.corne@erli.fr> |
;; Frederic Corne <frederic.corne@erli.fr> |
392 |
;; Peter Craft <craft@alacritech.com> |
;; Peter Craft <craft@alacritech.com> |
393 |
;; Charles Curley <ccurley@trib.com> |
;; Charles Curley <ccurley@trib.com> |
421 |
;; Geoff Voelker <voelker@cs.washington.edu> |
;; Geoff Voelker <voelker@cs.washington.edu> |
422 |
;; Eli Zaretskii <eliz@is.elta.co.il> |
;; Eli Zaretskii <eliz@is.elta.co.il> |
423 |
|
|
|
(defvar woman-version "0.54 (beta)" "WoMan version information.") |
|
|
|
|
424 |
;;; History: |
;;; History: |
425 |
;; For recent change log see end of file. |
;; For recent change log see end of file. |
426 |
|
|
427 |
|
|
428 |
;;; Code: |
;;; Code: |
429 |
|
|
430 |
|
(defvar woman-version "0.551 (beta)" "WoMan version information.") |
431 |
|
|
432 |
(require 'man) |
(require 'man) |
433 |
(eval-when-compile ; to avoid compiler warnings |
(eval-when-compile ; to avoid compiler warnings |
434 |
(require 'dired) |
(require 'dired) |
440 |
;; Based on the Standard Lisp function MAPCAN but with args swapped! |
;; Based on the Standard Lisp function MAPCAN but with args swapped! |
441 |
(and x (nconc (funcall fn (car x)) (woman-mapcan fn (cdr x))))) |
(and x (nconc (funcall fn (car x)) (woman-mapcan fn (cdr x))))) |
442 |
|
|
443 |
(defun woman-parse-colon-path (cd-path) |
(defun woman-parse-colon-path (paths) |
444 |
"Explode a search path CD-PATH into a list of directory names. |
"Explode search path string PATHS into a list of directory names. |
445 |
|
Allow Cygwin colon-separated search paths on Microsoft platforms. |
446 |
Replace null components by calling `woman-parse-man.conf'. |
Replace null components by calling `woman-parse-man.conf'. |
447 |
Allow UN*X-style search paths on Microsoft platforms, i.e. allow path |
As a special case, if PATHS is nil then replace it by calling |
448 |
elements to be separated by colons and convert Cygwin-style drive |
`woman-parse-man.conf'." |
|
specifiers `//x/' to `x:'." |
|
449 |
;; Based on suggestions by Jari Aalto and Eli Zaretskii. |
;; Based on suggestions by Jari Aalto and Eli Zaretskii. |
450 |
(mapcar |
;; parse-colon-path returns nil for a null path component and |
451 |
(lambda (path) ; //a/b -> a:/b |
;; an empty substring of MANPATH denotes the default list. |
452 |
(when (and path (string-match "\\`//./" path)) |
(if (memq system-type '(windows-nt ms-dos)) |
453 |
(setq path (substring path 1)) ; //a/b -> /a/b |
(cond ((null paths) |
454 |
(aset path 0 (aref path 1)) ; /a/b -> aa/b |
(mapcar 'woman-Cyg-to-Win (woman-parse-man.conf))) |
455 |
(aset path 1 ?:)) ; aa/b -> a:/b |
((string-match ";" paths) |
456 |
path) |
;; Assume DOS-style path-list... |
457 |
(woman-mapcan ; splice into list... |
(woman-mapcan ; splice list into list |
458 |
(lambda (path) |
(lambda (x) |
459 |
;; parse-colon-path returns nil for a null path component and |
(if x |
460 |
;; an empty substring of MANPATH denotes the default list... |
(list x) |
461 |
(if path (list path) (woman-parse-man.conf))) |
(mapcar 'woman-Cyg-to-Win (woman-parse-man.conf)))) |
462 |
(if (and (memq system-type '(windows-nt ms-dos)) |
(parse-colon-path paths))) |
463 |
(not (string-match ";" cd-path))) |
((string-match "\\`[a-zA-Z]:" paths) |
464 |
(let ((path-separator ":")) |
;; Assume single DOS-style path... |
465 |
(parse-colon-path cd-path)) |
paths) |
466 |
(parse-colon-path cd-path))))) |
(t |
467 |
|
;; Assume UNIX/Cygwin-style path-list... |
468 |
|
(woman-mapcan ; splice list into list |
469 |
|
(lambda (x) |
470 |
|
(mapcar 'woman-Cyg-to-Win |
471 |
|
(if x (list x) (woman-parse-man.conf)))) |
472 |
|
(let ((path-separator ":")) |
473 |
|
(parse-colon-path paths))))) |
474 |
|
;; Assume host-default-style path-list... |
475 |
|
(woman-mapcan ; splice list into list |
476 |
|
(lambda (x) (if x (list x) (woman-parse-man.conf))) |
477 |
|
(parse-colon-path (or paths ""))))) |
478 |
|
|
479 |
|
(defun woman-Cyg-to-Win (file) |
480 |
|
"Convert an absolute filename FILE from Cygwin to Windows form." |
481 |
|
;; Code taken from w32-symlinks.el |
482 |
|
(if (eq (aref file 0) ?/) |
483 |
|
;; Try to use Cygwin mount table via `cygpath.exe'. |
484 |
|
(condition-case nil |
485 |
|
(with-temp-buffer |
486 |
|
;; cygpath -m file |
487 |
|
(call-process "cygpath" nil t nil "-m" file) |
488 |
|
(buffer-substring 1 (buffer-size))) |
489 |
|
(error |
490 |
|
;; Assume no `cygpath' program available. |
491 |
|
;; Hack /cygdrive/x/ or /x/ or (obsolete) //x/ to x:/ |
492 |
|
(when (string-match "\\`\\(/cygdrive\\|/\\)?/./" file) |
493 |
|
(if (match-string 1) ; /cygdrive/x/ or //x/ -> /x/ |
494 |
|
(setq file (substring file (match-end 1)))) |
495 |
|
(aset file 0 (aref file 1)) ; /x/ -> xx/ |
496 |
|
(aset file 1 ?:)) ; xx/ -> x:/ |
497 |
|
file)) |
498 |
|
file)) |
499 |
|
|
500 |
|
|
501 |
;;; User options: |
;;; User options: |
534 |
:group 'woman) |
:group 'woman) |
535 |
|
|
536 |
(defcustom woman-man.conf-path |
(defcustom woman-man.conf-path |
537 |
'("/etc" "/etc/manpath.config" "/usr/local/lib") |
(let ((path '("/usr/lib" "/etc"))) |
538 |
|
(if (eq system-type 'windows-nt) |
539 |
|
(mapcar 'woman-Cyg-to-Win path) |
540 |
|
path)) |
541 |
"*List of dirs to search and/or files to try for man config file. |
"*List of dirs to search and/or files to try for man config file. |
|
Default is '(\"/etc\" \"/usr/local/lib\") [for GNU/Linux, Cygwin resp.] |
|
542 |
A trailing separator (`/' for UNIX etc.) on directories is optional |
A trailing separator (`/' for UNIX etc.) on directories is optional |
543 |
and the filename matched if a directory is specified is the first to |
and the filename used if a directory is specified is the first to |
544 |
contain the string \"man.conf\". |
match the regexp \"man.*\\.conf\". |
545 |
If MANPATH is not set but a config file is found then it is parsed |
If MANPATH is not set but a config file is found then it is parsed |
546 |
instead to provide a default value for `woman-manpath'." |
instead to provide a default value for `woman-manpath'." |
547 |
:type '(repeat string) |
:type '(repeat string) |
548 |
:group 'woman-interface) |
:group 'woman-interface) |
549 |
|
|
550 |
(defun woman-parse-man.conf () |
(defun woman-parse-man.conf () |
551 |
"Parse if possible Linux-style configuration file for man command. |
"Parse if possible configuration file for man command. |
552 |
Used only if MANPATH is not set or contains null components. |
Used only if MANPATH is not set or contains null components. |
553 |
Look in `woman-man.conf-path' and return a value for `woman-manpath'. |
Look in `woman-man.conf-path' and return a value for `woman-manpath'. |
554 |
Concatenate data from all lines in the config file of the form |
Concatenate data from all lines in the config file of the form |
555 |
|
MANPATH /usr/man |
|
MANPATH /usr/man |
|
|
|
|
556 |
or |
or |
557 |
|
MANDATORY_MANPATH /usr/man" |
|
MANDATORY_MANPATH /usr/man" |
|
558 |
;; Functionality suggested by Charles Curley. |
;; Functionality suggested by Charles Curley. |
559 |
(let ((path woman-man.conf-path) |
(let ((path woman-man.conf-path) |
560 |
file manpath) |
file manpath) |
566 |
(or (not (file-directory-p file)) |
(or (not (file-directory-p file)) |
567 |
(and |
(and |
568 |
(setq file |
(setq file |
569 |
(directory-files file t "man\\.conf" t)) |
(directory-files file t "man.*\\.conf" t)) |
570 |
(file-readable-p (setq file (car file))))) |
(file-readable-p (setq file (car file))))) |
571 |
;; Parse the file -- if no MANPATH data ignore it: |
;; Parse the file -- if no MANPATH data ignore it: |
572 |
(with-temp-buffer |
(with-temp-buffer |
573 |
(insert-file-contents file) |
(insert-file-contents file) |
574 |
(while (re-search-forward |
(while (re-search-forward |
575 |
"^[ \t]*\\(MANDATORY_\\)?MANPATH[ \t]+\\(\\S-+\\)" nil t) |
;; `\(?: ... \)' is a "shy group" |
576 |
(setq manpath (cons (match-string 2) manpath))) |
"\ |
577 |
|
^[ \t]*\\(?:MANDATORY_\\)?MANPATH[ \t]+\\(\\S-+\\)" nil t) |
578 |
|
(setq manpath (cons (match-string 1) manpath))) |
579 |
manpath)) |
manpath)) |
580 |
)) |
)) |
581 |
(setq path (cdr path))) |
(setq path (cdr path))) |
582 |
(nreverse manpath))) |
(nreverse manpath))) |
583 |
|
|
584 |
(defcustom woman-manpath |
(defcustom woman-manpath |
585 |
(let ((manpath (getenv "MANPATH"))) |
(or (woman-parse-colon-path (getenv "MANPATH")) |
586 |
(or |
'("/usr/man" "/usr/share/man" "/usr/local/man")) |
|
(and manpath (woman-parse-colon-path manpath)) |
|
|
(woman-parse-man.conf) |
|
|
'("/usr/man" "/usr/share/man" "/usr/local/man") |
|
|
)) |
|
587 |
"*List of DIRECTORY TREES to search for UN*X manual files. |
"*List of DIRECTORY TREES to search for UN*X manual files. |
588 |
Each element should be the name of a directory that contains |
Each element should be the name of a directory that contains |
589 |
subdirectories of the form `man?', or more precisely subdirectories |
subdirectories of the form `man?', or more precisely subdirectories |
592 |
|
|
593 |
If not set then the environment variable MANPATH is used. If no such |
If not set then the environment variable MANPATH is used. If no such |
594 |
environment variable is found, the default list is determined by |
environment variable is found, the default list is determined by |
595 |
consulting the man configuration file if found. By default this is |
consulting the man configuration file if found, which is determined by |
596 |
either `/etc/man.config' or `/usr/local/lib/man.conf', which is |
the user option `woman-man.conf-path'. An empty substring of MANPATH |
597 |
determined by the user option `woman-man.conf-path'. An empty |
denotes the default list. |
|
substring of MANPATH denotes the default list. Otherwise, the default |
|
|
value of this variable is |
|
|
|
|
|
(\"/usr/man\" \"/usr/local/man\"). |
|
598 |
|
|
599 |
Any environment variables (names must have the UN*X-style form $NAME, |
Any environment variables (names must have the UN*X-style form $NAME, |
600 |
e.g. $HOME, $EMACSDATA, $EMACS_DIR) are evaluated first but each |
e.g. $HOME, $EMACSDATA, $emacs_dir) are evaluated first but each |
601 |
element must evaluate to a SINGLE directory name. Trailing `/'s are |
element must evaluate to a SINGLE directory name. Trailing `/'s are |
602 |
ignored. (Specific directories in `woman-path' are also searched.) |
ignored. (Specific directories in `woman-path' are also searched.) |
603 |
|
|
604 |
Microsoft platforms: |
Microsoft platforms: |
605 |
I recommend including drive letters explicitly, e.g. |
I recommend including drive letters explicitly, e.g. |
606 |
|
|
607 |
(\"C:/Cygnus/cygwin-b20/man\" \"C:/usr/man\" \"C:/usr/local/man\"). |
(\"C:/Cygwin/usr/man/\" \"C:/Cygwin/usr/local/man\"). |
608 |
|
|
609 |
The MANPATH environment variable may be set using DOS semi-colon- |
The MANPATH environment variable may be set using DOS semi-colon- |
610 |
separated or UN*X / Cygwin colon-separated syntax (but not mixed)." |
separated or UN*X/Cygwin colon-separated syntax (but not mixed)." |
611 |
:type '(repeat string) |
:type '(repeat string) |
612 |
:group 'woman-interface) |
:group 'woman-interface) |
613 |
|
|
636 |
and unreadable files are ignored. The default value is nil. |
and unreadable files are ignored. The default value is nil. |
637 |
|
|
638 |
Any environment variables (which must have the UN*X-style form $NAME, |
Any environment variables (which must have the UN*X-style form $NAME, |
639 |
e.g. $HOME, $EMACSDATA, $EMACS_DIR) are evaluated first but each |
e.g. $HOME, $EMACSDATA, $emacs_dir) are evaluated first but each |
640 |
element must evaluate to a SINGLE directory name (regexp, see above). |
element must evaluate to a SINGLE directory name (regexp, see above). |
641 |
For example |
For example |
642 |
|
|
643 |
(\"$EMACSDATA\") [or equivalently (\"$EMACS_DIR/etc\")]. |
(\"$EMACSDATA\") [or equivalently (\"$emacs_dir/etc\")]. |
644 |
|
|
645 |
Trailing `/'s are discarded. (The directory trees in `woman-manpath' |
Trailing `/'s are discarded. (The directory trees in `woman-manpath' |
646 |
are also searched.) On Microsoft platforms I recommend including |
are also searched.) On Microsoft platforms I recommend including |
813 |
|
|
814 |
(defcustom woman-default-indent 5 |
(defcustom woman-default-indent 5 |
815 |
"*Default prevailing indent set by -man macros -- default is 5. |
"*Default prevailing indent set by -man macros -- default is 5. |
816 |
Set this variable to 7 to emulate Linux man formatting." |
Set this variable to 7 to emulate GNU man formatting." |
817 |
:type 'integer |
:type 'integer |
818 |
:group 'woman-formatting) |
:group 'woman-formatting) |
819 |
|
|
889 |
|
|
890 |
(defface woman-addition-face |
(defface woman-addition-face |
891 |
'((t (:foreground "orange"))) |
'((t (:foreground "orange"))) |
892 |
"Face for all additions made by WoMan to man pages. |
"Face for all WoMan additions to man pages." |
|
Default: foreground orange." |
|
893 |
:group 'woman-faces) |
:group 'woman-faces) |
894 |
|
|
895 |
(defun woman-default-faces () |
(defun woman-default-faces () |
1059 |
Default is '(?n ?e ?o). Set via `woman-emulation'.") |
Default is '(?n ?e ?o). Set via `woman-emulation'.") |
1060 |
|
|
1061 |
|
|
|
;;; Button types: |
|
|
|
|
|
(define-button-type 'woman-xref |
|
|
'action (lambda (button) (woman (button-label button))) |
|
|
'help-echo "RET, mouse-2: display this man page") |
|
|
|
|
|
|
|
1062 |
;;; Specialized utility functions: |
;;; Specialized utility functions: |
1063 |
|
|
1064 |
;;; Fast deletion without saving on the kill ring (cf. simple.el): |
;;; Fast deletion without saving on the kill ring (cf. simple.el): |
1340 |
;; including `.' and `..', so remove any trailing / !!! |
;; including `.' and `..', so remove any trailing / !!! |
1341 |
(if (string= (substring dir -1) "/") |
(if (string= (substring dir -1) "/") |
1342 |
(setq dir (substring dir 0 -1))) |
(setq dir (substring dir 0 -1))) |
1343 |
(if (memq system-type '(windows-nt ms-dos)) ; what else? |
(if (memq system-type '(windows-nt ms-dos cygwin)) ; what else? |
1344 |
;; Match capitalization used by `file-name-directory': |
;; Match capitalization used by `file-name-directory': |
1345 |
(setq dir (concat (file-name-directory dir) |
(setq dir (concat (file-name-directory dir) |
1346 |
(file-name-nondirectory dir)))) |
(file-name-nondirectory dir)))) |
1862 |
(setq woman-imenu-done nil) |
(setq woman-imenu-done nil) |
1863 |
(if woman-imenu (woman-imenu)) |
(if woman-imenu (woman-imenu)) |
1864 |
(setq buffer-read-only nil) |
(setq buffer-read-only nil) |
1865 |
(WoMan-highlight-references) |
(Man-highlight-references) |
1866 |
(setq buffer-read-only t) |
(setq buffer-read-only t) |
1867 |
(set-buffer-modified-p nil))) |
(set-buffer-modified-p nil))) |
1868 |
|
|
1957 |
(- (cadr time) (cadr WoMan-Man-start-time))))) |
(- (cadr time) (cadr WoMan-Man-start-time))))) |
1958 |
(message "Man formatting done in %d seconds" time))) |
(message "Man formatting done in %d seconds" time))) |
1959 |
|
|
|
(defun WoMan-highlight-references () |
|
|
"Highlight the references (in the SEE ALSO section) on mouse-over." |
|
|
;; Based on `Man-build-references-alist' in `man'. |
|
|
(when (Man-find-section Man-see-also-regexp) |
|
|
(forward-line 1) |
|
|
(let ((end (save-excursion |
|
|
(Man-next-section 1) |
|
|
(point)))) |
|
|
(back-to-indentation) |
|
|
(while (re-search-forward Man-reference-regexp end t) |
|
|
;; Highlight reference when mouse is over it. |
|
|
;; (NB: WoMan does not hyphenate!) |
|
|
(make-text-button (match-beginning 1) (match-end 1) |
|
|
'type 'woman-xref))))) |
|
|
|
|
1960 |
|
|
1961 |
;;; Buffer handling: |
;;; Buffer handling: |
1962 |
|
|
2118 |
;; ***** Need test for .ec arg and warning here! ***** |
;; ***** Need test for .ec arg and warning here! ***** |
2119 |
(woman-delete-whole-line))) |
(woman-delete-whole-line))) |
2120 |
|
|
2121 |
;; Delete comments .\"<anything>, \"<anything>, pre-processor |
;; Delete comments .\"<anything>, \"<anything> and null requests. |
2122 |
;; directives '\"<anything> (should give warning?) and null |
;; (However, should null . requests cause a break?) |
|
;; requests. (However, should null . requests cause a break?) |
|
2123 |
(goto-char from) |
(goto-char from) |
2124 |
(while (re-search-forward "^[.'][ \t]*\\(\\\\\".*\\)?\n\\|\\\\\".*" to t) |
(while (re-search-forward "^[.'][ \t]*\\(\\\\\".*\\)?\n\\|\\\\\".*" to t) |
2125 |
(woman-delete-match 0)) |
(woman-delete-match 0))) |
|
) |
|
2126 |
|
|
2127 |
(defun woman-non-underline-faces () |
(defun woman-non-underline-faces () |
2128 |
"Prepare non-underlined versions of underlined faces." |
"Prepare non-underlined versions of underlined faces." |
2137 |
(set-face-underline-p face-no-ul nil)))) |
(set-face-underline-p face-no-ul nil)))) |
2138 |
(setq face-list (cdr face-list))))) |
(setq face-list (cdr face-list))))) |
2139 |
|
|
2140 |
|
;; Preprocessors |
2141 |
|
;; ============= |
2142 |
|
|
2143 |
|
;; This information is based on documentation for the man command by |
2144 |
|
;; Graeme W. Wilford <G.Wilford@ee.surrey.ac.uk> |
2145 |
|
|
2146 |
|
;; First, the environment variable $MANROFFSEQ is interrogated, and if |
2147 |
|
;; not set then the initial line of the nroff file is parsed for a |
2148 |
|
;; preprocessor string. To contain a valid preprocessor string, the |
2149 |
|
;; first line must resemble |
2150 |
|
;; |
2151 |
|
;; '\" <string> |
2152 |
|
;; |
2153 |
|
;; where string can be any combination of the following letters that |
2154 |
|
;; specify the sequence of preprocessors to run before nroff or |
2155 |
|
;; troff/groff. Not all installations will have a full set of |
2156 |
|
;; preprocessors. Some of the preprocessors and the letters used to |
2157 |
|
;; designate them are: eqn (e), grap (g), pic (p), tbl (t), vgrind |
2158 |
|
;; (v), refer (r). This option overrides the $MANROFFSEQ environment |
2159 |
|
;; variable. zsoelim is always run as the very first preprocessor. |
2160 |
|
|
2161 |
|
(defvar woman-emulate-tbl nil |
2162 |
|
"True if WoMan should emulate the tbl preprocessor. |
2163 |
|
This applies to text between .TE and .TS directives. |
2164 |
|
Currently set only from '\" t in the first line of the source file.") |
2165 |
|
|
2166 |
(defun woman-decode-region (from to) |
(defun woman-decode-region (from to) |
2167 |
"Decode the region between FROM and TO in UN*X man-page source format." |
"Decode the region between FROM and TO in UN*X man-page source format." |
2168 |
;; Suitable for use in format-alist. |
;; Suitable for use in format-alist. |
2206 |
(not (and (integerp woman-fill-column) (> woman-fill-column 0)))) |
(not (and (integerp woman-fill-column) (> woman-fill-column 0)))) |
2207 |
(setq woman-fill-column (- (frame-width) woman-default-indent))) |
(setq woman-fill-column (- (frame-width) woman-default-indent))) |
2208 |
|
|
2209 |
|
;; Check for preprocessor requests: |
2210 |
|
(goto-char from) |
2211 |
|
(if (looking-at "'\\\\\"[ \t]*\\([a-z]+\\)") |
2212 |
|
(let ((letters (append (match-string 1) nil))) |
2213 |
|
(if (memq ?t letters) |
2214 |
|
(setq woman-emulate-tbl t |
2215 |
|
letters (delete ?t letters))) |
2216 |
|
(if letters |
2217 |
|
(WoMan-warn "Unhandled preprocessor request letters %s" |
2218 |
|
(concat letters))) |
2219 |
|
(woman-delete-line 1))) |
2220 |
|
|
2221 |
(woman-pre-process-region from nil) |
(woman-pre-process-region from nil) |
2222 |
;; Process ignore requests, macro definitions, |
;; Process ignore requests, macro definitions, |
2223 |
;; conditionals and switch source requests: |
;; conditionals and switch source requests: |
2472 |
(woman-strings to) |
(woman-strings to) |
2473 |
(goto-char from) ; necessary! |
(goto-char from) ; necessary! |
2474 |
;; Strip font-change escapes: |
;; Strip font-change escapes: |
2475 |
(while (re-search-forward "\\\\f\\((..\\|.\\)" to t) |
(while (re-search-forward "\\\\f\\(\\[[^]]+\\]\\|(..\\|.\\)" to t) |
2476 |
(woman-delete-match 0)) |
(woman-delete-match 0)) |
2477 |
(goto-char from) ; necessary! |
(goto-char from) ; necessary! |
2478 |
(woman2-process-escapes to 'numeric)) |
(woman2-process-escapes to 'numeric)) |
2780 |
|
|
2781 |
;;; Process strings: |
;;; Process strings: |
2782 |
|
|
2783 |
|
(defun woman-match-name () |
2784 |
|
"Match and move over name of form: x, (xx or [xxx...]. |
2785 |
|
Applies to number registers, fonts, strings/macros/diversions, and |
2786 |
|
special characters." |
2787 |
|
(cond ((= (following-char) ?\[ ) |
2788 |
|
(forward-char) |
2789 |
|
(re-search-forward "[^]]+") |
2790 |
|
(forward-char)) ; skip closing ] |
2791 |
|
((= (following-char) ?\( ) |
2792 |
|
(forward-char) |
2793 |
|
(re-search-forward "..")) |
2794 |
|
(t (re-search-forward ".")))) |
2795 |
|
|
2796 |
(defun woman-strings (&optional to) |
(defun woman-strings (&optional to) |
2797 |
"Process ?roff string requests and escape sequences up to buffer position TO. |
"Process ?roff string requests and escape sequences up to buffer position TO. |
2798 |
Strings are defined/updated by `.ds xx string' requests and |
Strings are defined/updated by `.ds xx string' requests and |
2825 |
(woman-delete-line 1)) |
(woman-delete-line 1)) |
2826 |
(t ; \* |
(t ; \* |
2827 |
(let ((beg (match-beginning 0))) |
(let ((beg (match-beginning 0))) |
2828 |
(cond ((= (following-char) ?\( ) |
(woman-match-name) |
|
(forward-char) |
|
|
(re-search-forward "..")) |
|
|
(t (re-search-forward "."))) |
|
2829 |
(let* ((stringname (match-string 0)) |
(let* ((stringname (match-string 0)) |
2830 |
(string (assoc stringname woman-string-alist))) |
(string (assoc stringname woman-string-alist))) |
2831 |
(cond (string |
(cond (string |
2910 |
t) |
t) |
2911 |
|
|
2912 |
(defun woman-special-characters (to) |
(defun woman-special-characters (to) |
2913 |
"Process special character escapes \(xx up to buffer position TO. |
"Process special character escapes \\(xx, \\[xxx] up to buffer position TO. |
2914 |
\(This must be done AFTER translation, which may use special characters.)" |
\(This must be done AFTER translation, which may use special characters.)" |
2915 |
(while (re-search-forward "\\\\(\\(..\\)" to t) |
(while (re-search-forward "\\\\\\(?:(\\(..\\)\\|\\[\\([[^]]+\\)\\]\\)" to t) |
2916 |
(let ((replacement |
(let* ((name (or (match-string-no-properties 1) |
2917 |
(assoc (match-string-no-properties 1) woman-special-characters))) |
(match-string-no-properties 2))) |
2918 |
(if (and |
(replacement (assoc name woman-special-characters))) |
2919 |
|
(unless |
2920 |
|
(and |
2921 |
replacement |
replacement |
2922 |
(cond ((and (cddr replacement) |
(cond ((and (cddr replacement) |
2923 |
(if (nthcdr 3 replacement) |
(if (nthcdr 3 replacement) |
2930 |
(woman-replace-match (nth 2 replacement)))))) |
(woman-replace-match (nth 2 replacement)))))) |
2931 |
((cadr replacement) ; Use ASCII simulation |
((cadr replacement) ; Use ASCII simulation |
2932 |
(woman-replace-match (cadr replacement))))) |
(woman-replace-match (cadr replacement))))) |
2933 |
() |
(WoMan-warn (concat "Special character " |
2934 |
(WoMan-warn "Special character \\(%s not interpolated!" |
(if (match-string 1) "\\(%s" "\\[%s]") |
2935 |
(match-string-no-properties 1)) |
" not interpolated!") name) |
2936 |
(if woman-ignore (woman-delete-match 0)))) |
(if woman-ignore (woman-delete-match 0)))) |
2937 |
)) |
)) |
2938 |
|
|
3256 |
((match-string 4) |
((match-string 4) |
3257 |
;; \f escape found |
;; \f escape found |
3258 |
(setq beg (match-beginning 0)) |
(setq beg (match-beginning 0)) |
3259 |
(cond ((= (following-char) ?\( ) |
(woman-match-name)) |
|
(forward-char) |
|
|
(re-search-forward "..")) |
|
|
(t (re-search-forward "."))) |
|
|
) |
|
3260 |
(t (setq notfont t))) |
(t (setq notfont t))) |
3261 |
(if notfont |
(if notfont |
3262 |
() |
() |
3322 |
(defun woman-get-next-char () |
(defun woman-get-next-char () |
3323 |
"Return and delete next char in buffer, including special chars." |
"Return and delete next char in buffer, including special chars." |
3324 |
(if ;;(looking-at "\\\\(\\(..\\)") |
(if ;;(looking-at "\\\\(\\(..\\)") |
3325 |
;; Match special \(xx and strings \*x, \*(xx: |
;; Match special \(xx and strings \*[xxx], \*(xx, \*x: |
3326 |
(looking-at "\\\\\\((..\\|\\*\\((..\\|.\\)\\)") |
(looking-at "\\\\\\((..\\|\\*\\(\\[[^]]+\\]\\|(..\\|.\\)\\)") |
3327 |
(prog1 (match-string 0) |
(prog1 (match-string 0) |
3328 |
(woman-delete-match 0)) |
(woman-delete-match 0)) |
3329 |
(prog1 (char-to-string (following-char)) |
(prog1 (char-to-string (following-char)) |
3533 |
;; currently needed to set match-end, even though |
;; currently needed to set match-end, even though |
3534 |
;; string-to-number returns 0 if number not parsed. |
;; string-to-number returns 0 if number not parsed. |
3535 |
(string-to-number (match-string 0))) |
(string-to-number (match-string 0))) |
3536 |
((looking-at "\\\\n\\([-+]\\)?\\(\(\\(..\\)\\|\\(.\\)\\)") |
((looking-at "\\\\n\\([-+]\\)?\\(?:\ |
3537 |
|
\\[\\([^]]+\\)\\]\\|\(\\(..\\)\\|\\(.\\)\\)") |
3538 |
;; interpolate number register, maybe auto-incremented |
;; interpolate number register, maybe auto-incremented |
3539 |
(let* ((pm (match-string-no-properties 1)) |
(let* ((pm (match-string-no-properties 1)) |
3540 |
(name (or (match-string-no-properties 3) |
(name (or (match-string-no-properties 2) |
3541 |
|
(match-string-no-properties 3) |
3542 |
(match-string-no-properties 4))) |
(match-string-no-properties 4))) |
3543 |
(value (assoc name woman-registers))) |
(value (assoc name woman-registers))) |
3544 |
(if value |
(if value |
3560 |
0) ; default to zero |
0) ; default to zero |
3561 |
)) |
)) |
3562 |
((re-search-forward |
((re-search-forward |
3563 |
;; Delimiter can be special char escape \(.. or |
;; Delimiter can be special char escape \[xxx], |
3564 |
;; single normal char (usually '): |
;; \(xx or single normal char (usually '): |
3565 |
"\\=\\\\w\\(\\\\(..\\|.\\)" nil t) |
"\\=\\\\w\\(\\\\\\[[^]]+\\]\\|\\\\(..\\|.\\)" nil t) |
3566 |
(let ((from (match-end 0)) |
(let ((from (match-end 0)) |
3567 |
(delim (regexp-quote (match-string 1)))) |
(delim (regexp-quote (match-string 1)))) |
3568 |
(if (re-search-forward delim nil t) |
(if (re-search-forward delim nil t) |
3686 |
(defun woman2-PD (to) |
(defun woman2-PD (to) |
3687 |
".PD d -- Set the interparagraph distance to d. |
".PD d -- Set the interparagraph distance to d. |
3688 |
Round to whole lines, default 1 line. Format paragraphs upto TO. |
Round to whole lines, default 1 line. Format paragraphs upto TO. |
3689 |
(Breaks, but should not.)" |
\(Breaks, but should not.)" |
3690 |
;; .ie \\n[.$] .nr PD (v;\\$1) |
;; .ie \\n[.$] .nr PD (v;\\$1) |
3691 |
;; .el .nr PD .4v>?\n[.V] |
;; .el .nr PD .4v>?\n[.V] |
3692 |
(woman-set-interparagraph-distance) |
(woman-set-interparagraph-distance) |
3995 |
|
|
3996 |
(defun woman2-na (to) |
(defun woman2-na (to) |
3997 |
".na -- No adjusting. Format paragraphs upto TO. |
".na -- No adjusting. Format paragraphs upto TO. |
3998 |
(Breaks, but should not.)" |
\(Breaks, but should not.)" |
3999 |
(setq woman-adjust-previous woman-adjust |
(setq woman-adjust-previous woman-adjust |
4000 |
woman-justify-previous woman-justify |
woman-justify-previous woman-justify |
4001 |
woman-adjust woman-adjust-left ; fill but do not adjust |
woman-adjust woman-adjust-left ; fill but do not adjust |
4408 |
(woman2-format-paragraphs to)) |
(woman2-format-paragraphs to)) |
4409 |
|
|
4410 |
|
|
4411 |
|
;;; Preliminary table support (.TS/.TE) |
4412 |
|
|
4413 |
|
(defun woman2-TS (to) |
4414 |
|
".TS -- Start of table code for the tbl processor. |
4415 |
|
Format paragraphs upto TO." |
4416 |
|
;; This is a preliminary hack that seems to suffice for lilo.8. |
4417 |
|
(woman-delete-line 1) ; ignore any arguments |
4418 |
|
(when woman-emulate-tbl |
4419 |
|
;; Assumes column separator is \t and intercolumn spacing is 3. |
4420 |
|
;; The first line may optionally be a list of options terminated by |
4421 |
|
;; a semicolon. Currently, just delete it: |
4422 |
|
(if (looking-at ".*;[ \t]*$") (woman-delete-line 1)) ; |
4423 |
|
;; The following lines must specify the format of each line of the |
4424 |
|
;; table and end with a period. Currently, just delete them: |
4425 |
|
(while (not (looking-at ".*\\.[ \t]*$")) (woman-delete-line 1)) |
4426 |
|
(woman-delete-line 1) |
4427 |
|
;; For each column, find its width and align it: |
4428 |
|
(let ((start (point)) (col 1)) |
4429 |
|
(while (prog1 (search-forward "\t" to t) (goto-char start)) |
4430 |
|
;; Find current column width: |
4431 |
|
(while (< (point) to) |
4432 |
|
(when (search-forward "\t" to t) |
4433 |
|
(backward-char) |
4434 |
|
(if (> (current-column) col) (setq col (current-column)))) |
4435 |
|
(forward-line)) |
4436 |
|
;; Align current column: |
4437 |
|
(goto-char start) |
4438 |
|
(setq col (+ col 3)) ; intercolumn space |
4439 |
|
(while (< (point) to) |
4440 |
|
(when (search-forward "\t" to t) |
4441 |
|
(delete-char -1) |
4442 |
|
(insert-char ?\ (- col (current-column)))) |
4443 |
|
(forward-line)) |
4444 |
|
(goto-char start)))) |
4445 |
|
;; Format table with no filling or adjusting (cf. woman2-nf): |
4446 |
|
(setq woman-nofill t) |
4447 |
|
(woman2-format-paragraphs to)) |
4448 |
|
|
4449 |
|
(defalias 'woman2-TE 'woman2-fi) |
4450 |
|
;; ".TE -- End of table code for the tbl processor." |
4451 |
|
;; Turn filling and adjusting back on. |
4452 |
|
|
4453 |
|
|
4454 |
;;; WoMan message logging: |
;;; WoMan message logging: |
4455 |
|
|
4456 |
;; The basis for this logging code was shamelessly pirated from bytecomp.el |
;; The basis for this logging code was shamelessly pirated from bytecomp.el |
4526 |
|
|
4527 |
(provide 'woman) |
(provide 'woman) |
4528 |
|
|
|
;; RECENT CHANGE LOG |
|
|
;; ================= |
|
|
|
|
|
;; Changes in version 0.50 ([*] => user interface change) |
|
|
;; [*] Requires GNU Emacs 20.3+. |
|
|
;; [*] `defface' used to define faces. |
|
|
;; [*] Follow `see also' references with mouse-2 click. |
|
|
;; Number register increment support added (woman-registers). |
|
|
;; .j must be a NUMBER acceptable by .ad request. |
|
|
;; Very crude field support added. |
|
|
;; Vertical unit specifier `v' added to register handling. |
|
|
;; Improvement to local horizontal motion processing. |
|
|
;; Minor fix to handle negative numeric arguments. |
|
|
;; Handle horizontal motion escapes `\h' better. |
|
|
;; Allow arbitrary delimiters in `.if', inc. special character escapes. |
|
|
;; Allow `\n' within `.if' string comparisons. |
|
|
;; Allow arbitrary delimiters in `\w', inc. special character escapes. |
|
|
;; Processing of `\h' moved much later -- after indenting etc! |
|
|
|
|
|
;; Changes in version 0.51 ([*] => user interface change) |
|
|
;; [*] Improved handling of underlined faces (mainly for "italics"). |
|
|
;; [*] Allow environment variables in directory path elements. |
|
|
;; Display of pre-formatted files improved. |
|
|
;; [*] Unintentional interaction with standard Man mode reduced. |
|
|
;; [*] bzip2 decompression support added. All decompression now |
|
|
;; works by turning on `auto-compression-mode' to decompress the |
|
|
;; file if necessary, rather than decompressing explicitly. |
|
|
;; Filename and compression regexps are now customizable user |
|
|
;; options. |
|
|
|
|
|
;; Changes in version 0.52 ([*] => user interface change) |
|
|
;; Speeded up handling of underlined faces (mainly for "italics"). |
|
|
;; [*] WoMan formatting time display and log added. Emacs `man' |
|
|
;; formatting time display advice added. (This suggests that |
|
|
;; WoMan formatting is faster than Emacs `man' *formatting*, |
|
|
;; i.e. when man is not using `catman' caching. E.g. `woman |
|
|
;; bash' takes 27s whereas `man bash' takes 35s and for smaller |
|
|
;; files `woman' can be relatively much faster than `man'.) |
|
|
;; [*] Experimental support for non-ASCII characters from the |
|
|
;; default and symbol fonts added, initially only for MS-Windows. |
|
|
;; NOTE: It is off by default, mainly because it may increase the |
|
|
;; line spacing; customize `woman-use-symbols' to `on' to use it. |
|
|
;; Pad character handling for .fc fixed. |
|
|
;; Tested: see `woman.status'. |
|
|
|
|
|
;; Changes in version 0.53 ([*] => user interface change) |
|
|
;; [*] Customization option to use a separate frame for WoMan windows. |
|
|
;; [*] Experimental option to emulate nroff (default) or troff (not tested). |
|
|
;; [*] Separation of extended and symbol font options. |
|
|
;; Only symbol font size 16 seems to work, and only with Win 95, not NT! |
|
|
;; [*] `Advanced' sub-menu containing: |
|
|
;; `View Source' option; |
|
|
;; `Show Log' option; |
|
|
;; `Extended Font' toggle and reformat; |
|
|
;; `Symbol Font' toggle and reformat; |
|
|
;; `Font Map' option; |
|
|
;; `Emulation' radio buttons. |
|
|
;; [*] Support for man config file added for default manpath. |
|
|
|
|
|
;; Changes in version 0.54 |
|
|
;; Revised for distribution with Emacs 21. |
|
|
;; Comment order and doc strings changed substantially. |
|
|
;; MS-DOS support added (by Eli Zaretskii). |
|
|
;; checkdoc run: no real errors. |
|
|
;; woman topic interface speeded up. |
|
|
|
|
4529 |
;;; woman.el ends here |
;;; woman.el ends here |