OneKey

OneKey to rule them all, OneKey to find them, OneKey to bring them all and in the darkness bind them.

What is OneKey ?

One Key provides a single keystroke that when pressed presents you with a menu of commands which can be executed with a further keystroke. The menu is presented as a buffer either within the current frame or within its own frame (see screenshot below).

It provides a convenient way to quickly find commands, or other objects such as Yasnippets or bookmarks, and to learn keybindings (which are displayed in the menu).

By default the menu items are highlighted according to usage to help you identify commonly used items, and you can apply your own colour scheme to make them more readable.

Different types of menus for accessing different types of objects are defined by one-key plugin libraries (see plugins below). You can also easily create your own menus on the fly, or edit existing ones, and save them. By default menus for common prefix keys and commands, as well as major-mode keybindings, are defined.

Several different menus can be stored together as a menu set, and you can switch between these menus using the left/right arrow keys. Different menu sets can be associated with different major-modes or buffers, and OneKey will open the appropriate menu set when the top key is pressed (see menusets below).

Why do I need OneKey ?

By default OneKey comes with a top-level menu containing submenus for all the commonly used prefix keys and commands.
The emacs keybindings are displayed next to the commands to help you learn them.
More frequently accessed items are highlighted to help you quickly pick them out.
OneKey contains a major-mode menu which contains the keybindings and menu items for the current major-mode.
It also allows you to quickly find a command by filtering by regular expressions.
OneKey allows you to easily create your own menus, which can be saved and automatically reloaded when you restart emacs.
With OneKey plugins you get quick access to bookmarks, yasnippets, registers, keyboard macros, and other items.
You can use the OneKey functions ‘one-key-read’, ‘one-key-read-tree’, ‘one-key-read-list’ and ‘one-key-read-logical-formula’
in your code for prompting the user for different types of items.

Installation

