summaryrefslogtreecommitdiff
path: root/reviews/emacs/hype.org
blob: 0ec1bcff166bf8bd7948a5f84164089a5300bf89 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
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.
* 31
** Applications
*** 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).
** UI
*** Completion
**** ~completion-eager-display~
**** ~completion-pcm-leading-wildcard~
**** ~completion-styles~ bindings
- to set completion-ignore-case
* 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 =<table>= 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:<m1bk5adq1z.fsf@eshelyaron.com> 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-<up>= and =M-<down>= 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 <METHOD>= shows what characters
=<METHOD>= 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.