p.enthalabs

What's New in Emacs 31.1?

Emacs 31.1 is finally out! Unlike earlier Emacs versions, there is not a singular big-bang feature in this release. From what I could gather, the new garbage collector was possibly planned for inclusion in Emacs 31.1, but it has been postponed to Emacs 32. But more on that in a future post; it’s an interesting subject.

Some of the more notable features in Emacs 31.1 are small, quality of life fixes, and one deprecation that marks the end of an era.

As always, my book, Mastering Emacs is 31% off for the next week to celebrate the release also.

**The unexec/pdumper controversy and subsequent deprecation**

Emacs is… not a normal application. When you compile and link it, you get `temacs` which is the heart of Emacs but without most of the libraries that ship with it. It’s a bare-bones Emacs with little more than the C core and the interpreter; it’s not really that useful.

To get the Emacs binary you know and love, you have to run `temacs` and tell it to load the standard library into memory. That is slow. There is a lot of elisp and housekeeping that has to happen. It can take several minutes and a fair bit of CPU and ram to start Emacs this way; it’s untenable.

This has been a problem that has dogged Emacs for decades. It’s not a huge deal today, but back in the day it could break the back on home computers or even shared multi-user environments if a brace of enthusiastic Emacs users all decide to launch Emacs at the same time in the morning.

The solution to this problem? Load it all in once and then _literally dump the text/data/bss/etc. segments of Emacs’s memory_ to a new binary. Do that, and you don’t have to bootstrap all that Emacs lisp state again and again. It feels like a wrestling move almost. You corral a top-heavy Emacs into position and apply The Attitude Adjustment, body slamming Emacs into a new binary, and everything’s all set up and ready to go.

It’s a pretty boss move.

But to make this, uh, wrestling move work, Emacs depended on a number of snowflake functions in glibc. After a couple of decades of enabling this sort of bad behavior the glibc team called it quits, and Emacs had to find another way of doing it.

Daniel Colascione built a much better solution, though not everyone was happy about it, that – put simply – standardizes the serialization of Emacs’s internal structures into something that is not a 1:1 dump of its internal memory structures.

The portable dumper’s been the default for a number of years now. It was first introduced around ten years ago, and in keeping with Emacs’s long history of backwards compatibility, the old unexec dumper was kept around ostensibly for the one or two users who found the idea of a portable dumper risible or unworkable.

But now it is finally gone for good. The end of an era.

**User Lisp Directory**

Classic problem: you git clone or download an Emacs package somewhere and now you want it to work. But how? It’s not _that_ trivial; there are quite a few competing ways of doing it. The simplest one is to tell users to drop their package into the `user-lisp/` in your `.emacs.d` directory and Emacs will sort out loading and setting up autoload (so the right stuff appears in `M-x`.)

**Minibuffer and Completions**

Emacs 30.1 gained `completion-preview-mode`, a native “pop-up window” system not unlike Company and Corfu, but more attuned to Emacs’s own way of doing things: using the `*Completions*` window instead of a floating child frame like Company and friends.

Emacs 31.1 builds on that with a wide range of customizable options you’re sure to want to customize if you want to go native.

**Rotating Window Layouts**

`M-x window-layout-rotate-clockwise` (see `C-x w C-h` for the manifold new options) and suchlike rotate your window layouts. Another little UI winner.

**Exchanging the point and mark without activating the region**

I’ve talked (mostly in the my book) about how transient-mark-mode is a rather awkward one-size-fits-all that was draped over Emacs’s multitude of “region-affecting” commands, like `kill-region` (`C-w`).

So `C-x C-x`, that exchanges point and mark, also activates the region whether you want it to or not. Fixing the mark commands in transient mark mode is an old article of mine where I demonstrate how to do exactly that. But now there’s a builtin option to not have it do that — sweet.

**Tree-sitter now offers to install its grammars for you**

Two blockers work in tandem to hold back the wider adoption of tree-sitter in Emacs:

1. The fact that TS demands a special major mode to work; and that said mode is often a thread-bare re-implementation of the original.

2. That installing grammars, especially on Windows, is a giant pain in the neck, as you have to not only thread the needle with the exacting ABI version of the tree-sitter library _itself_, but also ensure you just the exacting version of each language grammar, or everything goes up in smoke.

The former is still a problem, but the latter is now mostly resolved. Emacs can now finally offer to install the right language grammar for TS modes it knows about.

Now there’s no excuse not to try out Combobulate: Structured Movement and Editing with Tree-Sitter.

**and so much more**

Lots of little tweaks and changes. Have a read.

Installation Changes in Emacs 31.1

``` unexec dumper removed. The traditional unexec dumper, deprecated since Emacs 27, has been removed. ``` `The portable dumper now works on m68k a.out targets.` As I wrote in the introduction at the top, this is indeed the end of an era.

``` Emacs's old 'ctags' program is no longer built or installed. You are encouraged to use Universal Ctags <https://ctags.io/> instead. For now, to get the old 'ctags' behavior you can can run 'etags --ctags' or use a shell script named 'ctags' that runs 'etags --ctags "$@"'. ```

If you’re a TAGS user you should check with `where` and make sure you’ve got a newer one installed. (If you don’t know if you use TAGS, you do not.)

``` Changed GCC default options on 32-bit x86 systems. When using GCC 4 or later to build Emacs on 32-bit x86 systems, 'configure' now defaults to using the GCC options '-mfpmath=sse' (if the host system supports SSE2) or '-fno-tree-sra' (if not). These GCC options work around GCC bug 58416, which can cause Emacs to behave incorrectly in rare cases. ```

``` New configure option '--with-systemduserunitdir'. This allows specifying the directory where the user unit file for systemd is installed; the default is '${prefix}/usr/lib/systemd/user'. ```

