mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-03-01 11:20:41 -08:00
243 lines
9.5 KiB
Org Mode
243 lines
9.5 KiB
Org Mode
* which-key Introduction
|
|
This is a rewrite of [[https://github.com/kai2nenobu/guide-key][guide-key-mode]] for emacs. The intention is to provide the
|
|
following features:
|
|
1. A different polling mechanism to make it lighter on resources than guide-key
|
|
2. An improved display of keys with more keys being shown by default and a nicer
|
|
presentation
|
|
3. Customization options that allow for the rewriting of command names on the
|
|
fly through easily modifiable alists
|
|
4. Good default configurations that work well with most themes
|
|
5. A well configured back-end for displaying keys (removing the popwin
|
|
dependency) that can be easily customized by writing new display functions
|
|
|
|
* Table of Contents :TOC@4:
|
|
- [[#which-key-introduction][which-key Introduction]]
|
|
- [[#install][Install]]
|
|
- [[#minibuffer-option][Minibuffer Option]]
|
|
- [[#side-window-right-option][Side Window Right Option]]
|
|
- [[#side-window-bottom-option][Side Window Bottom Option]]
|
|
- [[#special-features-and-configuration-options][Special Features and Configuration Options]]
|
|
- [[#several-popup-types][Several Popup Types]]
|
|
- [[#minibuffer][minibuffer]]
|
|
- [[#side-window][side window]]
|
|
- [[#frame][frame]]
|
|
- [[#custom][custom]]
|
|
- [[#custom-string-replacement][Custom String Replacement]]
|
|
- [[#key-based-replacement]["Key-Based" replacement]]
|
|
- [[#key-and-description-replacement][Key and Description replacement]]
|
|
- [[#nice-display-with-split-frame][Nice Display with Split Frame]]
|
|
- [[#status][Status]]
|
|
- [[#thanks][Thanks]]
|
|
|
|
* Install
|
|
Add which-key.el to your =load-path= and require. Something like
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-to-list 'load-path "path/to/which-key.el")
|
|
(require 'which-key)
|
|
(which-key-mode)
|
|
#+END_SRC
|
|
|
|
There are 3 choices of default configs for you to try (then customize to your
|
|
liking). The main choice is where you want the which-key buffer to display.
|
|
Screenshots of the default options are shown in the next sections.
|
|
|
|
In each case, we show as many key bindings as we can fit in the buffer within
|
|
the constraints. The constraints are determined by several factors, including
|
|
your emacs settings, the size of the current emacs frame, and the which-key
|
|
settings (which are configurable but not well documented at the moment).
|
|
|
|
By default which-key makes substitutions for text all with the aim of saving
|
|
space. The most noticeable are the "special keys" like SPC, TAB, RET, etc. This
|
|
can be turned off, but the default is to truncate these keys to one character
|
|
and display them using =:inverse-video= (flips foreground and background
|
|
colors). You can see the effect in the screenshots.
|
|
|
|
There are other substitution abilities included, which are quite flexible
|
|
(ability to use regexp for example). This makes which-key very customizable.
|
|
This functionality is targeting [[https://github.com/syl20bnr/spacemacs][spacemacs]].
|
|
|
|
** Minibuffer Option
|
|
Take over the minibuffer. Setup by default, but you can also use
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(which-key-setup-minibuffer)
|
|
#+END_SRC
|
|
|
|
[[./img/which-key-minibuffer.png]]
|
|
|
|
Note the maximum height of the minibuffer is controlled through the built-in
|
|
variable =max-mini-window-height=.
|
|
|
|
** Side Window Right Option
|
|
Popup side window on right. For defaults use
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(which-key-setup-side-window-right)
|
|
#+END_SRC
|
|
|
|
Note the defaults are fairly conservative and will tend to not display on
|
|
narrower frames. If you get a message saying which-key can't display the keys,
|
|
try making your frame wider or adjusting the defaults related to the maximum
|
|
width (see =M-x customize-group which-key=).
|
|
|
|
[[./img/which-key-right.png]]
|
|
|
|
** Side Window Bottom Option
|
|
Popup side window on bottom. For defaults use
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(which-key-setup-side-window-bottom)
|
|
#+END_SRC
|
|
|
|
[[./img/which-key-bottom.png]]
|
|
|
|
* Special Features and Configuration Options
|
|
There are more options than the ones described here. All of the configurable
|
|
variables are available through =M-x customize-group which-key=.
|
|
** Several Popup Types
|
|
There are three different popup types that which-key can use by default to
|
|
display the available keys. The variable =which-key-popup-type= decides which
|
|
one is used.
|
|
*** minibuffer
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq which-key-popup-type 'minibuffer)
|
|
#+END_SRC
|
|
Show keys in the minibuffer.
|
|
*** side window
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq which-key-popup-type 'side-window)
|
|
#+END_SRC
|
|
Show keys in a side window. This popup type has further options:
|
|
#+BEGIN_SRC emacs-lisp
|
|
;; location of which-key window. valid values: top, bottom, left, right
|
|
(setq which-key-side-window-location 'bottom)
|
|
|
|
;; max width of which-key window, when displayed at left or right.
|
|
;; valid values: number of columns (integer), or percentage out of current
|
|
;; frame's width (float larger than 0 and smaller than 1)
|
|
(setq which-key-side-window-max-width 0.33)
|
|
|
|
;; max height of which-key window, when displayed at top or bottom.
|
|
;; valid values: number of lines (integer), or percentage out of current
|
|
;; frame's height (float larger than 0 and smaller than 1)
|
|
(setq which-key-side-window-max-height 0.25)
|
|
#+END_SRC
|
|
*** frame
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq which-key-popup-type 'frame)
|
|
#+END_SRC
|
|
Show keys in a popup frame. This popup won't work very well in a terminal,
|
|
where only one frame can be shown at any given moment. This popup type has
|
|
further options:
|
|
#+BEGIN_SRC emacs-lisp
|
|
;; max width of which-key frame: number of columns (an integer)
|
|
(setq which-key-frame-max-width 60)
|
|
|
|
;; max height of which-key frame: number of lines (an integer)
|
|
(setq which-key-frame-max-height 20)
|
|
#+END_SRC
|
|
|
|
*** custom
|
|
Write your own display functions! This requires you to write three functions,
|
|
=which-key-custom-popup-max-dimensions-function=,
|
|
=which-key-custom-show-popup-function=, and
|
|
=which-key-custom-hide-popup-function=. Refer to the documentation for those
|
|
variables for more information, but here is a working example (this is the
|
|
current implementation of side-window bottom).
|
|
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq which-key-popup-type 'custom)
|
|
(defun which-key-custom-popup-max-dimensions-function (ignore)
|
|
(cons
|
|
(which-key-height-or-percentage-to-height which-key-side-window-max-height)
|
|
(frame-width)))
|
|
(defun fit-horizonatally ()
|
|
(let ((fit-window-to-buffer-horizontally t))
|
|
(fit-window-to-buffer)))
|
|
(defun which-key-custom-show-popup-function (act-popup-dim)
|
|
(let* ((alist '((window-width . fit-horizontally)
|
|
(window-height . fit-window-to-buffer))))
|
|
(if (get-buffer-window which-key--buffer)
|
|
(display-buffer-reuse-window which-key--buffer alist)
|
|
(display-buffer-in-major-side-window which-key--buffer 'bottom 0 alist))))
|
|
(defun which-key-custom-hide-popup-function ()
|
|
(when (buffer-live-p which-key--buffer)
|
|
(quit-windows-on which-key--buffer)))
|
|
#+END_SRC
|
|
|
|
** Custom String Replacement
|
|
You can customize the way the keys show in the buffer using three different
|
|
replacement methods, each of which corresponds replacement alist. The basic idea
|
|
of behind each alist is that you specify a selection string in the =car= of each
|
|
cons cell and the replacement string in the =cdr=.
|
|
|
|
*** "Key-Based" replacement
|
|
The relevant variable is the awkwardly named
|
|
=which-key-key-based-description-replacement-alist=. In this alist you can have
|
|
cons cells of two types. An example of the first type is
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
("C-x C-f" . "find files")
|
|
#+END_SRC
|
|
|
|
where the string on the left is the key combination whose description you want
|
|
to replace. For that key combination, which-key overwrites the description with
|
|
the second string, "find files". In the second type of entry you can restrict
|
|
the replacements to a major-mode. For example,
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(org-mode . (("C-c C-c" . "Org C-c C-c") ("C-c C-a" . "Org Attach"))
|
|
#+END_SRC
|
|
|
|
Here the first entry is the major-mode and the second is a list of the first
|
|
type of entries. In case the same key combination is listed under a major-mode
|
|
and by itself, the major-mode version will take precedence.
|
|
|
|
There are two helper functions to add entries to this list,
|
|
=which-key-add-key-based-replacements= and
|
|
=which-key-add-major-mode-key-based-replacements=. You can modify the alist
|
|
directly or use these.
|
|
|
|
*** Key and Description replacement
|
|
The second and third methods target the text used for the keys and the
|
|
descriptions directly. The relevant variables are
|
|
=which-key-key-replacement-alist= and =which-key-description-replacement-alist=.
|
|
Here's an example of one of the default key replacements
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
("<\\(\\(C-\\|M-\\)*.+\\)>" . "\\1")
|
|
#+END_SRC
|
|
|
|
The =car= takes a string which may use emacs regexp and the =cdr= takes a string
|
|
with the replacement text. As shown, you can specify a sub-expression of the
|
|
match. The replacements do not need to use regexp and can be as simple as
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
("left" . "lft")
|
|
#+END_SRC
|
|
|
|
You can add this element to the key list with (there are no helper functions for
|
|
these alists)
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-to-list 'which-key-key-replacement-alist '("left" . "lft"))
|
|
#+END_SRC
|
|
|
|
** Nice Display with Split Frame
|
|
Unlike guide-key, which-key looks good even if the frame is split into several
|
|
windows.
|
|
#+CAPTION: which-key in a frame with 3 horizontal splits
|
|
[[./img/which-key-right-split.png]]
|
|
|
|
#+CAPTION: which-key in a frame with 2 vertical splits
|
|
[[./img/which-key-bottom-split.png]]
|
|
|
|
* Status
|
|
It requires testing on different platforms with different configurations, which
|
|
is beyond my capabilities. The default configuration has been reasonably stable
|
|
for me.
|
|
* Thanks
|
|
Thanks to @bmag for helping with the initial development and finding many bugs.
|