Embark
Emacs Mini-Buffer Actions Rooted in Keymaps
Install / Use
/learn @oantolin/EmbarkREADME
#+TITLE: Embark: Emacs Mini-Buffer Actions Rooted in Keymaps #+AUTHOR: Omar Antolín Camarena #+OPTIONS: d:nil #+EXPORT_FILE_NAME: embark.texi #+TEXINFO_DIR_CATEGORY: Emacs misc features #+TEXINFO_DIR_TITLE: Embark: (embark). #+TEXINFO_DIR_DESC: Emacs Mini-Buffer Actions Rooted in Keymaps
#+html: <a href="http://elpa.gnu.org/packages/embark.html"><img alt="GNU ELPA" src="https://elpa.gnu.org/packages/embark.svg"/></a> #+html: <a href="http://elpa.gnu.org/devel/embark.html"><img alt="GNU-devel ELPA" src="https://elpa.gnu.org/devel/embark.svg"/></a> #+html: <a href="https://melpa.org/#/embark"><img alt="MELPA" src="https://melpa.org/packages/embark-badge.svg"/></a> #+html: <a href="https://stable.melpa.org/#/embark"><img alt="MELPA Stable" src="https://stable.melpa.org/packages/embark-badge.svg"/></a>
- Overview
Embark makes it easy to choose a command to run based on what is near point, both during a minibuffer completion session (in a way familiar to Helm or Counsel users) and in normal buffers. Bind the command =embark-act= to a key and it acts like prefix-key for a keymap of /actions/ (commands) relevant to the /target/ around point. With point on an URL in a buffer you can open the URL in a browser or eww or download the file it points to. If while switching buffers you spot an old one, you can kill it right there and continue to select another. Embark comes preconfigured with over a hundred actions for common types of targets such as files, buffers, identifiers, s-expressions, sentences; and it is easy to add more actions and more target types. Embark can also collect all the candidates in a minibuffer to an occur-like buffer or export them to a buffer in a major-mode specific to the type of candidates, such as dired for a set of files, ibuffer for a set of buffers, or customize for a set of variables.
** Acting on targets
You can think of =embark-act= as a keyboard-based version of a right-click contextual menu. The =embark-act= command (which you should bind to a convenient key), acts as a prefix for a keymap offering you relevant /actions/ to use on a /target/ determined by the context:
- In the minibuffer, the target is the current top completion candidate.
- In the =Completions= buffer the target is the completion at point.
- In a regular buffer, the target is the region if active, or else the file, symbol, URL, s-expression or defun at point.
Multiple targets can be present at the same location and you can cycle between them by repeating the =embark-act= key binding. The type of actions offered depend on the type of the target. Here is a sample of a few of the actions offered in the default configuration:
- For files you get offered actions like deleting, copying, renaming, visiting in another window, running a shell command on the file, etc.
- For buffers the actions include switching to or killing the buffer.
- For package names the actions include installing, removing or visiting the homepage.
- For Emacs Lisp symbols the actions include finding the definition, looking up documentation, evaluating (which for a variable immediately shows the value, but for a function lets you pass it some arguments first). There are some actions specific to variables, such as setting the value directly or though the customize system, and some actions specific to commands, such as binding it to a key.
By default when you use =embark-act= if you don't immediately select an action, after a short delay Embark will pop up a buffer showing a list of actions and their corresponding key bindings. If you are using =embark-act= outside the minibuffer, Embark will also highlight the current target. These behaviors are configurable via the variable =embark-indicators=. Instead of selecting an action via its key binding, you can select it by name with completion by typing =C-h= after =embark-act=.
Everything is easily configurable: determining the current target, classifying it, and deciding which actions are offered for each type in the classification. The above introduction just mentions part of the default configuration.
Configuring which actions are offered for a type is particularly easy and requires no programming: the variable =embark-keymap-alist= associates target types with variables containing keymaps, and those keymaps containing bindings for the actions. (To examine the available categories and their associated keymaps, you can use =C-h v embark-keymap-alist= or customize that variable.) For example, in the default configuration the type =file= is associated with the symbol =embark-file-map=. That symbol names a keymap with single-letter key bindings for common Emacs file commands, for instance =c= is bound to =copy-file=. This means that if you are in the minibuffer after running a command that prompts for a file, such as =find-file= or =rename-file=, you can copy a file by running =embark-act= and then pressing =c=.
These action keymaps are very convenient but not strictly necessary when using =embark-act=: you can use any command that reads from the minibuffer as an action and the target of the action will be inserted at the first minibuffer prompt. After running =embark-act= all of your key bindings and even =execute-extended-command= can be used to run a command. For example, if you want to replace all occurrences of the symbol at point, just use =M-%= as the action, there is no need to bind =query-replace= in one of Embark's keymaps. Also, those action keymaps are normal Emacs keymaps and you should feel free to bind in them whatever commands you find useful as actions and want to be available through convenient bindings.
The actions in =embark-general-map= are available no matter what type of completion you are in the middle of. By default this includes bindings to save the current candidate in the kill ring and to insert the current candidate in the previously selected buffer (the buffer that was current when you executed a command that opened up the minibuffer).
Emacs's minibuffer completion system includes metadata indicating the /category/ of what is being completed. For example, =find-file='s metadata indicates a category of =file= and =switch-to-buffer='s metadata indicates a category of =buffer=. Embark has the related notion of the /type/ of a target for actions, and by default when category metadata is present it is taken to be the type of minibuffer completion candidates when used as targets. Emacs commands often do not set useful category metadata so the [[https://github.com/minad/marginalia][Marginalia]] package, which supplies this missing metadata, is highly recommended for use with Embark.
Embark's default configuration has actions for the following target types: files, buffers, symbols, packages, URLs, bookmarks, and as a somewhat special case, actions for when the region is active. You can read about the [[https://github.com/oantolin/embark/wiki/Default-Actions][default actions and their key bindings]] on the GitHub project wiki.
** The default action on a target
Embark has a notion of default action for a target:
- If the target is a minibuffer completion candidate, then the default action is whatever command opened the minibuffer in the first place. For example if you run =kill-buffer=, then the default action will be to kill buffers.
- If the target comes from a regular buffer (i.e., not a minibuffer), then the default action is whatever is bound to =RET= in the keymap of actions for that type of target. For example, in Embark's default configuration for a URL found at point the default action is =browse-url=, because =RET= is bound to =browse-url= in the =embark-url-map= keymap.
To run the default action you can press =RET= after running =embark-act=. Note that if there are several different targets at a given location, each has its own default action, so first cycle to the target you want and then press =RET= to run the corresponding default action.
There is also =embark-dwim= which runs the default action for the first target found. It's pretty handy in non-minibuffer buffers: with Embark's default configuration it will:
- Open the file at point.
- Open the URL at point in a web browser (using the =browse-url= command).
- Compose a new email to the email address at point.
- In an Emacs Lisp buffer, if point is on an opening parenthesis or right after a closing one, it will evaluate the corresponding expression.
- Go to the definition of an Emacs Lisp function, variable or macro at point.
- Find the file corresponding to an Emacs Lisp library at point.
** Working with sets of possible targets
Besides acting individually on targets, Embark lets you work collectively on a set of target /candidates/. For example, while you are in the minibuffer the candidates are simply the possible completions of your input. Embark provides three main commands to work on candidate sets:
-
The =embark-act-all= command runs the same action on each of the current candidates. It is just like using =embark-act= on each candidate in turn. (Because you can easily act on many more candidates than you meant to, by default Embark asks you to confirm uses of =embark-act-all=; you can turn this off by setting the user option =embark-confirm-act-all= to =nil=.)
-
The =embark-collect= command produces a buffer listing all the current candidates, for you to peruse and run actions on at your leisure. The candidates are displayed as a list showing additional annotations. If any of the candidates contain newlines, then horizontal lines are used to separate candidates.
The Embark Collect buffer is somewhat "dired-like": you can select and deselect candidates through =embark-select= (available as an action in =embark-act=, bound to =SPC=; but you could also give it a global key binding). In an Embark Collect buffer =embark-act= is bound to =a= and =embark-act-all= is bound to =A=; =embark-act-all= will act on all currently m