You can tell Emacs to install a systemd service to run Emacs’s server that way. I recommend doing this.

Startup Changes in Emacs 31.1

``` In compatible terminals, 'xterm-mouse-mode' is turned on by default. For these terminals the mouse will work by default. A compatible terminal is one that supports Emacs setting and getting the OS selection data (a.k.a. the clipboard) and mouse button and motion events. With 'xterm-mouse-mode' enabled, you must use Emacs keybindings to copy to the OS selection instead of terminal-specific keybindings.

You can keep the old behavior by customizing 'xterm-mouse-mode' to nil. ```

Most people do not know this but Emacs added mouse support to terminal Emacs years ago but left it off. Terminal capabilities vary widely so that was a nice and safe decision. But now it just works as you’d expect it to: menus are clickable and so forth. Good stuff.

``` site-start.el is now loaded before the user's early init file. Previously, the order was early-init.el, site-start.el and then the user's regular init file, but now site-start.el comes first. This allows site administrators to customize things that can normally only be done from early-init.el, such as adding to 'package-directory-list'. ```

If you’re on a single user system like your laptop or home computer, this is unlikely to matter much to you.

``` New User Lisp directory feature. If you have a subdirectory "user-lisp/" in your Emacs configuration directory, then Lisp files in it and any subdirectories are now recursively byte-compiled, scraped for autoload cookies and added to 'load-path'.

You can disable the feature by setting 'user-lisp-auto-scrape' to nil, and you can customize the option 'user-lisp-directory' to process some other directory instead. There is also a new command 'prepare-user-lisp' that you can invoke at any time. See the Info node "(emacs) User Lisp Directory" for more details. ```

Oh this is so useful. I have been cargo culting the same snippets of code around for 23 years to load directories with my stuff in it; yes `use-package` helps but it’s still a lot of manual hassle. About time!

``` The first client frame now shows warnings from daemon startup. When there are warnings emitted during Emacs startup, usually due to problems in your initialization file, these are shown in a "*Warnings*" buffer. Until now such warnings were not made visible in the case that Emacs was started as a daemon. Now the first frame after daemon startup will show the "*Warnings*" buffer. So for example, starting Emacs with a command like 'emacsclient -a "" -c' will now show "*Warnings*" just like a plain invocation of 'emacs' would. ```

Bad news. Emacs’s insistence on telling you about every minor stubbed toe in some random package will now plague you even if you’re running Emacs as a daemon. Such a cursed feature. Nobody cares. If it was important it’d be an error.

Changes in Emacs 31.1

``` 'line-spacing' now supports specifying spacing above the line. Previously, only spacing below the line could be specified. The user option can now be set to a cons cell to specify spacing both above and below the line, which allows you to vertically center text. ```

This is a global value to all of Emacs, it’s not a face setting, so you cannot use `M-x customize-face` to change it. Set it with `setopt` or customize ui.

``` New face 'margin' for the window margin display. A new basic face 'margin' is used by default for text displayed in the left and right margin areas, which are used by various packages for per-line annotations. Its background defaults to the frame default background, so existing behavior is unchanged for users who do not customize this new face.

Display strings shown in the margins now inherit unspecified face attributes from the 'margin' face, if the string itself does not fully specify its face. If your code relied on the face of the underlying buffer text to serve as a default for any unspecified face attributes of strings displayed in the margin, you must now apply those face attributes to the margin string itself using 'propertize'. ```

``` 'prettify-symbols-mode' attempts to ignore undisplayable characters. Previously, such characters would be rendered as, e.g., white boxes. ```

``` 'standard-display-table' now has more extra slots. 'standard-display-table' has been extended to allow specifying glyphs that are used for borders around child frames and menu separators on TTY frames.

Call the command 'standard-display-unicode-special-glyphs' to set up the 'standard-display-table's extra slots with Unicode characters. See the documentation of that command to see which slots of the display table it changes. ```

``` Child frames are now supported on TTY frames. This supports use-cases like Posframe, Corfu, and child frames acting like tooltips. To enable tooltips on TTY frames, call 'tty-tip-mode'.

The presence of child frame support on TTY frames can be checked with '(featurep 'tty-child-frames)'.

Recent versions of Posframe and Corfu are known to use child frames on TTYs if they are supported. ```

This is a welcome change for terminal users. Frames in the terminal do not work as they do in GUI — they behave more like tmux/screen “windows”. Here child frames are just inset popups like the ones you find in GUI Emacs.

``` Several font-lock face variables are now obsolete. The following variables are now obsolete: 'font-lock-builtin-face', 'font-lock-comment-delimiter-face', 'font-lock-comment-face', 'font-lock-constant-face', 'font-lock-doc-face', 'font-lock-doc-markup-face', 'font-lock-function-name-face', 'font-lock-keyword-face', 'font-lock-negation-char-face', 'font-lock-preprocessor-face', 'font-lock-string-face', 'font-lock-type-face', 'font-lock-variable-name-face', and 'font-lock-warning-face'.

These variables contributed both to confusion about the relation between faces and variables, and to inconsistency when major mode authors used one or the other (sometimes interchangeably). We always recommended using faces directly, and not creating variables going by the same name.

If you have customized these variables, you should now customize the corresponding faces instead, using something like:

M-x customize-face RET font-lock-string-face RET

If you have been using these variables in Lisp code (for example, in font-lock rules), simply quote the symbol, to use the face directly instead of its now-obsolete variable. ```

Note this is not about the _faces_ but about variables named the same as the faces. Yeah that is confusing. Emacs has faces like `font-lock-string-face` that you probably have customized already. But it also has _variables_ named the same as the faces. The _variables_ are deprecated.

If you have configured your faces with `M-x customize-face` (you should!) you have nothing to worry about.

