Subject: Re: bug#37419: [PATCH] Improve sorting in package list
From: Stefan Kangas <[email-masked]>
To: Lars Ingebrigtsen <[email-masked]>
Cc: [email-masked]
Date: Sat, 28 Sep 2019 17:09:44 +0200
List-Id: <debbugs-submit.debbugs.gnu.org>

Lars Ingebrigtsen <[email-masked]> writes:

> > The attached patch fixes sorting by version or description in the
> > package list.  It also improves sorting by archive to fall back to
> > name, and adds doc strings.
> >
> > Any comments?
>
> I haven't tried the code, but it looks good to me.

Thanks.  No other comments in 8 days, so I've now pushed the attached
as commit a444bb78ad.

Best regards,
Stefan Kangas
From a444bb78ad5d1a06f8d5b043e16941fdcc24de16 Mon Sep 17 00:00:00 2001
From: Stefan Kangas <[email-masked]>
Date: Mon, 16 Sep 2019 09:29:48 +0200
Subject: [PATCH] Improve sorting in package list (Bug#37419)

* lisp/emacs-lisp/package.el (package-menu-mode): Allow sorting by
version or description.
(package-menu--version-predicate): Fix sorting by version.
(package-menu--description-predicate): Fix sorting by description.
(package-menu--archive-predicate): Fall back to sorting by name if
archive is the same.
(package-menu--name-predicate, package-menu--status-predicate): Add
doc string.
* etc/NEWS: Announce the above changes.
---
 etc/NEWS                   |  3 +++
 lisp/emacs-lisp/package.el | 29 +++++++++++++++++++++--------
 2 files changed, 24 insertions(+), 8 deletions(-)

diff --git a/etc/NEWS b/etc/NEWS
index 97b96d1e4e..34b7a5aa29 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -983,6 +983,9 @@ early init file.
 ---
 *** Imenu support has been added to 'package-menu-mode'.
 
+---
+*** The package list can now be sorted by version or description.
+
 ** Info
 
 +++
diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el
index a8362cb205..ab1fb8b90f 100644
--- a/lisp/emacs-lisp/package.el
+++ b/lisp/emacs-lisp/package.el
@@ -2725,11 +2725,11 @@ package-menu-mode
                              package-menu--transaction-status)))
   (setq tabulated-list-format
         `[("Package" 18 package-menu--name-predicate)
-          ("Version" 13 nil)
+          ("Version" 13 package-menu--version-predicate)
           ("Status"  10 package-menu--status-predicate)
           ,@(if (cdr package-archives)
                 '(("Archive" 10 package-menu--archive-predicate)))
-          ("Description" 0 nil)])
+          ("Description" 0 package-menu--description-predicate)])
   (setq tabulated-list-padding 2)
   (setq tabulated-list-sort-key (cons "Status" nil))
   (add-hook 'tabulated-list-revert-hook #'package-menu--refresh nil t)
@@ -3469,13 +3469,17 @@ package-menu-execute
               (message "Operation %s finished" message-template))))))))
 
 (defun package-menu--version-predicate (A B)
-  (let ((vA (or (aref (cadr A) 1)  '(0)))
-        (vB (or (aref (cadr B) 1) '(0))))
+  "Predicate to sort \"*Packages*\" buffer by the version column.
+This is used for `tabulated-list-format' in `package-menu-mode'."
+  (let ((vA (or (version-to-list (aref (cadr A) 1)) '(0)))
+        (vB (or (version-to-list (aref (cadr B) 1)) '(0))))
     (if (version-list-= vA vB)
         (package-menu--name-predicate A B)
       (version-list-< vA vB))))
 
 (defun package-menu--status-predicate (A B)
+  "Predicate to sort \"*Packages*\" buffer by the status column.
+This is used for `tabulated-list-format' in `package-menu-mode'."
   (let ((sA (aref (cadr A) 2))
         (sB (aref (cadr B) 2)))
     (cond ((string= sA sB)
@@ -3506,19 +3510,28 @@ package-menu--status-predicate
           (t (string< sA sB)))))
 
 (defun package-menu--description-predicate (A B)
-  (let ((dA (aref (cadr A) 3))
-        (dB (aref (cadr B) 3)))
+  "Predicate to sort \"*Packages*\" buffer by the description column.
+This is used for `tabulated-list-format' in `package-menu-mode'."
+  (let ((dA (aref (cadr A) (if (cdr package-archives) 4 3)))
+        (dB (aref (cadr B) (if (cdr package-archives) 4 3))))
     (if (string= dA dB)
         (package-menu--name-predicate A B)
       (string< dA dB))))
 
 (defun package-menu--name-predicate (A B)
+  "Predicate to sort \"*Packages*\" buffer by the name column.
+This is used for `tabulated-list-format' in `package-menu-mode'."
   (string< (symbol-name (package-desc-name (car A)))
            (symbol-name (package-desc-name (car B)))))
 
 (defun package-menu--archive-predicate (A B)
-  (string< (or (package-desc-archive (car A)) "")
-           (or (package-desc-archive (car B)) "")))
+  "Predicate to sort \"*Packages*\" buffer by the archive column.
+This is used for `tabulated-list-format' in `package-menu-mode'."
+  (let ((a (or (package-desc-archive (car A)) ""))
+        (b (or (package-desc-archive (car B)) "")))
+    (if (string= a b)
+        (package-menu--name-predicate A B)
+      (string< a b))))
 
 (defun package-menu--populate-new-package-list ()
   "Decide which packages are new in `package-archives-contents'.
-- 
2.20.1