branch: master commit 56b0fc8b4a5b4f89ea2ab3e6317f035d6f6f40f7 Merge: a86cf29 7559a79 Author: Justin Burkett <jus...@burkett.cc> Commit: Justin Burkett <jus...@burkett.cc>
Merge commit '7559a79e95aada65601f7413a1c3f08bfa34557b' --- packages/which-key/.travis.yml | 27 +- packages/which-key/Makefile | 6 +- packages/which-key/README.org | 787 +++++++++++++++++++++------------------- packages/which-key/which-key.el | 184 +++++++--- 4 files changed, 562 insertions(+), 442 deletions(-) diff --git a/packages/which-key/.travis.yml b/packages/which-key/.travis.yml index b22aa13..918e5f1 100644 --- a/packages/which-key/.travis.yml +++ b/packages/which-key/.travis.yml @@ -1,29 +1,24 @@ -language: generic -sudo: false - -branches: - only: - - master - -before_install: - - curl -fsSkL https://gist.github.com/rejeep/ebcd57c3af83b049833b/raw > x.sh && source ./x.sh - - evm install $EVM_EMACS --use --skip - - cask - +# language: emacs-lisp env: - - EVM_EMACS=emacs-24.3-travis - EVM_EMACS=emacs-24.4-travis - EVM_EMACS=emacs-24.5-travis - EVM_EMACS=emacs-25.1-travis - EVM_EMACS=emacs-25.2-travis + - EVM_EMACS=emacs-25.3-travis - EVM_EMACS=emacs-git-snapshot-travis +before_install: + - git clone https://github.com/rejeep/evm.git $HOME/.evm + - export PATH="$HOME/.evm/bin:$PATH" + - export PATH="$HOME/.cask/bin:$PATH" + - evm config path /tmp + - evm install $EVM_EMACS --use --skip + - curl -fsSkL https://raw.github.com/cask/cask/master/go | python + matrix: fast_finish: true allow_failures: - env: - - EVM_EMACS=emacs-24.3-travis - - EVM_EMACS=emacs-git-snapshot-travis + - env: EVM_EMACS=emacs-git-snapshot-travis script: - emacs --version diff --git a/packages/which-key/Makefile b/packages/which-key/Makefile index facb1f8..a60edf6 100644 --- a/packages/which-key/Makefile +++ b/packages/which-key/Makefile @@ -1,15 +1,15 @@ .PHONY : test -EMACS ?= emacs +emacs ?= emacs CASK ?= cask LOADPATH = -L . ELPA_DIR = \ - .cask/$(shell $(EMACS) -Q --batch --eval '(princ emacs-version)')/elpa + .cask/$(shell $(emacs) -Q --batch --eval '(princ emacs-version)')/elpa test: elpa - $(CASK) exec $(EMACS) -Q -batch $(LOADPATH) \ + $(CASK) exec $(emacs) -Q -batch $(LOADPATH) \ -l which-key-tests.el -f ert-run-tests-batch-and-exit elpa: $(ELPA_DIR) diff --git a/packages/which-key/README.org b/packages/which-key/README.org index ac8b97f..2567e44 100644 --- a/packages/which-key/README.org +++ b/packages/which-key/README.org @@ -1,453 +1,486 @@ -* which-key -[[http://melpa.org/#/which-key][http://melpa.org/packages/which-key-badge.svg]] [[http://stable.melpa.org/#/which-key][file:http://stable.melpa.org/packages/which-key-badge.svg]] [[https://travis-ci.org/justbur/emacs-which-key][file:https://travis-ci.org/justbur/emacs-which-key.svg?branch=master]] +* which-key + [[http://melpa.org/#/which-key][http://melpa.org/packages/which-key-badge.svg]] [[http://stable.melpa.org/#/which-key][file:http://stable.melpa.org/packages/which-key-badge.svg]] [[https://travis-ci.org/justbur/emacs-which-key][file:https://travis-ci.org/justbur/emacs-which-key.svg?branch=master]] ** Recent Changes -*** 2016-12-20: Added =which-key-max-display-columns= -Allows control over the number of columns in the popup. See [[#other-options][Other Options]]. -*** 2016-11-21: Replacement list changes -The alists controlling the replacement of key binding descriptions was -simplified to use one centralized alist, =which-key-replacement-alist=. This -change also allows for some new features compared to the old method. The other -alists are deprecated. See [[#custom-string-replacement-options][Custom String Replacement Options]]. +*** 2017-12-13: Added =which-key-enable-extended-define-key= + Allows for a concise syntax to specify replacement text using =define-key= + or alternatives that use =define-key= internally. See the docstring and + [[#custom-string-replacement-options][Custom String Replacement]]. + +*** 2017-11-13: Added =which-key-show-major-mode= + Shows active bindings in current major-mode map. ** Introduction -=which-key= is a minor mode for Emacs that displays the key bindings following -your currently entered incomplete command (a prefix) in a popup. For example, -after enabling the minor mode if you enter =C-x= and wait for the default of 1 -second the minibuffer will expand with all of the available key bindings that -follow =C-x= (or as many as space allows given your settings). This includes -prefixes like =C-x 8= which are shown in a different face. Screenshots of what -the popup will look like are included below. =which-key= started as a rewrite of -[[https://github.com/kai2nenobu/guide-key][guide-key-mode]], but the feature sets have diverged to a certain extent. + =which-key= is a minor mode for Emacs that displays the key bindings + following your currently entered incomplete command (a prefix) in a + popup. For example, after enabling the minor mode if you enter =C-x= and wait + for the default of 1 second the minibuffer will expand with all of the + available key bindings that follow =C-x= (or as many as space allows given + your settings). This includes prefixes like =C-x 8= which are shown in a + different face. Screenshots of what the popup will look like are included + below. =which-key= started as a rewrite of [[https://github.com/kai2nenobu/guide-key][guide-key-mode]], but the feature + sets have diverged to a certain extent. ** Table of Contents :TOC_3: - - [[#which-key][which-key]] - - [[#recent-changes][Recent Changes]] - - [[#2016-12-20-added-which-key-max-display-columns][2016-12-20: Added =which-key-max-display-columns=]] - - [[#2016-11-21-replacement-list-changes][2016-11-21: Replacement list changes]] - - [[#introduction][Introduction]] - - [[#install][Install]] - - [[#melpa][MELPA]] - - [[#manually][Manually]] - - [[#initial-setup][Initial Setup]] - - [[#side-window-bottom-option][Side Window Bottom Option]] - - [[#side-window-right-option][Side Window Right Option]] - - [[#side-window-right-then-bottom][Side Window Right then Bottom]] - - [[#minibuffer-option][Minibuffer Option]] - - [[#additional-commands][Additional Commands]] - - [[#special-features-and-configuration-options][Special Features and Configuration Options]] - - [[#popup-type-options][Popup Type Options]] - - [[#custom-string-replacement-options][Custom String Replacement Options]] - - [[#sorting-options][Sorting Options]] - - [[#paging-options][Paging Options]] - - [[#face-customization-options][Face Customization Options]] - - [[#other-options][Other Options]] - - [[#support-for-third-party-libraries][Support for Third-Party Libraries]] - - [[#key-chord][Key-chord]] - - [[#evil-operators][Evil operators]] - - [[#god-mode][God-mode]] - - [[#more-examples][More Examples]] - - [[#nice-display-with-split-frame][Nice Display with Split Frame]] - - [[#thanks][Thanks]] +- [[#which-key][which-key]] + - [[#recent-changes][Recent Changes]] + - [[#2017-12-13-added-which-key-enable-extended-define-key][2017-12-13: Added =which-key-enable-extended-define-key=]] + - [[#2017-11-13-added-which-key-show-major-mode][2017-11-13: Added =which-key-show-major-mode=]] + - [[#introduction][Introduction]] + - [[#install][Install]] + - [[#melpa][MELPA]] + - [[#manually][Manually]] + - [[#initial-setup][Initial Setup]] + - [[#side-window-bottom-option][Side Window Bottom Option]] + - [[#side-window-right-option][Side Window Right Option]] + - [[#side-window-right-then-bottom][Side Window Right then Bottom]] + - [[#minibuffer-option][Minibuffer Option]] + - [[#additional-commands][Additional Commands]] + - [[#special-features-and-configuration-options][Special Features and Configuration Options]] + - [[#popup-type-options][Popup Type Options]] + - [[#custom-string-replacement-options][Custom String Replacement Options]] + - [[#sorting-options][Sorting Options]] + - [[#paging-options][Paging Options]] + - [[#face-customization-options][Face Customization Options]] + - [[#other-options][Other Options]] + - [[#support-for-third-party-libraries][Support for Third-Party Libraries]] + - [[#key-chord][Key-chord]] + - [[#evil-operators][Evil operators]] + - [[#god-mode][God-mode]] + - [[#more-examples][More Examples]] + - [[#nice-display-with-split-frame][Nice Display with Split Frame]] + - [[#thanks][Thanks]] ** Install *** MELPA -After setting up [[http://melpa.org][MELPA]] as a repository, use =M-x package-install which-key= or -your preferred method. You will need to call =which-key-mode= to enable the -minor mode of course. + After setting up [[http://melpa.org][MELPA]] as a repository, use =M-x package-install which-key= + or your preferred method. You will need to call =which-key-mode= to enable + the minor mode of course. *** Manually -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 + 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 ** Initial Setup -No further setup is required if you are happy with the default setup. To try -other options, there are 3 choices of default configs that are preconfigured -(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. + No further setup is required if you are happy with the default setup. To try + other options, there are 3 choices of default configs that are preconfigured + (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, most of which are described below. + 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, most of which are described below. -There are many substitution abilities included, which are quite flexible -(ability to use regexp for example). This makes which-key very customizable. + There are many substitution abilities included, which are quite flexible + (ability to use regexp for example). This makes which-key very customizable. *** Side Window Bottom Option -Popup side window on bottom. This is the current default. To restore this setup use + Popup side window on bottom. This is the current default. To restore this + setup use -#+BEGIN_SRC emacs-lisp + #+BEGIN_SRC emacs-lisp (which-key-setup-side-window-bottom) -#+END_SRC + #+END_SRC -[[./img/which-key-bottom.png]] + [[./img/which-key-bottom.png]] *** Side Window Right Option -Popup side window on right. For defaults use + Popup side window on right. For defaults use -#+BEGIN_SRC emacs-lisp + #+BEGIN_SRC emacs-lisp (which-key-setup-side-window-right) -#+END_SRC + #+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=). + 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]] + [[./img/which-key-right.png]] *** Side Window Right then Bottom -This is a combination of the previous two choices. It will try to use the right -side, but if there is no room it will switch to using the bottom, which is -usually easier to fit keys into. This setting can be helpful if the size of -the Emacs frame changes frequently, which might be the case if you are using -a dynamic/tiling window manager. + This is a combination of the previous two choices. It will try to use the + right side, but if there is no room it will switch to using the bottom, + which is usually easier to fit keys into. This setting can be helpful if the + size of the Emacs frame changes frequently, which might be the case if you + are using a dynamic/tiling window manager. -#+BEGIN_SRC emacs-lisp -(which-key-setup-side-window-right-bottom) -#+END_SRC + #+BEGIN_SRC emacs-lisp + (which-key-setup-side-window-right-bottom) + #+END_SRC *** Minibuffer Option -Take over the minibuffer. For the recommended configuration use + Take over the minibuffer. For the recommended configuration use -#+BEGIN_SRC emacs-lisp -(which-key-setup-minibuffer) -#+END_SRC + #+BEGIN_SRC emacs-lisp + (which-key-setup-minibuffer) + #+END_SRC -[[./img/which-key-minibuffer.png]] + [[./img/which-key-minibuffer.png]] -Note the maximum height of the minibuffer is controlled through the built-in -variable =max-mini-window-height=. + Note the maximum height of the minibuffer is controlled through the built-in + variable =max-mini-window-height=. Also, the paging commands do not work + reliably with the minibuffer option. Use the side window on the bottom + option if you need paging. ** Additional Commands -- =which-key-show-top-level= will show most key bindings without a prefix. It is - most and not all, because many are probably not interesting to most users. -- =which-key-show-next-page= is the command used for paging. -- =which-key-undo= can be used to undo the last keypress when in the middle of a - key sequence. + - =which-key-show-top-level= will show most key bindings without a prefix. It + is most and not all, because many are probably not interesting to most + users. + - =which-key-show-major-mode= will show the currently active major-mode + bindings. It's similar to =C-h m= but in a which-key format. It is also + aware of evil commands defined using =evil-define-key=. + - =which-key-show-next-page= is the command used for paging. + - =which-key-undo= can be used to undo the last keypress when in the middle + of a key sequence. ** 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=. + There are more options than the ones described here. All of the configurable + variables are available through =M-x customize-group which-key=. *** Popup Type Options -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. + 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. + #+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, -;; or a list of any of the two. If it's a list, which-key will always try -;; the first location first. It will go to the second location if there is -;; not enough room to display any keys in the first location -(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 + #+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, + ;; or a list of any of the two. If it's a list, which-key will always try + ;; the first location first. It will go to the second location if there is + ;; not enough room to display any keys in the first location + (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) + #+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 + ;; 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 + 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 Options #+NAME: #custom-string-replacement-options -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=. + 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 -Using this method, the description of a key is replaced using a string that you -provide. Here's an example +**** Automatic + A newer option is to set =which-key-enable-extended-define-key= which + advises =define-key= to allow which-key to pre-process its arguments. The + statement -#+BEGIN_SRC emacs-lisp -(which-key-add-key-based-replacements - "C-x C-f" "find files") -#+END_SRC + #+BEGIN_SRC emacs-lisp + (define-key some-map "f" '("foo" . long-name-for-command-foo)) + #+END_SRC -where the first string is the key combination whose description you want to -replace, in a form suitable for =kbd=. 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, + is valid in Emacs. Setting this variable makes which-key automatically + replace the corresponding command name with the text in the string. A nice + example is in naming prefixes. The following binds "b" to =nil= and names + the binding as a prefix. -#+BEGIN_SRC emacs-lisp -(which-key-add-major-mode-key-based-replacements 'org-mode - "C-c C-c" "Org C-c C-c" - "C-c C-a" "Org Attach") -#+END_SRC + #+BEGIN_SRC emacs-lisp + (define-key some-map "b" '("bar-prefix")) + #+END_SRC -Here the first entry is the major-mode followed by 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 takes precedence. +**** "Key-Based" replacement + Using this method, the description of a key is replaced using a string that + you provide. Here's an example + + #+BEGIN_SRC emacs-lisp + (which-key-add-key-based-replacements + "C-x C-f" "find files") + #+END_SRC + + where the first string is the key combination whose description you want to + replace, in a form suitable for =kbd=. 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 + (which-key-add-major-mode-key-based-replacements '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 followed by 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 takes precedence. **** Key and Description replacement -The second and third methods target the text used for the keys and the -descriptions directly. The relevant variable is =which-key-replacement-alist=. -Here's an example of one of the default key replacements - -#+BEGIN_SRC emacs-lisp -(push '(("<\\([[:alnum:]-]+\\)>" . nil) . ("\\1" . nil)) - which-key-replacement-alist) -#+END_SRC - -Each element of the outer cons cell is a cons cell of the form =(KEY -. BINDING)=. The =car= of the outer cons determines how to match key bindings -while the =cdr= determines how those matches are replaced. See the docstring of -=which-key-replacement-alist= for more information. - -The next example shows how to replace the description. - -#+BEGIN_SRC emacs-lisp -(push '((nil . "left") . (nil . "lft")) which-key-replacement-alist) -#+END_SRC - -Here is an example of using key replacement to include Unicode characters in the -results. Unfortunately, using Unicode characters may upset the alignment of the -which-key buffer, because Unicode characters can have different widths even in a -monospace font and alignment is based on character width. - -#+BEGIN_SRC emacs-lisp -(add-to-list 'which-key-replacement-alist '(("TAB" . nil) . ("↹" . nil)) -(add-to-list 'which-key-replacement-alist '(("RET" . nil) . ("⏎" . nil)) -(add-to-list 'which-key-replacement-alist '(("DEL" . nil) . ("⇤" . nil)) -(add-to-list 'which-key-replacement-alist '(("SPC" . nil) . ("␣" . nil)) -#+END_SRC - -The =cdr= may also be a function that receives a =cons= of the form =(KEY -. BINDING)= and produces a =cons= of the same form. This allows for interesting -ideas like this one suggested by [[https://github.com/pdcawley][@pdcawley]] in [[https://github.com/justbur/emacs-which-key/pull/147][PR #147]]. - -#+BEGIN_SRC emacs-lisp -(push (cons '(nil . "paredit-mode") - (lambda (kb) - (cons (car kb) - (if paredit-mode - "[x] paredit-mode" - "[ ] paredit-mode")))) - which-key-replacement-alist) -#+END_SRC - -The box will be checked if =paredit-mode= is currently active. + The second and third methods target the text used for the keys and the + descriptions directly. The relevant variable is + =which-key-replacement-alist=. Here's an example of one of the default key + replacements + + #+BEGIN_SRC emacs-lisp + (push '(("<\\([[:alnum:]-]+\\)>" . nil) . ("\\1" . nil)) + which-key-replacement-alist) + #+END_SRC + + Each element of the outer cons cell is a cons cell of the form =(KEY + . BINDING)=. The =car= of the outer cons determines how to match key + bindings while the =cdr= determines how those matches are replaced. See the + docstring of =which-key-replacement-alist= for more information. + + The next example shows how to replace the description. + + #+BEGIN_SRC emacs-lisp + (push '((nil . "left") . (nil . "lft")) which-key-replacement-alist) + #+END_SRC + + Here is an example of using key replacement to include Unicode characters + in the results. Unfortunately, using Unicode characters may upset the + alignment of the which-key buffer, because Unicode characters can have + different widths even in a monospace font and alignment is based on + character width. + + #+BEGIN_SRC emacs-lisp + (add-to-list 'which-key-replacement-alist '(("TAB" . nil) . ("↹" . nil)) + (add-to-list 'which-key-replacement-alist '(("RET" . nil) . ("⏎" . nil)) + (add-to-list 'which-key-replacement-alist '(("DEL" . nil) . ("⇤" . nil)) + (add-to-list 'which-key-replacement-alist '(("SPC" . nil) . ("␣" . nil)) + #+END_SRC + + The =cdr= may also be a function that receives a =cons= of the form =(KEY + . BINDING)= and produces a =cons= of the same form. This allows for + interesting ideas like this one suggested by [[https://github.com/pdcawley][@pdcawley]] in [[https://github.com/justbur/emacs-which-key/pull/147][PR #147]]. + + #+BEGIN_SRC emacs-lisp + (push (cons '(nil . "paredit-mode") + (lambda (kb) + (cons (car kb) + (if paredit-mode + "[x] paredit-mode" + "[ ] paredit-mode")))) + which-key-replacement-alist) + #+END_SRC + + The box will be checked if =paredit-mode= is currently active. *** Sorting Options -By default the output is sorted by the key in a custom order. The default order -is to sort lexicographically within each "class" of key, where the classes and -their order are - -=Special (SPC, TAB, ...) < Single Character (ASCII) (a, ...) < Modifier (C-, M-, ...) < Other= - -You can control the order by setting this variable. This also shows the other -available options. - -#+BEGIN_SRC emacs-lisp -;; default -(setq which-key-sort-order 'which-key-key-order) -;; same as default, except single characters are sorted alphabetically -;; (setq which-key-sort-order 'which-key-key-order-alpha) -;; same as default, except all prefix keys are grouped together at the end -;; (setq which-key-sort-order 'which-key-prefix-then-key-order) -;; same as default, except all keys from local maps shown first -;; (setq which-key-sort-order 'which-key-local-then-key-order) -;; sort based on the key description ignoring case -;; (setq which-key-sort-order 'which-key-description-order) -#+END_SRC + By default the output is sorted by the key in a custom order. The default + order is to sort lexicographically within each "class" of key, where the + classes and their order are + + =Special (SPC, TAB, ...) < Single Character (ASCII) (a, ...) < Modifier (C-, M-, ...) < Other= + + You can control the order by setting this variable. This also shows the + other available options. + + #+BEGIN_SRC emacs-lisp + ;; default + (setq which-key-sort-order 'which-key-key-order) + ;; same as default, except single characters are sorted alphabetically + ;; (setq which-key-sort-order 'which-key-key-order-alpha) + ;; same as default, except all prefix keys are grouped together at the end + ;; (setq which-key-sort-order 'which-key-prefix-then-key-order) + ;; same as default, except all keys from local maps shown first + ;; (setq which-key-sort-order 'which-key-local-then-key-order) + ;; sort based on the key description ignoring case + ;; (setq which-key-sort-order 'which-key-description-order) + #+END_SRC *** Paging Options -There are at least several prefixes that have many keys bound to them, like -=C-x=. which-key displays as many keys as it can given your settings, but for -these prefixes this may not be enough. The paging feature gives you the ability -to bind a key to the function =which-key-C-h-dispatch= which will allow you to -cycle through the pages without changing the key sequence you were in the middle -of typing. There are two slightly different ways of doing this. + There are at least several prefixes that have many keys bound to them, like + =C-x=. which-key displays as many keys as it can given your settings, but + for these prefixes this may not be enough. The paging feature gives you the + ability to bind a key to the function =which-key-C-h-dispatch= which will + allow you to cycle through the pages without changing the key sequence you + were in the middle of typing. There are two slightly different ways of doing + this. **** Method 1 (default): Using C-h (or =help-char=) -This is the easiest way, and is turned on by default. Use -#+BEGIN_SRC emacs-lisp -(setq which-key-use-C-h-commands nil) -#+END_SRC -to disable the behavior (this will only take effect after toggling -which-key-mode if it is already enabled). =C-h= can be used with any prefix to -switch pages when there are multiple pages of keys. This changes the default -behavior of Emacs which is to show a list of key bindings that apply to a prefix. -For example, if you were to type =C-x C-h= you would get a list of commands that -follow =C-x=. This uses which-key instead to show those keys, and unlike the -Emacs default saves the incomplete prefix that you just entered so that the next -keystroke can complete the command. - -The commands are: - - Cycle through the pages forward with =n= (or =C-n=) - - Cycle backwards with =p= (or =C-p=) - - Undo the last entered key (!) with =u= (or =C-u=) - - Call the default command bound to =C-h=, usually =describe-prefix-bindings=, - with =h= (or =C-h=) - -This is especially useful for those who like =helm-descbinds= but also want to -use =C-h= as their which-key paging key. - -Note =C-h= is by default equivalent to =?= in this context. + This is the easiest way, and is turned on by default. Use + #+BEGIN_SRC emacs-lisp + (setq which-key-use-C-h-commands nil) + #+END_SRC + to disable the behavior (this will only take effect after toggling + which-key-mode if it is already enabled). =C-h= can be used with any prefix + to switch pages when there are multiple pages of keys. This changes the + default behavior of Emacs which is to show a list of key bindings that + apply to a prefix. For example, if you were to type =C-x C-h= you would + get a list of commands that follow =C-x=. This uses which-key instead to + show those keys, and unlike the Emacs default saves the incomplete prefix + that you just entered so that the next keystroke can complete the command. + + The commands are: + - Cycle through the pages forward with =n= (or =C-n=) + - Cycle backwards with =p= (or =C-p=) + - Undo the last entered key (!) with =u= (or =C-u=) + - Call the default command bound to =C-h=, usually + =describe-prefix-bindings=, with =h= (or =C-h=) + + This is especially useful for those who like =helm-descbinds= but also want to + use =C-h= as their which-key paging key. + + Note =C-h= is by default equivalent to =?= in this context. **** Method 2: Bind your own keys -Essentially, all you need to do for a prefix like =C-x= is the following which -will bind =<f5>= to the relevant command. + Essentially, all you need to do for a prefix like =C-x= is the following + which will bind =<f5>= to the relevant command. -#+BEGIN_SRC emacs-lisp + #+BEGIN_SRC emacs-lisp (define-key which-key-mode-map (kbd "C-x <f5>") 'which-key-C-h-dispatch) -#+END_SRC + #+END_SRC -This is completely equivalent to + This is completely equivalent to -#+BEGIN_SRC emacs-lisp + #+BEGIN_SRC emacs-lisp (setq which-key-paging-prefixes '("C-x")) (setq which-key-paging-key "<f5>") -#+END_SRC + #+END_SRC -where the latter are provided for convenience if you have a lot of prefixes. + where the latter are provided for convenience if you have a lot of + prefixes. *** Face Customization Options -The faces that which-key uses are -| Face | Applied To | Default Definition | -|----------------------------------------+-------------------------------+-------------------------------------------------------------| -| =which-key-key-face= | Every key sequence | =:inherit font-lock-constant-face= | -| =which-key-separator-face= | The separator (→) | =:inherit font-lock-comment-face= | -| =which-key-note-face= | Hints and notes | =:inherit which-key-separator-face= | -| =which-key-special-key-face= | User-defined special keys | =:inherit which-key-key-face :inverse-video t :weight bold= | -| =which-key-group-description-face= | Command groups (i.e, keymaps) | =:inherit font-lock-keyword-face= | -| =which-key-command-description-face= | Commands not in local-map | =:inherit font-lock-function-name-face= | -| =which-key-local-map-description-face= | Commands in local-map | =:inherit which-key-command-description-face= | - -The last two deserve some explanation. A command lives in one of many possible -keymaps. You can distinguish between local maps, which depend on the buffer you -are in, which modes are active, etc., and the global map which applies -everywhere. It might be useful for you to distinguish between the two. One way -to do this is to remove the default face from -=which-key-command-description-face= like this - -#+BEGIN_SRC emacs-lisp + The faces that which-key uses are + | Face | Applied To | Default Definition | + |----------------------------------------+-------------------------------+-------------------------------------------------------------| + | =which-key-key-face= | Every key sequence | =:inherit font-lock-constant-face= | + | =which-key-separator-face= | The separator (→) | =:inherit font-lock-comment-face= | + | =which-key-note-face= | Hints and notes | =:inherit which-key-separator-face= | + | =which-key-special-key-face= | User-defined special keys | =:inherit which-key-key-face :inverse-video t :weight bold= | + | =which-key-group-description-face= | Command groups (i.e, keymaps) | =:inherit font-lock-keyword-face= | + | =which-key-command-description-face= | Commands not in local-map | =:inherit font-lock-function-name-face= | + | =which-key-local-map-description-face= | Commands in local-map | =:inherit which-key-command-description-face= | + + The last two deserve some explanation. A command lives in one of many possible + keymaps. You can distinguish between local maps, which depend on the buffer you + are in, which modes are active, etc., and the global map which applies + everywhere. It might be useful for you to distinguish between the two. One way + to do this is to remove the default face from + =which-key-command-description-face= like this + + #+BEGIN_SRC emacs-lisp (set-face-attribute 'which-key-command-description-face nil :inherit nil) -#+END_SRC + #+END_SRC -another is to make the local map keys appear in bold + another is to make the local map keys appear in bold -#+BEGIN_SRC emacs-lisp + #+BEGIN_SRC emacs-lisp (set-face-attribute 'which-key-local-map-description-face nil :weight 'bold) -#+END_SRC + #+END_SRC -You can also use =M-x customize-face= to customize any of the above faces to -your liking. + You can also use =M-x customize-face= to customize any of the above faces to + your liking. *** Other Options #+NAME: #other-options -The options below are also available through customize. Their defaults are -shown. - -#+BEGIN_SRC emacs-lisp - ;; Set the time delay (in seconds) for the which-key popup to appear. A value of - ;; zero might cause issues so a non-zero value is recommended. - (setq which-key-idle-delay 1.0) - - ;; Set the maximum length (in characters) for key descriptions (commands or - ;; prefixes). Descriptions that are longer are truncated and have ".." added. - (setq which-key-max-description-length 27) - - ;; Use additonal padding between columns of keys. This variable specifies the - ;; number of spaces to add to the left of each column. - (setq which-key-add-column-padding 0) - - ;; The maximum number of columns to display in the which-key buffer. nil means - ;; don't impose a maximum. - (setq which-key-max-display-columns nil) - - ;; Set the separator used between keys and descriptions. Change this setting to - ;; an ASCII character if your font does not show the default arrow. The second - ;; setting here allows for extra padding for Unicode characters. which-key uses - ;; characters as a means of width measurement, so wide Unicode characters can - ;; throw off the calculation. - (setq which-key-separator " → " ) - (setq which-key-unicode-correction 3) - - ;; Set the prefix string that will be inserted in front of prefix commands - ;; (i.e., commands that represent a sub-map). - (setq which-key-prefix-prefix "+" ) - - ;; Set the special keys. These are automatically truncated to one character and - ;; have which-key-special-key-face applied. Disabled by default. An example - ;; setting is - ;; (setq which-key-special-keys '("SPC" "TAB" "RET" "ESC" "DEL")) - (setq which-key-special-keys nil) - - ;; Show the key prefix on the left, top, or bottom (nil means hide the prefix). - ;; The prefix consists of the keys you have typed so far. which-key also shows - ;; the page information along with the prefix. - (setq which-key-show-prefix 'left) - - ;; Set to t to show the count of keys shown vs. total keys in the mode line. - (setq which-key-show-remaining-keys nil) -#+END_SRC + The options below are also available through customize. Their defaults are + shown. + + #+BEGIN_SRC emacs-lisp + ;; Set the time delay (in seconds) for the which-key popup to appear. A value of + ;; zero might cause issues so a non-zero value is recommended. + (setq which-key-idle-delay 1.0) + + ;; Set the maximum length (in characters) for key descriptions (commands or + ;; prefixes). Descriptions that are longer are truncated and have ".." added. + (setq which-key-max-description-length 27) + + ;; Use additonal padding between columns of keys. This variable specifies the + ;; number of spaces to add to the left of each column. + (setq which-key-add-column-padding 0) + + ;; The maximum number of columns to display in the which-key buffer. nil means + ;; don't impose a maximum. + (setq which-key-max-display-columns nil) + + ;; Set the separator used between keys and descriptions. Change this setting to + ;; an ASCII character if your font does not show the default arrow. The second + ;; setting here allows for extra padding for Unicode characters. which-key uses + ;; characters as a means of width measurement, so wide Unicode characters can + ;; throw off the calculation. + (setq which-key-separator " → " ) + (setq which-key-unicode-correction 3) + + ;; Set the prefix string that will be inserted in front of prefix commands + ;; (i.e., commands that represent a sub-map). + (setq which-key-prefix-prefix "+" ) + + ;; Set the special keys. These are automatically truncated to one character and + ;; have which-key-special-key-face applied. Disabled by default. An example + ;; setting is + ;; (setq which-key-special-keys '("SPC" "TAB" "RET" "ESC" "DEL")) + (setq which-key-special-keys nil) + + ;; Show the key prefix on the left, top, or bottom (nil means hide the prefix). + ;; The prefix consists of the keys you have typed so far. which-key also shows + ;; the page information along with the prefix. + (setq which-key-show-prefix 'left) + + ;; Set to t to show the count of keys shown vs. total keys in the mode line. + (setq which-key-show-remaining-keys nil) + #+END_SRC ** Support for Third-Party Libraries Some support is provided for third-party libraries which don't use standard methods of looking up commands. Some of these need to be enabled @@ -461,23 +494,23 @@ shown. before which-key and through =which-key-show-operator-state-maps= which needs to be enabled explicitly because it is more of a hack. The former allows for the inner and outer text object maps to show, while the latter - shows motions as well. + shows motions as well. *** God-mode Call =(which-key-enable-god-mode-support)= after loading god-mode to enable support for god-mode key sequences. This is new and experimental, so please report any issues. ** More Examples *** 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]] + 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]] + #+CAPTION: which-key in a frame with 2 vertical splits + [[./img/which-key-bottom-split.png]] ** Thanks -Special thanks to -- [[https://github.com/bmag][@bmag]] for helping with the initial development and finding many bugs. -- [[https://github/iqbalansari][@iqbalansari]] who among other things adapted the code to make - =which-key-show-top-level= possible. + Special thanks to + - [[https://github.com/bmag][@bmag]] for helping with the initial development and finding many bugs. + - [[https://github/iqbalansari][@iqbalansari]] who among other things adapted the code to make + =which-key-show-top-level= possible. diff --git a/packages/which-key/which-key.el b/packages/which-key/which-key.el index 0e2c6da..f973c19 100644 --- a/packages/which-key/which-key.el +++ b/packages/which-key/which-key.el @@ -5,7 +5,7 @@ ;; Author: Justin Burkett <jus...@burkett.cc> ;; Maintainer: Justin Burkett <jus...@burkett.cc> ;; URL: https://github.com/justbur/emacs-which-key -;; Version: 3.0.2 +;; Version: 3.1.0 ;; Keywords: ;; Package-Requires: ((emacs "24.4")) @@ -152,10 +152,10 @@ remapped given the currently active keymaps." `(((nil . "Prefix Command") . (nil . "prefix")) ((nil . "\\`\\?\\?\\'") . (nil . "lambda")) ((nil . "which-key-show-next-page-no-cycle") . (nil . "wk next pg")) - (("<\\([[:alnum:]-]+\\)>") . ("\\1")) ,@(unless which-key-dont-use-unicode - '((("left") . ("←")) - (("right") . ("→")))))) + '((("<left>") . ("←")) + (("<right>") . ("→")))) + (("<\\([[:alnum:]-]+\\)>") . ("\\1")))) "Association list to determine how to manipulate descriptions of key bindings in the which-key popup. Each element of the list is a nested cons cell with the format @@ -476,6 +476,24 @@ it." :group 'which-key :type 'boolean) +(defcustom which-key-enable-extended-define-key nil + "Advise `define-key' to make which-key aware of definitions of the form + + \(define-key KEYMAP KEY '(\"DESCRIPTION\" . DEF)) + +With the advice, this definition will have the side effect of +creating a replacement in `which-key-replacement-alist' that +replaces DEF with DESCRIPTION when the key sequence ends in +KEY. Using a cons cell like this is a valid definition for +`define-key'. All this does is to make which-key aware of it. + +Since many higher level keybinding functions use `define-key' +internally, this will affect most if not all of those as well. + +This variable must be set before loading which-key." + :group 'which-key + :type 'boolean) + ;; Hooks (defcustom which-key-init-buffer-hook '() "Hook run when which-key buffer is initialized." @@ -778,7 +796,10 @@ bottom." ;;;###autoload (defun which-key-setup-minibuffer () - "Apply suggested settings for minibuffer." + "Apply suggested settings for minibuffer. +Do not use this setup if you use the paging commands. Instead use +`which-key-setup-side-window-bottom', which is nearly identical +but more functional." (interactive) (which-key--setup-echo-keystrokes) (setq which-key-popup-type 'minibuffer @@ -887,6 +908,19 @@ If AT-ROOT is non-nil the binding is also placed at the root of MAP." (which-key-define-key-recursively df key def t))) map)) +(defun which-key--process-define-key-args (keymap key def) + "When DEF takes the form (\"DESCRIPTION\". DEF), make sure +which-key uses \"DESCRIPTION\" for this binding. This function is +meant to be used as :before advice for `define-key'." + (with-demoted-errors "Which-key extended define-key error: %s" + (when (and (consp def) + (stringp (car def)) + (symbolp (cdr def))) + (define-key keymap (which-key--pseudo-key key) `(which-key ,def))))) + +(when which-key-enable-extended-define-key + (advice-add #'define-key :before #'which-key--process-define-key-args)) + ;;; Functions for computing window sizes (defun which-key--text-width-to-total (text-width) @@ -1324,31 +1358,49 @@ local bindings coming first. Within these categories order using (throw 'res res))))))) (nreverse res))) +(defun which-key--get-pseudo-binding (key-binding) + (let* ((pseudo-binding + (key-binding (which-key--pseudo-key (kbd (car key-binding)) t))) + (pseudo-binding (when pseudo-binding (cadr pseudo-binding))) + (pseudo-desc (when pseudo-binding (car pseudo-binding))) + (pseudo-def (when pseudo-binding (cdr pseudo-binding))) + (real-def (key-binding (kbd (car key-binding)))) + ;; treat keymaps as if they're nil bindings. This creates the + ;; possibility that we rename the wrong binding but this seems + ;; unlikely. + (real-def (unless (keymapp real-def) real-def))) + (when (and pseudo-binding + (eq pseudo-def real-def)) + (cons (car key-binding) pseudo-desc)))) + (defun which-key--maybe-replace (key-binding) "Use `which-key--replacement-alist' to maybe replace KEY-BINDING. KEY-BINDING is a cons cell of the form \(KEY . BINDING\) each of which are strings. KEY is of the form produced by `key-binding'." - (let* ((mode-res (which-key--get-replacements key-binding t)) - (all-repls (or mode-res - (which-key--get-replacements key-binding)))) - (dolist (repl all-repls key-binding) - (setq key-binding - (cond ((or (not (consp repl)) (null (cdr repl))) - key-binding) - ((functionp (cdr repl)) - (funcall (cdr repl) key-binding)) - ((consp (cdr repl)) - (cons - (cond ((and (caar repl) (cadr repl)) - (replace-regexp-in-string - (caar repl) (cadr repl) (car key-binding) t)) - ((cadr repl) (cadr repl)) - (t (car key-binding))) - (cond ((and (cdar repl) (cddr repl)) - (replace-regexp-in-string - (cdar repl) (cddr repl) (cdr key-binding) t)) - ((cddr repl) (cddr repl)) - (t (cdr key-binding)))))))))) + (let* ((pseudo-binding (which-key--get-pseudo-binding key-binding))) + (if pseudo-binding + pseudo-binding + (let* ((mode-res (which-key--get-replacements key-binding t)) + (all-repls (or mode-res + (which-key--get-replacements key-binding)))) + (dolist (repl all-repls key-binding) + (setq key-binding + (cond ((or (not (consp repl)) (null (cdr repl))) + key-binding) + ((functionp (cdr repl)) + (funcall (cdr repl) key-binding)) + ((consp (cdr repl)) + (cons + (cond ((and (caar repl) (cadr repl)) + (replace-regexp-in-string + (caar repl) (cadr repl) (car key-binding) t)) + ((cadr repl) (cadr repl)) + (t (car key-binding))) + (cond ((and (cdar repl) (cddr repl)) + (replace-regexp-in-string + (cdar repl) (cddr repl) (cdr key-binding) t)) + ((cddr repl) (cddr repl)) + (t (cdr key-binding)))))))))))) (defsubst which-key--current-key-list (&optional key-str) (append (listify-key-sequence which-key--current-prefix) @@ -1363,6 +1415,27 @@ which are strings. KEY is of the form produced by `key-binding'." (current-local-map) (kbd (which-key--current-key-string (car keydesc)))) (intern (cdr keydesc)))) +(defun which-key--map-binding-p (map keydesc) + (or + (when (bound-and-true-p evil-state) + (eq (which-key--safe-lookup-key + map + (kbd (which-key--current-key-string + (format "<%s-state> %s" evil-state (car keydesc))))) + (intern (cdr keydesc)))) + (eq (which-key--safe-lookup-key + map (kbd (which-key--current-key-string (car keydesc)))) + (intern (cdr keydesc))))) + +(defun which-key--pseudo-key (key &optional use-current-prefix) + "Replace the last key in the sequence KEY by a special symbol +in order for which-key to allow looking up a description for the key." + (let* ((seq (listify-key-sequence key)) + (final (intern (format "which-key-%s" (key-description (last seq)))))) + (if use-current-prefix + (vconcat (which-key--current-key-list) (list final)) + (vconcat (butlast seq) (list final))))) + (defun which-key--maybe-get-prefix-title (keys) "KEYS is a string produced by `key-description'. A title is possibly returned using @@ -1387,7 +1460,7 @@ no title exists." (if alternate alternate (concat "Following " keys))) (t "")))) - (which-key--using-top-level "Top-level bindings") + (which-key--using-top-level which-key--using-top-level) (which-key--current-show-keymap-name which-key--current-show-keymap-name) (t ""))) @@ -1513,19 +1586,18 @@ alists. Returns a list (key separator description)." new-list)))) (nreverse new-list))) -(defun which-key--get-keymap-bindings (keymap &optional filter) +(defun which-key--get-keymap-bindings (keymap) "Retrieve top-level bindings from KEYMAP." (let (bindings) (map-keymap (lambda (ev def) - (unless (and (functionp filter) (funcall filter ev def)) - (cl-pushnew - (cons (key-description (list ev)) - (cond ((keymapp def) "Prefix Command") - ((symbolp def) (copy-sequence (symbol-name def))) - ((eq 'lambda (car-safe def)) "lambda") - (t (format "%s" def)))) - bindings :test (lambda (a b) (string= (car a) (car b)))))) + (cl-pushnew + (cons (key-description (list ev)) + (cond ((keymapp def) "Prefix Command") + ((symbolp def) (copy-sequence (symbol-name def))) + ((eq 'lambda (car-safe def)) "lambda") + (t (format "%s" def)))) + bindings :test (lambda (a b) (string= (car a) (car b))))) keymap) bindings)) @@ -1548,7 +1620,8 @@ Requires `which-key-compute-remaps' to be non-nil" (ignore-keys-regexp (eval-when-compile (regexp-opt '("mouse-" "wheel-" "remap" "drag-" "scroll-bar" - "select-window" "switch-frame" "-state")))) + "select-window" "switch-frame" "-state" + "which-key-")))) (ignore-sections-regexp (eval-when-compile (regexp-opt '("Key translations" "Function key map translations" @@ -1615,10 +1688,12 @@ Requires `which-key-compute-remaps' to be non-nil" (forward-line)) (nreverse bindings))))) -(defun which-key--get-formatted-key-bindings (&optional bindings) +(defun which-key--get-formatted-key-bindings (&optional bindings filter) "Uses `describe-buffer-bindings' to collect the key bindings in BUFFER that follow the key sequence KEY-SEQ." (let* ((unformatted (if bindings bindings (which-key--get-current-bindings)))) + (when filter + (setq unformatted (cl-remove-if-not filter unformatted))) (when which-key-sort-order (setq unformatted (sort unformatted which-key-sort-order))) @@ -2019,10 +2094,25 @@ after first page." (defun which-key-show-top-level () "Show top-level bindings." (interactive) - (setq which-key--using-top-level t) + (setq which-key--using-top-level "Top-level bindings") (which-key--create-buffer-and-show nil)) ;;;###autoload +(defun which-key-show-major-mode () + "Show top-level bindings in the map of the current major mode. + +This function will also detect evil bindings made using +`evil-define-key' in this map. These bindings will depend on the +current evil state. " + (interactive) + (setq which-key--using-top-level "Major-mode bindings") + (let ((map-sym (intern (format "%s-map" major-mode)))) + (if (and (boundp map-sym) (keymapp (symbol-value map-sym))) + (which-key--create-buffer-and-show + nil nil (apply-partially #'which-key--map-binding-p (symbol-value map-sym))) + (message "which-key: No map named %s" map-sym)))) + +;;;###autoload (defun which-key-undo-key () "Undo last keypress and force which-key update." (interactive) @@ -2175,9 +2265,10 @@ is selected interactively by mode in `minor-mode-map-alist'." (cons keymap-name keymap))) (t (which-key--hide-popup))))) -(defun which-key--evil-operator-filter (_ev def) - (and (functionp def) - (evil-get-command-property def :suppress-operator))) +(defun which-key--evil-operator-filter (binding) + (let ((def (intern (cdr binding)))) + (and (functionp def) + (not (evil-get-command-property def :suppress-operator))))) (defun which-key--show-evil-operator-keymap () (if which-key--inhibit-next-operator-popup @@ -2191,8 +2282,8 @@ is selected interactively by mode in `minor-mode-map-alist'." which-key--using-show-operator-keymap t) (when (keymapp keymap) (let ((formatted-keys (which-key--get-formatted-key-bindings - (which-key--get-keymap-bindings - keymap 'which-key--evil-operator-filter)))) + (which-key--get-keymap-bindings keymap) + #'which-key--evil-operator-filter))) (cond ((= (length formatted-keys) 0) (message "which-key: Keymap empty")) ((listp which-key-side-window-location) @@ -2215,7 +2306,7 @@ is selected interactively by mode in `minor-mode-map-alist'." (which-key--hide-popup) (setq unread-command-events (listify-key-sequence key)))))))) -(defun which-key--create-buffer-and-show (&optional prefix-keys from-keymap) +(defun which-key--create-buffer-and-show (&optional prefix-keys from-keymap filter) "Fill `which-key--buffer' with key descriptions and reformat. Finally, show the buffer." (setq which-key--current-prefix prefix-keys @@ -2223,7 +2314,8 @@ Finally, show the buffer." (let ((start-time (when which-key--debug (current-time))) (formatted-keys (which-key--get-formatted-key-bindings (when from-keymap - (which-key--get-keymap-bindings from-keymap)))) + (which-key--get-keymap-bindings from-keymap)) + filter)) (prefix-keys (key-description which-key--current-prefix))) (cond ((= (length formatted-keys) 0) (message "%s- which-key: There are no keys to show" prefix-keys))