The following is an issue that comes up from time to time on #emacs, and we don’t really have a good answer to it. I don’t for a minute think that I have figured this whole thing out, but here goes.
Joe Hacker is an Emacs user, and is quite content, only some he doesn’t like a particular key-binding. To make things concrete, he doesn’t like that in non-text buffers ‘g’ is the key to refresh, and would rather it were ‘r’. So he dutifully sets out and modifies the key-bindings to every Emacs extension he uses replacing uses of ‘g’ for refresh with ‘r’, and he lives happily ever after….Until he finds out about the cool new bloat.el and needs to do it again.
See the problem?
In Emacs, modes have a notion of a keymap, and this keymap dictates what actions key combinations perform within that mode. While keymaps can inherit from one another, many modes replace large sections of keybindings with variants of a command more suited to that mode. This is all very well and good, and since we have good conventions in place, much information about modes is transferable. But if you want to go against the convention, you are in for a world of pain.
To take our concrete example from above, if you wanted to change the keybinding for “refresh” for a whole class of modes at once, you’d try and find a parent keymap common to all these, and perform the changes there. This would work quite well if it weren’t for specific modes being smart and trying to provide more “mode-appropriate” behaviour for a particular keybinding.
Similar issues arise with extensions that aim to emulate other editing environments, especially vim emulation.
The issue then is that we treat keybindings as a representative for a particular behaviour, and change the binding to modify the behaviour, when the behaviour and the keybinding should be in some sense separate from each other, so that each can be updated separately.
All problems in computer science can be solved by another level of indirection – David Wheeler
In Emacs, right now, there are certain keybindings that redirect to another one. For example, <tab> refers to the Tab key on your keyboard, and it is usually bound to TAB, which corresponds to the key combination C-i. This allows graphical Emacs instances to behave similar to terminal Emacs instances by default, while still allowing extra flexibility to GUI users which can make the distinction between C-i and <tab>.
What I am proposing is to extend Emacs in a similar fashion, using additional “semantic” keybindings to refer to specific behaviours: Reverting could be bound to <revert>, Completion to <complete>, indenting to <indent>, and so on. We can then, hopefully, have a few common keymaps provided bindings for these, e.g. “g” in a non-text-keymap being bound to <revert>, and instead of rebinding particular keys in modes, we rebind the approprite “semantic binding”.
In theory, this needn’t be an extension to either the current keymap API, nor require additional keybindings to be literally supported. Similar to how people bind custom bindings in mode hooks, we could encourage a style or rebinding “pointer variables” within mode-hooks. Similar to how we would have hacked overriding keybindings if we didn’t have keymaps.
In fact, Emacs already provides such a notion of a “mode-local” variable which I think we can take advantage of here.
Issues with the solution
backwards compatibility / how to handle mixed behaviour
defining suitable “semantic” keymaps for common emacs extensions
Finding the commonality in existing Emacs extensions is probably the most important, and most difficult task in this whole idea. Much of the work seems to be labour-intensive “standardising” work, and I’m not sure how much of it can be automated. We may be able to with some dumb heuristics, like checking for two modes that bind the same key with similarly named (maybe modulo the module-prefix) functions.
Fortunately, we are in good company. The common Emacs creation myth credits just such an effort to rms and Guy Steele back in the 70s.
I also don’t think it will be necessary to make the change all at once. From a users point of view, Emacs should behave exactly the same after making the change as before we made it, so this effort could take place over a prolonged period of time.
new problem domains will lead to fragmentation
Fragmentation is a pain in every type of software, whether purposefully, or through ignorance of an existing solution.
If both foo.el and bar.el have a notion of “baz” and want to define a semantic keybinding for it, it is likely that we will end up with a foo-baz and a bar-baz binding.
I think this may be a less serious problem, since, after discovering the similarity, it should be possible to get the two authors to hash something together, or to provide a separate extension that fixes them both. (sigh, yet another layer of indirection)
it may make built-in emacs help less useful
Right now, if you C-h k on a key you get the function bound to it. If the user instead got information about the ideal behaviour of this keybinding as opposed to the function itself, this would be undesirable. Emacs would need to take into account any indirection.