``` New char-table 'special-mirror-table' for mirroring special glyphs. This char-table is used to mirror special glyphs (truncation and continuation) when the user has defined an alternative representation for those characters via display tables. ```

``` find-func.el commands now have history enabled. The 'find-function', 'find-library', 'find-face-definition', and 'find-variable' commands now allow retrieving previous input using the usual minibuffer history commands. Each command has a separate history. ```

Huh. I never noticed they did not have their own history; now they do. That is good to know I guess but unlikely to affect me much.

``` New minor mode 'find-function-mode' replaces 'find-function-setup-keys'. The new minor mode defines the keys at a higher precedence level than the old function, one more usual for a minor mode. To restore the old behavior, customize 'find-function-mode-lower-precedence' to non-nil. ```

You’re unlikely to have much of a need to customize this.

`'find-function' can now find 'cl-defmethod' invocations inside macros.` ``` New minor mode 'prettify-special-glyphs-mode'. The new minor mode prettifies the special character glyphs (truncation and continuation) on TTY frames (and GUI frames without fringes). You can customize the associated new face 'special-glyphs'. ```

Minibuffer and Completions

``` Support for immediate display of the "*Completions*" buffer. Whenever a minibuffer with completion is opened, then if the completion table sets the 'eager-display' completion property to non-nil, the "*Completions*" buffer will now be displayed immediately. This property can be overridden for different completion categories by customizing 'completion-category-overrides'. Alternatively, the new user option 'completion-eager-display' can be set to t to force eager display of "*Completions*" for all minibuffers, or nil to suppress this for all minibuffers. ```

``` Support for updating "*Completions*" as you type. If the "*Completions*" buffer is displayed and the completion table sets the completion property 'eager-update' to non-nil, then the "*Completions*" buffer will be updated as you type. This property can be overridden for different completion categories by customizing 'completion-category-overrides'. Alternatively, the new user option 'completion-eager-update' can be set to t to make "*Completions*" always be updated as you type, or nil to suppress this always. Note that for large or inefficient completion tables, this can slow down typing. ```

``` 'RET' chooses the completion selected with 'M-<UP>/M-<DOWN>'. If a completion candidate is selected with 'M-<UP>' or 'M-<DOWN>', typing 'RET' will exit completion with that candidate as the result. This works both in minibuffer completion and for in-buffer completion. This feature supersedes 'minibuffer-completion-auto-choose', which previously provided similar behavior; that variable is now nil by default. ```

This goes hand in hand with the changes in Emacs 30.1 to make Emacs’s minibuffer completion system behave a little bit more like traditional company/corfu-style completers.

I really rate these new inclusions but I do warn they require a fair bit of customization to really get them to behave like something that does not get in your way.

``` Support for completion category inheritance. You can now define completion categories that inherit properties from existing categories, using the new function 'define-completion-category'. ```

``` New optional value of 'minibuffer-visible-completions'. If the value of this option is 'up-down', only the '<UP>' and '<DOWN>' arrow keys move point between candidates shown in the "*Completions*" buffer display, while '<RIGHT>' and '<LEFT>' arrows move point in the minibuffer. ```

``` New user option 'completion-pcm-leading-wildcard'. This option configures how the partial-completion style does completion. It defaults to nil, which preserves the existing behavior. When it is set to t, the partial-completion style behaves more like the substring style, in that the input can match a candidate anywhere in the candidate string. ```

Another minor tweak to a completion style to make it behave more like something it once did. Emacs has a diverse set of completion styles. The default have changed a lot over the years, sometimes to the chagrin of people who were used to the quirks of a now-relegated default style. For example there’s both an emacs21 and an emacs22 completion style in `completion-styles-alist`. But see Understanding Minibuffer Completion for more information.

``` 'completion-styles' now can contain lists of bindings. In addition to a symbol naming a completion style, an element of 'completion-styles' can now be a list of the form '(STYLE ((VARIABLE VALUE) ...))' where STYLE is a symbol naming a completion style. VARIABLE will be bound to VALUE (without evaluating it) while the style is executing. This allows multiple references to the same style with different values for completion-affecting variables like 'completion-pcm-leading-wildcard' or 'completion-ignore-case'. This also applies to the styles configuration in 'completion-category-overrides' and 'completion-category-defaults'. ```

Oh man. That is niche. `completion-styles` is a shopping list of how Emacs must match things in stuff like the minibuffer’s completer. Now you can make it so `initials` ignores case but `substring` does not.

``` Navigating "*Completions*" now accommodates 'completions-format'. When 'completions-format' is set to 'vertical', typing 'n', 'TAB' or 'M-<DOWN>' in the "*Completions*" buffer (the latter also in the minibuffer) now moves point to the completion candidate in the next line in the current column, and wraps to the next column after the last completion candidate of the current column. Likewise, typing 'p', 'S-TAB' or 'M-<UP>' moves point to the completion candidate in the previous line or wraps to the previous column. Previously, these keys ignored the vertical format, i.e., they moved point only to the item in the same line of the next or previous column, in accordance with the default horizontal format. In the vertical format, typing '<LEFT>' and '<RIGHT>' in the "*Completions*" buffer (and when 'minibuffer-visible-completions' is non-nil, also in the minibuffer) moves point only within the current line, analogously to how, in the horizontal format, '<DOWN>' and '<UP>' move point only within the current column. ```

You’ll want to configure this for sure if you are intent on using the Completions buffer and window for in-buffer completion. I always found navigating between the tabular structure in completions to be a bit weird and offputting; it’s a good use of space, for sure, but a flat list of matches is much easier to reason about.

``` Selected completion candidate is preserved across "*Completions*" updates. When the window point is on a completion candidate in the "*Completions*" buffer (because of 'minibuffer-next-completion' or for any other reason), it will remain on that candidate after the "*Completions*" is updated with a new list of completions. The candidate is deselected when the "*Completions*" buffer is hidden. ```

