aboutsummaryrefslogtreecommitdiffstats
path: root/lisp
diff options
context:
space:
mode:
authorChong Yidong2010-08-29 18:15:09 -0400
committerChong Yidong2010-08-29 18:15:09 -0400
commit96ae4c8fa704b0385d6f2cf10b69bf289e2fb7ef (patch)
tree8103ecf3d53c19b0dc714f71b682572c7686b4d2 /lisp
parentaad4679e7ddbc55a998a4b1111b0cc8c5d3a359f (diff)
downloademacs-96ae4c8fa704b0385d6f2cf10b69bf289e2fb7ef.tar.gz
emacs-96ae4c8fa704b0385d6f2cf10b69bf289e2fb7ef.zip
Merge Finder and package-menu functionality.
* lisp/finder.el: Require `package'. (finder-known-keywords): Tweak descriptions. Retire `oop' keyword. (finder-package-info): Var deleted. (finder-keywords-hash, finder--builtins-alist): New vars. (finder-compile-keywords): Compute package--builtins and finder-keywords-hash instead of finder-keywords-hash, respecting the "Package" header. (finder-unknown-keywords, finder-list-matches): Use finder-keywords-hash and package--list-packages. (finder-mode): Don't set font-lock-defaults. (finder-exit): We don't use "*Finder-package*" and "*Finder Category*" buffers anymore. * lisp/info.el (Info-finder-find-node): Search package-alist instead of finder-package-info. * lisp/emacs-lisp/package.el (package--builtins-base): Var deleted. (package--builtins): Set default value to nil. (package-initialize): Load precomputed value of package--builtins from finder-inf.el. (package-alist, package-compute-transaction) (package-download-transaction): Improve docstring. (package-read-all-archive-contents): Do not change package--builtins here. (list-packages): Make package-list-packages an alias for this. Sort by status by default. (package--list-packages): Add optional PACKAGES arg. (describe-package-1): Use font-lock-face property. For built-in packages, insert file commentary. (package--generate-package-list): Rename from package-list-packages-internal; all callers changed. Add optional PACKAGES arg. Add alphabetical sort fallbacks. (package-menu--version-predicate, package-menu--status-predicate) (package-menu--description-predicate) (package-menu--name-predicate): New functions.
Diffstat (limited to 'lisp')
-rw-r--r--lisp/ChangeLog38
-rw-r--r--lisp/emacs-lisp/package.el344
-rw-r--r--lisp/finder.el292
-rw-r--r--lisp/ibuffer.el2
-rw-r--r--lisp/info.el83
5 files changed, 435 insertions, 324 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index d4ba7de1635..63aeae241c4 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,5 +1,43 @@
12010-08-29 Chong Yidong <cyd@stupidchicken.com> 12010-08-29 Chong Yidong <cyd@stupidchicken.com>
2 2
3 * finder.el: Require `package'.
4 (finder-known-keywords): Tweak descriptions. Retire `oop' keyword.
5 (finder-package-info): Var deleted.
6 (finder-keywords-hash, finder--builtins-alist): New vars.
7 (finder-compile-keywords): Compute package--builtins and
8 finder-keywords-hash instead of finder-keywords-hash, respecting
9 the "Package" header.
10 (finder-unknown-keywords, finder-list-matches): Use
11 finder-keywords-hash and package--list-packages.
12 (finder-mode): Don't set font-lock-defaults.
13 (finder-exit): We don't use "*Finder-package*" and "*Finder
14 Category*" buffers anymore.
15
16 * emacs-lisp/package.el (package--builtins-base): Var deleted.
17 (package--builtins): Set default value to nil.
18 (package-initialize): Load precomputed value of package--builtins
19 from finder-inf.el.
20 (package-alist, package-compute-transaction)
21 (package-download-transaction): Improve docstring.
22 (package-read-all-archive-contents): Do not change
23 package--builtins here.
24 (list-packages): Make package-list-packages an alias for this.
25 Sort by status by default.
26 (package--list-packages): Add optional PACKAGES arg.
27 (describe-package-1): Use font-lock-face property. For built-in
28 packages, insert file commentary.
29 (package--generate-package-list): Rename from
30 package-list-packages-internal; all callers changed. Add optional
31 PACKAGES arg. Add alphabetical sort fallbacks.
32 (package-menu--version-predicate, package-menu--status-predicate)
33 (package-menu--description-predicate)
34 (package-menu--name-predicate): New functions.
35
36 * info.el (Info-finder-find-node): Search package-alist instead of
37 finder-package-info.
38
392010-08-29 Chong Yidong <cyd@stupidchicken.com>
40
3 * subr.el (version-regexp-alist): Don't use "a" and "b" for 41 * subr.el (version-regexp-alist): Don't use "a" and "b" for
4 "alpha" and "beta". 42 "alpha" and "beta".
5 (version-to-list): Handle versions like "10.3d". 43 (version-to-list): Handle versions like "10.3d".
diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el
index 7042566724c..214830b8b54 100644
--- a/lisp/emacs-lisp/package.el
+++ b/lisp/emacs-lisp/package.el
@@ -273,46 +273,35 @@ contrast, `package-user-dir' contains packages for personal use."
273 :group 'package 273 :group 'package
274 :version "24.1") 274 :version "24.1")
275 275
276(defconst package--builtins-base 276;; The value is precomputed in finder-inf.el, but don't load that
277 ;; We use package-version split here to make sure to pick up the 277;; until it's needed (i.e. when `package-intialize' is called).
278 ;; minor version. 278(defvar package--builtins nil
279 `((emacs . [,(version-to-list emacs-version) nil 279 "Alist of built-in packages.
280 "GNU Emacs"]) 280Each element has the form (PKG . DESC), where PKG is a package
281 (package . [,(version-to-list package-el-version) 281name (a symbol) and DESC is a vector that describes the package.
282 nil "Simple package system for GNU Emacs"])) 282
283 "Packages which are always built-in.") 283The vector DESC has the form [VERSION REQS DOCSTRING].
284 284 VERSION is a version list.
285(defvar package--builtins 285 REQS is a list of packages (symbols) required by the package.
286 (delq nil 286 DOCSTRING is a brief description of the package.")
287 (append
288 package--builtins-base
289 (if (>= emacs-major-version 22)
290 ;; FIXME: emacs 22 includes tramp, rcirc, maybe
291 ;; other things...
292 '((erc . [(5 2) nil "Internet Relay Chat client"])
293 ;; The external URL is version 1.15, so make sure the
294 ;; built-in one looks newer.
295 (url . [(1 16) nil "URL handling libary"])))
296 (if (>= emacs-major-version 23)
297 '(;; Strangely, nxml-version is missing in Emacs 23.
298 ;; We pick the merge date as the version.
299 (nxml . [(20071123) nil "Major mode for XML documents"])
300 (bubbles . [(0 5) nil "A puzzle game"])))))
301 "Alist of all built-in packages.
302Maps the package name to a vector [VERSION REQS DOCSTRING].")
303(put 'package--builtins 'risky-local-variable t) 287(put 'package--builtins 'risky-local-variable t)
304 288
305(defvar package-alist package--builtins 289(defvar package-alist nil
306 "Alist of all packages available for activation. 290 "Alist of all packages available for activation.
307This maps the package name to a vector [VERSION REQS DOCSTRING]. 291Each element has the form (PKG . DESC), where PKG is a package
292name (a symbol) and DESC is a vector that describes the package.
308 293
309The value is generated by `package-load-descriptor', usually 294The vector DESC has the form [VERSION REQS DOCSTRING].
310called via `package-initialize'. For user customizations of 295 VERSION is a version list.
311which packages to load/activate, see `package-load-list'.") 296 REQS is a list of packages (symbols) required by the package.
297 DOCSTRING is a brief description of the package.
298
299This variable is set automatically by `package-load-descriptor',
300called via `package-initialize'. To change which packages are
301loaded and/or activated, customize `package-load-list'.")
312(put 'package-archive-contents 'risky-local-variable t) 302(put 'package-archive-contents 'risky-local-variable t)
313 303
314(defvar package-activated-list 304(defvar package-activated-list nil
315 (mapcar #'car package-alist)
316 "List of the names of currently activated packages.") 305 "List of the names of currently activated packages.")
317(put 'package-activated-list 'risky-local-variable t) 306(put 'package-activated-list 'risky-local-variable t)
318 307
@@ -673,7 +662,19 @@ It will move point to somewhere in the headers."
673 (version-list-<= min-version 662 (version-list-<= min-version
674 (package-desc-vers (cdr pkg-desc)))))) 663 (package-desc-vers (cdr pkg-desc))))))
675 664
676(defun package-compute-transaction (result requirements) 665(defun package-compute-transaction (package-list requirements)
666 "Return a list of packages to be installed, including PACKAGE-LIST.
667PACKAGE-LIST should be a list of package names (symbols).
668
669REQUIREMENTS should be a list of additional requirements; each
670element in this list should have the form (PACKAGE VERSION),
671where PACKAGE is a package name and VERSION is the required
672version of that package (as a list).
673
674This function recursively computes the requirements of the
675packages in REQUIREMENTS, and returns a list of all the packages
676that must be installed. Packages that are already installed are
677not included in this list."
677 (dolist (elt requirements) 678 (dolist (elt requirements)
678 (let* ((next-pkg (car elt)) 679 (let* ((next-pkg (car elt))
679 (next-version (cadr elt))) 680 (next-version (cadr elt)))
@@ -704,13 +705,13 @@ but version %s required"
704 (symbol-name next-pkg) (package-version-join next-version) 705 (symbol-name next-pkg) (package-version-join next-version)
705 (package-version-join (package-desc-vers (cdr pkg-desc))))) 706 (package-version-join (package-desc-vers (cdr pkg-desc)))))
706 ;; Only add to the transaction if we don't already have it. 707 ;; Only add to the transaction if we don't already have it.
707 (unless (memq next-pkg result) 708 (unless (memq next-pkg package-list)
708 (setq result (cons next-pkg result))) 709 (setq package-list (cons next-pkg package-list)))
709 (setq result 710 (setq package-list
710 (package-compute-transaction result 711 (package-compute-transaction package-list
711 (package-desc-reqs 712 (package-desc-reqs
712 (cdr pkg-desc)))))))) 713 (cdr pkg-desc))))))))
713 result) 714 package-list)
714 715
715(defun package-read-from-string (str) 716(defun package-read-from-string (str)
716 "Read a Lisp expression from STR. 717 "Read a Lisp expression from STR.
@@ -744,22 +745,10 @@ Will throw an error if the archive version is too new."
744 (cdr contents)))))) 745 (cdr contents))))))
745 746
746(defun package-read-all-archive-contents () 747(defun package-read-all-archive-contents ()
747 "Re-read `archive-contents' and `builtin-packages', if they exist. 748 "Re-read `archive-contents', if it exists.
748Set `package-archive-contents' and `package--builtins' if successful. 749If successful, set `package-archive-contents'."
749Throw an error if the archive version is too new."
750 (dolist (archive package-archives) 750 (dolist (archive package-archives)
751 (package-read-archive-contents (car archive))) 751 (package-read-archive-contents (car archive))))
752 (let ((builtins (package--read-archive-file "builtin-packages")))
753 (if builtins
754 ;; Version 1 of 'builtin-packages' is a list where the car is
755 ;; a split emacs version and the cdr is an alist suitable for
756 ;; package--builtins.
757 (let ((our-version (version-to-list emacs-version))
758 (result package--builtins-base))
759 (setq package--builtins
760 (dolist (elt builtins result)
761 (if (version-list-<= (car elt) our-version)
762 (setq result (append (cdr elt) result)))))))))
763 752
764(defun package-read-archive-contents (archive) 753(defun package-read-archive-contents (archive)
765 "Re-read `archive-contents' and `builtin-packages' for ARCHIVE. 754 "Re-read `archive-contents' and `builtin-packages' for ARCHIVE.
@@ -787,9 +776,13 @@ Also, add the originating archive to the end of the package vector."
787 (version-list-< (aref existing-package 0) version)) 776 (version-list-< (aref existing-package 0) version))
788 (add-to-list 'package-archive-contents entry)))) 777 (add-to-list 'package-archive-contents entry))))
789 778
790(defun package-download-transaction (transaction) 779(defun package-download-transaction (package-list)
791 "Download and install all the packages in the given transaction." 780 "Download and install all the packages in PACKAGE-LIST.
792 (dolist (elt transaction) 781PACKAGE-LIST should be a list of package names (symbols).
782This function assumes that all package requirements in
783PACKAGE-LIST are satisfied, i.e. that PACKAGE-LIST is computed
784using `package-compute-transaction'."
785 (dolist (elt package-list)
793 (let* ((desc (cdr (assq elt package-archive-contents))) 786 (let* ((desc (cdr (assq elt package-archive-contents)))
794 ;; As an exception, if package is "held" in 787 ;; As an exception, if package is "held" in
795 ;; `package-load-list', download the held version. 788 ;; `package-load-list', download the held version.
@@ -1028,6 +1021,9 @@ download."
1028 "Load Emacs Lisp packages, and activate them. 1021 "Load Emacs Lisp packages, and activate them.
1029The variable `package-load-list' controls which packages to load." 1022The variable `package-load-list' controls which packages to load."
1030 (interactive) 1023 (interactive)
1024 (require 'finder-inf nil t)
1025 (setq package-alist package--builtins)
1026 (setq package-activated-list (mapcar #'car package-alist))
1031 (setq package-obsolete-alist nil) 1027 (setq package-obsolete-alist nil)
1032 (package-load-all-descriptors) 1028 (package-load-all-descriptors)
1033 (package-read-all-archive-contents) 1029 (package-read-all-archive-contents)
@@ -1066,6 +1062,7 @@ The variable `package-load-list' controls which packages to load."
1066 (describe-package-1 package))))) 1062 (describe-package-1 package)))))
1067 1063
1068(defun describe-package-1 (package) 1064(defun describe-package-1 (package)
1065 (require 'lisp-mnt)
1069 (let ((package-name (symbol-name package)) 1066 (let ((package-name (symbol-name package))
1070 (built-in (assq package package--builtins)) 1067 (built-in (assq package package--builtins))
1071 desc pkg-dir reqs version installable) 1068 desc pkg-dir reqs version installable)
@@ -1088,9 +1085,10 @@ The variable `package-load-list' controls which packages to load."
1088 installable t) 1085 installable t)
1089 (insert "an uninstalled package.\n\n")) 1086 (insert "an uninstalled package.\n\n"))
1090 1087
1091 (insert " " (propertize "Status" 'face 'bold) ": ") 1088 (insert " " (propertize "Status" 'font-lock-face 'bold) ": ")
1092 (cond (pkg-dir 1089 (cond (pkg-dir
1093 (insert (propertize "Installed" 'face 'font-lock-comment-face)) 1090 (insert (propertize "Installed"
1091 'font-lock-face 'font-lock-comment-face))
1094 (insert " in `") 1092 (insert " in `")
1095 ;; Todo: Add button for uninstalling. 1093 ;; Todo: Add button for uninstalling.
1096 (help-insert-xref-button (file-name-as-directory pkg-dir) 1094 (help-insert-xref-button (file-name-as-directory pkg-dir)
@@ -1112,14 +1110,17 @@ The variable `package-load-list' controls which packages to load."
1112 'package-symbol package 1110 'package-symbol package
1113 'action 'package-install-button-action))) 1111 'action 'package-install-button-action)))
1114 (built-in 1112 (built-in
1115 (insert (propertize "Built-in" 'face 'font-lock-builtin-face) ".")) 1113 (insert (propertize "Built-in"
1114 'font-lock-face 'font-lock-builtin-face) "."))
1116 (t (insert "Deleted."))) 1115 (t (insert "Deleted.")))
1117 (insert "\n") 1116 (insert "\n")
1118 (when version 1117 (and version
1119 (insert " " (propertize "Version" 'face 'bold) ": " version "\n")) 1118 (> (length version) 0)
1119 (insert " "
1120 (propertize "Version" 'font-lock-face 'bold) ": " version "\n"))
1120 (setq reqs (package-desc-reqs desc)) 1121 (setq reqs (package-desc-reqs desc))
1121 (when reqs 1122 (when reqs
1122 (insert " " (propertize "Requires" 'face 'bold) ": ") 1123 (insert " " (propertize "Requires" 'font-lock-face 'bold) ": ")
1123 (let ((first t) 1124 (let ((first t)
1124 name vers text) 1125 name vers text)
1125 (dolist (req reqs) 1126 (dolist (req reqs)
@@ -1134,38 +1135,46 @@ The variable `package-load-list' controls which packages to load."
1134 (t (insert ", "))) 1135 (t (insert ", ")))
1135 (help-insert-xref-button text 'help-package name)) 1136 (help-insert-xref-button text 'help-package name))
1136 (insert "\n"))) 1137 (insert "\n")))
1137 (insert " " (propertize "Summary" 'face 'bold) 1138 (insert " " (propertize "Summary" 'font-lock-face 'bold)
1138 ": " (package-desc-doc desc) "\n\n") 1139 ": " (package-desc-doc desc) "\n\n")
1139 1140
1140 ;; Insert the package commentary. 1141 (if (assq package package--builtins)
1141 ;; FIXME: We should try to be smarter about when to download. 1142 ;; For built-in packages, insert the commentary.
1142 (let ((readme (expand-file-name (concat package-name "-readme.txt") 1143 (let ((fn (locate-file (concat package-name ".el") load-path
1143 package-user-dir))) 1144 load-file-rep-suffixes))
1144 ;; Try downloading the commentary. If that fails, try an 1145 (opoint (point)))
1145 ;; existing readme file in `package-user-dir'. 1146 (insert (or (lm-commentary fn) ""))
1146 (cond ((let ((buffer 1147 (save-excursion
1147 (condition-case nil 1148 (goto-char opoint)
1148 (url-retrieve-synchronously 1149 (when (re-search-forward "^;;; Commentary:\n" nil t)
1149 (concat (package-archive-url package) 1150 (replace-match ""))
1150 package-name "-readme.txt")) 1151 (while (re-search-forward "^\\(;+ ?\\)" nil t)
1151 (error nil))) 1152 (replace-match ""))))
1152 response) 1153 (let ((readme (expand-file-name (concat package-name "-readme.txt")
1153 (when buffer 1154 package-user-dir)))
1154 (with-current-buffer buffer 1155 ;; For elpa packages, try downloading the commentary. If that
1155 (setq response (url-http-parse-response)) 1156 ;; fails, try an existing readme file in `package-user-dir'.
1156 (if (or (< response 200) (>= response 300)) 1157 (cond ((let ((buffer (ignore-errors
1157 (setq response nil) 1158 (url-retrieve-synchronously
1158 (setq buffer-file-name 1159 (concat (package-archive-url package)
1159 (expand-file-name readme package-user-dir)) 1160 package-name "-readme.txt"))))
1160 (delete-region (point-min) (1+ url-http-end-of-headers)) 1161 response)
1161 (save-buffer))) 1162 (when buffer
1162 (when response 1163 (with-current-buffer buffer
1163 (insert-buffer-substring buffer) 1164 (setq response (url-http-parse-response))
1164 (kill-buffer buffer) 1165 (if (or (< response 200) (>= response 300))
1165 t)))) 1166 (setq response nil)
1166 ((file-readable-p readme) 1167 (setq buffer-file-name
1167 (insert-file-contents readme) 1168 (expand-file-name readme package-user-dir))
1168 (goto-char (point-max))))))) 1169 (delete-region (point-min) (1+ url-http-end-of-headers))
1170 (save-buffer)))
1171 (when response
1172 (insert-buffer-substring buffer)
1173 (kill-buffer buffer)
1174 t))))
1175 ((file-readable-p readme)
1176 (insert-file-contents readme)
1177 (goto-char (point-max))))))))
1169 1178
1170(defun package-install-button-action (button) 1179(defun package-install-button-action (button)
1171 (let ((package (button-get button 'package-symbol))) 1180 (let ((package (button-get button 'package-symbol)))
@@ -1195,6 +1204,8 @@ The variable `package-load-list' controls which packages to load."
1195 (define-key map "x" 'package-menu-execute) 1204 (define-key map "x" 'package-menu-execute)
1196 (define-key map "h" 'package-menu-quick-help) 1205 (define-key map "h" 'package-menu-quick-help)
1197 (define-key map "?" 'package-menu-describe-package) 1206 (define-key map "?" 'package-menu-describe-package)
1207 (define-key map [follow-link] 'mouse-face)
1208 (define-key map [mouse-2] 'mouse-select-window)
1198 (define-key map [menu-bar package-menu] (cons "Package" menu-map)) 1209 (define-key map [menu-bar package-menu] (cons "Package" menu-map))
1199 (define-key menu-map [mq] 1210 (define-key menu-map [mq]
1200 '(menu-item "Quit" quit-window 1211 '(menu-item "Quit" quit-window
@@ -1246,6 +1257,7 @@ The variable `package-load-list' controls which packages to load."
1246(defvar package-menu-sort-button-map 1257(defvar package-menu-sort-button-map
1247 (let ((map (make-sparse-keymap))) 1258 (let ((map (make-sparse-keymap)))
1248 (define-key map [header-line mouse-1] 'package-menu-sort-by-column) 1259 (define-key map [header-line mouse-1] 'package-menu-sort-by-column)
1260 (define-key map [header-line mouse-2] 'package-menu-sort-by-column)
1249 (define-key map [follow-link] 'mouse-face) 1261 (define-key map [follow-link] 'mouse-face)
1250 map) 1262 map)
1251 "Local keymap for package menu sort buttons.") 1263 "Local keymap for package menu sort buttons.")
@@ -1276,12 +1288,12 @@ package menu. This lets you see what new packages are
1276available for download." 1288available for download."
1277 (interactive) 1289 (interactive)
1278 (package-refresh-contents) 1290 (package-refresh-contents)
1279 (package-list-packages-internal)) 1291 (package--generate-package-list))
1280 1292
1281(defun package-menu-revert () 1293(defun package-menu-revert ()
1282 "Update the list of packages." 1294 "Update the list of packages."
1283 (interactive) 1295 (interactive)
1284 (package-list-packages-internal)) 1296 (package--generate-package-list))
1285 1297
1286(defun package-menu-describe-package () 1298(defun package-menu-describe-package ()
1287 "Describe the package in the current line." 1299 "Describe the package in the current line."
@@ -1429,7 +1441,7 @@ Emacs."
1429;; This decides how we should sort; nil means by package name. 1441;; This decides how we should sort; nil means by package name.
1430(defvar package-menu-sort-key nil) 1442(defvar package-menu-sort-key nil)
1431 1443
1432(defun package-list-packages-internal () 1444(defun package--generate-package-list (&optional packages)
1433 (package-initialize) ; FIXME: do this here? 1445 (package-initialize) ; FIXME: do this here?
1434 (with-current-buffer (get-buffer-create "*Packages*") 1446 (with-current-buffer (get-buffer-create "*Packages*")
1435 (setq buffer-read-only nil) 1447 (setq buffer-read-only nil)
@@ -1439,34 +1451,35 @@ Emacs."
1439 builtin) 1451 builtin)
1440 ;; List installed packages 1452 ;; List installed packages
1441 (dolist (elt package-alist) 1453 (dolist (elt package-alist)
1442 ;; Ignore the Emacs package. 1454 (setq name (car elt))
1443 (setq name (car elt) 1455 (when (and (not (eq name 'emacs)) ; Hide the `emacs' package.
1444 desc (cdr elt) 1456 (or (null packages)
1445 hold (assq name package-load-list)) 1457 (memq name packages)))
1446 (unless (memq name '(emacs package)) 1458 (setq desc (cdr elt)
1459 hold (cadr (assq name package-load-list))
1460 builtin (cdr (assq name package--builtins)))
1447 (setq info-list 1461 (setq info-list
1448 (package-list-maybe-add 1462 (package-list-maybe-add
1449 name (package-desc-vers desc) 1463 name (package-desc-vers desc)
1450 ;; FIXME: it turns out to be tricky to see if this 1464 ;; FIXME: it turns out to be tricky to see if this
1451 ;; package is presently activated. 1465 ;; package is presently activated.
1452 (cond ((stringp (cadr hold)) 1466 (cond ((stringp hold) "held")
1453 "held") 1467 ((and builtin
1454 ((and (setq builtin (assq name package--builtins))
1455 (version-list-= 1468 (version-list-=
1456 (package-desc-vers (cdr builtin)) 1469 (package-desc-vers builtin)
1457 (package-desc-vers desc))) 1470 (package-desc-vers desc)))
1458 "built-in") 1471 "built-in")
1459 (t "installed")) 1472 (t "installed"))
1460 (package-desc-doc desc) 1473 (package-desc-doc desc)
1461 info-list)))) 1474 info-list))))
1462 ;; List available packages 1475
1476 ;; List available and disabled packages
1463 (dolist (elt package-archive-contents) 1477 (dolist (elt package-archive-contents)
1464 (setq name (car elt) 1478 (setq name (car elt)
1465 desc (cdr elt) 1479 desc (cdr elt)
1466 hold (assq name package-load-list)) 1480 hold (assq name package-load-list))
1467 (unless (and hold (stringp (cadr hold)) 1481 (when (or (null packages)
1468 (package-installed-p 1482 (memq name packages))
1469 name (version-to-list (cadr hold))))
1470 (setq info-list 1483 (setq info-list
1471 (package-list-maybe-add name 1484 (package-list-maybe-add name
1472 (package-desc-vers desc) 1485 (package-desc-vers desc)
@@ -1488,47 +1501,80 @@ Emacs."
1488 info-list))) 1501 info-list)))
1489 (cdr elt))) 1502 (cdr elt)))
1490 package-obsolete-alist) 1503 package-obsolete-alist)
1491 (let ((selector (cond 1504
1492 ((string= package-menu-sort-key "Version") 1505 (setq info-list
1493 ;; FIXME this doesn't work. 1506 (sort info-list
1494 #'(lambda (e) (cdr (car e)))) 1507 (cond ((string= package-menu-sort-key "Version")
1495 ((string= package-menu-sort-key "Status") 1508 'package-menu--version-predicate)
1496 #'(lambda (e) (car (cdr e)))) 1509 ((string= package-menu-sort-key "Status")
1497 ((string= package-menu-sort-key "Description") 1510 'package-menu--status-predicate)
1498 #'(lambda (e) (car (cdr (cdr e))))) 1511 ((string= package-menu-sort-key "Description")
1499 (t ; "Package" is default. 1512 'package-menu--description-predicate)
1500 #'(lambda (e) (symbol-name (car (car e)))))))) 1513 (t ; Sort by package name by default
1501 (setq info-list 1514 'package-menu--name-predicate))))
1502 (sort info-list 1515
1503 (lambda (left right) 1516 (dolist (elt info-list)
1504 (let ((vleft (funcall selector left)) 1517 (package-print-package (car (car elt))
1505 (vright (funcall selector right))) 1518 (cdr (car elt))
1506 (string< vleft vright)))))) 1519 (car (cdr elt))
1507 (mapc (lambda (elt) 1520 (car (cdr (cdr elt))))))
1508 (package-print-package (car (car elt))
1509 (cdr (car elt))
1510 (car (cdr elt))
1511 (car (cdr (cdr elt)))))
1512 info-list))
1513 (goto-char (point-min)) 1521 (goto-char (point-min))
1522 (set-buffer-modified-p nil)
1514 (current-buffer))) 1523 (current-buffer)))
1515 1524
1525(defun package-menu--version-predicate (left right)
1526 (let ((vleft (cdr (car left)))
1527 (vright (cdr (car right))))
1528 (if (version-list-= vleft right)
1529 (package-menu--name-predicate left right)
1530 (version-list-< left right))))
1531
1532(defun package-menu--status-predicate (left right)
1533 (let ((sleft (cadr left))
1534 (sright (cadr right)))
1535 (cond ((string= sleft sright)
1536 (package-menu--name-predicate left right))
1537 ((string= sleft "available") t)
1538 ((string= sright "available") nil)
1539 ((string= sleft "installed") t)
1540 ((string= sright "installed") nil)
1541 ((string= sleft "held") t)
1542 ((string= sright "held") nil)
1543 ((string= sleft "built-in") t)
1544 ((string= sright "built-in") nil)
1545 ((string= sleft "obsolete") t)
1546 ((string= sright "obsolete") nil)
1547 (t (string< sleft sright)))))
1548
1549(defun package-menu--description-predicate (left right)
1550 (let ((sleft (car (cddr left)))
1551 (sright (car (cddr right))))
1552 (if (string= sleft sright)
1553 (package-menu--name-predicate left right)
1554 (string< sleft sright))))
1555
1556(defun package-menu--name-predicate (left right)
1557 (string< (symbol-name (caar left))
1558 (symbol-name (caar right))))
1559
1516(defun package-menu-sort-by-column (&optional e) 1560(defun package-menu-sort-by-column (&optional e)
1517 "Sort the package menu by the last column clicked on." 1561 "Sort the package menu by the last column clicked on."
1518 (interactive (list last-input-event)) 1562 (interactive "e")
1519 (if e (mouse-select-window e)) 1563 (if e (mouse-select-window e))
1520 (let* ((pos (event-start e)) 1564 (let* ((pos (event-start e))
1521 (obj (posn-object pos)) 1565 (obj (posn-object pos))
1522 (col (if obj 1566 (col (if obj
1523 (get-text-property (cdr obj) 'column-name (car obj)) 1567 (get-text-property (cdr obj) 'column-name (car obj))
1524 (get-text-property (posn-point pos) 'column-name)))) 1568 (get-text-property (posn-point pos) 'column-name)))
1525 (setq package-menu-sort-key col)) 1569 (inhibit-read-only t))
1526 (package-list-packages-internal)) 1570 (setq package-menu-sort-key col)
1527 1571 (package--generate-package-list)))
1528(defun package--list-packages () 1572
1529 "Display a list of packages. 1573(defun package--list-packages (&optional packages)
1530Helper function that does all the work for the user-facing functions." 1574 "Display the properties of PACKAGES.
1531 (with-current-buffer (package-list-packages-internal) 1575PACKAGES should be a list of package names (symbols).
1576If PACKAGES is nil, display all packages in `package-alist'."
1577 (with-current-buffer (package--generate-package-list packages)
1532 (package-menu-mode) 1578 (package-menu-mode)
1533 ;; Set up the header line. 1579 ;; Set up the header line.
1534 (setq header-line-format 1580 (setq header-line-format
@@ -1560,22 +1606,22 @@ Helper function that does all the work for the user-facing functions."
1560 "")) 1606 ""))
1561 1607
1562 ;; It's okay to use pop-to-buffer here. The package menu buffer 1608 ;; It's okay to use pop-to-buffer here. The package menu buffer
1563 ;; has keybindings, and the user just typed 'M-x 1609 ;; has keybindings, and the user just typed `M-x list-packages',
1564 ;; package-list-packages', suggesting that they might want to use 1610 ;; suggesting that they might want to use them.
1565 ;; them.
1566 (pop-to-buffer (current-buffer)))) 1611 (pop-to-buffer (current-buffer))))
1567 1612
1568;;;###autoload 1613;;;###autoload
1569(defun package-list-packages () 1614(defun list-packages ()
1570 "Display a list of packages. 1615 "Display a list of packages.
1571Fetches the updated list of packages before displaying. 1616Fetches the updated list of packages before displaying.
1572The list is displayed in a buffer named `*Packages*'." 1617The list is displayed in a buffer named `*Packages*'."
1573 (interactive) 1618 (interactive)
1574 (package-refresh-contents) 1619 (package-refresh-contents)
1620 (setq package-menu-sort-key "Status")
1575 (package--list-packages)) 1621 (package--list-packages))
1576 1622
1577;;;###autoload 1623;;;###autoload
1578(defalias 'list-packages 'package-list-packages) 1624(defalias 'package-list-packages 'list-packages)
1579 1625
1580(defun package-list-packages-no-fetch () 1626(defun package-list-packages-no-fetch ()
1581 "Display a list of packages. 1627 "Display a list of packages.
diff --git a/lisp/finder.el b/lisp/finder.el
index b7eccf3ac70..0e16b9aa44a 100644
--- a/lisp/finder.el
+++ b/lisp/finder.el
@@ -30,6 +30,7 @@
30 30
31;;; Code: 31;;; Code:
32 32
33(require 'package)
33(require 'lisp-mnt) 34(require 'lisp-mnt)
34(require 'find-func) ;for find-library(-suffixes) 35(require 'find-func) ;for find-library(-suffixes)
35;; Use `load' rather than `require' so that it doesn't get loaded 36;; Use `load' rather than `require' so that it doesn't get loaded
@@ -39,46 +40,42 @@
39;; These are supposed to correspond to top-level customization groups, 40;; These are supposed to correspond to top-level customization groups,
40;; says rms. 41;; says rms.
41(defvar finder-known-keywords 42(defvar finder-known-keywords
42 '( 43 '((abbrev . "abbreviation handling, typing shortcuts, and macros")
43 (abbrev . "abbreviation handling, typing shortcuts, macros") 44 (bib . "bibliography processors")
44 ;; Too specific: 45 (c . "C and related programming languages")
45 (bib . "code related to the `bib' bibliography processor") 46 (calendar . "calendar and time management tools")
46 (c . "support for the C language and related languages") 47 (comm . "communications, networking, and remote file access")
47 (calendar . "calendar and time management support")
48 (comm . "communications, networking, remote access to files")
49 (convenience . "convenience features for faster editing") 48 (convenience . "convenience features for faster editing")
50 (data . "support for editing files of data") 49 (data . "editing data (non-text) files")
51 (docs . "support for Emacs documentation") 50 (docs . "Emacs documentation facilities")
52 (emulations . "emulations of other editors") 51 (emulations . "emulations of other editors")
53 (extensions . "Emacs Lisp language extensions") 52 (extensions . "Emacs Lisp language extensions")
54 (faces . "support for multiple fonts") 53 (faces . "fonts and colors for text")
55 (files . "support for editing and manipulating files") 54 (files . "file editing and manipulation")
56 (frames . "support for Emacs frames and window systems") 55 (frames . "Emacs frames and window systems")
57 (games . "games, jokes and amusements") 56 (games . "games, jokes and amusements")
58 (hardware . "support for interfacing with exotic hardware") 57 (hardware . "interfacing with system hardware")
59 (help . "support for on-line help systems") 58 (help . "on-line help systems")
60 (hypermedia . "support for links between text or other media types") 59 (hypermedia . "links between text or other media types")
61 (i18n . "internationalization and alternate character-set support") 60 (i18n . "internationalization and character-set support")
62 (internal . "code for Emacs internals, build process, defaults") 61 (internal . "code for Emacs internals, build process, defaults")
63 (languages . "specialized modes for editing programming languages") 62 (languages . "specialized modes for editing programming languages")
64 (lisp . "Lisp support, including Emacs Lisp") 63 (lisp . "Lisp support, including Emacs Lisp")
65 (local . "code local to your site") 64 (local . "code local to your site")
66 (maint . "maintenance aids for the Emacs development group") 65 (maint . "Emacs development tools and aids")
67 (mail . "modes for electronic-mail handling") 66 (mail . "email reading and posting")
68 (matching . "various sorts of searching and matching") 67 (matching . "searching, matching, and sorting")
69 (mouse . "mouse support") 68 (mouse . "mouse support")
70 (multimedia . "images and sound support") 69 (multimedia . "images and sound")
71 (news . "support for netnews reading and posting") 70 (news . "USENET news reading and posting")
72 (oop . "support for object-oriented programming") 71 (outlines . "hierarchical outlining and note taking")
73 (outlines . "support for hierarchical outlining") 72 (processes . "processes, subshells, and compilation")
74 (processes . "process, subshell, compilation, and job control support") 73 (terminals . "text terminals (ttys)")
75 (terminals . "support for terminal types") 74 (tex . "the TeX document formatter")
76 (tex . "supporting code for the TeX formatter")
77 (tools . "programming tools") 75 (tools . "programming tools")
78 (unix . "front-ends/assistants for, or emulators of, UNIX-like features") 76 (unix . "UNIX feature interfaces and emulators")
79 (vc . "version control") 77 (vc . "version control")
80 (wp . "word processing") 78 (wp . "word processing")))
81 ))
82 79
83(defvar finder-mode-map 80(defvar finder-mode-map
84 (let ((map (make-sparse-keymap)) 81 (let ((map (make-sparse-keymap))
@@ -125,8 +122,9 @@
125 122
126;;; Code for regenerating the keyword list. 123;;; Code for regenerating the keyword list.
127 124
128(defvar finder-package-info nil 125(defvar finder-keywords-hash nil
129 "Assoc list mapping file names to description & keyword lists.") 126 "Hash table mapping keywords to lists of package names.
127Keywords and package names both should be symbols.")
130 128
131(defvar generated-finder-keywords-file "finder-inf.el" 129(defvar generated-finder-keywords-file "finder-inf.el"
132 "The function `finder-compile-keywords' writes keywords into this file.") 130 "The function `finder-compile-keywords' writes keywords into this file.")
@@ -142,10 +140,91 @@ cus-load\\|finder-inf\\|esh-groups\\|subdirs\\)\\.el$\\)"
142 140
143(autoload 'autoload-rubric "autoload") 141(autoload 'autoload-rubric "autoload")
144 142
143(defvar finder--builtins-alist
144 '(("calc" . calc)
145 ("ede" . ede)
146 ("erc" . erc)
147 ("eshell" . eshell)
148 ("gnus" . gnus)
149 ("international" . emacs)
150 ("language" . emacs)
151 ("mh-e" . mh-e)
152 ("semantic" . semantic)
153 ("analyze" . semantic)
154 ("bovine" . semantic)
155 ("decorate" . semantic)
156 ("symref" . semantic)
157 ("wisent" . semantic)
158 ("nxml" . nxml)
159 ("org" . org)
160 ("srecode" . srecode)
161 ("term" . emacs)
162 ("url" . url))
163 "Alist of built-in package directories.
164Each element should have the form (DIR . PACKAGE), where DIR is a
165directory name and PACKAGE is the name of a package (a symbol).
166When generating `package--builtins', Emacs assumes any file in
167DIR is part of the package PACKAGE.")
168
145(defun finder-compile-keywords (&rest dirs) 169(defun finder-compile-keywords (&rest dirs)
146 "Regenerate the keywords association list into `generated-finder-keywords-file'. 170 "Regenerate list of built-in Emacs packages.
147Optional arguments DIRS are a list of Emacs Lisp directories to compile from; 171This recomputes `package--builtins' and `finder-keywords-hash',
148no arguments compiles from `load-path'." 172and prints them into the file `generated-finder-keywords-file'.
173
174Optional DIRS is a list of Emacs Lisp directories to compile
175from; the default is `load-path'."
176 ;; Allow compressed files also.
177 (setq package--builtins nil)
178 (setq finder-keywords-hash (make-hash-table :test 'eq))
179 (let ((el-file-regexp "^\\([^=].*\\)\\.el\\(\\.\\(gz\\|Z\\)\\)?$")
180 package-override files base-name processed
181 summary keywords package version entry desc)
182 (dolist (d (or dirs load-path))
183 (when (file-exists-p (directory-file-name d))
184 (message "Directory %s" d)
185 (setq package-override
186 (intern-soft
187 (cdr-safe
188 (assoc (file-name-nondirectory (directory-file-name d))
189 finder--builtins-alist))))
190 (setq files (directory-files d nil el-file-regexp))
191 (dolist (f files)
192 (unless (or (string-match finder-no-scan-regexp f)
193 (null (setq base-name
194 (and (string-match el-file-regexp f)
195 (intern (match-string 1 f)))))
196 (memq base-name processed))
197 (push base-name processed)
198 (with-temp-buffer
199 (insert-file-contents (expand-file-name f d))
200 (setq summary (lm-synopsis)
201 keywords (mapcar 'intern (lm-keywords-list))
202 package (or package-override
203 (intern-soft (lm-header "package"))
204 base-name)
205 version (lm-header "version")))
206 (when summary
207 (setq version (ignore-errors (version-to-list version)))
208 (setq entry (assq package package--builtins))
209 (cond ((null entry)
210 (push (cons package (vector version nil summary))
211 package--builtins))
212 ((eq base-name package)
213 (setq desc (cdr entry))
214 (aset desc 0 version)
215 (aset desc 2 summary)))
216 (dolist (kw keywords)
217 (puthash kw
218 (cons package
219 (delq package
220 (gethash kw finder-keywords-hash)))
221 finder-keywords-hash))))))))
222
223 (setq package--builtins
224 (sort package--builtins
225 (lambda (a b) (string< (symbol-name (car a))
226 (symbol-name (car b))))))
227
149 (save-excursion 228 (save-excursion
150 (find-file generated-finder-keywords-file) 229 (find-file generated-finder-keywords-file)
151 (setq buffer-undo-list t) 230 (setq buffer-undo-list t)
@@ -153,40 +232,23 @@ no arguments compiles from `load-path'."
153 (insert (autoload-rubric generated-finder-keywords-file 232 (insert (autoload-rubric generated-finder-keywords-file
154 "keyword-to-package mapping" t)) 233 "keyword-to-package mapping" t))
155 (search-backward " ") 234 (search-backward " ")
156 (insert "(setq finder-package-info '(\n") 235 (insert "(setq package--builtins '(\n")
157 (let (processed summary keywords) 236 (dolist (package package--builtins)
158 (mapc 237 (insert " (")
159 (lambda (d) 238 (prin1 (car package) (current-buffer))
160 (when (file-exists-p (directory-file-name d)) 239 (insert " .\n [")
161 (message "Directory %s" d) 240 (let ((desc (cdr package)))
162 (mapc 241 (prin1 (aref desc 0) (current-buffer))
163 (lambda (f) 242 (insert " ")
164 ;; FIXME should this not be using (expand-file-name f d)? 243 (prin1 (aref desc 1) (current-buffer))
165 (unless (or (member f processed) 244 (insert " ")
166 (string-match finder-no-scan-regexp f)) 245 (prin1 (aref desc 2) (current-buffer)))
167 (setq processed (cons f processed)) 246 (insert "])\n"))
168 (with-temp-buffer 247 (insert " ))\n\n")
169 (insert-file-contents (expand-file-name f d)) 248 ;; Insert hash table.
170 (setq summary (lm-synopsis) 249 (insert "(setq finder-keywords-hash\n ")
171 keywords (lm-keywords-list))) 250 (prin1 finder-keywords-hash (current-buffer))
172 (insert 251 (insert ")\n")
173 (format " (\"%s\"\n "
174 (if (string-match "\\.\\(gz\\|Z\\)$" f)
175 (file-name-sans-extension f)
176 f)))
177 (prin1 summary (current-buffer))
178 (insert "\n ")
179 (prin1 (mapcar 'intern keywords) (current-buffer))
180 (insert ")\n")))
181 (directory-files d nil
182 ;; Allow compressed files also. FIXME:
183 ;; generalize this, especially for
184 ;; MS-DOG-type filenames.
185 "^[^=].*\\.el\\(\\.\\(gz\\|Z\\)\\)?$"
186 ))))
187 (or dirs load-path)))
188 (insert " ))\n")
189 (eval-buffer) ; so we get the new keyword list immediately
190 (basic-save-buffer))) 252 (basic-save-buffer)))
191 253
192(defun finder-compile-keywords-make-dist () 254(defun finder-compile-keywords-make-dist ()
@@ -226,26 +288,14 @@ no arguments compiles from `load-path'."
226 288
227(defun finder-unknown-keywords () 289(defun finder-unknown-keywords ()
228 "Return an alist of unknown keywords and number of their occurences. 290 "Return an alist of unknown keywords and number of their occurences.
229Unknown are keywords that are present in `finder-package-info' 291Unknown keywords are those present in `finder-keywords-hash' but
230but absent in `finder-known-keywords'." 292not `finder-known-keywords'."
231 (let ((unknown-keywords-hash (make-hash-table))) 293 (let (alist)
232 ;; Prepare a hash where key is a keyword 294 (maphash (lambda (kw packages)
233 ;; and value is the number of keyword occurences. 295 (unless (assq kw finder-known-keywords)
234 (mapc (lambda (package) 296 (push (cons kw (length packages)) alist)))
235 (mapc (lambda (keyword) 297 finder-keywords-hash)
236 (unless (assq keyword finder-known-keywords) 298 (sort alist (lambda (a b) (string< (car a) (car b))))))
237 (puthash keyword
238 (1+ (gethash keyword unknown-keywords-hash 0))
239 unknown-keywords-hash)))
240 (nth 2 package)))
241 finder-package-info)
242 ;; Make an alist from the hash and sort by the keyword name.
243 (sort (let (unknown-keywords-list)
244 (maphash (lambda (key value)
245 (push (cons key value) unknown-keywords-list))
246 unknown-keywords-hash)
247 unknown-keywords-list)
248 (lambda (a b) (string< (car a) (car b))))))
249 299
250;;;###autoload 300;;;###autoload
251(defun finder-list-keywords () 301(defun finder-list-keywords ()
@@ -255,46 +305,28 @@ but absent in `finder-known-keywords'."
255 (pop-to-buffer "*Finder*") 305 (pop-to-buffer "*Finder*")
256 (pop-to-buffer (get-buffer-create "*Finder*")) 306 (pop-to-buffer (get-buffer-create "*Finder*"))
257 (finder-mode) 307 (finder-mode)
258 (setq buffer-read-only nil 308 (let ((inhibit-read-only t))
259 buffer-undo-list t) 309 (erase-buffer)
260 (erase-buffer) 310 (dolist (assoc finder-known-keywords)
261 (mapc 311 (let ((keyword (car assoc)))
262 (lambda (assoc) 312 (insert (propertize (symbol-name keyword)
263 (let ((keyword (car assoc))) 313 'font-lock-face 'font-lock-constant-face))
264 (insert (symbol-name keyword)) 314 (finder-insert-at-column 14 (concat (cdr assoc) "\n"))
265 (finder-insert-at-column 14 (concat (cdr assoc) "\n")) 315 (finder-mouse-face-on-line)))
266 (finder-mouse-face-on-line))) 316 (goto-char (point-min))
267 finder-known-keywords) 317 (setq finder-headmark (point)
268 (goto-char (point-min)) 318 buffer-read-only t)
269 (setq finder-headmark (point) 319 (set-buffer-modified-p nil)
270 buffer-read-only t) 320 (balance-windows)
271 (set-buffer-modified-p nil) 321 (finder-summary))))
272 (balance-windows)
273 (finder-summary)))
274 322
275(defun finder-list-matches (key) 323(defun finder-list-matches (key)
276 (pop-to-buffer (set-buffer (get-buffer-create "*Finder Category*"))) 324 (let* ((id (intern key))
277 (finder-mode) 325 (packages (gethash id finder-keywords-hash)))
278 (setq buffer-read-only nil 326 (unless packages
279 buffer-undo-list t) 327 (error "No packages matching key `%s'" key))
280 (erase-buffer) 328 (setq package-menu-sort-key nil)
281 (let ((id (intern key))) 329 (package--list-packages packages)))
282 (insert
283 "The following packages match the keyword `" key "':\n\n")
284 (setq finder-headmark (point))
285 (mapc
286 (lambda (x)
287 (when (memq id (cadr (cdr x)))
288 (insert (car x))
289 (finder-insert-at-column 16 (concat (cadr x) "\n"))
290 (finder-mouse-face-on-line)))
291 finder-package-info)
292 (goto-char (point-min))
293 (forward-line)
294 (setq buffer-read-only t)
295 (set-buffer-modified-p nil)
296 (shrink-window-if-larger-than-buffer)
297 (finder-summary)))
298 330
299(define-button-type 'finder-xref 'action #'finder-goto-xref) 331(define-button-type 'finder-xref 'action #'finder-goto-xref)
300 332
@@ -381,8 +413,8 @@ FILE should be in a form suitable for passing to `locate-library'."
381\\[finder-select] more help for the item on the current line 413\\[finder-select] more help for the item on the current line
382\\[finder-exit] exit Finder mode and kill the Finder buffer." 414\\[finder-exit] exit Finder mode and kill the Finder buffer."
383 :syntax-table finder-mode-syntax-table 415 :syntax-table finder-mode-syntax-table
384 (setq font-lock-defaults '(finder-font-lock-keywords nil nil 416 (setq buffer-read-only t
385 (("+-*/.<>=!?$%_&~^:@" . "w")) nil)) 417 buffer-undo-list t)
386 (set (make-local-variable 'finder-headmark) nil)) 418 (set (make-local-variable 'finder-headmark) nil))
387 419
388(defun finder-summary () 420(defun finder-summary ()
@@ -399,8 +431,8 @@ finder directory, \\[finder-exit] = quit, \\[finder-summary] = help")))
399Delete the window and kill all Finder-related buffers." 431Delete the window and kill all Finder-related buffers."
400 (interactive) 432 (interactive)
401 (ignore-errors (delete-window)) 433 (ignore-errors (delete-window))
402 (dolist (buff '("*Finder*" "*Finder-package*" "*Finder Category*")) 434 (let ((buf "*Finder*"))
403 (and (get-buffer buff) (kill-buffer buff)))) 435 (and (get-buffer buf) (kill-buffer buf))))
404 436
405 437
406(provide 'finder) 438(provide 'finder)
diff --git a/lisp/ibuffer.el b/lisp/ibuffer.el
index 44e59a5c8bd..c2492818b45 100644
--- a/lisp/ibuffer.el
+++ b/lisp/ibuffer.el
@@ -2641,7 +2641,7 @@ will be inserted before the group at point."
2641;;;;;; ibuffer-backward-filter-group ibuffer-forward-filter-group 2641;;;;;; ibuffer-backward-filter-group ibuffer-forward-filter-group
2642;;;;;; ibuffer-toggle-filter-group ibuffer-mouse-toggle-filter-group 2642;;;;;; ibuffer-toggle-filter-group ibuffer-mouse-toggle-filter-group
2643;;;;;; ibuffer-interactive-filter-by-mode ibuffer-mouse-filter-by-mode 2643;;;;;; ibuffer-interactive-filter-by-mode ibuffer-mouse-filter-by-mode
2644;;;;;; ibuffer-auto-mode) "ibuf-ext" "ibuf-ext.el" "e1272bfdc7c3b6e926b2a68155217303") 2644;;;;;; ibuffer-auto-mode) "ibuf-ext" "ibuf-ext.el" "fa9822b5ef905f06d8a03dc9ce3a2894")
2645;;; Generated autoloads from ibuf-ext.el 2645;;; Generated autoloads from ibuf-ext.el
2646 2646
2647(autoload 'ibuffer-auto-mode "ibuf-ext" "\ 2647(autoload 'ibuffer-auto-mode "ibuf-ext" "\
diff --git a/lisp/info.el b/lisp/info.el
index 65b9492e351..4fa9503b14e 100644
--- a/lisp/info.el
+++ b/lisp/info.el
@@ -3372,7 +3372,6 @@ Build a menu of the possible matches."
3372 filename) 3372 filename)
3373 3373
3374(defvar finder-known-keywords) 3374(defvar finder-known-keywords)
3375(defvar finder-package-info)
3376(declare-function find-library-name "find-func" (library)) 3375(declare-function find-library-name "find-func" (library))
3377(declare-function finder-unknown-keywords "finder" ()) 3376(declare-function finder-unknown-keywords "finder" ())
3378(declare-function lm-commentary "lisp-mnt" (&optional file)) 3377(declare-function lm-commentary "lisp-mnt" (&optional file))
@@ -3388,15 +3387,14 @@ Build a menu of the possible matches."
3388 (insert "Finder Keywords\n") 3387 (insert "Finder Keywords\n")
3389 (insert "***************\n\n") 3388 (insert "***************\n\n")
3390 (insert "* Menu:\n\n") 3389 (insert "* Menu:\n\n")
3391 (mapc 3390 (dolist (assoc (append '((all . "All package info")
3392 (lambda (assoc) 3391 (unknown . "unknown keywords"))
3393 (let ((keyword (car assoc))) 3392 finder-known-keywords))
3394 (insert (format "* %-14s %s.\n" 3393 (let ((keyword (car assoc)))
3395 (concat (symbol-name keyword) "::") 3394 (insert (format "* %s %s.\n"
3396 (cdr assoc))))) 3395 (concat (symbol-name keyword) ": "
3397 (append '((all . "All package info") 3396 "kw:" (symbol-name keyword) ".")
3398 (unknown . "unknown keywords")) 3397 (cdr assoc))))))
3399 finder-known-keywords)))
3400 ((equal nodename "unknown") 3398 ((equal nodename "unknown")
3401 ;; Display unknown keywords 3399 ;; Display unknown keywords
3402 (insert (format "\n\^_\nFile: %s, Node: %s, Up: Top\n\n" 3400 (insert (format "\n\^_\nFile: %s, Node: %s, Up: Top\n\n"
@@ -3416,17 +3414,36 @@ Build a menu of the possible matches."
3416 Info-finder-file nodename)) 3414 Info-finder-file nodename))
3417 (insert "Finder Package Info\n") 3415 (insert "Finder Package Info\n")
3418 (insert "*******************\n\n") 3416 (insert "*******************\n\n")
3419 (mapc (lambda (package) 3417 (dolist (package package-alist)
3420 (insert (format "%s - %s\n" 3418 (insert (format "%s - %s\n"
3421 (format "*Note %s::" (nth 0 package)) 3419 (format "*Note %s::" (nth 0 package))
3422 (nth 1 package))) 3420 (nth 1 package)))))
3423 (insert "Keywords: " 3421 ((string-match "\\`kw:" nodename)
3424 (mapconcat (lambda (keyword) 3422 (setq nodename (substring nodename (match-end 0)))
3425 (format "*Note %s::" (symbol-name keyword))) 3423 ;; Display packages that match the keyword
3426 (nth 2 package) ", ") 3424 ;; or the list of keywords separated by comma.
3427 "\n\n")) 3425 (insert (format "\n\^_\nFile: %s, Node: kw:%s, Up: Top\n\n"
3428 finder-package-info)) 3426 Info-finder-file nodename))
3429 ((string-match-p "\\.el\\'" nodename) 3427 (insert "Finder Packages\n")
3428 (insert "***************\n\n")
3429 (insert
3430 "The following packages match the keyword `" nodename "':\n\n")
3431 (insert "* Menu:\n\n")
3432 (let ((keywords
3433 (mapcar 'intern (if (string-match-p "," nodename)
3434 (split-string nodename ",[ \t\n]*" t)
3435 (list nodename))))
3436 hits desc)
3437 (dolist (kw keywords)
3438 (push (copy-tree (gethash kw finder-keywords-hash)) hits))
3439 (setq hits (delete-dups (apply 'append hits)))
3440 (dolist (package hits)
3441 (setq desc (cdr-safe (assq package package-alist)))
3442 (when (vectorp desc)
3443 (insert (format "* %-16s %s.\n"
3444 (concat (symbol-name package) "::")
3445 (aref desc 2)))))))
3446 (t
3430 ;; Display commentary section 3447 ;; Display commentary section
3431 (insert (format "\n\^_\nFile: %s, Node: %s, Up: Top\n\n" 3448 (insert (format "\n\^_\nFile: %s, Node: %s, Up: Top\n\n"
3432 Info-finder-file nodename)) 3449 Info-finder-file nodename))
@@ -3447,29 +3464,7 @@ Build a menu of the possible matches."
3447 (goto-char (point-min)) 3464 (goto-char (point-min))
3448 (while (re-search-forward "^;+ ?" nil t) 3465 (while (re-search-forward "^;+ ?" nil t)
3449 (replace-match "" nil nil)) 3466 (replace-match "" nil nil))
3450 (buffer-string)))))) 3467 (buffer-string))))))))
3451 (t
3452 ;; Display packages that match the keyword
3453 ;; or the list of keywords separated by comma.
3454 (insert (format "\n\^_\nFile: %s, Node: %s, Up: Top\n\n"
3455 Info-finder-file nodename))
3456 (insert "Finder Packages\n")
3457 (insert "***************\n\n")
3458 (insert
3459 "The following packages match the keyword `" nodename "':\n\n")
3460 (insert "* Menu:\n\n")
3461 (let ((keywords
3462 (mapcar 'intern (if (string-match-p "," nodename)
3463 (split-string nodename ",[ \t\n]*" t)
3464 (list nodename)))))
3465 (mapc
3466 (lambda (package)
3467 (unless (memq nil (mapcar (lambda (k) (memq k (nth 2 package)))
3468 keywords))
3469 (insert (format "* %-16s %s.\n"
3470 (concat (nth 0 package) "::")
3471 (nth 1 package)))))
3472 finder-package-info)))))
3473 3468
3474;;;###autoload 3469;;;###autoload
3475(defun info-finder (&optional keywords) 3470(defun info-finder (&optional keywords)