Subject: [PATCH] package.el: Add built-in version check and loaded package marking

From: david <[email-masked]>
Date: Tue, 18 Mar 2025 17:57:35 -0400

Hello everyone, this is the corrected patch incorporating suggestions
from Philip and Stefan.  I also changed "activated" to "loaded", as
the latter is more accurate for marking packages in the "Other
versions" section.

I’m submitting this patch to enhance `describe-package` by adding
information about the currently loaded package and improving the
built-in version check.  Since "Other versions" already displays the
current version of the package, I’ve added a "loaded" marker to
indicate which version is loaded in the current Emacs session.

This patch for `package.el` introduces two improvements:

1. The package menu now compares the built-in version of a package
with the available version.  If the available version is newer, the
status is set to "available"; otherwise, it is marked as "built-in".
This helps users identify when updates are available for built-in
packages.

2. Packages listed in the "Other versions" section are now marked with
", loaded" if they are currently loaded in the Emacs session.  This
provides clarity on which versions are in use.

I’d appreciate your feedback and suggestions for integrating this
corrected patch into the master branch.

>From 63852636e1461d53ca52e9b135b652ffb33e5fb6 Mon Sep 17 00:00:00 2001
From: dimagid <[email-masked]>
Date: Tue, 18 Mar 2025 13:02:40 -0400
Subject: [PATCH] package.el: Add built-in version check and loaded package
 marking

This commit introduces two improvements to package.el:

1. The package menu now compares the built-in version of a package with
the available version.  If the available version is newer, the status
is set to "available"; otherwise, it is marked as "built-in".  This
helps users identify when updates are available for built-in packages.

2. Packages listed in the "Other versions" section are now marked with
", loaded" if they are currently loaded in the Emacs session.  This
provides clarity on which versions are in use.

These changes enhance the user experience by making it easier to
identify updates for built-in packages and track which package
versions are currently loaded.

* lisp/emacs-lisp/package.el (package-menu--print-info-simple): Add
built-in version check and loaded package marking.
(package-menu--check-builtin-version): New function to compare
built-in and available versions.
(describe-package-1): Update logic to mark loaded packages.
---
 lisp/emacs-lisp/package.el | 72 ++++++++++++++++++++++++++++----------
 1 file changed, 53 insertions(+), 19 deletions(-)

diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el
index b9a8dacab15..186ce8238d7 100644
--- a/lisp/emacs-lisp/package.el
+++ b/lisp/emacs-lisp/package.el
@@ -2977,26 +2977,36 @@ describe-package-1
         (package--print-email-button author)))
     (let* ((all-pkgs (append (cdr (assq name package-alist))
                              (cdr (assq name package-archive-contents))
-                             (let ((bi (assq name package--builtins)))
-                               (if bi (list (package--from-builtin bi))))))
-           (other-pkgs (delete desc all-pkgs)))
+                             ;; Add built-in packages to the list if they exist.
+                             (and-let* ((bi (assq name package--builtins)))
+                               (list (package--from-builtin bi)))))
+           (other-pkgs (remove desc all-pkgs)))
       (when other-pkgs
         (package--print-help-section "Other versions"
-          (mapconcat (lambda (opkg)
-                       (let* ((ov (package-desc-version opkg))
-                              (dir (package-desc-dir opkg))
-                              (from (or (package-desc-archive opkg)
-                                        (if (stringp dir) "installed" dir))))
-                         (if (not ov) (format "%s" from)
-                           (format "%s (%s)"
-                                   (make-text-button (package-version-join ov) nil
-                                                     'font-lock-face 'link
-                                                     'follow-link t
-                                                     'action
-                                                     (lambda (_button)
-                                                       (describe-package opkg)))
-                                   from))))
-                     other-pkgs ", ")
+          (mapconcat
+           (lambda (opkg)
+             (let* ((ov (package-desc-version opkg))
+                    (dir (package-desc-dir opkg))
+                    (from (or (package-desc-archive opkg)
+                              (if (stringp dir) "installed" "built-in")))
+                    ;; Check if the package is currently loaded and
+                    ;; matches the described version.
+                    (loaded (and (member (package-desc-name opkg)
+                                         package-activated-list)
+                                 (equal ov (package-desc-version desc)))))
+               (format "%s (%s%s)"
+                       (if ov
+                           (make-text-button
+                            (package-version-join ov) nil
+                            'font-lock-face 'link
+                            'follow-link t
+                            'action
+                            (lambda (_button)
+                              (describe-package opkg)))
+                         "n/a")
+                       from
+                       (if loaded ", loaded" ""))))
+           other-pkgs ", ")
           ".")))
 
     (insert "\n")
@@ -3640,11 +3650,35 @@ package-status-avail-obso
 
 ;;; Package menu printing
 
+(defun package-menu--check-builtin-version (pkg)
+  "Check if PKG is a built-in package and compare versions.
+Return the appropriate status for PKG."
+  (let* ((status (package-desc-status pkg))
+         (name (package-desc-name pkg))
+         (version (package-desc-version pkg))
+         ;; Check if the package is built-in by looking it up in
+         ;; `package--builtins'.
+         (built-in-pkg (assq name package--builtins))
+         ;; If the package is built-in, get its version.
+         (built-in-version (if built-in-pkg
+                               (package-desc-version
+                                (package--from-builtin built-in-pkg)))))
+    (cond
+     ((not (and built-in-pkg (equal status "available")))
+      status)
+     ;; If the built-in version is older than the available version,
+     ;; return "available".
+     ((version-list-< built-in-version version)
+      "available")
+     ;; Otherwise, return "built-in".
+     (t
+      "built-in"))))
+
 (defun package-menu--print-info-simple (pkg)
   "Return a package entry suitable for `tabulated-list-entries'.
 PKG is a `package-desc' object.
 Return (PKG-DESC [NAME VERSION STATUS DOC])."
-  (let* ((status  (package-desc-status pkg))
+  (let* ((status (package-menu--check-builtin-version pkg))
          (face (pcase status
                  ("built-in"  'package-status-built-in)
                  ("external"  'package-status-external)
-- 
2.48.1