This keymap library is inspired by Emacsy (keymap.scm
), which in turn is
inspired by Emacs.
The main types are:
- A
key
structure that holds:- a numeric
code
- a hardware keycode;
- a string
value
- a character (except for whitespaces);
- an ordered set of modifiers (to ensure equality on permutation).
- a numeric
- A
keyspec
is a string representation of akey
(e.g. “control-a”). Akeyspecs
is the string concatenation of two or more =keyspec=s (e.g. “control-a control-b control-c”). - A
keymap
contains a hash-table that mapskeyspecs
to either keymaps, function designators or nil (to unbind thekeyspecs
).
- Define keymaps with a prefix key (commonly known as prefix keymaps). For
instance, my-mode-map can be defined as a prefix keymap that makes all of its
bindings accessible after pressing
C-c
. - List all bindings matching a given prefix.
- List the bindings associated to a command.
- Multiple inheritance.
- Keycode support.
- Validate keyspec at compile time.
- Set multiple bindings in a single call to
define-key
. - Multiple keyschemes to make it easy to switch between, say, Emacs-style and VI-style bindings. This orthogonality to keymaps composes better than having multiple keymaps: changing keyscheme applies to the entire program, which is easier than looping through all keymaps to change them.
- Translate keyspecs as a fallback. For instance if
shift-a
is unbound, checkA
. - Customizable behaviour with global parameters such as
*print-shortcut*
. - Merge multiple keymaps via
compose
. - Handle gracefully multiple arguments when sensible (e.g. multiple keymaps for
lookup-key
). - Key remapping à-la Emacs.
- Typed keymaps, i.e. keymaps where bound values can only be of a given type.
This is convenient to catch typos, for instance when binding
'FOO
instead of#'FOO
.
- Customizable modifiers: the input system must decide how to map
meta
,control
, etc. - Dead key support: the input system must handle it.
- Fallback function when binding is not found: the caller of
lookup-key
getsnil
when unbound, thus it can decide of a default behaviour. - Provide a self-insert function: the caller must handle it.
- Global or local bindings: it’s up to the calling application to manage the locality of their keymaps.
(let* ((parent-keymap (nkeymaps:make-keymap "parent-keymap"))
(my-keymap (nkeymaps:make-keymap "my-keymap" parent-keymap)))
(nkeymaps:define-key parent-keymap
"C-c" 'copy
"C-v" 'paste)
(nkeymaps:define-key my-keymap
"C-x" 'cut)
(values
(nkeymaps:lookup-key "C-x" parent-keymap)
(nkeymaps:lookup-key "C-x" my-keymap)
(nkeymaps:lookup-key "C-c" my-keymap)
(nkeymaps:binding-keys 'cut parent-keymap)
(nkeymaps:binding-keys 'copy my-keymap)
(nkeymaps:binding-keys 'paste my-keymap)))
;; => NIL, CUT, COPY, NIL, ("C-c"), ("C-v")
See the package documentation for a usage guide and more examples.
NKeymaps was originally developed for keymap management in Nyxt, so the “N” may stand for it, or “New”, or whatever poetic meaning you may find behind it!
- [ ] Lookup order (for instance parent-first or next-keymap-first) should be customizable.
- [ ] For now
*translator*
is a global, but ideally it would be part of the keyscheme and keymap. But this would impact the lookup order, since translations come after all the keymaps and their parents have been searched for.
- Remove
NASDF
as a dependency. - Minor fix relative to
pretty-binding-keys
.
- New
pretty-binding-keys
function that prints keybindings using OS-dependent modifier terminology. - Improve documentation.
- Add
NASDF
as a dependency. - Add
cl-str
as a dependency.
- Renamed
scheme-name
tokeyscheme
andscheme
tokeyscheme-map
. It’s more consistent and intuitive. The previous naming was really confusing. - All warnings have now their own conditions, see the
nkeymaps/conditions
package. define-keyscheme-map
has a different syntax, it’s now(define-keyscheme-map "NAME-PREFIX" (:import OPTIONAL-KEYSCHEME-MAP-TO-IMPORT) KEYSCHEME BINDINGS...)
- The predefined
keyscheme=s are now accessible from the =nkeymaps
package. - New
default
keyscheme
which is the new parent of other keyschemes (includingcua
), instead ofcua
. *modifier-list*
is no longer exported. Instead, bothkeyscheme
andkeymap
have amodifiers
slot for the modifiers they accept.- Switched testing framework from
Prove
toLisp-Unit2
. - Removed the
cl-str
dependency.