aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Kastrup2004-06-03 19:53:53 +0000
committerDavid Kastrup2004-06-03 19:53:53 +0000
commitd0923e437b00977c09b7ef1a54677ccf4d3e00ab (patch)
tree99daa29cf40d57c0947876ea1485a85ac429518f
parent67c41d86aa7ba1b3bf24d62bf87a3668bfac4f0e (diff)
downloademacs-d0923e437b00977c09b7ef1a54677ccf4d3e00ab.tar.gz
emacs-d0923e437b00977c09b7ef1a54677ccf4d3e00ab.zip
(woman-mapcan): More concise code.
(woman-topic-all-completions, woman-topic-all-completions-1) (woman-topic-all-completions-merge): Replace by a simpler and much faster implementation based on O(n log n) sort/merge instead of the old O(n^2) behavior.
-rw-r--r--lisp/woman.el104
1 files changed, 53 insertions, 51 deletions
diff --git a/lisp/woman.el b/lisp/woman.el
index d69c631f27b..ba511bca1ae 100644
--- a/lisp/woman.el
+++ b/lisp/woman.el
@@ -1,6 +1,6 @@
1;;; woman.el --- browse UN*X manual pages `wo (without) man' 1;;; woman.el --- browse UN*X manual pages `wo (without) man'
2 2
3;; Copyright (C) 2000, 2002 Free Software Foundation, Inc. 3;; Copyright (C) 2000, 2002, 2004 Free Software Foundation, Inc.
4 4
5;; Author: Francis J. Wright <F.J.Wright@qmul.ac.uk> 5;; Author: Francis J. Wright <F.J.Wright@qmul.ac.uk>
6;; Maintainer: Francis J. Wright <F.J.Wright@qmul.ac.uk> 6;; Maintainer: Francis J. Wright <F.J.Wright@qmul.ac.uk>
@@ -402,6 +402,7 @@
402;; Alexander Hinds <ahinds@thegrid.net> 402;; Alexander Hinds <ahinds@thegrid.net>
403;; Stefan Hornburg <sth@hacon.de> 403;; Stefan Hornburg <sth@hacon.de>
404;; Theodore Jump <tjump@cais.com> 404;; Theodore Jump <tjump@cais.com>
405;; David Kastrup <dak@gnu.org>
405;; Paul Kinnucan <paulk@mathworks.com> 406;; Paul Kinnucan <paulk@mathworks.com>
406;; Jonas Linde <jonas@init.se> 407;; Jonas Linde <jonas@init.se>
407;; Andrew McRae <andrewm@optimation.co.nz> 408;; Andrew McRae <andrewm@optimation.co.nz>
@@ -438,7 +439,8 @@
438 "Return concatenated list of FN applied to successive `car' elements of X. 439 "Return concatenated list of FN applied to successive `car' elements of X.
439FN must return a list, cons or nil. Useful for splicing into a list." 440FN must return a list, cons or nil. Useful for splicing into a list."
440 ;; Based on the Standard Lisp function MAPCAN but with args swapped! 441 ;; Based on the Standard Lisp function MAPCAN but with args swapped!
441 (and x (nconc (funcall fn (car x)) (woman-mapcan fn (cdr x))))) 442 ;; More concise implementation than the recursive one. -- dak
443 (apply #'nconc (mapcar fn x)))
442 444
443(defun woman-parse-colon-path (paths) 445(defun woman-parse-colon-path (paths)
444 "Explode search path string PATHS into a list of directory names. 446 "Explode search path string PATHS into a list of directory names.
@@ -1367,15 +1369,16 @@ The cdr of each alist element is the path-index / filename."
1367 ;; is re-processed by `woman-topic-all-completions-merge'. 1369 ;; is re-processed by `woman-topic-all-completions-merge'.
1368 (let (dir files (path-index 0)) ; indexing starts at zero 1370 (let (dir files (path-index 0)) ; indexing starts at zero
1369 (while path 1371 (while path
1370 (setq dir (car path) 1372 (setq dir (pop path))
1371 path (cdr path))
1372 (if (woman-not-member dir path) ; use each directory only once! 1373 (if (woman-not-member dir path) ; use each directory only once!
1373 (setq files 1374 (push (woman-topic-all-completions-1 dir path-index)
1374 (nconc files 1375 files))
1375 (woman-topic-all-completions-1 dir path-index))))
1376 (setq path-index (1+ path-index))) 1376 (setq path-index (1+ path-index)))
1377 ;; Uniquefy topics: 1377 ;; Uniquefy topics:
1378 (woman-topic-all-completions-merge files))) 1378 ;; Concate all lists with a single nconc call to
1379 ;; avoid retraversing the first lists repeatedly -- dak
1380 (woman-topic-all-completions-merge
1381 (apply #'nconc files))))
1379 1382
1380(defun woman-topic-all-completions-1 (dir path-index) 1383(defun woman-topic-all-completions-1 (dir path-index)
1381 "Return an alist of the man topics in directory DIR with index PATH-INDEX. 1384 "Return an alist of the man topics in directory DIR with index PATH-INDEX.
@@ -1388,55 +1391,54 @@ of the first `woman-cache-level' elements from the following list:
1388 ;; unnecessary. So let us assume that `woman-file-regexp' will 1391 ;; unnecessary. So let us assume that `woman-file-regexp' will
1389 ;; filter out any directories, which probably should not be there 1392 ;; filter out any directories, which probably should not be there
1390 ;; anyway, i.e. it is a user error! 1393 ;; anyway, i.e. it is a user error!
1391 (mapcar 1394 ;;
1392 (lambda (file) 1395 ;; Don't sort files: we do that when merging, anyway. -- dak
1393 (cons 1396 (let (newlst (lst (directory-files dir nil woman-file-regexp t))
1394 (file-name-sans-extension 1397 ;; Make an explicit regexp for stripping extension and
1395 (if (string-match woman-file-compression-regexp file) 1398 ;; compression extension: file-name-sans-extension is a
1396 (file-name-sans-extension file) 1399 ;; far too costly function. -- dak
1397 file)) 1400 (ext (format "\\(\\.[^.\\/]*\\)?\\(%s\\)?\\'"
1398 (if (> woman-cache-level 1) 1401 woman-file-compression-regexp)))
1399 (cons 1402 ;; Use a loop instead of mapcar in order to avoid the speed
1400 path-index 1403 ;; penalty of binding function arguments. -- dak
1401 (if (> woman-cache-level 2) 1404 (dolist (file lst newlst)
1402 (cons file nil)))))) 1405 (push
1403 (directory-files dir nil woman-file-regexp))) 1406 (cons
1407 (if (string-match ext file)
1408 (substring file 0 (match-beginning 0))
1409 file)
1410 (and (> woman-cache-level 1)
1411 (cons
1412 path-index
1413 (and (> woman-cache-level 2)
1414 (list file)))))
1415 newlst))))
1404 1416
1405(defun woman-topic-all-completions-merge (alist) 1417(defun woman-topic-all-completions-merge (alist)
1406 "Merge the alist ALIST so that the keys are unique. 1418 "Merge the alist ALIST so that the keys are unique.
1407Also make each path-info component into a list. 1419Also make each path-info component into a list.
1408\(Note that this function changes the value of ALIST.)" 1420\(Note that this function changes the value of ALIST.)"
1409 ;; Intended to be fast by avoiding recursion and list copying. 1421 ;; Replaces unreadably "optimized" O(n^2) implementation.
1410 (if (> woman-cache-level 1) 1422 ;; Instead we use sorting to merge stuff efficiently. -- dak
1411 (let ((newalist alist)) 1423 (let (elt newalist)
1412 (while newalist 1424 ;; Sort list into reverse order
1413 (let ((tail newalist) (topic (car (car newalist)))) 1425 (setq alist (sort alist (lambda(x y) (string< (car y) (car x)))))
1414 ;; Make the path-info into a list: 1426 ;; merge duplicate keys.
1415 (setcdr (car newalist) (list (cdr (car newalist)))) 1427 (if (> woman-cache-level 1)
1416 (while tail 1428 (while alist
1417 (while (and tail (not (string= topic (car (car (cdr tail)))))) 1429 (setq elt (pop alist))
1418 (setq tail (cdr tail))) 1430 (if (equal (car elt) (caar newalist))
1419 (if tail ; merge path-info into (car newalist) 1431 (unless (member (cdr elt) (cdar newalist))
1420 (let ((path-info (cdr (car (cdr tail))))) 1432 (setcdr (car newalist) (cons (cdr elt)
1421 (if (member path-info (cdr (car newalist))) 1433 (cdar newalist))))
1422 () 1434 (setcdr elt (list (cdr elt)))
1423 ;; Make the path-info into a list: 1435 (push elt newalist)))
1424 (nconc (car newalist) (list path-info)))
1425 (setcdr tail (cdr (cdr tail))))
1426 ))
1427 (setq newalist (cdr newalist))))
1428 alist)
1429 ;; woman-cache-level = 1 => elements are single-element lists ... 1436 ;; woman-cache-level = 1 => elements are single-element lists ...
1430 (while (and alist (member (car alist) (cdr alist))) 1437 (while alist
1431 (setq alist (cdr alist))) 1438 (setq elt (pop alist))
1432 (if alist 1439 (unless (equal (car elt) (caar newalist))
1433 (let ((newalist alist) cdr_alist) 1440 (push elt newalist))))
1434 (while (setq cdr_alist (cdr alist)) 1441 newalist))
1435 (if (not (member (car cdr_alist) (cdr cdr_alist)))
1436 (setq alist cdr_alist)
1437 (setcdr alist (cdr cdr_alist)))
1438 )
1439 newalist))))
1440 1442
1441(defun woman-file-name-all-completions (topic) 1443(defun woman-file-name-all-completions (topic)
1442 "Return an alist of the files in all man directories that match TOPIC." 1444 "Return an alist of the files in all man directories that match TOPIC."