``` "*Completions*" is now displayed faster when there are many candidates. As before, if there are more completion candidates than can be displayed in the current frame, only a subset of the candidates is displayed. This process is now faster: only that subset of the candidates is actually inserted into "*Completions*" until you run a command which interacts with the text of the "*Completions*" buffer. This optimization only applies when 'completions-format' is 'horizontal' or 'one-column'. ```

``` New user option 'crm-prompt' for 'completing-read-multiple'. This option configures the prompt format of 'completing-read-multiple'. By default, the prompt indicates to the user that the completion command accepts a comma-separated list. The prompt format can include the separator description and the separator string, which are both stored as text properties of the 'crm-separator' regular expression. ```

It’s a pretty rare feature, that. You can “toggle-select” multiple matches from the minibuffer; few things use it, to be honest. I find the user experience rather poor if I am perfectly honest, no matter the completer. Helm is one of the few tools I think that does it well.

For a practical example of multi-select see Fuzzy Finding with Emacs Instead of fzf.

``` New user option 'completion-preview-sort-function'. This option controls how Completion Preview mode sorts completion candidates. If you use this mode together with an in-buffer completion popup interface, such as the interfaces that the GNU ELPA packages Corfu and Company provide, you can set this option to the same sort function that your popup interface uses for a more integrated experience.

('completion-preview-sort-function' was already present in Emacs 30.1, but as a plain Lisp variable, not a user option.) ```

``` New user option 'completion-preview-inhibit-functions'. This option provides fine-grained control over Completion Preview mode activation. You can use it to specify arbitrary conditions in which to inhibit the mode's operation. ```

Another thing you’ll want to customize. You may want certain movement commands like those used in `paredit` or `combobulate` commands to not trigger the completion window.

``` New mode 'minibuffer-nonselected-mode'. This mode, enabled by default, directs attention to the active minibuffer window in the case the minibuffer window is no longer selected, but still waiting for input. This uses the new 'minibuffer-nonselected' face. ```

I like this. I am glad it is enabled by default; it can be a little bit confusing not having a selected/non-selected state.

``` 'read-multiple-choice' now uses the minibuffer to read a character. It still can use 'read-key' when the variable 'read-char-choice-use-read-key' is non-nil. ```

``` 'map-y-or-n-p' now uses the minibuffer to read a character. It still can use 'read-key' when the variable 'y-or-n-p-use-read-key' is non-nil. ```

Ugh. They mucked around with the default method used for answering “yes or no” prompts in Emacs to make it more like a regular minibuffer thing instead and it caught me out by surprise some years ago when they did that, and it was a pain to track down. Keep you eye on this one if you’re of a similar mind to me on this.

``` 'flex' completion style rewritten to be faster and more accurate. Completion and highlighting use a new, superior algorithm. For example, pattern "scope" now ranks 'elisp-scope-*' functions well above 'dos-codepage' and 'test-completion'. Pattern "botwin" finds 'menu-bar-bottom-window-divider' before 'ibuffer-other-window'. ```

Flex matching is an ido-mode feature, and I believe this is strictly speaking a reimplementation of it for the `fido-mode` completer built on the “new” minibuffer completion system. See Introduction to Ido Mode for IDO mode; and Understanding Minibuffer Completion for the latter.

Mouse

``` New mode 'mouse-shift-adjust-mode' extends selection with 'S-<mouse-1>'. When enabled, you can use the left mouse button with the '<Shift>' modifier to extend the boundaries of the active region by dragging the mouse pointer. ```

Cool. I rarely drag-select stuff in Emacs, but for finicky stuff it does actually work faster than a keyboard if it’s a one-off.

``` 'context-menu-mode' now includes a "Send to..." menu item. The menu item enables sending current file(s) or region text to external (non-Emacs) applications or services. See send-to.el for customizations. ```

Oh my this is great. `M-x context-menu-mode` itself is a reasonably new feature itself (Emacs 28) and is not on by default. It adds contextual right-click menus to stuff. I have not kept abreast with all the places it has had custom commands added to it, and as the default is a bit… barebones, I can imagine most people bounced right off.

You can manually trigger the context menu mode (minor mode active or not) with `M-x context-menu-open`.

``` The mouse now drags lines in character increments again. Dragging a horizontal or vertical line like the mode line or the lines dividing side-by-side windows now happens in increments of the corresponding frame's character size again. This is the behavior described in the manual and was the default behavior before 'window-resize-pixelwise' was added for Emacs 24.1. To drag in pixel increments, as with Emacs 24 through Emacs 30, customize 'window-resize-pixelwise' to t. ```

Windows

``` New commands to modify window layouts of frames. 'window-layout-rotate-clockwise' ('C-x w r <RIGHT>') and its counterpart 'window-layout-rotate-anticlockwise' ('C-x w r <LEFT>') rotate an entire window layout. 'window-layout-flip-topdown' ('C-x w f <DOWN>', 'C-x w f <UP>') and 'window-layout-flip-leftright' ('C-x w f <LEFT>', 'C-x w f <RIGHT>') flip the window layout vertically and horizontally. 'window-layout-transpose' ('C-x w t') reorganizes windows such that every horizontal split becomes a vertical split and vice versa. 'rotate-windows' ('C-x w o <RIGHT>') and its counterpart 'rotate-windows-back' ('C-x w o <LEFT>') rotate windows in cyclic ordering. ```

Oh I love this. But I’ll probably just pick one direction, clockwise or whatever, and bind that to an easy-to-reach key and suffer the indignity of tapping a few times. It is not often I wish to do this sort of thing. I’m a bit curious though because I am guessing the implementation will cycle through all nodes (Emacs’s window tiling window splits are represented as a tree structure) in the tree — try `M-: (window-tree)` to see the internal representation.

