aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWolfgang Jenkner2013-01-10 10:01:35 -0500
committerStefan Monnier2013-01-10 10:01:35 -0500
commit327a6ccaa01cdcd220e74df4f71acf0ad7e92f5f (patch)
treeff27057bd411d31de8cc44960650ba210d7c1747
parented9112575ebdf0fefec530d7b2687f83eea7bb8a (diff)
downloademacs-327a6ccaa01cdcd220e74df4f71acf0ad7e92f5f.tar.gz
emacs-327a6ccaa01cdcd220e74df4f71acf0ad7e92f5f.zip
* lisp/man.el: Handle different "man -k" behaviors. Use utf-8.
(Man-man-k-use-anchor): New var. (Man-parse-man-k): New function. (Man-completion-table): Use it. (man): Flush the completion cache between uses. * test/automated/man-tests.el: New file. Fixes: debbugs:13160
-rw-r--r--lisp/ChangeLog8
-rw-r--r--lisp/man.el79
-rw-r--r--test/ChangeLog4
-rw-r--r--test/automated/man-tests.el118
4 files changed, 196 insertions, 13 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 507550dbec0..f26c009bf2b 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,11 @@
12013-01-10 Wolfgang Jenkner <wjenkner@inode.at>
2
3 * man.el: Handle different "man -k" behaviors (bug#13160). Use utf-8.
4 (Man-man-k-use-anchor): New var.
5 (Man-parse-man-k): New function.
6 (Man-completion-table): Use it.
7 (man): Flush the completion cache between uses.
8
12013-01-10 Michael Albinus <michael.albinus@gmx.de> 92013-01-10 Michael Albinus <michael.albinus@gmx.de>
2 10
3 * autorevert.el: Add file watch support. 11 * autorevert.el: Add file watch support.
diff --git a/lisp/man.el b/lisp/man.el
index b6a6c179374..93a67128de4 100644
--- a/lisp/man.el
+++ b/lisp/man.el
@@ -1,4 +1,4 @@
1;;; man.el --- browse UNIX manual pages -*- coding: iso-8859-1 -*- 1;;; man.el --- browse UNIX manual pages -*- coding: utf-8 -*-
2 2
3;; Copyright (C) 1993-1994, 1996-1997, 2001-2013 Free Software 3;; Copyright (C) 1993-1994, 1996-1997, 2001-2013 Free Software
4;; Foundation, Inc. 4;; Foundation, Inc.
@@ -276,7 +276,7 @@ Used in `bookmark-set' to get the default bookmark name."
276 :type 'hook 276 :type 'hook
277 :group 'man) 277 :group 'man)
278 278
279(defvar Man-name-regexp "[-a-zA-Z0-9_­+][-a-zA-Z0-9_.:­+]*" 279(defvar Man-name-regexp "[-a-zA-Z0-9_­+][-a-zA-Z0-9_.:­+]*"
280 "Regular expression describing the name of a manpage (without section).") 280 "Regular expression describing the name of a manpage (without section).")
281 281
282(defvar Man-section-regexp "[0-9][a-zA-Z0-9+]*\\|[LNln]" 282(defvar Man-section-regexp "[0-9][a-zA-Z0-9+]*\\|[LNln]"
@@ -780,6 +780,59 @@ POS defaults to `point'."
780 ;; but apparently that's not the case in all cases, so let's add a cache. 780 ;; but apparently that's not the case in all cases, so let's add a cache.
781 "Cache of completion table of the form (PREFIX . TABLE).") 781 "Cache of completion table of the form (PREFIX . TABLE).")
782 782
783(defvar Man-man-k-use-anchor
784 ;; man-db or man-1.*
785 (memq system-type '(gnu gnu/linux gnu/kfreebsd))
786 "If non-nil prepend ^ to the prefix passed to \"man -k\" for completion.
787The value should be nil if \"man -k ^PREFIX\" may omit some man
788pages whose names start with PREFIX.
789
790Currently, the default value depends on `system-type' and is
791non-nil where the standard man programs are known to behave
792properly. Setting the value to nil always gives correct results
793but computing the list of completions may take a bit longer.")
794
795(defun Man-parse-man-k ()
796 "Parse \"man -k\" output and return the list of page names.
797
798The current buffer should contain the output of a command of the
799form \"man -k keyword\", which is traditionally also available with
800apropos(1).
801
802While POSIX man(1p) is a bit vague about what to expect here,
803this function tries to parse some commonly used formats, which
804can be described in the following informal way, with square brackets
805indicating optional parts and whitespace being interpreted
806somewhat loosely.
807
808foo[, bar [, ...]] [other stuff] (sec) - description
809foo(sec)[, bar(sec) [, ...]] [other stuff] - description
810
811For more details and some regression tests, please see
812test/automated/man-tests.el in the emacs bzr repository."
813 (goto-char (point-min))
814 ;; See man-tests for data about which systems use which format (hopefully we
815 ;; will be able to simplify the code if/when some of those formats aren't
816 ;; used any more).
817 (let (table)
818 (while (search-forward-regexp "^\\([^ \t,\n]+\\)\\(.*?\\)\
819\\(?:[ \t]\\(([^ \t,\n]+?)\\)\\)?\\(?:[ \t]+- ?\\(.*\\)\\)?$" nil t)
820 (let ((section (match-string 3))
821 (description (match-string 4))
822 (bound (match-end 2)))
823 (goto-char (match-end 1))
824 (while
825 (progn
826 ;; The first regexp grouping may already match the section
827 ;; tacked on to the name, which is ok since for the formats we
828 ;; claim to support the third (non-shy) grouping does not
829 ;; match in this case, i.e., section is nil.
830 (push (propertize (concat (match-string 1) section)
831 'help-echo description)
832 table)
833 (search-forward-regexp "\\=, *\\([^ \t,]+\\)" bound t)))))
834 (nreverse table)))
835
783(defun Man-completion-table (string pred action) 836(defun Man-completion-table (string pred action)
784 (cond 837 (cond
785 ;; This ends up returning t for pretty much any string, and hence leads to 838 ;; This ends up returning t for pretty much any string, and hence leads to
@@ -811,16 +864,15 @@ POS defaults to `point'."
811 ;; run differently in Man-getpage-in-background, an error 864 ;; run differently in Man-getpage-in-background, an error
812 ;; here may not necessarily mean that we'll also get an 865 ;; here may not necessarily mean that we'll also get an
813 ;; error later. 866 ;; error later.
814 (ignore-errors 867 (ignore-errors
815 (call-process manual-program nil '(t nil) nil 868 (call-process manual-program nil '(t nil) nil
816 "-k" (concat "^" prefix)))) 869 "-k" (concat (when (or Man-man-k-use-anchor
817 (goto-char (point-min)) 870 (string-equal prefix ""))
818 (while (re-search-forward "^\\([^ \t\n]+\\)\\(?: ?\\((.+?)\\)\\(?:[ \t]+- \\(.*\\)\\)?\\)?" nil t) 871 "^")
819 (push (propertize (concat (match-string 1) (match-string 2)) 872 prefix))))
820 'help-echo (match-string 3)) 873 (setq table (Man-parse-man-k)))
821 table))) 874 ;; Cache the table for later reuse.
822 ;; Cache the table for later reuse. 875 (setq Man-completion-cache (cons prefix table)))
823 (setq Man-completion-cache (cons prefix table)))
824 ;; The table may contain false positives since the match is made 876 ;; The table may contain false positives since the match is made
825 ;; by "man -k" not just on the manpage's name. 877 ;; by "man -k" not just on the manpage's name.
826 (if section 878 (if section
@@ -891,6 +943,7 @@ names or descriptions. The pattern argument is usually an
891 ;; ("man -k" is case-insensitive similarly, so the 943 ;; ("man -k" is case-insensitive similarly, so the
892 ;; table has everything available to complete) 944 ;; table has everything available to complete)
893 (completion-ignore-case t) 945 (completion-ignore-case t)
946 Man-completion-cache ;Don't cache across calls.
894 (input (completing-read 947 (input (completing-read
895 (format "Manual entry%s" 948 (format "Manual entry%s"
896 (if (string= default-entry "") 949 (if (string= default-entry "")
@@ -1395,7 +1448,7 @@ The following key bindings are currently in effect in the buffer:
1395 ;; Update len, in case a reference spans 1448 ;; Update len, in case a reference spans
1396 ;; more than two lines (paranoia). 1449 ;; more than two lines (paranoia).
1397 len (1- (length word)))) 1450 len (1- (length word))))
1398 (if (memq (aref word len) '(?- ?­)) 1451 (if (memq (aref word len) '(?- ?­))
1399 (setq hyphenated (substring word 0 len))) 1452 (setq hyphenated (substring word 0 len)))
1400 (and (string-match Man-reference-regexp word) 1453 (and (string-match Man-reference-regexp word)
1401 (not (member word Man--refpages)) 1454 (not (member word Man--refpages))
diff --git a/test/ChangeLog b/test/ChangeLog
index c409e891d97..7b058c1d2bd 100644
--- a/test/ChangeLog
+++ b/test/ChangeLog
@@ -1,3 +1,7 @@
12013-01-10 Wolfgang Jenkner <wjenkner@inode.at>
2
3 * automated/man-tests.el: New file.
4
12013-01-09 Aaron S. Hawley <aaron.s.hawley@gmail.com> 52013-01-09 Aaron S. Hawley <aaron.s.hawley@gmail.com>
2 6
3 * automated/undo-tests.el (undo-test0): Adjust error to code change. 7 * automated/undo-tests.el (undo-test0): Adjust error to code change.
diff --git a/test/automated/man-tests.el b/test/automated/man-tests.el
new file mode 100644
index 00000000000..8a2ec953002
--- /dev/null
+++ b/test/automated/man-tests.el
@@ -0,0 +1,118 @@
1;;; man-tests.el --- Test suite for man.
2
3;; Copyright (C) 2013 Free Software Foundation, Inc.
4
5;; Author: Wolfgang Jenkner <wjenkner@inode.at>
6;; Keywords: help, internal, unix
7
8;; This file is part of GNU Emacs.
9
10;; GNU Emacs is free software: you can redistribute it and/or modify
11;; it under the terms of the GNU General Public License as published by
12;; the Free Software Foundation, either version 3 of the License, or
13;; (at your option) any later version.
14
15;; GNU Emacs is distributed in the hope that it will be useful,
16;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18;; GNU General Public License for more details.
19
20;; You should have received a copy of the GNU General Public License
21;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
22
23;;; Code:
24
25(require 'ert)
26(require 'man)
27
28(defconst man-tests-parse-man-k-tests
29 '(;; GNU/Linux: man-db-2.6.1
30 ("\
31sin (3) - sine function
32sinf (3) - sine function
33sinl (3) - sine function"
34 . (#("sin(3)" 0 6 (help-echo "sine function")) #("sinf(3)" 0 7 (help-echo "sine function")) #("sinl(3)" 0 7 (help-echo "sine function"))))
35 ;; GNU/Linux: man-1.6g
36 ("\
37sin (3) - sine function
38sinf [sin] (3) - sine function
39sinl [sin] (3) - sine function"
40 . (#("sin(3)" 0 6 (help-echo "sine function")) #("sinf(3)" 0 7 (help-echo "sine function")) #("sinl(3)" 0 7 (help-echo "sine function"))))
41 ;; FreeBSD 9
42 ("\
43sin(3), sinf(3), sinl(3) - sine functions"
44 . (#("sin(3)" 0 6 (help-echo "sine functions")) #("sinf(3)" 0 7 (help-echo "sine functions")) #("sinl(3)" 0 7 (help-echo "sine functions"))))
45 ;; SunOS, Solaris
46 ;; http://docs.oracle.com/cd/E19455-01/805-6331/usradm-7/index.html
47 ;; SunOS 4
48 ("\
49tset, reset (1) - establish or restore terminal characteristics"
50 . (#("tset(1)" 0 7 (help-echo "establish or restore terminal characteristics")) #("reset(1)" 0 8 (help-echo "establish or restore terminal characteristics"))))
51 ;; SunOS 5.7, Solaris
52 ("\
53reset tset (1b) - establish or restore terminal characteristics
54tset tset (1b) - establish or restore terminal characteristics"
55 . (#("reset(1b)" 0 8 (help-echo "establish or restore terminal characteristics")) #("tset(1b)" 0 7 (help-echo "establish or restore terminal characteristics"))))
56 ;; Minix 3
57 ;; http://www.minix3.org/manpages/html5/whatis.html
58 ("\
59cawf, nroff (1) - C version of the nroff-like, Amazingly Workable (text) Formatter
60whatis (5) - database of online manual pages"
61 . (#("cawf(1)" 0 7 (help-echo "C version of the nroff-like, Amazingly Workable (text) Formatter")) #("nroff(1)" 0 8 (help-echo "C version of the nroff-like, Amazingly Workable (text) Formatter")) #("whatis(5)" 0 9 (help-echo "database of online manual pages"))))
62 ;; HP-UX
63 ;; http://docstore.mik.ua/manuals/hp-ux/en/B2355-60130/man.1.html
64 ;; Assuming that the line break in the zgrep description was
65 ;; introduced by the man page formatting.
66 ("\
67grep, egrep, fgrep (1) - search a file for a pattern
68zgrep(1) - search possibly compressed files for a regular expression"
69 . (#("grep(1)" 0 7 (help-echo "search a file for a pattern")) #("egrep(1)" 0 8 (help-echo "search a file for a pattern")) #("fgrep(1)" 0 8 (help-echo "search a file for a pattern")) #("zgrep(1)" 0 8 (help-echo "search possibly compressed files for a regular expression"))))
70 ;; AIX
71 ;; http://pic.dhe.ibm.com/infocenter/aix/v7r1/topic/com.ibm.aix.cmds/doc/aixcmds6/whatis.htm
72 ("\
73ls(1) -Displays the contents of a directory."
74 . (#("ls(1)" 0 5 (help-echo "Displays the contents of a directory."))))
75 ;; https://www.ibm.com/developerworks/mydeveloperworks/blogs/cgaix/entry/catman_0703_102_usr_lbin_mkwhatis_the_error_number_is_1?lang=en
76 ("\
77loopmount(1) - Associate an image file to a loopback device."
78 . (#("loopmount(1)" 0 12 (help-echo "Associate an image file to a loopback device."))))
79 )
80 "List of tests for `Man-parse-man-k'.
81Each element is a cons cell whose car is a string containing
82man -k output. That should result in the table which is stored
83in the cdr of the element.")
84
85(defun man-tests-name-equal-p (name description string)
86 (and (equal name string)
87 (not (next-single-property-change 0 'help-echo string))
88 (equal (get-text-property 0 'help-echo string) description)))
89
90(defun man-tests-parse-man-k-test-case (test)
91 (let ((temp-buffer (get-buffer-create " *test-man*"))
92 (man-k-output (car test)))
93 (unwind-protect
94 (save-window-excursion
95 (with-current-buffer temp-buffer
96 (erase-buffer)
97 (insert man-k-output)
98 (let ((result (Man-parse-man-k))
99 (checklist (cdr test)))
100 (while (and checklist result
101 (man-tests-name-equal-p
102 (car checklist)
103 (get-text-property 0 'help-echo
104 (car checklist))
105 (pop result)))
106 (pop checklist))
107 (and (null checklist) (null result)))))
108 (and (buffer-name temp-buffer)
109 (kill-buffer temp-buffer)))))
110
111(ert-deftest man-tests ()
112 "Test man."
113 (dolist (test man-tests-parse-man-k-tests)
114 (should (man-tests-parse-man-k-test-case test))))
115
116(provide 'man-tests)
117
118;;; man-tests.el ends here