temporary-mode.el
temporary-mode.el
allows defining temporary key bindings to easily chain
related commands.
Examples
Create new bindings
(define-temporary-mode git-nav-mode
"Navigate between git hunks in the buffer."
:lighter " GitNav"
:install "C-c g"
:bindings (("n" . git-gutter:next-hunk)
("p" . git-gutter:previous-hunk))
:body (when git-nav-mode
(git-gutter-mode 1)))
Snippet above defines a new minor mode named git-nav-mode
. When this minor
mode is active, pressing g
, n
or p
executes the corresponding git-gutter
commands (as described by the :bindings
block). Any other key deactivates the
mode and performs its usual action.
git-gutter
commands are not bound by default in the global map, so that we
want to create new global bindings to run git-gutter
commands and activate
git-nav-mode
to chain them. This is done via the :install
keyword, which
creates new bindings for the commands under the given C-c g
prefix in the
global map.
We also want to ensure that git-gutter-mode
is always active when
git-nav-mode
is enabled. This can be done by providing an elisp form to be
added in the body of git-nav-mode
.
After this setup, pressing C-c g n p a p
will run in turn the following
commands:
C-c g n
- activate
git-nav-mode
(which in turn activatesgit-gutter-mode
) and executegit-gutter:next
p
(equivalent toC-c g p
)- execute
git-gutter:previous
a
- deactivate
git-nav-mode
and insert “a”
p
- insert “p”
Rebind existing bindings
(define-temporary-mode gud-nav-mode
"Interact with gud"
:install "C-x C-a"
:bindings "C-x C-a")
Instead of defining new bindings, one can read an already existing keymap. In
the example above, the local gud-nav-mode
keymap will define all bindings
available under the C-x C-a
prefix in the global map.
Wrapper commands, which activate gud-nav-mode
before running their original
action, are then rebound in the global map in place of the regular gud
commands.
With this setup, the C-x C-a C-s
key sequence will then yield:
C-x C-a C-s
- activate
gud-nav-mode
and executegud-step
C-n
(equivalent toC-x C-a C-n
)- execute
gud-next
a
- deactivate
gud-nav-mode
and insert “a”
When the :install
and :bindings
keywords get the same argument, the :rebind
shortcut can be used to replace them both. The snippet above is thus equivalent
to:
(define-temporary-mode gud-nav-mode
"Interact with gud"
:rebind "C-x C-a")
Single entry point
It is not always desirable that all bindings available in the temporary mode be
available from the global map as well. In such cases, it is possible to restrict
the bindings installed in the global map using the :entry-points
keyword:
(define-temporary-mode error-mode
"Navigate between errors"
:lighter " Error"
:install "C-x"
:bindings (("`" . next-error)
("n" . next-error)
("p" . previous-error))
:entry-points ("`"))
In the example above, only C-x `
is globally rebound; C-x n
and C-x p
are left
untouched in the global map. But n
and p
are still bound in the temporary
mode map to easily chain them.
With this setup, the C-x ` n p x
sequence yields:
C-x `
- activate
error-mode
and executenext-error
. This is the only way to entererror-mode
(apart from usingM-x
). n
- execute
next-error
p
- execute
previous-error
x
- deactivate
error-mode
and insert “x”
API documentation
(define-temporary-mode MODE DOC &rest ARGS)
Define a new minor mode named MODE
, whose keymap is created after
BINDINGS
. While this mode is active, any command not mentioned in the keymap
will deactivate the mode.
MODE
: name of the minor mode.DOC
: docstring of the minor mode.ARGS
: property list with additional arguments, as described hereafter.
Terminology
The following conventions are used below:
- global map
- any keymap which is active when the temporary minor mode is
disabled. Usually
global-map
for read-only operations, andtemporary-mode-map
for modifications. See the documentation for the:install
keyword below.
- modal map
- the keymap which will be active while in the temporary mode. Any key sequence not handled by the modal map will cause the temporary mode to be deactivated.
KEY
(respectivelyPREFIX
)- a string describing a key chord (respectively
a prefix sequence), in a format suitable for
kbd
.
KEYMAP
- an unquoted symbol whose value is a global keymap.
COMMAND
- an unquoted command symbol.
Keywords
We list below all additional keywords supported by define-temporary-mode
, and
the possible formats for their arguments:
:bindings
-
- list of
(KEY . COMMAND)
cells - the modal keymap defines all listed bindings.
PREFIX
(PREFIX . KEYMAP)
-
the modal keymap will be determined by looking up
PREFIX
inKEYMAP
(defaults toglobal-map
).
- list of
:install
-
PREFIX
(PREFIX . KEYMAP)
-
install all modal bindings under
PREFIX
in a globalKEYMAP
. The commands are modified so that they activate the minor mode when called.KEYMAP
defaults totemporary-mode-map
, which is used only fordefine-temporary-mode
to install such bindings and has precedence overglobal-map
. This ensures that all bindings can easily be disabled by deactivatingtemporary-mode
. Also evaluating adefine-temporary-mode :rebind
stanza multiple times will less likely cause problems, sinceglobal-map
will be treated read-only, andtemporary-mode-map
will be the only one to be modified.
:rebind
-
PREFIX
(PREFIX . KEYMAP)
-
shorthand specifying the same value for both
:bindings
and:install
. This allows easily setting up a temporary mode for all commands under the given prefix.
:entry-points (list KEY-OR-COMMAND)
- limit the bindings installed in the
global keymap (via the
:install
keyword) to those listed. Each elementKEY-OR-COMMAND
can be either a string describing a key chord, or a command symbol. In the latter case, all modal bindings to that command will be installed in the global map.
:lighter LIGHTER
- specify a lighter for the minor mode.
:body FORM
- specify a form to be added to the minor-mode body.