``` New user option 'rotate-windows-change-selected'. This controls whether 'rotate-windows' and 'rotate-windows-back' change the selected window. If nil, the selected window does not change. The default is t, which means the new selected window will be the one that winds up at the location of the previously-selected window. ```

Rotate windows but not move with it? Not for me, thanks.

``` New user option 'transpose-dedicated-windows'. This controls how functions transposing or rotating windows handle dedicated windows. The default is nil, which causes these function to signal an error if they encounter a dedicated window. ```

Yeah you’ll want this at nil; dedicated windows are sticky windows. Rotating them around is probably not what you intend — or maybe it is, if you have a peculiar workflow.

``` Windmove commands now move to skipped windows if invoked twice in a row. The new user option 'windmove-allow-repeated-command-override' controls this behavior: if it is non-nil, invoking the same windmove command twice overrides the 'no-other-window' property, allowing navigation to windows that would normally be skipped. The default is t; customize it to nil if you want the old behavior. ```

`C-x o` taps through windows as you probably know. But you can flag a window (see Demystifying Emacs’s Window Manager) as `no-other-window` so it is exempt from that command. Windmove of course lets you move between windows using your arrow keys.

``` New hook 'window-deletable-functions'. This abnormal hook gives its client a way to save a window from being deleted implicitly by functions like 'kill-buffer', 'bury-buffer' and 'quit-restore-window'. ```

Emacs always had a weird, disconnected relationship between buffers and windows, as anybody who has ever tried to tame the window manager (see previously mentioned article) so this feels like another patch on top of what is a pretty irreconcilable problem: how do you keep two things that can be interchanged easily from manipulating something the user/package does not want it to? With more hooks, it seems…

``` Buffer-local window change functions now run in their buffers. Running the buffer-local version of each of the abnormal hooks 'window-buffer-change-functions', 'window-size-change-functions', 'window-selection-change-functions' and 'window-state-change-functions' will make the respective buffer temporarily current while running the hook. ```

``` 'window-buffer-change-functions' is run for removed buffers too. The buffer-local version of 'window-buffer-change-functions' may now be run twice: once for the buffer removed from the window and once for the buffer now shown in that window. ```

``` New user option 'quit-window-kill-buffer'. This option specifies whether 'quit-window' should preferably kill or bury the buffer shown by the window to quit. The default is nil. Customize it to t to always kill the buffer; customize to a list of major modes to kill if the buffer's major mode is one of those. ```

``` New user option 'kill-buffer-quit-windows'. This option has 'kill-buffer' call 'quit-restore-window' to handle the further destiny of any window showing the buffer to be killed. ```

``` 'split-window' can optionally resurrect deleted windows. A new optional argument REFER of 'split-window' makes it possible to, instead of making a new window object, reuse an existing, deleted one. This can be used to preserve the identity of windows when swapping or transposing them. ```

``` New window parameter 'quit-restore-prev'. This parameter is set up by 'display-buffer' when it detects that the window used already has a 'quit-restore' parameter. Its presence gives 'quit-restore-window' a way to undo a sequence of buffer display operations more intuitively. ```

``` 'quit-restore-window' handles new values for BURY-OR-KILL argument. The values 'killing' and 'burying' are like 'kill' and 'bury' but assume that the actual killing or burying of the buffer is done by the caller. ```

``` New user option 'quit-restore-window-no-switch'. With this option set, 'quit-restore-window' will delete its window more aggressively rather than switching to some other buffer in it. ```

Ahem yeah - as above. All these things are just ointment balmed on Emacs to try and solve an intractable problem. If you let a window host anything, and a buffer jump around and open anywhere (either mechanically or by the whim of the user) then… how do you lock it down properly if you want something IDE-like?

I like the idea of these things. And I predict few will ever really make use of them, even in packages.

``` The user option 'display-comint-buffer-action' has been removed. It has been obsolete since Emacs 30.1. Use '(category . comint)' instead. Another user option 'display-tex-shell-buffer-action' has been removed too, for which you can use '(category . tex-shell)'. ```

Nothing much to worry about.

``` New user option 'split-window-preferred-direction'. Functions called by 'display-buffer' split the selected window when they need to create a new window. A window can be split either vertically (one below the other) or horizontally (side by side). This new option determines which direction will be tried first in the case that both directions are possible according to the values of 'split-width-threshold' and 'split-height-threshold'. The default value is 'longest', which means to prefer to split horizontally if the window's frame is a "landscape" frame, and vertically if it is a "portrait" frame. (A frame is considered to be portrait if its vertical dimension in pixels is greater or equal to its horizontal dimension, otherwise it is considered to be landscape.) Previous versions of Emacs always tried to split vertically first, so to get the previous behavior, you can customize this option to 'vertical'. The value 'horizontal' always prefers the horizontal split. ```

Good news if you hated the random nature of window splits. Now you’ll have a little bit of control over which direction at least. I recommend you make a note of this and if you find it aggravating that it splits things the wrong way, do set it.

``` The default value of 'split-width-threshold' is reduced from 160 to 150. We believe that, after splitting, text filled to 75 columns remains comfortable to read. ```

No arguments here.

``` New optional argument INDIRECT for 'get-buffer-window-list'. With this argument non-nil, 'get-buffer-window-list' will include in the return value windows whose buffers share their text with BUFFER-OR-NAME. ```

``` New 'display-buffer' action alist entry 'reuse-indirect'. With such an entry, 'display-buffer-reuse-window' may also choose a window whose buffer shares text with the buffer to display. ```

