Subject: Re: bug#78881: [PATCH] New command 'toggle-mode-line-visibility'

From: Elijah Gabe Pérez <[email-masked]>
Date: Tue, 24 Jun 2025 11:04:35 -0600

Eli Zaretskii <[email-masked]> writes:

>> From: Elijah Gabe Pérez <[email-masked]>
>> Date: Mon, 23 Jun 2025 13:20:44 -0600
>> 
>> This new command allows toggle the mode line visibility in the current
>> buffer.
>> 
>> The mode line keeps hidden from each major mode change, avoiding having
>> to run this command many times.
>> 
>> This is based/inspired by `hide-mode-line-mode` (from MELPA), but unlike
>> latter one, this is a rewrite which uses a command instead a minor mode
>> and I'm interested in including this in Emacs :^).
>
> Thanks.  I think the idea of a minor mode is better.  Our experience
> is that many toggle commands end up being minor modes.  One advantage
> of a minor mode is that the ways of turning a mode on/off and toggling
> it are automagically done for you, and they are all uniformly familiar
> to users.

I agree, but the problem with making this command a minor mode is that
it have to check whether the minor mode variable is non-nil for
display/hide the mode-line (AFAIU), this brings problems because if a
buffer by default does not show the mode line, one would have to execute
the command twice to display it.

This would also create 2 variables of which I do not see much use: the
minor mode hook and minor mode variable.

Anyway, I changed it to a minor mode, but I am not very convinced of the
result.

>> --- a/etc/NEWS
>> +++ b/etc/NEWS
>> @@ -346,6 +346,14 @@ This option allows changing or removing the delimiters shown around
>>  the major mode and list of minor modes in the mode line.  The default
>>  retains the existing behavior of inserting parentheses.
>>  
>> +---
>> +*** New command 'toggle-mode-line-visibility'.
>> +This command toggles the mode line visibility in current buffer, if the
>> +current buffer displays a mode line, this will temporally hide it until
>> +'toggle-mode-line-visibility' is called again.  Otherwise, if the
>> +current buffer does not have a mode line by default, this will display
>> +one.
>
> This feature must be described in the user manual, so please add the
> necessary changes for that (and mark the NEWS entry with "+++").

Sure, but I'm not sure in which section of the manual I must document
it, maybe in "Optional Mode Line Features" from "emacs" manual?

>> +The mode line is hidden from every major mode change in current buffer.
>
> This sentence confused me.  What did you mean to say here?

e.g. If you call `toggle-mode-line-visibility` in the scratch buffer and
later call `text-mode` in the same buffer, the mode line will become
visible again, which is not convenient since this command is meant to
enable/disable the mode line per buffer, not per major mode.

>> +If HIDE-ONLY is non-nil, only hide the mode-line."
>
> What is the difference between "only hide" and the other situation?
> Please clarify.

It was only for internal use of the command, for ensure that the mode
line is hidden because this command can display it if the mode line is
already hidden, that's why `disable-mode-line` existed.

>From 67cfb180079d761dbe08dd66a9eab64fe29e4d34 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?El=C3=ADas=20Gabriel=20P=C3=A9rez?= <[email-masked]>
Date: Mon, 23 Jun 2025 12:50:28 -0600
Subject: [PATCH] New command 'toggle-mode-line-visibility'

This new command allows toggle the mode line visibility in the
current buffer.  (Bug#78881)

* etc/NEWS: Announce changes.
* lisp/bindings.el (toggle-mode-line--buf-state): New buffer
local variable.
(toggle-mode-line-visibility): New minor mode.
(toggle-mode-line--hide): New function.
---
 etc/NEWS         |  8 ++++++++
 lisp/bindings.el | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 54 insertions(+)

diff --git a/etc/NEWS b/etc/NEWS
index f7aebdf538f..59c77f3abb0 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -346,6 +346,14 @@ This option allows changing or removing the delimiters shown around
 the major mode and list of minor modes in the mode line.  The default
 retains the existing behavior of inserting parentheses.
 
+---
+*** New command 'toggle-mode-line-visibility'.
+This command toggles the mode line visibility in current buffer, if the
+current buffer displays a mode line, this will temporarily hide it until
+'toggle-mode-line-visibility' is called again.  Otherwise, if the
+current buffer does not have a mode line by default, this will display
+one.
+
 ** Tab Bars and Tab Lines
 
 ---
diff --git a/lisp/bindings.el b/lisp/bindings.el
index 8b021a05ce2..e6e78c18dac 100644
--- a/lisp/bindings.el
+++ b/lisp/bindings.el
@@ -56,6 +56,52 @@ mode-line-widen
     (widen)
     (force-mode-line-update)))
 
+;; Variable used by `toggle-mode-line-visibility' for
+;; store mode-line value in current buffer.
+(defvar-local toggle-mode-line--buf-state)
+
+(defun toggle-mode-line--hide ()
+  "Function used in command `toggle-mode-line-visibility' to hide the mode line."
+  (when mode-line-format
+    (setq toggle-mode-line--buf-state
+          (buffer-local-set-state mode-line-format nil))))
+
+(define-minor-mode toggle-mode-line-visibility
+  "Toggle mode line visibility in current buffer.
+If current buffer displays a mode line, temporarily hide it until
+command `toggle-mode-line-visibility' is called again.  Otherwise,
+display one if the buffer does not have a mode line by default.
+
+The mode line is hidden from every major mode change in current buffer."
+  :init-value nil
+  ;; Since this is a toggle command, ensure if we must display or hide
+  ;; the mode line according to `mode-line-format' value
+  (if mode-line-format
+      (progn
+        ;; Hook to prevent the mode line from being displayed again at
+        ;; each change of major mode.
+        ;; We cannot use `toggle-mode-line-visibility' in this hook
+        ;; since it will not ensure the mode line keeps hidden
+        (add-hook 'after-change-major-mode-hook #'toggle-mode-line--hide nil t)
+        (toggle-mode-line--hide))
+
+    (remove-hook 'after-change-major-mode-hook #'toggle-mode-line--hide t)
+
+    (when toggle-mode-line--buf-state
+      (setq toggle-mode-line--buf-state
+            (buffer-local-restore-state toggle-mode-line--buf-state)))
+
+    ;; Display a mode line if buffer does not have one by default
+    (unless mode-line-format
+      (setq-local mode-line-format (default-value 'mode-line-format)))
+
+    ;; Update mode line
+    (when (called-interactively-p 'any)
+      (force-mode-line-update))))
+
+(put 'toggle-mode-line--buf-state 'permanent-local t)
+(put 'toggle-mode-line--hide 'permanent-local-hook t)
+
 (defvar mode-line-input-method-map
   (let ((map (make-sparse-keymap)))
     (define-key map [mode-line mouse-2]
-- 
2.49.0

-- 
                                          - E.G via GNU Emacs and Org.