GNU bug report logs -
#79412
30.2; `define-globalized-minor-mode' does not respect `:variable'
Previous Next
Reported by: inet0 <at> qq.com
Date: Tue, 9 Sep 2025 02:01:03 UTC
Severity: normal
Found in version 30.2
Done: Eli Zaretskii <eliz <at> gnu.org>
Full log
Message #11 received at 79412 <at> debbugs.gnu.org (full text, mbox):
> Date: Tue, 09 Sep 2025 03:40:36 +0800
> From: inet0--- via "Bug reports for GNU Emacs,
> the Swiss army knife of text editors" <bug-gnu-emacs <at> gnu.org>
>
> I am using Emacs as a GUI application on Android (distributed by F-Droid
> if that matters) so `emacs -Q' is not an option, but the symptoms should
> be reproduced by
>
> (1) evaluating the program segments below, then
>
> (2) typing `C-c b' twice.
>
> (define-minor-mode bidi-display-reordering-mode
> nil
> :variable bidi-display-reordering)
>
> (define-globalized-minor-mode global-bidi-display-reordering-mode
> bidi-display-reordering-mode
> (lambda () (bidi-display-reordering-mode 1))
> :variable bidi-display-reordering)
>
> (keymap-global-set "C-c b" 'global-bidi-display-reordering-mode)
>
> Buffer *Messages*:
>
> Loading gnus...done
> For information about GNU Emacs and the GNU system, type C-h C-a.
> Global Bidi-Display-Reordering mode enabled
> if: Symbol’s value as variable is void: bidi-display-reordering-mode
The ELisp manual says about ':variable':
‘:variable PLACE’
This replaces the default variable MODE, used to store the
state of the mode. If you specify this, the MODE variable is
not defined, and any INIT-VALUE argument is unused.
What this means is that using :variable leaves the mode variable, in
this case bidi-display-reordering-mode, undefined. Therefore, I think
you must define some non-trivial BODY for your minor mode, because the
default body will try to reference bidi-display-reordering-mode, and
will fail, as this backtrace shows:
> Buffer *Backtrace*:
>
> Debugger entered--Lisp error: (void-variable bidi-display-reordering-mode)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> With that in mind, I suspect that the buffer-local mode name is
> mistakenly referenced instead of the name specified by keyword
> `:variable', thus causing a void-variable error.
I don't think this is accurate. A globalized minor mode works by
walking the list of all the buffers and turning on the local minor
mode in each one of them.
> I have found something suspicious at source code
> `lisp/emacs-lisp/easy-mmode.el:569:23':
>
> ;; Go through existing buffers.
> (dolist (buf (buffer-list))
> (with-current-buffer buf
> (if ,global-mode (funcall ,turn-on-function)
> (when ,mode (,mode -1)))))
>
> It seems that `mode' at the predicate position of `when' should really
> be `MODE-variable'!
Adding Stefan in case he has some insights.
> As an aside, the docstring of `define-globalized-minor-mode' is a bit
> off the description in the ELisp manual. (Jumping between `C-h f' and
> `C-h i m el i' is annoying, isn't it?)
>
> The manual says:
>
> By default, the buffer-local minor mode variable that says whether
> the mode is switched on or off is the same as the name of the mode
> itself. Use ‘:variable VARIABLE’ if that’s not the case–some minor
> modes use a different variable to store this state information.
>
> While in docstring:
>
> Other keywords have the same meaning as in ‘define-minor-mode’,
> which see.
>
> Clearly, `:variable' in `define-globalized-minor-mode' does not have the
> same meaning as in `define-minor-mode', otherwise you would be
> specifying the mode variable of the global mode, which is not the case.
Thanks.
This bug report was last modified 1 day ago.
Previous Next
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.