[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Enhancements to "minor-mode-map-alist" functionality.

From: Kim F. Storm
Subject: Re: Enhancements to "minor-mode-map-alist" functionality.
Date: 19 Apr 2002 01:07:39 +0200
User-agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.2.50

Richard Stallman <address@hidden> writes:

>     Consider a keymap K which has a binding for [C-x 1],
>     a keymap P which has a binding for [C-x 2], and
>     a keymap S which has a binding for [C-x 3].
>     Keymap S has a filter which means that it is only active
>     if mark-active is non-nil.
>     Now, we want keymap P to be a parent map for K, and
>     we want S to be a submap of K.
> Why do we want that?  What job are you trying to do?

I've described that several times by now -- I'm trying to find the
right approach to address the issues with complex modes which uses a
lot of keymaps (like cua and viper) and base the selection between
those keymaps on combining various state information, i.e. to provide
a more versatile keymap functionality than what is currently

I think I have ironed this out for cua by now via a (tedious)
post-command-hook to do this through minor-mode-map-alist, but where I
could just condition a keymap with `mark-active' if the decision is
made when a key is actually processed, I need an expression like (and
mark-active (not deactivate-mark)) in the post-command-hook -- and
hope that nothing else changes the mark state under my feet....

Here is the current cua code where the cua--fix-keymaps function is run
by the post-command-hook after every command:

now>    (defvar cua-global-keymap (make-sparse-keymap))
now>    (defvar cua--cua-keys-keymap (make-sparse-keymap))
now>    (defvar cua--prefix-override-keymap (make-sparse-keymap))
now>    (defvar cua--prefix-repeat-keymap (make-sparse-keymap))
now>    (defvar cua--global-mark-keymap (make-sparse-keymap))
now>    (defvar cua--rectangle-keymap (make-sparse-keymap))
now>    (defvar cua--region-keymap (make-sparse-keymap))
now>    (defvar cua--ena-cua-keys-keymap nil)
now>    (defvar cua--ena-prefix-override-keymap nil)
now>    (defvar cua--ena-prefix-repeat-keymap nil)
now>    (defvar cua--ena-region-keymap nil)
now>    (defvar cua--ena-global-mark-keymap nil)
now>    (defvar cua--mmap-prefix-override-keymap (cons 
'cua--ena-prefix-override-keymap cua--prefix-override-keymap))
now>    (defvar cua--mmap-prefix-repeat-keymap (cons 
'cua--ena-prefix-repeat-keymap cua--prefix-repeat-keymap))
now>    (defvar cua--mmap-cua-keys-keymap (cons 'cua--ena-cua-keys-keymap 
now>    (defvar cua--mmap-global-mark-keymap (cons 'cua--ena-global-mark-keymap 
now>    (defvar cua--mmap-rectangle-keymap (cons 'cua--rectangle 
now>    (defvar cua--mmap-region-keymap (cons 'cua--ena-region-keymap 
now>    (defvar cua--mmap-global-keymap (cons 'cua-mode cua-global-keymap))
now>    (defvar cua--mmap-list
now>      (list cua--mmap-prefix-override-keymap
now>            cua--mmap-prefix-repeat-keymap
now>            cua--mmap-cua-keys-keymap
now>            cua--mmap-global-mark-keymap
now>            cua--mmap-rectangle-keymap
now>            cua--mmap-region-keymap
now>            cua--mmap-global-keymap))
now>    (defun cua--fix-keymaps (disable)
now>      ;; Ensure that cua's keymaps are in minor-mode-map-alist and
now>      ;; in the correct order, and set control variables.
now>      (let (fix
now>            (mmap minor-mode-map-alist)
now>            (ml cua--mmap-list))
now>        (while (and (not fix) mmap ml)
now>          (if (not (eq (car mmap) (car ml)))
now>              (setq fix t)
now>            (setq mmap (cdr mmap)
now>                  ml (cdr ml))))
now>        (if ml
now>            (setq fix t))
now>        (when (or fix disable)
now>          (setq ml cua--mmap-list)
now>          (while ml
now>            (setq minor-mode-map-alist (delq (car ml) minor-mode-map-alist))
now>            (setq ml (cdr ml))))
now>        (when (and fix (not disable))
now>          (setq minor-mode-map-alist
now>                (append (copy-sequence cua--mmap-list) 
now>      (setq cua--ena-region-keymap
now>            (and mark-active (not deactivate-mark)))
now>      (setq cua--ena-prefix-override-keymap
now>            (and cua--ena-region-keymap
now>                 cua-enable-cua-keys
now>                 (or (eq cua-enable-cua-keys t)
now>                     (not cua--explicit-region-start))
now>                 (not executing-kbd-macro)
now>                 (not cua--prefix-override-timer)))
now>      (setq cua--ena-prefix-repeat-keymap
now>            (and cua--ena-region-keymap
now>                 (timerp cua--prefix-override-timer)))
now>      (setq cua--ena-cua-keys-keymap
now>            (and cua-enable-cua-keys
now>                 (or (eq cua-enable-cua-keys t)
now>                     cua--last-region-shifted)))
now>      (setq cua--ena-global-mark-keymap
now>            (and cua--global-mark-active
now>                 (not (window-minibuffer-p)))))

to the code as it would look like with a dynamic setup via the
proposed emulation-mode-map-alists (andn nothing is needed in the

emma>   (defvar cua-global-keymap (make-sparse-keymap))
emma>   (defvar cua--cua-keys-keymap (make-sparse-keymap))
emma>   (defvar cua--prefix-override-keymap (make-sparse-keymap))
emma>   (defvar cua--prefix-repeat-keymap (make-sparse-keymap))
emma>   (defvar cua--global-mark-keymap (make-sparse-keymap)) ; Initalized when 
cua-gmrk.el is loaded
emma>   (defvar cua--rectangle-keymap (make-sparse-keymap))   ; Initalized when 
cua-rect.el is loaded
emma>   (defvar cua--region-keymap (make-sparse-keymap))
emma>   (setq emulation-mode-map-alists
emma>         (cons
emma>           `((lambda . (and mark-active
emma>                            cua-enable-cua-keys
emma>                            (or (eq cua-enable-cua-keys t)
emma>                                (not cua--explicit-region-start))
emma>                            (not executing-kbd-macro)
emma>                            (not cua--prefix-override-timer)
emma>                            '(cua--prefix-override . 
emma>             (lambda . (and mark-active
emma>                            (timerp cua--prefix-override-timer)
emma>                            '(cua--prefix-override . 
emma>             (lambda . (and cua-enable-cua-keys
emma>                            (or (eq cua-enable-cua-keys t)
emma>                                cua--last-region-shifted)
emma>                            '(cua-enable-cua-keys . 
emma>             (lambda . (and cua--global-mark-active
emma>                            (not (window-minibuffer-p))
emma>                            '(cua--global-mark-active . 
emma>             (cua--rectangle . ,cua--rectangle-keymap)
emma>             (mark-active . ,cua--region-keymap)
emma>             (cua-mode . ,cua-global-keymap))
emma>           emulation-mode-map-alists))

>     With my proposal, C-x 1, C-x 2, and (if mark-active) C-x 3 will all
>     work seemlessly
> What does it mean for them to "work"?  Once again, what job
> are you trying to do?  It is not useful to address this backwards.

I have N keymaps which all make bindings starting with C-x -- and I want
all of those bindings to "work".

I tried the `simple' approach by putting these keymaps into the proposed
`emulation-mode-map-alists', but that idea was turned down.  

If it wasn't for the problem evalling code in the current_minor_maps
function [I believe there are ways to solve that], would that solution
be acceptable?

> We must not introduce more complex features merely because they look
> appealing in the abstract.  We have to look at the job first, then
> determine how much complexity is really *necessary*.
>     > What problem is it meant to solve?
>     Multiple keymap inheritance as well as conditional keymaps.
> Multiple inheritance is a mess.  We should avoid it if we can.

But the `parent keymap' inheritance is already pretty messy.
A clean way to add multiple inheritance would fix that!

Stefan told me he was working on a way to support things like this,
but it had a number of problems (such as unnecessary consing), so I
made another proposal (which doesn't do consing), but has other

>     > There is no way to implement such a restriction,
>     > and users don't generally know which functions do consing.
>     This is not intended to be a user feature, it is for package
>     writers. 
> I know which users this feature is for.  The users of Emacs Lisp
> don't generally know which functions do consing.  That can change.
>     I didn't think we should `implement' the restriction -- simply
>     document it.
> No way.


> This proposal includes many aspects each of which is very undesirable.
> The entire approach is wrong.  We need to start by looking at the actual
> problem that we actually need to solve.

Ok, that's what I've tried to do all along!  I've already described it
several times now, so what aspects of the problem are still unclear?

So, please look at the problem!

You (and others) don't approve of the proposals I've made to solve
this.  That's ok, but then I ask you to come up with a better proposal
which deals with the problem at hand.

Thank you!

Kim F. Storm <address@hidden> http://www.cua.dk

reply via email to

[Prev in Thread] Current Thread [Next in Thread]