Package: emacs;
Reported by: Pengji Zhang <me <at> pengjiz.com>
Date: Sat, 29 Mar 2025 11:09:02 UTC
Severity: normal
Tags: patch
Done: Eli Zaretskii <eliz <at> gnu.org>
Bug is archived. No further changes may be made.
View this message in rfc822 format
From: help-debbugs <at> gnu.org (GNU bug Tracking System) To: Eli Zaretskii <eliz <at> gnu.org> Cc: tracker <at> debbugs.gnu.org Subject: bug#77361: closed ([PATCH] New user option to hide minor mode lighters) Date: Sun, 13 Apr 2025 08:48:02 +0000
[Message part 1 (text/plain, inline)]
Your message dated Sun, 13 Apr 2025 11:46:33 +0300 with message-id <865xj8la8m.fsf <at> gnu.org> and subject line Re: bug#77361: [PATCH] New user option to hide minor mode lighters has caused the debbugs.gnu.org bug report #77361, regarding [PATCH] New user option to hide minor mode lighters to be marked as done. (If you believe you have received this mail in error, please contact help-debbugs <at> gnu.org.) -- 77361: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=77361 GNU Bug Tracking System Contact help-debbugs <at> gnu.org with problems
[Message part 2 (message/rfc822, inline)]
From: Pengji Zhang <me <at> pengjiz.com> To: bug-gnu-emacs <at> gnu.org Subject: [PATCH] New user option to hide minor mode lighters Date: Sat, 29 Mar 2025 19:07:40 +0800[Message part 3 (text/plain, inline)]Hello, The attached patch adds a new user option to hide some minor mode lighters on the mode line (by collapsing them into a menu), which is to shorten the mode line and prioritize important information when many minor modes are on. There exist a few packages that solve the problem. To name a few: - diminish[1] and delight[2]. Both offer a way to change the minor mode lighters by modifying 'minor-mode-alist'. To hide a minor mode lighter, one may change it to nil. - minions[3], which partially inspired this patch. It replaces minor mode lighters by a menu to toggle all minor modes. This patch is different from those solutions in two aspects: - Unlike diminish or delight, one can still see the lighters by clicking the button, instead of hiding them permanently. Besides, this patch is compatible with those two packages. - Unlike minions, this patch focuses on *lighters* for *enabled* minor modes. The menu contains only lighters, making it a more space efficient replacement for lighters on mode line, instead of a way to manage minor modes like minions. So I hope this patch is still useful given the existing similar solutions. Please let me know what you think. Thanks! Pengji [1] https://github.com/myrjola/diminish.el [2] https://elpa.gnu.org/packages/delight.html [3] https://github.com/tarsius/minions[0001-New-user-option-to-hide-minor-mode-lighters.patch (text/x-patch, inline)]From c1e27606247761c31cec3d363714875c74b30277 Mon Sep 17 00:00:00 2001 From: Pengji Zhang <me <at> pengjiz.com> Date: Sat, 29 Mar 2025 19:04:58 +0800 Subject: [PATCH] New user option to hide minor mode lighters * lisp/bindings.el (mode-line-collapse-minor-modes): New user option. (mode-line-minor-modes): New variable to hold mode line constructs for minor modes. (mode-line-modes): Use the new variable 'mode-line-minor-modes', and adjust the order of elements so the indicator for hidden minor modes is shown towards the end. (mode-line--make-lighter-menu): New helper function to generate the menu for hidden minor modes. (mode-line--minor-modes): New helper function to computer mode line constructs for minor mode lighters. * doc/lispref/modes.texi (Mode Line Basics): Document the new user option. * etc/NEWS (Note): Annouce the new user option. --- doc/lispref/modes.texi | 12 ++++ etc/NEWS | 9 +++ lisp/bindings.el | 122 ++++++++++++++++++++++++++++++++++++++--- 3 files changed, 136 insertions(+), 7 deletions(-) diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi index 788d98fdf20..23c363be12c 100644 --- a/doc/lispref/modes.texi +++ b/doc/lispref/modes.texi @@ -2163,6 +2163,18 @@ Mode Line Basics variable can be buffer-local to only compress mode-lines in certain buffers. +@vindex mode-line-collapse-minor-modes + To further ``compress'' the mode line, you may customize the +@code{mode-line-collapse-minor-modes} option to a non-@code{nil} value, +and Emacs will hide some minor mode indicators on the mode line by +collapsing them into a single clickable button. The option can also be +a list of symbols to select minor modes indicators to hide or show. If +the list starts with the symbol @code{not}, it specifies minor modes to +show, otherwise it means minor modes to hide. For example, setting it +to @code{(not flymake-mode)} makes only the indicator for Flymake mode +shown, and setting it to @code{(eldoc-mode)} hides only the indicator +for ElDoc mode. + @node Mode Line Data @subsection The Data Structure of the Mode Line @cindex mode line construct diff --git a/etc/NEWS b/etc/NEWS index 1bd2fd6d486..8b7dfa0ee04 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -316,6 +316,15 @@ This will inhibit implied resizing while a new frame is made and can be useful on tiling window managers where the initial frame size should be specified by external means. +** Mode Line + ++++ +*** New user option 'mode-line-collapse-minor-modes'. +If non-nil, minor mode lighters on the mode line are collapsed into a +single button. It could also be a list to specify minor mode lighters +to hide or show. The default value is nil, which retains the previous +behavior of showing all minor mode lighters. + ** Tab Bars and Tab Lines --- diff --git a/lisp/bindings.el b/lisp/bindings.el index 9707ce4b474..a32e3d58dc7 100644 --- a/lisp/bindings.el +++ b/lisp/bindings.el @@ -429,6 +429,120 @@ bindings--sort-menu-keymap (bindings--menu-item-string (cdr-safe b)))))) (nconc (make-sparse-keymap prompt) bindings))) +(defcustom mode-line-collapse-minor-modes nil + "Minor modes for which mode line lighters are hidden. +Hidden lighters are collapsed into one. + +The value could be a list (MODES ...) which means to collapse lighters +only for MODES, or a list (not MODES ...) which means to collapse all +lighters for minor modes not in MODES. Other non-nil values make all +lighters hidden." + :type '(choice (const :tag "No modes" nil) + (repeat :tag "Modes" symbol) + (cons :tag "All modes except" + (const not) (repeat symbol)) + (const :tag "All modes" t)) + :group 'mode-line) + +(defvar mode-line-minor-modes '(:eval (mode-line--minor-modes)) + "Mode line construct for minor mode lighters.") +;;;###autoload +(put 'mode-line-minor-modes 'risky-local-variable t) + +(defun mode-line--make-lighter-menu (alist) + "Return a menu keymap for minor mode lighters in ALIST. +ALIST should be in the same format as `minor-mode-alist'. + +Return nil if no lighters in ALIST should be visible, for example, there +are no active minor modes or non-empty lighters." + (let ((menu (make-sparse-keymap "Minor Modes")) + (empty t)) + (dolist (item alist) + (when-let* ((variable (car item)) + ((and (boundp variable) + (symbol-value variable))) + (lighter (format-mode-line `("" ,@(cdr-safe item)))) + ((not (string= lighter ""))) + (toggle (or (get variable :minor-mode-function) variable)) + ;; Follow the format in `mouse-minor-mode-menu' + (name (format "%s - %s" lighter + (capitalize + (string-replace + "-" " " (symbol-name toggle)))))) + (when (eq ? (aref name 0)) + (setq name (substring name 1))) + (let* ((map (cdr-safe (assq variable minor-mode-map-alist))) + (mm-menu (and (keymapp map) + (keymap-lookup map "<menu-bar>")))) + (setq mm-menu + (cond (mm-menu (mouse-menu-non-singleton mm-menu)) + ((fboundp toggle) + (define-keymap :name name + "<help>" (list 'menu-item + "Help for minor mode" + (lambda () (interactive) + (describe-function toggle))) + "<turn-off>" (list 'menu-item + "Turn off minor mode" + toggle))) + ;; No menu and not a minor mode function, so just + ;; display the label without a sub-menu. + (t nil))) + (keymap-set menu (format "<%s>" toggle) + (list 'menu-item name mm-menu)) + (setq empty nil)))) + (and (not empty) menu))) + +(defun mode-line--minor-modes () + "Compute mode line constructs for minor mode lighters." + (let (visible hidden) + (cond + ((not mode-line-collapse-minor-modes) + (setq visible minor-mode-alist + hidden nil)) + ((eq 'not (car-safe mode-line-collapse-minor-modes)) + (let ((modes (cdr mode-line-collapse-minor-modes))) + (dolist (item minor-mode-alist) + (if (memq (car item) modes) + (push item visible) + (push item hidden))) + (setq visible (nreverse visible) + hidden (nreverse hidden)))) + ((listp mode-line-collapse-minor-modes) + (let ((modes mode-line-collapse-minor-modes)) + (dolist (item minor-mode-alist) + (if (memq (car item) modes) + (push item hidden) + (push item visible))) + (setq visible (nreverse visible) + hidden (nreverse hidden)))) + (t (setq visible nil + hidden minor-mode-alist))) + (list "" + `(:propertize ("" ,visible) + mouse-face mode-line-highlight + help-echo "Minor mode\n\ +mouse-1: Display minor mode menu\n\ +mouse-2: Show help for minor mode\n\ +mouse-3: Toggle minor modes" + local-map ,mode-line-minor-mode-keymap) + (when-let* ((menu (mode-line--make-lighter-menu hidden)) + (menu-binding (list 'menu-item "Display" menu + :filter #'bindings--sort-menu-keymap)) + (toggle-binding (list 'menu-item "Toggle" mode-line-mode-menu + :fitler #'bindings--sort-menu-keymap)) + (keymap (define-keymap + "<mode-line> <down-mouse-1>" menu-binding + "<mode-line> <mouse-2>" #'describe-mode + "<mode-line> <down-mouse-3>" toggle-binding))) + `(:propertize ,(if (char-displayable-p ?…) " …" " ...") + mouse-face mode-line-highlight + help-echo "Hidden minor modes\n\ +mouse-1: Display hidden minor modes\n\ +mouse-2: Show help for enabled minor modes\n\ +mouse-3: Toggle minor modes" + local-map ,keymap))))) + (defvar mode-line-major-mode-keymap (let ((map (make-sparse-keymap))) (define-key map [mode-line down-mouse-1] @@ -466,17 +580,11 @@ mode-line-modes mouse-face mode-line-highlight local-map ,mode-line-major-mode-keymap) '("" mode-line-process) - `(:propertize ("" minor-mode-alist) - mouse-face mode-line-highlight - help-echo "Minor mode\n\ -mouse-1: Display minor mode menu\n\ -mouse-2: Show help for minor mode\n\ -mouse-3: Toggle minor modes" - local-map ,mode-line-minor-mode-keymap) (propertize "%n" 'help-echo "mouse-2: Remove narrowing from buffer" 'mouse-face 'mode-line-highlight 'local-map (make-mode-line-mouse-map 'mouse-2 #'mode-line-widen)) + '("" mode-line-minor-modes) ")" (propertize "%]" 'help-echo recursive-edit-help-echo) " ")) -- 2.49.0
[Message part 5 (message/rfc822, inline)]
From: Eli Zaretskii <eliz <at> gnu.org> To: Pengji Zhang <me <at> pengjiz.com> Cc: 77361-done <at> debbugs.gnu.org Subject: Re: bug#77361: [PATCH] New user option to hide minor mode lighters Date: Sun, 13 Apr 2025 11:46:33 +0300> From: Pengji Zhang <me <at> pengjiz.com> > Cc: 77361 <at> debbugs.gnu.org > Date: Sun, 06 Apr 2025 16:05:00 +0800 > > Eli Zaretskii <eliz <at> gnu.org> writes: > > > Please in future submissions of the patch mention the bug number in > > the log message. > > Thanks for the review! Bug number added in the updated patch. > > >> --- a/doc/lispref/modes.texi > >> +++ b/doc/lispref/modes.texi > >> @@ -2163,6 +2163,18 @@ Mode Line Basics > >> variable can be buffer-local to only compress mode-lines in certain > >> buffers. > >> > >> +@vindex mode-line-collapse-minor-modes > >> + To further ``compress'' the mode line, you may customize the > >> +@code{mode-line-collapse-minor-modes} option to a non-@code{nil} value, > >> +and Emacs will hide some minor mode indicators on the mode line by > >> +collapsing them into a single clickable button. The option can also be > >> +a list of symbols to select minor modes indicators to hide or show. If > >> +the list starts with the symbol @code{not}, it specifies minor modes to > >> +show, otherwise it means minor modes to hide. For example, setting it > >> +to @code{(not flymake-mode)} makes only the indicator for Flymake mode > >> +shown, and setting it to @code{(eldoc-mode)} hides only the indicator > >> +for ElDoc mode. > > > > I think this text and the preceding paragraph should be moved to the > > Emacs user manual, into the "Optional Mode Line" node. These are > > user-facing features, so their place is not in the ELisp Reference > > manual. > > > > For the user manual, the above description of the possible values of > > mode-line-collapse-minor-modes is too detailed. I suggest to have > > there only the first sentence, and then refer to the doc string for > > the various alternative forms of the value. > > I have moved the paragraph for 'mode-line-compact' to the "Optional Mode > Line" node, and added the first sentence for > 'mode-line-collapse-minor-modes' to that paragraph. > > >> ++++ > >> +*** New user option 'mode-line-collapse-minor-modes'. > >> +If non-nil, minor mode lighters on the mode line are collapsed into a > >> +single button. It could also be a list to specify minor mode lighters > > ^^^^^^^^^^^^^^^^^^^^^^^ > > "The value could also be a list..." > > Fixed. > > >> +(defcustom mode-line-collapse-minor-modes nil > >> + "Minor modes for which mode line lighters are hidden. > >> +Hidden lighters are collapsed into one. > >> + > >> +The value could be a list (MODES ...) which means to collapse lighters > >> +only for MODES, or a list (not MODES ...) which means to collapse all > >> +lighters for minor modes not in MODES. Other non-nil values make all > >> +lighters hidden." > >> + :type '(choice (const :tag "No modes" nil) > >> + (repeat :tag "Modes" symbol) > >> + (cons :tag "All modes except" > >> + (const not) (repeat symbol)) > >> + (const :tag "All modes" t)) > >> + :group 'mode-line) > > > > The :version tag is missing. > > Added. Thanks, now installed on the master branch, and closing the bug.
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.