1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-03-01 11:20:41 -08:00
emacs/README.org
justbur 3ab7a2eebb Switch to only using dashes for symbol names
Matches elisp conventions to the letter
2015-07-14 19:49:43 -04:00

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.