Indirect buffers are a power user feature. If you want to do separate things in the same buffer, you can split and “point” your new window to an already-visited buffer in another window, but then you’ll run into awkward things like shared major modes, the point not always remembering the right place you were because of how points and windows work. An indirect buffer points to a base buffer that you clone from; it is the same underlying text, but everything else is separate (like major mode)

``` New variable 'window-state-normalize-buffer-name'. When bound to non-nil, 'window-state-get' will normalize 'uniquify' managed buffer names by removing 'uniquify' prefixes and suffixes. This helps to restore window buffers across Emacs sessions. ```

``` New action alist entry 'this-command' for 'display-buffer'. You can use this in 'display-buffer-alist' to match buffers displayed during the execution of particular commands. ```

That’s really cool, but will it work well if you trigger stuff through stuff like magit’s gnarly dispatchers or orgs’?

``` New command 'other-window-backward' ('C-x O'). This moves in the opposite direction of 'other-window' and is for its default keybinding consistent with 'repeat-mode'. ```

No more need for using the negative prefix argument to go backwards.

``` New functions 'combine-windows' and 'uncombine-window'. 'combine-windows' is useful to make a new parent window for several adjacent windows and subsequently operate on that parent. 'uncombine-window' can then be used to restore the window configuration to the state it had before running 'combine-windows'. ```

I wonder how this fits into atomic windows which are another way of ‘combining’ windows. I am sure there is a substantial difference, perhaps because this one is not tied at all to `display-buffer-alist`.

``` New function 'window-cursor-info'. This function returns a vector of pixel-level information about the physical cursor in a given window, including its type, coordinates, dimensions, and ascent. ```

Frames

``` New function 'frame-deletable-p'. If this function returns nil, the following call to 'delete-frame' might fail to delete its argument FRAME or might signal an error. It is therefore advisable to use this function as part of a condition that determines whether to call 'delete-frame'. ```

``` New function 'frame-use-time'. This function is the frame equivalent of the function 'window-use-time' for a window. The result is the 'window-use-time' of the frame's most recently used window. ```

``` New functions 'get-mru-frames' and 'get-mru-frame'. 'get-mru-frames' returns a list of frames sorted by their most recent use time, among all frames, or among those visible or iconified on the same terminal as the selected frame. Child frames can be excluded. A single frame can be excluded (e.g. the selected frame). 'get-mru-frame' returns the single most recently used frame. ```

``` After deleting, 'delete-frame' now selects the most recently used frame. Previously, after deleting a specified frame, 'delete-frame' would select the oldest visible frame on the same terminal. To revert to the old behavior, set the new user option 'delete-frame-choose-selected' to nil. ```

I am not a massive frame user as I never found the customization to make it work the way I liked it worth the effort, even though I do also use a tiling WM. But returning to the last seen frame does seem like an odd thing to only add now; this will no doubt restore the same of people who prefer frame-only approaches to windows.

``` New value 'force' for user option 'frame-inhibit-implied-resize'. This will inhibit implied resizing while a new frame is made. It can be useful on tiling window managers where the initial frame size should be specified by external means. ```

``` New user option 'alter-fullscreen-frames'. This option is useful to maintain a consistent state when attempting to resize fullscreen frames. It defaults to 'inhibit' on NS builds which means that a fullscreen frame will not change size. It defaults to nil everywhere else, which means that the window manager is supposed to either resize the frame and change the fullscreen status accordingly, or keep the frame size unchanged. The value t means to first reset the fullscreen status and then resize the frame. ```

``` New functions to set frame size and position in one compound step. 'set-frame-size-and-position' sets the new size and position of a frame in one compound step. Both size and position can be specified as with the corresponding frame parameters 'width', 'height', 'left' and 'top'. 'set-frame-size-and-position-pixelwise' is similar but has a more restricted set of values for specifying size and position. ```

``` New commands 'split-frame' and 'merge-frames'. 'split-frame' moves a specified number of windows from an existing frame to a newly-created frame. 'merge-frames' merges all windows from two frames into one of these frames and deletes the other one. ```

``` Frames can now be renamed to "F<number>" on text terminals. Unlike with other frame names, an attempt to rename to "F<number>" signals an error when a frame of that name already exists. ```

As I mentioned earlier frames in terminal Emacs are really just another way of doing a window configuration / screen-style “window pane”.

``` New frame parameters 'cloned-from' and 'undeleted'. The frame parameter 'cloned-from' is set to the frame from which the new frame is cloned using the command 'clone-frame'.

The frame parameter 'undeleted' is set to t when a frame is undeleted using the command 'undelete-frame'.

These are useful if you need to detect a cloned or undeleted frame in hooks like 'after-make-frame-functions' and 'server-after-make-frame-hook'. ```

``` Frames now have unique ids and the new function 'frame-id'. Each non-tooltip frame is assigned a unique integer id. This allows you to unambiguously identify frames even if they share the same name or title. When 'undelete-frame-mode' is enabled, each deleted frame's id is stored for resurrection. The function 'frame-id' returns a frame's id (in C, use the frame struct member 'id'). ```

``` New commands 'select-frame-by-id', 'undelete-frame-by-id'. The command 'select-frame-by-id' selects a frame by ID and undeletes it if deleted. The command 'undelete-frame-by-id' undeletes a frame by its ID. When called interactively, both functions prompt for an ID. ```

Mode Line

``` New definitions for mode line faces on dark backgrounds. The faces 'mode-line' and 'mode-line-highlight' now have separate definitions for dark backgrounds. Previously, these two faces looked the same with both light and dark background modes. To get the previous visuals for these two faces, customize them to have the colors "grey75" and "grey40", respectively, regardless of the background mode. ```

``` New user option 'mode-line-collapse-minor-modes'. This is a new, built-in facility to hide minor mode lighters. If non-nil, minor mode lighters on the mode line are collapsed into a single button. The value can also be a list to specify minor mode lighters to hide or show. The default value is nil, which retains the previous behavior of showing all minor mode lighters. ```

