Subject: [PATCH] Improve package-menu-filter by sorting

From: Stefan Kangas <[email-masked]>
Date: Mon, 16 Sep 2019 02:53:32 +0200

When I say M-x list-packages and then f, I get to filter the package
list by keyword.  However, the list of completions is filled with
duplicates, and also not sorted.  The attached patch fixes that.

Any comments?

Best regards,
Stefan Kangas
From a919e2bae7ce2303fea620656120a2f1996fe382 Mon Sep 17 00:00:00 2001
From: Stefan Kangas <[email-masked]>
Date: Mon, 16 Sep 2019 02:41:40 +0200
Subject: [PATCH] Improve package-menu-filter by sorting

* lisp/emacs-lisp/package.el (package-menu-filter): Sort keywords
alphabetically for completion.
(package-all-keywords): Remove duplicate keywords.
---
 lisp/emacs-lisp/package.el | 19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el
index 18b5c962f6..f67b55dc61 100644
--- a/lisp/emacs-lisp/package.el
+++ b/lisp/emacs-lisp/package.el
@@ -2938,11 +2938,19 @@ package-menu--refresh
           (mapcar #'package-menu--print-info-simple info-list))))
 
 (defun package-all-keywords ()
-  "Collect all package keywords."
-  (let ((key-list))
+  "Return a list of all known package keywords.
+This takes into account all packages from all archives, even if
+they have not been installed."
+  ;; This would be easier with e.g. `seq-uniq', but it's a bit slow to
+  ;; first create the list and then filter it.  This seen hash version
+  ;; gives better performance on my machine by a factor of 6.
+  (let ((key-list)
+        (seen (make-hash-table :test 'equal)))
     (package--mapc (lambda (desc)
-                     (setq key-list (append (package-desc--keywords desc)
-                                            key-list))))
+              (dolist (key (package-desc--keywords desc))
+                (when (not (gethash key seen))
+                  (puthash key t seen)
+                  (push key key-list)))))
     key-list))
 
 (defun package--mapc (function &optional packages)
@@ -3642,7 +3650,8 @@ package-menu-filter
 To restore the full package list, type `q'."
   (interactive
    (list (completing-read-multiple
-          "Keywords (comma separated): " (package-all-keywords))))
+          "Keywords (comma separated): "
+          (sort (package-all-keywords) 'string-lessp))))
   (package-show-package-list t (if (stringp keyword)
                                    (list keyword)
                                  keyword)))
-- 
2.20.1