Subject: Re: bug#47150: 28.0.50; Incorrect major-mode in minibuffer

From: Alan Mackenzie <[email-masked]>
Date: Mon, 15 Mar 2021 21:30:41 +0000

Hello, Sheng.

On Mon, Mar 15, 2021 at 13:15:02 -0500, Sheng Yang wrote:
> Hi Alan,

> On Mon, Mar 15, 2021, at 02:59, Alan Mackenzie wrote:
> > Why is fundamental-mode incorrect for a minibuffer, and what should the
> > major mode be instead?

> > What problems does fundamental-mode give you in a minibuffer?

> The word "correct" here has a two-fold meaning, 1) the design itself
> is good (whether it is good can be discussed), 2) the behavior is as
> intended.

> For the first point, I think before the offending commit, the
> major-mode of a minibuffer is minibuffer-inactive-mode. I am not aware
> of the reasons behind the decision, but it seems a reasonable choice.
> We do not need a reason to keep the existing decision, but we do need
> an explanation for a decision to change it to fundamental-mode.
> Anyway, I would give a few points for keeping the major-mode as
> minibuffer-inactive-mode: 

OK, I'll start with 2).  Up to Emacs-27, a minibuffer got created in
fundamental-mode, got used, then after the user typed RET or C-g, was
put into minibuffer-inactive-mode.  When the minibuffer got used a
second time, it got left in minibuffer-inactive-mode.  This was a bug,
though not a serious one.  The minibuffer then stayed in that mode until
Emacs shutdown.

minibuffer-inactive-mode: the critical thing here is "inactive", which
means "doing nothing", or "not in use", or even "sleeping".  The
opposite word is "active".  From its name, this major mode was never
intended for use in active minibuffers, but somehow nobody noticed that
the buffer never got shifted out of minibuffer-inactive-mode when it
came to be used again.

I've been fixing things in minibuf.c recently, and when I discovered
this anomaly, I fixed it, so that an active minibuffer now runs in
fundamental-mode, as originally intended.  I did wonder why there was no
"minibuffer-mode".  But it was clear from the code that whoever wrote it
intended minibuffers to use fundamental-mode whilst active.

> 1. Packages depend on it, to name a few: lispy, smartparens, and
> telega.

The maintainers of those packages are probably unhappy about
minibuffer-inactive-mode.  In any case, it doesn't work on the first use
of a minibuffer (see above).

> 2. We do need something to check that we are in the minibuffer, and
> apply something.

As you say, there is (minibufferp).  What is wrong with that?

> For my case, I want automatic paren pairing and editing in
> eval-expression.

That does indeed suggest we really want a minibuffer-mode, rather than
just fundamental-mode.  But surely, the parenthesis pairing will be
dependant on the sort of text you're typing into the minibuffer, so it
can't really be connected with, say, minibuffer-mode.

> Plus we also need a keymap for it, which is
> minibuffer-inactive-mode-map.

No.  That keymap is very low functionality, and almost useless, as it's
intended to be.  The idea is that while a minibuffer is inactive, a user
can't do any damage with it.

When a (low-level) minibuffer function is called, a keymap is an
argument to that function, and that gets used instead.

> We can use (minibufferp), but this will prevent the existing use of
> *-global-modes in packages to decide whether to enable in the
> minibuffer.

Sorry, I don't understand what you mean, here.  How will the use of
(minibufferp) prevent anything else?

> 3. The choice of minibuffer-inactive-mode is written in elisp manual.
> I believe any changes that breaks backward compatibility needs a sound
> reason.

minibuffer-inactive-mode is described in the elisp manual as being for
INACTIVE minibuffers, i.e. those that aren't currently in use.  It was a
bug that that major mode was still in force for active minibuffers
(apart from their first use in an Emacs session).

> If you are aware of a thread on an explanation for the decision to
> switch to fundamantal-mode, please send me a pointer.

I hope my description in this post is satisfactory.

> For the second point, the new behavior seems not intended according to
> the commit message of the offending commit. Here is the whole commit
> message of 636ef445af:

> >     With minibuffer-follows-selected-frame `hybrid', preserve recursive Mbuffers

> >     ...when enable-recursive-minibuffers is non-nil, and several minibuffers are
> >     activated from different frames.  Also set the major mode of a reused active
> >     minibuffer to `fundamental-mode' - up till now it's been
> >     minibuffer-inactive-mode.

> >     * src/minibuf.c (read_minibuf): with the indicated settings of variables,
> >     "stack up" all containing minibuffers on the mini-window of the current
> >     frame.  Delete another, now superfluous such stacking up.
> >     (set_minibuffer_mode): New function.
> >     (get_minibuffer): Call the above new function (twice), in place of inline
> >     code, ensuring active minibuffers are never left in minibuffer-inactive-mode.

It was me that made that commit.  The change to the major mode was fully
intended.  I thought the description of the change was adequate.

> At the point of reporting the bug, I thought the change of major mode
> only applies when you have minibuffer-follows-selected-frame set to
> `hybrid'.

Sorry, that wasn't the intended meaning.  The change in major mode is
regardless of the setting of minibuffer-follows-selected-frame.

> I am less sure about this understanding now. Currently, from
> what I understand, it is only when we reuse an active minibuffer when
> we have fundamental-mode set as major mode. However, with a single
> buffer, and the first interactive usage of the minibuffer by pressing
> M-:, the major-mode is reported as fundamental-mode, instead of
> minibuffer-inactive-mode, as in Emacs 27.1. What does a "reuse" means
> here?

"Reuse", probably better written as "re-use", just means to use again.

> I am not sure I understand the differences between an active and
> inactive minibuffer, and the elisp manual does not really help me
> much.

"Active" means "in use", "inactive" means "not in use", in this context.

> It seems to me the minibuffer is always inactive? I tried M-x,
> M-!, M-:, all reports minibuffer-inactive-mode in Emacs 27.1.  Is this
> a mistake and the offending commit was trying to fix this
> inconsistency?

Very much so!

> > > 3. Press M-; to call eval-expression, which will report that the
> > > major-mode is fundamental-mode

> Typo fix: to call eval-expression, the key-binding is `M-:' instead of
> `M-:'

So, a quick summary: (i) the change in the minibuffer's major mode to
fundamental-mode was intended; (ii) there may be some problems in some
packages because of this; (iii) we aren't yet in agreement on how to
proceed with this bug report.

> Sheng Yang(杨圣), PhD
> Computer Science Department
> University of Maryland, College Park
> E-mail: [email-masked]
> E-mail (old but still used): [email-masked]

-- 
Alan Mackenzie (Nuremberg, Germany).