One of my earliest articles was Hiding and replacing modeline strings with clean-mode-line. It’s been an issue as long as mode authors have had a say in how loud their mode line lighters should be.

Glad it is finally built in. No word on whether it plugs into `:delight` / `:diminish` in `use-package`.

``` New user option 'mode-line-modes-delimiters'. This option allows changing or removing the delimiters shown around the major mode and list of minor modes in the mode line. The default retains the existing behavior of using parentheses. ```

``` New minor mode 'mode-line-invisible-mode'. This minor mode makes the mode line of the current buffer invisible. The command 'mode-line-invisible-mode' toggles the visibility of the current-buffer's mode line. The default is to show the mode line of every buffer. ```

People do ask for this all the time, so it’s good to see a built in feature to do this instead of all the hacky tricks people got up to before.

``` The standard mode line no longer specifies minimum widths. The default values for the 'mode-line-position' variable and 'mode-line-format' user option no longer specify any minimum widths. If you use a proportional font for your mode line, you may need to customize the values of these variables to include minimum widths again. ```

Tab Bars and Tab Lines

Tab bars are window configurations you switch between; tab lines are like browser tabs that point to buffers in the window.

``` New commands 'split-tab' and 'merge-tabs'. 'split-tab' moves a specified number of windows from an existing tab to a newly created tab. 'merge-tabs' merges all windows from two tabs into one of these tabs, and closes the other. ```

``` New abnormal hook 'tab-bar-auto-width-functions'. This hook allows you to control which tab-bar tabs are auto-resized. ```

``` 'mouse-face' properties are now supported on the 'tab-bar'. 'tab-bar' tab buttons are now highlighted when the mouse pointer hovers over them. You can customize the new face 'tab-bar-tab-highlight'. ```

``` New abnormal hook 'tab-bar-post-undo-close-tab-functions'. This hook allows you to operate on a reopened tab.

This is useful when you define custom tab parameters that may need adjustment when a tab is restored, without resorting to advice. ```

I do actually end up closing tab bar tabs by mistake quite often. And it has had an undo feature `C-x t u` to fix screwups like that for a long time now.

``` Tabs are now closed upon releasing the middle mouse button. Previously, closing the tab-bar's tabs occurred upon pressing the button. ```

``` New user option 'tab-bar-define-keys'. This controls which key bindings tab-bar creates. Values are t, the default, which defines all keys and is backwards compatible, 'numeric' for tab number selection only, 'tab' for the 'TAB' and 'S-TAB' keys only, and nil for none.

This is useful to avoid key binding conflicts, such as when folding in outline mode using 'TAB' keys, or when a user wants to define her own tab-bar keys without first having to remove the defaults. ```

``` New variable 'tab-bar-format-tab-help-text-function'. This variable may be overridden with a user-provided function to customize the help text for tabs displayed on the tab-bar. Help text is normally shown in the echo area or via tooltips. See the variable's docstring for the arguments passed to a help-text function. ```

``` New variable 'tab-bar-truncate'. When non-nil, it truncates the tab bar, and therefore prevents wrapping and resizing the tab bar to more than one line. ```

``` New user option 'tab-line-define-keys'. When t, the default, it redefines window buffer switching keys such as 'C-x <LEFT>' and 'C-x <RIGHT>' to tab-line specific variants for switching tabs. ```

``` New command 'tab-line-move-tab-forward' ('C-x M-<RIGHT>'). Together with the new command 'tab-line-move-tab-backward' ('C-x M-<LEFT>'), it can be used to move the current tab on the tab line to a different position. ```

``` New command 'tab-line-close-other-tabs'. It is bound to the tab's context menu item "Close other tabs". ```

``` New user option 'tab-line-exclude-buffers'. This user option controls where 'tab-line-mode' should not be enabled in a buffer. The value must be a condition which is passed to 'buffer-match-p'. ```

``` New user option 'tab-line-close-modified-button-show'. With this user option, if non-nil (the default), the tab close button will change its appearance if the tab's selected buffer has been modified. ```

``` New user option 'tab-line-tabs-window-buffers-filter-function'. This user option controls which buffers should appear in the tab line. By default, this is set so as to not filter out any buffers. ```

Aha this is useful. One problem with tab line is that it’s quite indiscriminate; it won’t show hidden buffers by default (they start with a whitespace) obviously but it’s still a bit heavyhanded. Now you can at least limit what you see.

``` New faces 'tab-line-active' and 'tab-line-inactive'. These inherit from the 'tab-line' face, but the faces actually used on the tab lines are now these two: the selected window uses 'tab-line-active', and non-selected windows use 'tab-line-inactive'. ```

Help

`New binding 'C-h u' for 'apropos-user-option'.` ``` IDLWAVE has moved to GNU ELPA. The version included with Emacs is out-of-date, and is now marked as obsolete. Use 'list-packages' to install the 'idlwave' package from GNU ELPA instead. ```

``` New faces 'header-line-active' and 'header-line-inactive'. These inherit from the 'header-line' face, but the faces actually used on the header lines are now these two: the selected window uses 'header-line-active', and non-selected windows use 'header-line-inactive'. ```

Useful; header line is an immovable header that appears at the top of a window. It is commonly used for things like column headers in tables, as seen in `M-x list-packages`.

`In 'customize-face', the "Font family" attribute now supports completion.`

Heavenly manna indeed. I have long argued that all this complex futzing around with .Xresources, frame-setting faces and all manner of complicated ways of setting your default font is a bad habit and that `M-x customize-face RET default RET` is the simplest and most effective compared to the alternatives. Well, you don’t have to guess at the names of fonts any more! Emacs is finally capable of auto completing them. Excellent change.