Note: the current version of OneKey has only been tested in an X-windows environment on Linux.
It has been found to have problems in when used without a graphical frame. This will be fixed soon.
Download Lisp:one-key.el and save it in your load-path (usually “~/.emacs.d/”).
Make sure that you also have Lisp:hexrgb.el in your load-path
Then add:
        (require 'one-key)
        (global-set-key (kbd "<menu>") 'one-key-open-associated-menu-set)
to your ~/.emacs file, and replace <menu> with whatever top key you want to use
(to find the name of a keybinding press C-h k followed by the keybinding and check the top left of the "*Help*" buffer).
It is also recommended that you increase the values of ‘max-lisp-eval-depth’ and ‘max-specpdl-size’ from their defaults to prevent the probability of an error occurring.
You can do this with: M-x customize-variable max-lisp-eval-depth and M-x customize-variable max-specpdl-size
It is recommended to use values of 10000 or larger.

Usage

Press the top key (e.g. “<menu>”) and the One-Key buffer will popup. Read on for further details…

The *One-Key* buffer

Pressing the top key or running the command ‘one-key-open-default-menu-set’ or ‘one-key-open-menu-set’ opens the One-Key buffer. Within the One-Key buffer you will see a list of command descriptions each with a corresponding key in square brackets to its left. Pressing one of these keys executes the corresponding command. Press q to quit.

Along the top of the buffer in the header line you will see a list of menu names. One of these names will be highlighted and indicates the current menu. You can navigate between the different menus by pressing the left/right arrow keys.

You can scroll the menus up & down using the up/down arrow keys and scroll up/down keys, and you can toggle the visibility and size of the One-Key window by repeatedly pressing the top key. This is useful if there are a large number of items in the menu, or when you need to see part of the buffer that is obscured by the One-Key window.

By default the One-Key window will close after pressing a key corresponding to one of the menu items. If you want to keep the window open after pressing an item key you should toggle the menu persistence by pressing the appropriate special key (C-menu by default, see “Special keybindings” below). To quit one-key and close the One-Key window press q. If you want to quit but keep the window open (e.g. to see the keybindings for a major mode), press C-q.

Special keybindings

For each different type of menu certain “special” keybindings are defined which activate menu specific commands, such as sorting or editing the menu items, adding new menus, etc. These special keybindings are specific to each menu type, though many of them will be the same for all menu types. For example the arrow keys are defined as special keybindings for navigating around menus.

Pressing the f1 key displays a help message listing all the special keybindings for the current menu.

By default, when a menu is created one-key will ensure that the keys corresponding to menu items do not clash with the special keybindings for that menu type. However, if for some reason there is a clash then the menu item gets priority over the special keybinding unless the help window is displayed (by pressing f1), in which case the special keybinding gets priority.

You can alter or add new special keybindings by customizing ‘one-key-special-keybindings’, and ‘one-key-default-special-keybindings’. Extension libraries (such as ‘one-key-dir’ or ‘one-key-regs’) may also define customizable special keys specific to the menu type defined in the library.

By default the following special keybindings are defined:

qQuit and close menu window C-qQuit, but keep menu window open C-menuToggle menu persistence
menuToggle menu display leftChange to next menu rightChange to previous menu
upScroll/move up one line downScroll/move down one line Page UpScroll menu down one page
Page DownScroll menu up one page C-hShow help for next item chosen C-sSave current state of menu
f1Toggle this help buffer f2Toggle column/row ordering of items f3Sort items by next method
C-f3Sort items by previous method f4Reverse order of items /Limit items to those matching regexp
C-/Highlight items matching regexp f5Edit a menu item f6Delete a menu item
f7Copy/kill coloured items C-f7Yank copied items f8Swap menu item keys
f9Add a menu item C-f9Add a menu C-S-f9Remove this menu
f10Reposition item (with arrow keys)f11Donate to support further development C-f11Report a bug

Adding menus

Persistent menus are stored in the file ‘one-key-menus-save-file’ (customizable), but you should never need to edit this file. Instead you can create and edit menus from within the One-Key buffer. If you press the special key corresponding to “Add a menu” you will be prompted for the type of menu to add. By default the following menu types are defined, but more may be added with extension libraries, or by creating them yourself (see ‘one-key-types-of-menu’):

Default menu types

Saving menus

If ‘one-key-autosave-menus’ is non-nil then any new menus or menus that have been changed will be saved on Emacs exit, unless they are listed in ‘one-key-exclude-from-save’ Alternatively you may save individual menus by pressing the special key for “Save the current state of menu” (C-s by default).

Menu sets

A menu set is a collection of menu names. When you open the One-Key buffer with ‘one-key-open-associated-menu-set’ it opens a collection of menus associated with the current major-mode or buffer. By default this is the set of menus in ‘one-key-default-menu-set’. You can define other menu sets by customizing ‘one-key-sets-of-menus-alist’, and associate them with different major-modes or buffers by customizing ‘one-key-associations-for-menu-sets’. Each menu set consists of a name for the menu set, and a list of menu names. one-key reconstructs a menu from its name by searching ‘one-key-types-of-menu’ for a matching entry, and applying the associated function to create the menu. With the “menu-sets” menu you can see what menu sets are currently defined, switch menu sets, and save the current menus as a menu set (C-s). See “Creating menus” above for info on how to add the “menu-sets” menu to the One-Key buffer.

Other features

Item help: to get help on a particular menu item press C-h followed by the key for the item. The help page for the associated command will be displayed. If part of the Help buffer is obscured by the One-Key buffer, you can hide the One-Key buffer by pressing the top key to toggle the window visibility.

Item brightening: By default the background colour of a menu item is increased relative to the brightness of other items each time the item is executed. This means you can easily see the most frequently used items. To turn this feature off set ‘one-key-auto-brighten-used-keys’ to nil.

Sorting items: you can sort the items in a menu by pressing the appropriate special key, and add new sort methods by customizing ‘one-key-default-sort-method-alist’. The current sort method is displayed in the mode-line. You can also toggle between row/column ordering of items, and reverse the order of items. By trying out different sort and ordering combinations you can find a configuration which is most readable, or fits most items on screen. The order of menu items is persistent between sessions if the menus are saved (see “Saving menus”).

Filtering and colouring items: you can filter the items displayed to match a regular expression, or specify the background colour of items that match a given regular expression (press f1 to see which key to press). This can make the menus more readable. The background colours will be saved with the menu.

Editing menus: you can add, delete and edit menu items, and also copy, kill (i.e. cut) and yank (i.e. paste) items from one menu to another. To copy or kill a bunch of items first make sure they are all highlighted with the same background colour (doesn’t matter if they have different brightness levels), and then press the appropriate special key (press f1 for help). You will be prompted for an item in the group, and whether or not you want to also kill the items from the current menu. The items will be saved in ‘one-key-copied-items’ and can be then be yanked into another menu. Any further copy/kills will overwrite the value of ‘one-key-copied-items’. You cannot retrieve previous kills so take care. You can also reposition items in a menu:

  1. press the special key for repositioning items (default is f10, press f1 to check)
  2. press the key of the item to be moved
  3. use the up/down arrow keys to move the item
  4. exit one-key to fix the item

Customize

All the options below can be customized by M-x customize-group RET one-key RET

one-key-default-menu-keysA list of chars which may be used as the default keys in automatically generated one-key menus.
one-key-min-keymap-submenu-sizeThe minimum number of elements allowed in a submenu when creating menus from keymaps.
one-key-popup-windowWhether to popup window when one-key-menu is run for the first time.
one-key-buffer-nameThe buffer name of the popup menu window.
one-key-column-major-orderIf true then menu items are displayed in column major order, otherwise row major order.
one-key-force-multi-column-keymap-menusIf non-nil then one-key menus created from keymaps will have command descriptions shortened to fit two columns.
one-key-menu-window-max-heightThe max height of popup menu window.
one-key-menus-save-fileThe file where one-key menus are saved.
one-key-autosave-menusIf non-nil then one-key menus will automatically be saved when created or changed.
one-key-exclude-from-saveList of regular expressions matching names of menus which should not be autosaved.
one-key-include-menubar-itemsWhether or not to include menu items with no keybinding when creating one-key menus from keymaps.
one-key-item-foreground-colourForeground colour of highlighted items in one-key menus.
one-key-auto-brighten-used-keysIf non-nil then set brightness of menu items colours according to how often the keys are pressed.
one-key-submenus-replace-parentsIf non-nil then when a submenu of a one-key menu is opened it will replace the parent menu.
one-key-major-mode-remap-alistA list of cons cells mapping major modes to one-key-menus.
one-key-toplevel-alistThe one-key top-level alist.
one-key-sets-of-menus-alistSaved menu sets (sets of menus).
one-key-default-menu-setThe default menu set. It’s value should be the car of one of the items in one-key-sets-of-menus-alist’
one-key-default-sort-method-alistAn alist of sorting methods to use on the one-key menu items.
one-key-special-keybindingsAn list of special keys; labels, keybindings, descriptions and associated functions.
one-key-default-special-keybindingsList of special keys to be used if no other set of special keys is defined for a given one-key menu type.
one-key-menu-sets-special-keybindingsList of special keys to be used for menu-sets menus (see one-key-default-special-keybindings for more info).
one-key-disallowed-keymap-menu-keysList of keys that should be excluded from one-key menus created from keymaps.
one-key-types-of-menuA list of names of different types of one-key menu, and associated functions.
one-key-persistent-menu-numberIf non-nil then when the default menu set is opened it will start with the same menu as when previously opened.
one-key-mode-line-messageForm that when evaluated should produce a string for the mode-line in the One-Key buffer.

Tips

Press F1 to toggle the help window showing special keybindings and their associated actions.
Press C-h followed by one of the keys in the menu to show a description of the associated command.
Press q to quit OneKey and hide the One-Key window.
Press F11 to help support further development by donating to the author :’)
You can always use the keystroke C-g to abort OneKey, whatever special keybindings you have set.

Plugins

The following plugin libraries are available:

Lisp:one-key-dir.el - one-key menus for quickly navigating directories (useful for navigating procfs or sysfs on *nix systems)
Lisp:one-key-yas.el - one-key menus for yasnippet templates (see Yasnippet)
Lisp:one-key-bmkp.el - one-key menus for bookmark+ bookmarks (see BookmarkPlus)
one-key-local.el - one-key menus for any major-mode and minor-mode

OneKey menus for your own elisp code

Note: the following functions are not yet complete, but should be finished soon.

You can use the following functions in your own code to offer the user a simple way to select different types of items:

one-key-readOneKey replacement for the built-in ‘completing-read’ function
one-key-read-treeRead a tree (recursive list) of items using OneKey menus
one-key-read-listOneKey replacement for the ‘completing-read-multiple’ function
one-key-read-logical-formulaRead a logical/boolean formula (e.g. for filtering items) using OneKey menus. The result is an elisp form which can be evaluated.

Github

If you want to help develop OneKey have a look at the github repo: https://github.com/vapniks/one-key The code there is currently broken as I am in the midst of a major refactoring (but the code here on the wiki should work).

Bugs

You can report a bug from within emacs by entering M-x one-key-submit-bug-report, or press C-f11 in the One-Key buffer.

Related

You can find it at Lisp:lazy-search.el .
And have some enhanced functions for LazySearch, at Lisp:lazy-search-extension.el .

Screenshot

The OneKey “top-level” menu. The two menu items “mode specific bindings” and “outline commands” are highlighted which indicates that they have been used more often than the others.

OneKeyScreenshot

Notice that “top-level” is highlighted in yellow in the header line, and other menu types are listed to the left and right of this. The user can navigate to the other menus by pressing the left/right arrow keys. Notice also that the mode line indicates the current sort method.

Discussion

Do you know OneTwoThreeMenu? – rubikitch
Wow, i have never heard it, and looks have same design purpose for remember keystroke.
At the beginning, i just want write a mode to help me remember keystroke and free my handy keystrokes for other extensions.
So i write OneKey, just for lazy. – AndyStewart

I have a problem when assigning, for example, ‘mark-paragraph’ function to a key, the paragraph is not marked. While using ‘M-x mark-paragraph’ works! Any idea what is wrong?

I found Lisp:one-key-default.el a bit annoying: after loading it, I can’t bind key to ‘C-x j’,‘C-x p’ etc any longer (as ‘C-x’ is no longer a prefix key), and I can’t use ‘C-x C-h’ to query the keybindings list either. Thus it is only useful for learning Emacs default keys.

I wrote a new routine to bind e.g. ‘ESC C-x’ to the one-key-menu. ‘C-x’ is still a prefix key. You can add keybindings to ‘C-x j’, you can use ‘C-x C-h’ to query keybindings list and you can use ‘one-key-refresh-menu’ to refresh the menu (after adding ‘C-x j’, ‘C-x p’ etc).

    (defun one-key-bind-keymap (key keymap-prefix)
      "Generate an one-key menu for keys starting with `keymap-prefix', and bind it to `key'.

    It also bind `keymap-prefix'-? to the same one-key menu, if not in use.

    For example, when called with ('ESC <f1>', '<f1>'), it would
    generate one-key menu 'one-key-menu-<f1>', and bind 'ESC <f1>'
    and '<f1> ?' to one-key-menu-<f1>.
    "
      (if (keymapp (key-binding (read-kbd-macro keymap-prefix)))
          (let ( (one-key-menu-sym (intern (format "one-key-menu-%s"
                               (replace-regexp-in-string " " "-" keymap-prefix)))) )
        (let ( (prefixed-?-key (read-kbd-macro (concat keymap-prefix " ?"))) )
          (unless (key-binding prefixed-?-key)
            (global-set-key prefixed-?-key one-key-menu-sym)))
        (with-temp-buffer
          (one-key-insert-template keymap-prefix keymap-prefix)
          (eval-buffer))
        (global-set-key (read-kbd-macro key) one-key-menu-sym))
        (message "'%s' is not a keymap-prefix" keymap-prefix)))

    ;; use it this way in your ~/.emacs
    (one-key-bind-keymap "ESC C-x" "C-x")


    (defun one-key-refresh-menu (fkey)
      (interactive "sfkey: ")
      (one-key-bind-keymap (concat "ESC " fkey) fkey))

    ;;use `M-x one-key-refresh-menu' at anytime to refresh the menu
    

The above code won’t work with the new version of one-key and is not recommended. Also `one-key-default.el’ is now redundant.

The new version has a “top-level” menu containing all the common prefix keys. This is much safer than the above method since the old keybindings are not lost. It is also just as fast since you only need press a single key to open the top-level one-key menu, followed by the key for the required prefix key.

I found that when I have (one-key-default-setup-keys) in my .emacs, I do not get the eshell prompt.

That command is now redundant. Just use the “top-level” menu instead.

Could you please update the git repository (and keep it up-to-date) – JonasBernoulli

OK, just pushed the “no-structs” branch to github, which is the version here on the emacswiki. The no-structs branch should work (at least on linux with graphical windows).

The master branch on github is not usable. Really sorry about this, but I want to make it more flexible and extensible allowing multiple One-Key windows for example. This requires a large refactoring which is taking some time. My current strategy is to learn a few tools such as smartparens to aid the otherwise painful process.