Subject: Re: bug#71823: 31.0.50; project-mode-line and eglot duplicate project-name in mode-line

From: Spencer Baugh <[email-masked]>
Date: Wed, 03 Jul 2024 09:17:49 -0400

João Távora <[email-masked]> writes:

> On Sun, Jun 30, 2024, 13:51 <[email-masked]> wrote:
>
>  João Távora <[email-masked]> writes:
>  > On Sat, Jun 29, 2024, 15:24 Spencer Baugh <[email-masked]> wrote:
>  >
>  >  Or, here's an alternative idea, more aggressive:
>  >
>  >  What if Eglot just sets project-mode-line=t in eglot-managed buffers, and removes the project-name from the Eglot entry
>  >  entirely?
>  >
>  >  Then the language identifier would be the major mode, the project identifier would be project-mode-line, and the eglot
>  status
>  >  indicator would just be for the status of the server.
>  >
>  > Works for me, it's in line with Eglot's policy of setting other modes when managing buffers. Show a patch. 
>
>  Attached.
>
>  I do think this is a great way to resolve this - now that
>  project-mode-line exists, using it deletes one small bit of
>  eglot-specific functionality, which is in line with the Eglot design
>  philosophy.
>
> Yes.
>
>  The only issue is that this was only added to mode-line-format in Emacs
>  30, so we can only use it in Emacs 30 or later.
>
> No, that's not an issue, or rather your solution isn't the way to solve it. In trunk Eglot use everything that is in trunk Emacs. In
> released Eglot versions name sure you depend on capable versions of core GNU Elpa packages, a set which already includes
> project.el. So basically version bumps solves it.

Yes, certainly.  That's why I bumped the required version of project.el
in the Package-Requires.

But, loading a newer version of project.el doesn't add the
project-mode-line entry to mode-line-format.  That's done in
bindings.el, and can't be updated.  So we still need to do something
else to accomodate an Emacs 29 user with an updated eglot.el and
project.el.

Juri says "(member '(project-mode-line project-mode-line-format)
mode-line-format)" check is good, though, so I think we can just do
that.

> So please show an updated patch, and don't forget the etc/EGLOT-NEWS entry.

Ok, here's a new version of the patch with an etc/EGLOT-NEWS entry.

>From c7ab7a1f7b74effeca4cebbc5adb602bc8a57c87 Mon Sep 17 00:00:00 2001
From: Spencer Baugh <[email-masked]>
Date: Wed, 3 Jul 2024 09:11:51 -0400
Subject: [PATCH] Use project-mode-line for the project nick in Eglot

The existence of project-mode-line now means that eglot can have
an indicator for the current project of the current buffer,
without using the eglot mode-line entry to do it.

This commit teaches eglot to (when possible) set
project-mode-line true in eglot-managed buffers and remove
project-name from the eglot mode line entry.

* etc/EGLOT-NEWS: Announce usage of project-mode-line.
* lisp/progmodes/eglot.el (eglot--managed-mode): Set
project-mode-line if the project-mode-line entry is in
mode-line-format.
(eglot-menu): Always include eglot-server-menu as a submenu.
(eglot--mode-line-format): Don't include project-name when
project-mode-line is set. (bug#71823)
---
 etc/EGLOT-NEWS          |  8 +++++
 lisp/progmodes/eglot.el | 72 ++++++++++++++++++++++-------------------
 2 files changed, 46 insertions(+), 34 deletions(-)

diff --git a/etc/EGLOT-NEWS b/etc/EGLOT-NEWS
index 0e3e4b7aff8..7462edd1cf0 100644
--- a/etc/EGLOT-NEWS
+++ b/etc/EGLOT-NEWS
@@ -26,6 +26,14 @@ Eglot will now try to not register $/progress messages from the server
 when the defcustom is set to nil.  This requires a restart of the server
 for the change to take effect.
 
+** Mode line entry now uses project-mode-line for project name
+
+In buffers managed by Eglot, the mode line has always contained the
+project-name of that buffer's project (usually the basename of the VCS
+root directory).  Previously project-name was part of Eglot's mode line
+entry; now project-name is in a separate entry provided by
+project-mode-line.
+
 
 * Changes in Eglot 1.17 (25/1/2024)
 
diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el
index bb6b0281d9f..fa09fb5ea51 100644
--- a/lisp/progmodes/eglot.el
+++ b/lisp/progmodes/eglot.el
@@ -7,7 +7,7 @@
 ;; Maintainer: João Távora <[email-masked]>
 ;; URL: https://github.com/joaotavora/eglot
 ;; Keywords: convenience, languages
-;; Package-Requires: ((emacs "26.3") (compat "27.1") (eldoc "1.14.0") (external-completion "0.1") (flymake "1.2.1") (jsonrpc "1.0.24") (project "0.9.8") (seq "2.23") (track-changes "1.2") (xref "1.6.2"))
+;; Package-Requires: ((emacs "26.3") (compat "27.1") (eldoc "1.14.0") (external-completion "0.1") (flymake "1.2.1") (jsonrpc "1.0.24") (project "0.11.0") (seq "2.23") (track-changes "1.2") (xref "1.6.2"))
 
 ;; This is a GNU ELPA :core package.  Avoid adding functionality
 ;; that is not available in the version of Emacs recorded above or any
