E macsAir

Collecting frequent-committer miles

Releasing Transient

I am excited to announce the initial release of Transient.

Transient is the successor to Magit-Popup, which was created as part of Magit at the beginning of 2014, and which was released as a separate package at the end of 2017. Magit-Popup itself succeeded an even older implementation, magit-key-mode.el, whose first version goes back all the way to 2010.

The next release of Magit is going to use Transient instead of Magit-Popup. The Magit snapshot from Melpa already uses Transient.


Taking inspiration from prefix keys and prefix arguments, Transient implements a similar abstraction involving a prefix command, infix arguments and suffix commands. We could call this abstraction a “transient command”, but because it always involves at least two commands (a prefix and a suffix) we prefer to call it just a “transient”.

When the user calls a transient prefix command, then a transient (temporary) keymap is activated, which binds the transient’s infix and suffix commands, and functions that control the transient state are added to pre-command-hook and post-command-hook. The available suffix and infix commands and their state are shown in the echo area until the transient state is exited by invoking a suffix command.

Calling an infix command causes its value to be changed, possibly by reading a new value in the minibuffer.

Calling a suffix command usually causes the transient to be exited but suffix commands can also be configured to not exit the transient state.

A more detailed introduction is available in the manual. The manual is very extensive and I am not going to rehash everything here; not even every new feature.


Improvements Over Magit-Popup

The main technical differences are:

  1. Transient uses transient keymaps and embraces the command-loop, Magit-Popup implemented an inferior mechanism that does not use transient keymaps and that instead of using the command-loop implements a naive alternative based on read-char.

  2. Transient uses classes and generic functions to implement different types of infix and suffix commands. That makes it much easier to add new types. With Magit-Popup that was so difficult that only one additional type was ever added, which was not part of the initial release.

  3. Transient removes many arbitrary restrictions that Magit-Popup suffered from. Most importantly any key can be bound to any infix and suffix commands and infixes and suffixes can now placed freely into groups, making it possible to arrange them thematically instead of based on type as before.

Transient also adds many new features, some of which are described below. I strongly recommend that you read the Usage part of the manual to learn more.

Additionally you might want to see the section on Related Abstractions and Packages.

Improved History and Completion

Every time the user invokes a suffix command the transient’s current value is saved to its history. This values can be cycled through the same way one can cycle through the history of commands that read user-input in the minibuffer using M-p and M-n.

When reading the value of a command-line option, users are offered reasonable completion candidates much more often than before. Handling of minibuffer history was also improved. If, and only if, two arguments take the same kind of value, then they now share history.

Both transient-wide and per-infix history are preserved between Emacs sessions now.

Interactively Enabling and Disabling Suffixes

In the past we got many requests to add this or that argument to some Magit popup. Magit’s user base is very diverse; some users have been using it and Git for a decade, while others are just getting started now. That means that we had to find a balance between adding every argument that at least one user wants to be added and not overwhelming beginners with a wall of arguments they never use.

To cope with that, Transient supports placing suffix commands on different “levels”. Users can select a level to control how many suffixes they want to see. They can also place individual suffixes on a different level. This is done interactively, directly from the transient. See Enabling and Disabling Suffixes for more information.

Note that Magit currently places nearly all suffixes on the default level. So for the time being changing the level does not have as much of an effect as one might hope. But that will be worked on.


Learning Git

Some users learn Git by using Magit. That involves learning about the available arguments. For arguments we now try to always use key sequences that are equal to the respective short argument. Unfortunately that is not always possible, because Git does not provide a short argument for every --long argument.

Transient can now optionally highlight such mismatched key bindings so that you don’t learn any arguments that don’t actually exist.


Breaking changes

Posted on 14th February 2019