``` 'process-adaptive-read-buffering' is now nil by default. Setting this variable to a non-nil value reduces performance and leads to wrong results in some cases. We believe that it is no longer useful; please contact us if you still need it for some reason. ```

Another toggle switch to maybe possibly potentially speed Emacs up a tad; it’s part of a growing list of these magic feature toggles that may or may not have adverse consequences down the road. I checked my Emacs and mine is set to nil. I do not recall why I set it to nil, nor can I remember when.

`'byte-compile-cond-use-jump-table' is now obsolete.` ``` Modified settings for an enabled theme now apply immediately. Evaluating a 'custom-theme-set-faces' or 'custom-theme-set-variables' call for an enabled theme causes the settings to apply immediately, without a need to re-load the theme. ```

``` 'describe-variable' now automatically says if 'setopt' is needed. If a user option has a defcustom ':set' function, users will normally need to set it with 'setopt' for it to take an effect. If the docstring doesn't already mention 'setopt', the 'describe-variable' command will now add a note about this automatically. ```

One of the greatest challenges in Emacs is convincing people - including yours truly - to stop using `setq` to bind values to global/customizable variables. Emacs’s customize system – defined as anything you can edit with `M-x customize` – supports edge triggers: code that runs when one of its variables change. It was once uncommon enough that nobody really had to worry; more and more things in Emacs lean into this system though.

The primary reason people use `setq` is that it just kinda-sorta works (notwithstanding the edge-trigger) but also because the proper way to set variables via customize’s machinery is `custom-set-variables` which is an obnoxious utility function that not only has a bad prefix namespace `custom` vs `customize` but also it’s just so damn long to type.

So nobody bothered to use it. Emacs 29.1 added `setopt` which automatically does all the heavy lifting and it’s a drop-in replacement for `setq`.

``` New user option 'eldoc-help-at-pt' to show help at point via ElDoc. When enabled, display the 'help-at-pt-kbd-string' via ElDoc. This setting is an alternative to 'help-at-pt-display-when-idle'. ```

Eldoc is Emacs’s help/document/code argument lookup system that actives when you move point around. It relies on a complex timing machinery to trigger the help. Forcing it to appear at point (even if that is nearly always your current point) is a great utility function. Now you can have eldoc without the timer: bind it to a key when you need it and off it goes.

``` New user option 'native-comp-async-on-battery-power'. Customize this to nil to disable starting new asynchronous native compilations while AC power is not connected. ```

Somewhere someone with a laptop more dinged-up than Zildjian cymbal lost their last 5% of battery to native comp and furiously decided to solve this problem once and for all.

``` New user option 'show-paren-not-in-comments-or-strings'. If this option is non-nil, it tells 'show-paren-mode' not to highlight parens inside comments and strings. If set to 'all', 'show-paren-mode' will never highlight parens that are inside comments or strings. If set to 'on-mismatch', mismatched parens inside comments and strings will not be highlighted. If set to nil (the default), highlight parens wherever they are. ```

Show paren of course is Emacs paren highlighter, though its name today is doing it a disservice as it is designed to highlight like terms like braces, string quotes or things like `begin` and `end` terms.

``` New user option 'view-lossage-auto-refresh'. If this option is non-nil, the lossage buffer of 'view-lossage' will be refreshed automatically for each new input keystroke and command invoked. ```

Lossage is `C-h l` and it reflects the last N number of typed keys in your Emacs. With auto-refresh enabled you can simulate basic version of those “keypress overlays” people use in streaming videos. Useful for gifs too!

``` Change in SVG foreground color handling. SVG images no longer have the 'fill' attribute set to the value of ':foreground' or the current text foreground color. The 'currentcolor' CSS attribute is still set, as before.

This change should result in more consistent display of SVG images.

To use the ':foreground' or current text color ensure the 'fill' attribute in the SVG is set to 'currentcolor', or set the image spec's ':css' value to 'svg {fill: currentcolor;}'. ```

``` Errors signaled by 'emacsclient' connections can now enter the debugger. If 'debug-on-error' is non-nil, errors signaled by Lisp programs executed by 'emacsclient' connections will now enter the Lisp debugger and show a backtrace. If 'debug-on-error' is nil, these errors will be sent to 'emacsclient', as before, and will be displayed on the terminal from which 'emacsclient' was invoked. ```

``` Empty string arguments to emacsclient are no longer ignored. Emacs previously discarded arguments to emacsclient of zero length, such as in 'emacsclient --eval "(length (pop server-eval-args-left))" ""'. These are no longer discarded. ```

Huh. That may have explained some weird issues I’ve run into calling evals into emacsclient over the years. I always just assumed I did something wrong!

``` Emacs now uses the 'setrgbf' and 'setrgbb' terminfo capabilities. Emacs now uses 24-bit colors on terminals that support the 'setrgbf' and 'setrgbb' user-defined terminfo capabilities. These are supported by more terminals and applications than the old capabilities, 'setf24' and 'setb24', which are now obsolete. ```

I’m not an expert on termcaps so I cannot say what these caps offer people, but Emacs already supports 24-bit if you did not know. In fact, you can just set the environment variable `COLORTERM=truecolor` to force Emacs to treat your terminal as 24-bit capable.

``` New user option 'xterm-update-cursor' to update cursor display on TTYs. When enabled, Emacs sends Xterm escape sequences on Xterm-compatible terminals to update the cursor's appearance. Emacs can update the cursor's shape and color. For example, if you use a purple bar cursor on graphical displays then when this option is enabled Emacs will use a purple bar cursor on compatible terminals as well. See the Info node "(emacs) Cursor Display" for more information. ```

Neat. The highlight of course being that Emacs has multiple cursor styles.