@@ -2026,6 +2026,8 @@ eglot--managed-mode
     (eglot--setq-saving company-tooltip-align-annotations t)
     (eglot--setq-saving eldoc-documentation-strategy
                         #'eldoc-documentation-compose)
+    (when (member '(project-mode-line project-mode-line-format) mode-line-format)
+      (setq-local project-mode-line t))
     (unless (eglot--stay-out-of-p 'imenu)
       (add-function :before-until (local 'imenu-create-index-function)
                     #'eglot-imenu))
@@ -2161,10 +2163,24 @@ eglot-upgrade-eglot
       (package-delete existing t))
     (package-install (cadr (assoc 'eglot package-archive-contents)))))
 
+(easy-menu-define eglot-server-menu nil "Monitor server communication"
+  '("Debugging the server communication"
+    ["Reconnect to server" eglot-reconnect]
+    ["Quit server" eglot-shutdown]
+    "--"
+    ["LSP events buffer" eglot-events-buffer]
+    ["Server stderr buffer" eglot-stderr-buffer]
+    ["Customize event buffer size"
+     (lambda ()
+       (interactive)
+       (customize-variable 'eglot-events-buffer-size))]))
+
 (easy-menu-define eglot-menu nil "Eglot"
   `("Eglot"
     ;; Commands for getting information and customization.
     ["Customize Eglot" (lambda () (interactive) (customize-group "eglot"))]
+    ["Server" eglot-server-menu
+     :active (eglot-current-server)]
     "--"
     ;; xref like commands.
     ["Find definitions" xref-find-definitions
@@ -2211,18 +2227,6 @@ eglot-menu
     ["Quickfix" eglot-code-action-quickfix
      :visible (eglot-server-capable :codeActionProvider)]))
 
-(easy-menu-define eglot-server-menu nil "Monitor server communication"
-  '("Debugging the server communication"
-    ["Reconnect to server" eglot-reconnect]
-    ["Quit server" eglot-shutdown]
-    "--"
-    ["LSP events buffer" eglot-events-buffer]
-    ["Server stderr buffer" eglot-stderr-buffer]
-    ["Customize event buffer size"
-     (lambda ()
-       (interactive)
-       (customize-variable 'eglot-events-buffer-size))]))
-
 (defun eglot--mode-line-props (thing face defs &optional prepend)
   "Helper for function `eglot--mode-line-format'.
 Uses THING, FACE, DEFS and PREPEND."
@@ -2261,28 +2265,28 @@ eglot--mode-line-format
            'help-echo (format "Project '%s'\nmouse-1: LSP server control menu" nick)
            'keymap (let ((map (make-sparse-keymap)))
                      (define-key map [mode-line down-mouse-1] eglot-server-menu)
-                     map))
-         ,@(when last-error
-             `("/" ,(eglot--mode-line-props
-                     "error" 'compilation-mode-line-fail
-                     '((mouse-3 eglot-clear-status  "Clear this status"))
-                     (format "An error occurred: %s\n" (plist-get last-error
-                                                                  :message)))))
-         ,@(when (cl-plusp pending)
-             `("/" ,(eglot--mode-line-props
-                     (format "%d" pending) 'warning
-                     '((mouse-3 eglot-forget-pending-continuations
-                                "Forget pending continuations"))
-                     "Number of outgoing, \
+                     map))))
+     (when last-error
+       `("/" ,(eglot--mode-line-props
+               "error" 'compilation-mode-line-fail
+               '((mouse-3 eglot-clear-status  "Clear this status"))
+               (format "An error occurred: %s\n" (plist-get last-error
+                                                            :message)))))
+     (when (cl-plusp pending)
+       `("/" ,(eglot--mode-line-props
+               (format "%d" pending) 'warning
+               '((mouse-3 eglot-forget-pending-continuations
+                          "Forget pending continuations"))
+               "Number of outgoing, \
 still unanswered LSP requests to the server\n")))
-         ,@(cl-loop for pr hash-values of (eglot--progress-reporters server)
-                    when (eq (car pr)  'eglot--mode-line-reporter)
-                    append `("/" ,(eglot--mode-line-props
-                                   (format "%s%%%%" (or (nth 4 pr) "?"))
-                                   'eglot-mode-line
-                                   nil
-                                   (format "(%s) %s %s" (nth 1 pr)
-                                           (nth 2 pr) (nth 3 pr))))))))))
+     (cl-loop for pr hash-values of (eglot--progress-reporters server)
+              when (eq (car pr)  'eglot--mode-line-reporter)
+              append `("/" ,(eglot--mode-line-props
+                             (format "%s%%%%" (or (nth 4 pr) "?"))
+                             'eglot-mode-line
+                             nil
+                             (format "(%s) %s %s" (nth 1 pr)
+                                     (nth 2 pr) (nth 3 pr))))))))
 
 (add-to-list 'mode-line-misc-info
              `(eglot--managed-mode (" [" eglot--mode-line-format "] ")))
-- 
2.39.3