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>
To reply to this bug, email your comments to 77361 AT debbugs.gnu.org.
There is no need to reopen the bug first.
Toggle the display of automated, internal messages from the tracker.
View this report as an mbox folder, status mbox, maintainer mbox
bug-gnu-emacs <at> gnu.org
:bug#77361
; Package emacs
.
(Sat, 29 Mar 2025 11:09:02 GMT) Full text and rfc822 format available.Pengji Zhang <me <at> pengjiz.com>
:bug-gnu-emacs <at> gnu.org
.
(Sat, 29 Mar 2025 11:09:02 GMT) Full text and rfc822 format available.Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):
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 1 (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
bug-gnu-emacs <at> gnu.org
:bug#77361
; Package emacs
.
(Sat, 05 Apr 2025 09:05:02 GMT) Full text and rfc822 format available.Message #8 received at 77361 <at> debbugs.gnu.org (full text, mbox):
From: Eli Zaretskii <eliz <at> gnu.org> To: Pengji Zhang <me <at> pengjiz.com> Cc: 77361 <at> debbugs.gnu.org Subject: Re: bug#77361: [PATCH] New user option to hide minor mode lighters Date: Sat, 05 Apr 2025 12:03:43 +0300
> From: Pengji Zhang <me <at> pengjiz.com> > Date: Sat, 29 Mar 2025 19:07:40 +0800 > > 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! Thanks, some comments below. > >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. Please in future submissions of the patch mention the bug number in the log message. > --- 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. > ++++ > +*** 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..." > +(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.
bug-gnu-emacs <at> gnu.org
:bug#77361
; Package emacs
.
(Sat, 05 Apr 2025 11:46:02 GMT) Full text and rfc822 format available.Message #11 received at 77361 <at> debbugs.gnu.org (full text, mbox):
From: Daniel Mendler <mail <at> daniel-mendler.de> To: Pengji Zhang <me <at> pengjiz.com> Cc: 77361 <at> debbugs.gnu.org Subject: Re: bug#77361: [PATCH] New user option to hide minor mode lighters, [PATCH] New user option to hide minor mode lighters Date: Sat, 05 Apr 2025 13:45:10 +0200
Hello Pengji! Pengji Zhang <me <at> pengjiz.com> writes: > 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! This is a good idea. I've used both minions and diminish and it is nice to have this functionality ootb. I have some concerns however regarding the frequent mode line recomputation during redisplay. Do you see a possibility to cache the computed minor mode menu and collapsed lighter? In any case, the computation should be as efficient as possible. For profiling I suggest to enable your new user option and then scroll repeatedly in order to force redisplays and mode line recomputations. If certain mode line functions appear prominently in the profile they are candidates for optimization, in order to reduce redisplay latency. Daniel
bug-gnu-emacs <at> gnu.org
:bug#77361
; Package emacs
.
(Sun, 06 Apr 2025 08:06:02 GMT) Full text and rfc822 format available.Message #14 received at 77361 <at> debbugs.gnu.org (full text, mbox):
From: Pengji Zhang <me <at> pengjiz.com> To: Eli Zaretskii <eliz <at> gnu.org> Cc: 77361 <at> debbugs.gnu.org Subject: Re: bug#77361: [PATCH] New user option to hide minor mode lighters Date: Sun, 06 Apr 2025 16:05:00 +0800
[Message part 1 (text/plain, inline)]
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.
[0001-New-user-option-to-hide-minor-mode-lighters-bug-7736.patch (text/x-patch, inline)]
From ff653f559b9cd984f584756741b7b52815befe8d 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 (bug#77361) * 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--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. (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. * doc/lispref/modes.texi (Mode Line Basics): Move the paragraph for 'mode-line-compact' from here... * doc/emacs/display.texi (Optional Mode Line): ...to here, and document the new user option. * etc/NEWS: Annouce the new user option. --- doc/emacs/display.texi | 15 +++++ doc/lispref/modes.texi | 11 ---- etc/NEWS | 9 +++ lisp/bindings.el | 128 ++++++++++++++++++++++++++++++++++++++--- 4 files changed, 145 insertions(+), 18 deletions(-) diff --git a/doc/emacs/display.texi b/doc/emacs/display.texi index 520d3289f2d..ad496b5b1cd 100644 --- a/doc/emacs/display.texi +++ b/doc/emacs/display.texi @@ -1811,6 +1811,21 @@ Optional Mode Line @code{eol-mnemonic-dos}, @code{eol-mnemonic-mac}, and @code{eol-mnemonic-undecided} to the strings you prefer. +@vindex mode-line-compact +@vindex mode-line-collapse-minor-modes + Some modes put a lot of data in the mode line, pushing elements at the +end of the mode line off to the right. Emacs can ``compress'' the mode +line if the @code{mode-line-compact} variable is non-@code{nil} by +turning stretches of spaces into a single space. If this variable is +@code{long}, this is only done when the mode line is wider than the +currently selected window. (This computation is approximate, based on +the number of characters, and not their displayed width.) This variable +can be buffer-local to only compress mode-lines in certain buffers. 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. + @node Text Display @section How Text Is Displayed @cindex characters (in text) diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi index 788d98fdf20..0dd73fe17a8 100644 --- a/doc/lispref/modes.texi +++ b/doc/lispref/modes.texi @@ -2152,17 +2152,6 @@ Mode Line Basics @end lisp @end defun -@vindex mode-line-compact - Some modes put a lot of data in the mode line, pushing elements at -the end of the mode line off to the right. Emacs can ``compress'' the -mode line if the @code{mode-line-compact} variable is non-@code{nil} -by turning stretches of spaces into a single space. If this variable -is @code{long}, this is only done when the mode line is wider than the -currently selected window. (This computation is approximate, based on -the number of characters, and not their displayed width.) This -variable can be buffer-local to only compress mode-lines in certain -buffers. - @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 35e6edcd712..939dc748f54 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -322,6 +322,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. The value 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..2d6e1579e10 100644 --- a/lisp/bindings.el +++ b/lisp/bindings.el @@ -429,6 +429,126 @@ 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 + :version "31.1") + +(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) + (unless (string= "" (format-mode-line `("" ,hidden))) + (let* ((menu + ;; FIXME: This is to defer the computation of the + ;; menu, but may not play well with touchscreen. + (lambda (e) + (interactive "@e") + (if-let* ((m (mode-line--make-lighter-menu hidden))) + (popup-menu m e) + (message "No menu available")))) + (keymap + (define-keymap + :parent mode-line-minor-mode-keymap + "<mode-line> <down-mouse-1>" menu + "<mode-line> <mouse-2>" #'describe-mode))) + `(: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 +586,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
bug-gnu-emacs <at> gnu.org
:bug#77361
; Package emacs
.
(Sun, 06 Apr 2025 08:19:01 GMT) Full text and rfc822 format available.Message #17 received at 77361 <at> debbugs.gnu.org (full text, mbox):
From: Pengji Zhang <me <at> pengjiz.com> To: Daniel Mendler <mail <at> daniel-mendler.de> Cc: 77361 <at> debbugs.gnu.org Subject: Re: bug#77361: [PATCH] New user option to hide minor mode lighters Date: Sun, 06 Apr 2025 16:17:54 +0800
Daniel Mendler <mail <at> daniel-mendler.de> writes: > Hello Pengji! Hi Daniel! > This is a good idea. I've used both minions and diminish and it is nice > to have this functionality ootb. I have some concerns however regarding > the frequent mode line recomputation during redisplay. Do you see a > possibility to cache the computed minor mode menu and collapsed lighter? > In any case, the computation should be as efficient as possible. For > profiling I suggest to enable your new user option and then scroll > repeatedly in order to force redisplays and mode line recomputations. If > certain mode line functions appear prominently in the profile they are > candidates for optimization, in order to reduce redisplay latency. Thanks! I did not consider the performance issue much. How about deferring the computation of the minor mode menu, the most costly part? + (unless (string= "" (format-mode-line `("" ,hidden))) + (let* ((menu + ;; FIXME: This is to defer the computation of the + ;; menu, but may not play well with touchscreen. + (lambda (e) + (interactive "@e") + (if-let* ((m (mode-line--make-lighter-menu hidden))) + (popup-menu m e) + (message "No menu available")))) + (keymap + (define-keymap + :parent mode-line-minor-mode-keymap + "<mode-line> <down-mouse-1>" menu + "<mode-line> <mouse-2>" #'describe-mode))) + `(: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))) Still we need to split 'minor-mode-alist' and do some other work, but my profiling showed that there was little impact to the performance. Pengji
bug-gnu-emacs <at> gnu.org
:bug#77361
; Package emacs
.
(Sun, 06 Apr 2025 08:41:02 GMT) Full text and rfc822 format available.Message #20 received at 77361 <at> debbugs.gnu.org (full text, mbox):
From: Daniel Mendler <mail <at> daniel-mendler.de> To: Pengji Zhang <me <at> pengjiz.com> Cc: 77361 <at> debbugs.gnu.org Subject: Re: bug#77361: [PATCH] New user option to hide minor mode lighters Date: Sun, 06 Apr 2025 10:40:32 +0200
Pengji Zhang <me <at> pengjiz.com> writes: > Daniel Mendler <mail <at> daniel-mendler.de> writes: > >> Hello Pengji! > > Hi Daniel! > >> This is a good idea. I've used both minions and diminish and it is nice >> to have this functionality ootb. I have some concerns however regarding >> the frequent mode line recomputation during redisplay. Do you see a >> possibility to cache the computed minor mode menu and collapsed lighter? >> In any case, the computation should be as efficient as possible. For >> profiling I suggest to enable your new user option and then scroll >> repeatedly in order to force redisplays and mode line recomputations. If >> certain mode line functions appear prominently in the profile they are >> candidates for optimization, in order to reduce redisplay latency. > > Thanks! I did not consider the performance issue much. How about > deferring the computation of the minor mode menu, the most costly part? Deferring the menu computation sounds like a good idea, in particular since the menu is only accessed rarely. The repeated recomputation of the mode line elements itself should be fine. > Still we need to split 'minor-mode-alist' and do some other work, but my > profiling showed that there was little impact to the performance. Thanks for checking. Daniel
Eli Zaretskii <eliz <at> gnu.org>
:Pengji Zhang <me <at> pengjiz.com>
:Message #25 received at 77361-done <at> debbugs.gnu.org (full text, mbox):
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.
bug-gnu-emacs <at> gnu.org
:bug#77361
; Package emacs
.
(Sat, 19 Apr 2025 04:32:02 GMT) Full text and rfc822 format available.Message #28 received at 77361 <at> debbugs.gnu.org (full text, mbox):
From: Pengji Zhang <me <at> pengjiz.com> To: Jonas Bernoulli <jonas <at> bernoul.li> Cc: 77361 <at> debbugs.gnu.org Subject: Re: bug#77361: [PATCH] New user option to hide minor mode lighters Date: Sat, 19 Apr 2025 12:30:42 +0800
[Message part 1 (text/plain, inline)]
(Cc'ing the bug tracker thread in case others would like to chime in.) Hello Jonas, Jonas Bernoulli <jonas <at> bernoul.li> writes: > Pengji Zhang <me <at> pengjiz.com> writes: > >> - 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. > > As the author of minions I am going to stick with that, but even then > the addition of `mode-line-minor-modes' is beneficial. Minions can > now just modify this trivial element instead of the much more complex > `mode-line-modes', which lead to a lot of duplication (or alternatively > fragile patching of the built-in value). Thanks! Good to know it is useful to minions as well. > Unfortunately one still has to modify `mode-line-modes' to remove the > parens around the modes. IMO these are just unnecessary noise if one > uses minions or the new mode-line-collapse-minor-modes. > > Messages … > > is good enough for me, I can see how one might want parens if showing > enabled minor-modes directly in the mode-line > > (Messages foobar schalala other modes here) > > So I would like to suggest the addition of something like: > > (defcustom mode-line-modes-delimiters '("(" . ")") > "Strings placed near the edges of `mode-line-modes'." > :type '(choice (const :tag "No delimiters") > (cons (string :tag "Opening string") > (string :tag "Closing string"))) > :group 'mode-line > :version "31.1") > > used like so > > (defvar mode-line-modes > ... > - "(" > + '(:eval (car mode-line-modes-delimiters)) > ... > - ")" > + '(:eval (cdr mode-line-modes-delimiters)) Just my two cents -- I do think that it is good to make the delimiters customizable. > Additionally you might want to consider making the menu string > customizable instead of using > > (if (char-displayable-p ?…) " …" " ...") That makes sense. Please find the attached patch. > Cheers, > Jonas Regards, Pengji
[0001-Make-lighter-customizable-for-collapsed-minor-modes-.patch (text/x-patch, inline)]
From 656f03f48b2af0afab1e20ea3f13b2a007bc2bb8 Mon Sep 17 00:00:00 2001 From: Pengji Zhang <me <at> pengjiz.com> Date: Sat, 19 Apr 2025 12:04:36 +0800 Subject: [PATCH] Make lighter customizable for collapsed minor modes (bug#77361) * lisp/bindings.el (mode-line-collapsed-minor-modes-lighter): New option for the collapsed lighter of minor modes. (mode-line-collapse-minor-modes): Mention that the collapsed lighter could be customized. (mode-line--minor-modes): Use the new option. * etc/NEWS: Announce the new option. --- etc/NEWS | 5 +++++ lisp/bindings.el | 14 ++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index 98f8e703013..ac06b214499 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -334,6 +334,11 @@ single button. The value 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. +--- +*** New user option 'mode-line-collapsed-minor-modes-lighter'. +The value should be a string to speficify the mode line lighter for +collapsed minor modes. + ** Tab Bars and Tab Lines --- diff --git a/lisp/bindings.el b/lisp/bindings.el index 2d6e1579e10..9be467a421e 100644 --- a/lisp/bindings.el +++ b/lisp/bindings.el @@ -431,7 +431,8 @@ bindings--sort-menu-keymap (defcustom mode-line-collapse-minor-modes nil "Minor modes for which mode line lighters are hidden. -Hidden lighters are collapsed into one. +Hidden lighters are collapsed into one, which is customizable via option +`mode-line-collapsed-minor-modes-lighter'. 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 @@ -445,6 +446,15 @@ mode-line-collapse-minor-modes :group 'mode-line :version "31.1") +(defcustom mode-line-collapsed-minor-modes-lighter + (if (char-displayable-p ?…) " …" " ...") + "Lighter for collapsed minor modes. +This is effective only when `mode-line-collapse-minor-modes' is non-nil." + :type 'string + :initialize #'custom-initialize-delay + :group 'mode-line + :version "31.1") + (defvar mode-line-minor-modes '(:eval (mode-line--minor-modes)) "Mode line construct for minor mode lighters.") ;;;###autoload @@ -541,7 +551,7 @@ mode-line--minor-modes :parent mode-line-minor-mode-keymap "<mode-line> <down-mouse-1>" menu "<mode-line> <mouse-2>" #'describe-mode))) - `(:propertize ,(if (char-displayable-p ?…) " …" " ...") + `(:propertize mode-line-collapsed-minor-modes-lighter mouse-face mode-line-highlight help-echo "Hidden minor modes\n\ mouse-1: Display hidden minor modes\n\ -- 2.49.0
bug-gnu-emacs <at> gnu.org
:bug#77361
; Package emacs
.
(Sat, 19 Apr 2025 10:10:01 GMT) Full text and rfc822 format available.Message #31 received at 77361 <at> debbugs.gnu.org (full text, mbox):
From: Sean Whitton <spwhitton <at> spwhitton.name> To: Pengji Zhang <me <at> pengjiz.com> Cc: Jonas Bernoulli <jonas <at> bernoul.li>, 77361 <at> debbugs.gnu.org Subject: Re: bug#77361: [PATCH] New user option to hide minor mode lighters Date: Sat, 19 Apr 2025 18:08:44 +0800
Hello Pengji, Thanks. Making this customizable sounds good. A couple of comments on your patch: - It doesn't make sense to add an additional NEWS entry because the whole feature will be new in this release. So you can delete that part of your patch. - Ideally the name of the variable would start with mode-line-collapse- instead of mode-line-collapsed- in order to match the existing one. May I suggest mode-line-collapse-minor-modes-to ? Or mode-line-collapse-minor-modes-to-char ? Or could we get away with just one variable? mode-line-collapse-major-modes can be the string to use; a value of 't' means to use …. Possibly renaming it to mode-line-collapse-major-modes-to-char. -- Sean Whitton
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.