[comp.emacs] Minor modes

mesard@bbn.com (Wayne Mesard) (02/08/89)

[[[Note followup-to line!]]]

My line-number article [specifically my claim that minor modes aren't
doable in GNU Elisp] prompted a discussion about minor modes which I was
prepared to carry on via email, but jr suggested that others on this
list/group/entity might want to think on it a bit, so here is the reply
I sent to tale's posting to comp.emacs.

----
To: tale@pawl.rpi.edu
Subject: Re: line numbers in emacs
In-Reply-To: <TALE.89Feb6153713@consult1.its.rpi.edu>
References: <22@euteal.UUCP> <35659@bbn.COM>
Organization: Bolt Beranek and Newman Inc., Cambridge MA
Date: Tue, 07 Feb 89 14:09:53 -0500
From: mesard@bbn.com

In article <TALE.89Feb6153713@consult1.its.rpi.edu> you write:
>Whoa!  Hang on ... that's just not so.  You don't have to redefine
>entire keymaps or anything.  Whoa.
> 
>Heck, auto-fill can be written in Elisp.  Overwrite could too, though
>it's not as nice and pretty as in C.

Auto fill IS mostly written in lisp.  But it wouldn't do much without
the support for auto-fill-hook in the C code.

> More to the point though, minor
> modes can most certainly be written in Elisp.

Not without rebinding keys and/or putting hooks on functions.  To my
mind, once you start doing that, you're writing a major mode.  [Can you
think of an existing minor mode that rebinds keys?]

Now I know that you can have your minor mode function call the function
that the user really asked for (cf. Mark Weissman's hooks.el code).  As
I mentioned in my article, this was the first path I took in writing
display-line-nums.  And it can be done.  But the code would be ugly and
cumbersome given that you need to meet the following constraints:

    - possibly bind it to any or every key and command.
    - have the asked-for function (i.e. the major mode function called
      with the correct arguments.
    - do the right thing with other "minor modes" that are also
      rebinding keys and putting hooks on functions.
    - then there's subtler issues like  what happens when the user
      types "C-h c C-v" and Emacs replies "Waynes-minor-mode-function".
      [But now, I'm picking at nits.]


Try it.  Maybe you can get it to work.  But if you did I'd say you'd
done it in spite of Emacs, not because of its superb support of user
programmable minor modes.

So I guess I should have said that there's no clean way to do minor
modes.                                        ^^^^^

What would be adequate support of minor modes?  Well, lessee, I hadn't
given it much thought (since I didn't anticipate this discussion).  But
off the top of my head how 'bout something like [possibly argumentless]
hooks which can be attached any function.  Or maybe an "event
specification" system, so you can say things like:

  (register-event-func 'maybe-wrap '(> (current-column) fill-column))
  (register-event-func 'line-nums 'window-movedP) ;window-movedP is a function.

In fact, lets just keep 'em on an alist a la auto-mode-alist.  The
conditional form gets evaluated periodically (once each time through the
body of command_loop() ?), and if non-nil, the other form is evaluated.

Note that there are two types of minor modes.  Those which respond to
events, and those which modify the behavior of the major mode (like
overwrite).  This scheme only addresses the former.  The latter has to
be done with hooks, or by explicitly including code in the functions
which implement the to-be-modified behavior.
-- 
void Wayne_Mesard();
Mesard@BBN.COM             Edith Keillor died for your sins.
BBN, Cambridge, MA

maa@sei.cmu.edu (Mark Ardis) (02/11/89)

If you think about it, minor modes *should* be harder to write than
major modes: A minor mode attempts to coexist peacefully with other
modes, whereas a major mode just redefines things from scratch
(mostly).

A minor-mode author needs to consider how his mode will interact with
several major modes and with several other minor modes.  To do this
successfully requires knowledge of the behavior of lots of modes.  For
example, if a minor mode invents new key-bindings, should those
bindings replace existing bindings or should they be added to the
existing ones?  If they are added, what conventions should be
followed?  (E.g., should the prefix be "^X" or "^C"?)  Note that most
of these issues have nothing to do with the *implementation* of the
new features, but have a lot to do with the *use* of the features.

Mark A. Ardis
Software Engineering Institute
Carnegie-Mellon University
Pittsburgh, PA 15213
(412) 268-7636
maa@sei.cmu.edu