Emacs's NEWS files are useful as a searchable reference, but they can
be overwhelming as an entry point to a new release. In this file, I'm
keeping track of the changes /I/ am excited about.
* (Cooking)
Not merged yet; still excited about it.
** UI
*** Cursor
**** ~cursor-indicators-mode~ (bug#77224)
Change cursor style depending on arbitrary predicates. Might finally
stop me from activating repeat maps by accident.
* 31
** Applications
*** Dired
**** kill project-relative filename
With =C-u 1 w=.
*** grep
**** Editable =*grep*= buffers (bug#70820)
- =e= to start editing
- =C-c C-c= to apply
** Editing
*** DWIM =C-w= (bug#69097)
=kill-region-dwim= tells =C-w= what to do when the region is inactive:
- By default, kill the region anyway as long it exists, i.e. the mark
is set; in other words, kill the region revealed by =C-x C-x=.
- Otherwise kill "a word" backward.
The option can be set to kill either [[info:emacs#Words][an Emacs word]] (major-mode
dependant) or a [[info:readline#Commands For Killing][readline word]] (whitespace-separated).
** Elisp
*** So long /pure storage/ 🫡
This release does away with pure space, removing one of these subtle
bits of [[info:elisp#GNU Emacs Internals][{{{eldritch(the Internals)}}}]] that I usually ignore while
noodling in the Lisp Happy Lands of Immediate Feedback, and get
reminded of either when ~make bootstrap~ tuts at my patch, or when a
reviewer does 🫤
Nice that we no longer need to figure out which strings to ~purecopy~,
that we can always use ~define-key~ and forget about
~bindings--define-key~, that ~defconst~ no longer causes pure-copying
hazards…
** Programming
*** tree-sitter
**** Finer sexp movement (bug#73404, bug#76676)
Sexp commands no longer "overshoot" in tree-sitter modes. For
example, in previous releases, invoking =C-M-f= in c-ts-mode with
point…
- at the start of a function definition: point would jump to the end
of the function (redundant with =C-M-e=),
- at the start of a statement: point would jump to the end of the
statement (redundant with =M-e=).
Now:
- tree-sitter modes can opt into the more familiar "atom"-based
movement - in c-ts-mode, stopping over each identifier or keyword,
still leaping over delimiter pairs (=([{}])=), by defining a =list=
element in =treesit-thing-settings=.
- users can invoke ~treesit-cycle-sexp-type~ to make =C-M= commands
act on "treesit nodes" vs "syntax symbols".
** UI
*** Completion
**** ~completion-eager-display~
**** ~completion-pcm-leading-wildcard~
**** ~completion-styles~ bindings
- to set completion-ignore-case
*** Input
**** =repeat-continue=
Users can tell ~repeat-mode~ that some commands should not interrupt
repeat maps:
#+begin_src elisp
;; Allow C-l in the middle of a repeating sequence. Useful when
;; e.g. `next-error' shows point at the bottom of the window, and
;; recentering to the top will show more context that will let me
;; decide whether to keep searching or not.
(put 'recenter-top-bottom 'repeat-continue t)
#+end_src
Other ways to set the property:
- ~use-package~'s =:continue-only= keyword;
- ~defvar-keymap~'s =:continue= keyword.
*** Windows
**** New window layout commands (=window-x.el=)
Looking forward to ~flip~ and ~rotate~ and ~transpose~ 🫨
**** =split-window-preferred-direction=
By default, when splits are possible in either direction according to
=split-{height,width}-threshold=, Emacs is biased toward splitting
vertically. Setting this new option to ='longest= reduces that bias
by making Emacs consider the window layout: "landscape" windows (such
as a single window in a maximized frame) will be split horizontally.
* 30
** =:core= promotions
*** visual-wrap (was adaptive-wrap): soft & mode-sensitive wrap prefixes
This package enhances the way Emacs displays continuation lines.
Unpacking that word salad of a heading:
- wrap prefixes :: strings that Emacs prepends to continuation lines;
- soft :: these strings are intangible decoration, not actual buffer
content;
- mode-sensitive :: leverages the mode's [[info:emacs#Adaptive Fill][adaptive-fill settings]] to
determine the "proper" prefix, i.e. the same prefix you would get by
hard-wrapping with =M-q=.
*** which-key: key binding discovery (bug#68929)
** Applications
*** ERC
**** ~visual-line-mode~ integration
In previous versions, I would take =fill= off ~erc-modules~ and enable
~visual-line-mode~ in order to get reflowable windows; this would [[file:~/memory-leaks/itches/emacs/tracker.org::*+Make timestamps robust vs window width changes+][mess
with right-aligned timestamps]], however.
As of ERC 5.6, setting ~erc-fill-function~ to ~'erc-fill-wrap~ enables
~visual-line-mode~ and sets up all sorts of =line-prefix=,
=wrap-prefix= & margin trickery to (a) align nicks and messages (b)
make messages reflowable (c) keep timestamps firmly stuck to the right
margin.
*** shr
**** ~shr-fill-text~
Set to nil to completely disable shr's line-wrapping. This lets users
leverage ~visual-line-mode~ to get all the benefits of
display-engine-backed wrapping: text is reflowed on the fly as windows
are resized or text is rescaled.
Tables still use rigid wrapping though; this can be circumvented by
remapping =
= tags:
#+begin_src elisp
(pcase-dolist (`(,tag . ,shr-function)
'((table . shr-tag-div)
(thead . shr-tag-div)
(tbody . shr-tag-div)
(tr . shr-tag-ul)
(th . shr-tag-li)
(td . shr-tag-li)))
(setf (alist-get tag shr-external-rendering-functions) shr-function))
#+end_src
Eww automatically enables ~visual-line-mode~ when it detects that
~shr-fill-text~ is =nil=; Gnus does not yet, and so requires some
hand-holding to take full-advantage of ~visual-line-mode~:
#+begin_src elisp
;; Enable visual-line-mode after rendering an article:
(add-hook 'gnus-article-prepare-hook 'visual-line-mode)
;; This is to go e v e n f u r t h e r b e y o n d.
(setopt
;; Never hard-wrap any lines.
gnus-treat-fill-article nil
gnus-treat-fill-long-lines nil
;; Re-assemble headers into a single line.
gnus-article-unfold-long-headers t
gnus-treat-fold-headers nil
;; Unfurl format=flowed emails by "filling" them to an absurd width.
fill-flowed-display-column most-positive-fixnum
mm-fill-flowed t)
#+end_src
** Programming
*** imenu
**** bug#70846 imenu-flatten
See also emacs-devel: for follow-up
work to make completions preserve text properties, allowing
~completing-read~ callers to distinguish multiple candidates with the
same string value.
*** tags
**** ~etags-regen-mode~
Not sure how straightforward it is to set up for complex projects,
e.g. binutils-gdb where ~make TAGS~ generates TAGS files in multiple
subdirectories, and one source file uses symbols from multiple TAGS
files.
Sounds useful though.
** UI
*** Completion
**** ~completion-preview-mode~
*** Customization
**** ~customize-toggle-option~
*** Minibuffer
**** ~read-passwd-toggle-visibility~
*** Outline
**** bug#49731 outline-{show,hide}-by-heading-regexp
**** bug#68824 tree-sitter integration
**** bug#69305 buffer-menu & tabulated-list-mode integration
*** Windows
**** ~toggle-window-dedicated~ (=C-x w d=)
Matches my "opportunistic" window "management" perfectly; I generally
do not mind Emacs popping buffers left and right, but on occasion I'll
be…
- working on window (a),
- about to run a command 𝒳 that shows results in another window,
- having a window (b) displaying notes I want to keep visible,
- having a window (c) I consider disposable,
But 𝒳 would clobber (b) to display its results. Being able to
"freeze" (b) and ensure commands in (a) dump their results in (c) is
neat. =M-: (set-window-dedicated-p nil t)= is a thing I've actually
run on occasion.
Also, the mode-line indicator has the nice side-effect of making the
behavior of rigid interfaces à la ~gdb-many-windows~ less suprising.
* 29
** =:core= promotions
A couple of ELPA packages have moved to emacs.git, making them
available out of the box.
*** eglot ("Emacs Polyglot"): LSP client
Lets Emacs leverage language servers to boost completion-at-point,
eldoc, flymake, imenu, project, xref.
*** use-package: init-file management
A utility macro for configuring packages that makes init-file
management more pleasant (and efficient to boot):
- OT1H, brings some amount of structure and order when compared to a
fully free-form DYI =.emacs=,
- OTOH, allows more leeway on how to organize things, when compared to
Custom's rigid auto-generated forms (e.g. using regular code
comments, computing option values, sorting options arbitrarily),
- takes care of setting up the ~eval-after-load~ wizardry to keep
startup snappy.
A tedious aspect of porting a ~custom-file~ to ~use-package~
declarations is tracking down what package defines which variables,
since not every variable is named after the package it belongs to.
I wrote [[file:~/memory-leaks/guides/emacs/use-package.org::*Porting from ~custom-file~][some code to make the process faster]].
** Elisp
*** ~setopt~ sets variables and runs their Custom setters
** Programming
*** eglot
**** better composition of doc & lint messages
Eglot now sets ~eldoc-documentation-strategy~ to
~eldoc-documentation-compose~, so linter warnings are no longer hidden
by symbol documentation.
It used to be that a flymake warning would flash briefly in the echo
area before e.g. a function signature would clobber it and I would
have to resort to ~M-x flymake-show-buffer-diagnostics~, but no
longer: Eglot now sets things up so that both are visible in the echo
area.
*** imenu
**** now bound to =M-g i=
Turns out that lots of modes define an imenu.
*** Languages
*** Python
**** ~python-indent-def-block-scale~
Bumping that new option down to =1= ensures =python.el= and I remain
on good terms whenever I open lines inside parentheses.
** UI
*** Buffers
**** ~rename-visited-file~
Instead of =C-x C-w NEWNAME RET M-! rm OLDNAME RET=.
*** Fonts
**** ~global-text-scale-adjust~
~text-scale-adjust~ (bound to =C-x C-X= ∀ =X= ∈ =[=+-0]=) only scales
the font size in the current buffer; more often than not, one may want
to increase the default font size everywhere (e.g. when projecting
their screen).
To that end, users had to =M-x customize-face RET default= or =M-:=
~(set-face-attribute 'default nil :height …)~; now they can use the
new =C-x C-M-X= bindings to invoke ~global-text-scale-adjust~.
*** Outline
**** "fold hints" for outlines
~outline-minor-mode-use-buttons~ can be set to either
- =in-margins=: magit-section-like indicators,
- =t=: in-buffer buttons.
Initially the latter used arguably "garish" color emoji; with the
addition of the =icons.el= library, the way these buttons are
displayed can now be controlled with ~icon-preference~, which defaults
to more sober SVG images.
*** Windows
**** ~split-root-window-{below,right}~
E.g. when you already have a vertical split, and you'd like to spawn a
full-height window to the side (instead of splitting either the top or
bottom window horizontally and keeping the other full-width).
Been missing this in both Emacs and Terminator; glad Emacs now has a
solution.
Part of the new window keymap on =C-x w=.
** Honorable mentions
These have me excited too, but I have nits to pick with the current
incarnation.
*** "Pure GTK" Emacs
Some brave souls took it upon themselves to drag Emacs kicking and
screaming into The Wayland Future™: "pure GTK" means that Emacs will
only rely on GTK APIs, instead of a mix of GTK and X.
Try it out by giving =--with-pgtk= to =./configure=. One caveat is
that GTK input methods… [[https://debbugs.gnu.org/56653][eat modifiers]] or something? E.g. =S-SPC=
degrades to =SPC=. Apparently Emacs users are the only ones to care
about that? 🤷
Note 1: this problem can be reproduced on the X+GTK build by setting
~x-gtk-use-native-input~.
Note 2: debugging notes in [[file:~/memory-leaks/itches/emacs/tracker.org::*bug:56653][this itches tracker entry]].
Note 3: The Wayland Future™ seems more tolerant of X+GTK builds than I
anticipated, thanks to Xwayland.
*** ~pixel-scroll-precision-mode~
Setting that minor mode with ~pixel-scroll-precision-interpolate-page~
makes =PageUp= and =PageDown= much smoother. Would love for =M-v= and
=C-v= to use that as well… Heck, would love for all scrolling,
jumping and recentering commands to use that.
*** Picking completions from the minibuffer
=M-= and =M-= in the minibuffer cycle through completion
candidates. Would love for these to have non-arrow bindings
(e.g. =C-c C-[pn]= with a repeat map?).
Unsetting ~minibuffer-completion-auto-choose~ also lets the user
choose when to insert candidates in the minibuffer: =C-u M-RET= to
just insert, or =M-RET= to insert and immediately exit the minibuffer.
*** =C-x 8 e= keymap to search & insert emoji
Less hassle than =C-x 8 RET err what was the name again=, especially
for composed emoji 😵💫
Uses transient 👍 but relies on auto-generated, non-mnemonic =a-z=
suffixes to pick gender/color variations 👎 rather than taking
advantage of transient prefixes (e.g. =-g= for gender and =-s= for
skin tone), which
1. don't add an unecessary step for the common "ungendered Lego" case,
2. can remember a user's preferred values with ~transient-save~.
Upstream considers this idea "[[https://yhetil.org/emacs-devel/87ilxfx1ku.fsf@gnus.org/][fraught politically]]" 🤷
Others agree it would be [[https://yhetil.org/emacs-devel/87r1bx9pwo.fsf@bernoul.li/][nice-to-have, though not must-have]]; maybe
I'll take a stab at implementing it (making it opt-in, keeping the
alphabetical suffixes by default).
* 28
** Applications
*** Dired
**** ~dired-kill-when-opening-new-dired-buffer~
With this option, =RET= and =^= no longer make Dired buffers pile up 🎉
Previously, =a= (~dired-find-alternate-file~) could be used instead of
=RET=, but one had to write a custom command for =^=.
*** Gnus
**** =#= now toggles the process mark by default
No need for =M-#= anymore.
** Editing
*** Transient input methods
**** Background
Input methods make it easier to type in certain classes of characters.
Emacs includes different kinds of methods:
- alternative keyboard layouts :: if you are familiar with specific
layouts, e.g. Dvorak, French AZERTY, Russian, you can ask Emacs to
switch to this layout;
- composition :: some methods let you specify characters by typing in
short sequences of other symbols:
- =french-prefix= provides easy access to diacritics with e.g. ='e=
for =é=, =,c= for =ç=;
- =TeX= turns TeX macros such as =\alpha=, =\pi=, =\le=, =\ne=,
=\wedge= into their corresponding characters, i.e. α, π, ≤, ≠, ∧.
Input methods can be toggled with =C-\=; prefix that with =C-u= to
select a new method. =C-h I = shows what characters
== supports. =C-u C-x == on a character tells you how to
input that character with the current input method ("to input: …").
**** What's new
The new =C-x \= command enables an input method temporarily, just for
the next character, and disables it afterward.
As an occasional user of the =TeX= method, I find this useful because
I no longer need to choose between
1. enabling =TeX=, typing a sequence, disabling =TeX=, or
2. enabling =TeX=, typing a sequence, keeping =TeX= enabled, getting
bitten by it whenever I type in =oh_no= and that turns into =ohₙo=.
=C-x \= seems to follow the same rules as =C-\=:
- the first time you call it, it prompts for a method,
- subsequent calls do not prompt,
- add =C-u= to get a prompt back.
*** ~yank-from-kill-ring~
I've always been somewhat ambivalent about Emacs's ~kill-ring~:
1. Everything I ever copied is saved forever! This is a revolutionary
feature on par with the undo system 🙌
2. … Surely we can find a more ergonomic UI than =C-y M-y M-y M-y=
/dammit/ =C-_ C-_= /ah screw it/ =C-h v kill-ring RET C-s= 🤔
And lo! =M-y= now prompts for the ~kill-ring~ item to yank, with
completion. This makes the ~kill-ring~ much more accessible IMO.
** Elisp
*** New commands for ~describe-{function,variable}~:
- =c= :: for variables, bring up the *Customize* UI,
- =i= :: bring up the relevant *Info* page,
- =s= :: jump to the *source* definition.
*** ~shortdoc-display-group~
Concise reference docs for specific topics.
** UI
*** Input
**** ~repeat-mode~
=C-x o o o=!
*** Minibuffer
**** ~completions-group~, ~read-char-by-name-sort~
Some very welcome quality-of-life tweaks to =C-x 8 RET=.
**** Vertical icomplete
***** Settings
- ~completions-detailed~
- ~icomplete-scroll~
- ~icomplete-vertical-mode~
***** Advantages over plain icomplete
- annotations
- completion candidates are easier to tell apart
- =C-n= and =C-p= (=C-.= is awkward on AZERTY)
***** Advantages over Ivy and Vertico
- regular minibuffer bindings work:
- =SPC= completes
- =RET= yields current input, disregarding completion candidates
- =C-j= yields selected completion candidate
- regular icomplete bindings work:
- =C-M-i= inserts selected completion candidate
*** Outline
**** ~describe-bindings~ integration
~describe-bindings-outline~ makes =C-h b='s output less overwhelming.
**** Visibility-cycling with =TAB= in outline.el
=TAB= and =S-TAB= now work in Outline mode like they do in Org. Look
at e.g. NEWS (=C-h N=) to see them in action. Customize
~outline-minor-mode-cycle~ to enable this in ~outline-minor-mode~.
One small, /tiny/ step toward chipping good features out of Org in
order to generalize them.
*** Tabs
For a long time I did not bother to check out the new tab bar, since I
did not expect to find a way to make tabs work in my rather byzantine
buffer management.
Then one day I started playing with the =C-x t= prefix on a whim, and
I was surprised by how much mileage I got out of forking off to a new
tab in order to "tuck away" the current window layout.
*** Windows
**** ~same-window-prefix~, ~other-window-prefix~, ~other-frame-prefix~
The rules which govern how Emacs manages windows are beyond my
reckoning. I know [[https://protesilaos.com/codelog/2020-01-07-emacs-display-buffer/][it is possible to tame them]] with patience and
discipline; still, these new commands appeal to my humble caveman
brain.
Assuming the command run by key sequence =KEYSEQ= will display its own
buffer =BUF=,
- =C-x 4 1 KEYSEQ= says "please display =BUF= right here, in this
window";
- =C-x 4 4 KEYSEQ= says "please display =BUF= in another window";
- =C-x 5 5 KEYSEQ= says "please display =BUF= in another frame".
These new ~other-…-prefix~ commands can be seen as generalizations of
specialized shorthands such as =C-x 4 f= or =C-x 5 b=.
* 27
** UI
*** Inspection
**** ~what-cursor-show-names~
I sometimes use =C-u C-x == to (re)discover how the Unicode consortium
decided some character should be called; having plain =C-x == give me
that information without popping an extra buffer is neat.