summaryrefslogtreecommitdiff
path: root/personal/itches.md
blob: 0851ff33a1e63bddc68287f86e6545b2993d92c0 (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
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
# Emacs

- center/top point when
    - moving to text/tag search hit
    - going to man page section
    - opening eww on an anchor
    - visiting a function from its Help buffer
- make font-lock stop background at fill-column or max(len(line) for
  line in paragraph) rather than window-width when text spans >1 lines
- shell-mode
    - add faces instead of reusing font-lock-{comment,string}
    - understand `autocd` and `cd !$`
    - use Bash completions (e.g. `ls TAB` in a folder with one file)
- [.dir-locals changed priorities][bug#30008] between subfolder and
  major mode from 25 to 26
- eshell: `ls --group-directories-first` does not color folders
- emoji support
- eww, gnus-article: adapt filling to window width changes
- scroll-lock-mode
    - cursor stuck on lines wrapped by visual-line-mode
    - cursor stuck on lines with 😛
    - scroll when going down newline with forward-…
- matching-paren analysis fails: `;; (here is\n;; a comment)`
- some modes redefine C-M-h, which makes this binding hard to
  override; could mark-defun consult functions/values exposed by major
  modes instead?
- make ellipses for "invisible" text easily customizable (src/xdisp.c)
- Man-mode: make isearch skip end-of-line hyphens
- whitespace-mode: skip line/wrap-prefix variables and properties
- when opening `.gpg` files in a TTY, some characters (e.g. TAB) are
  swallowed by Emacs instead of being forwarded to the gpg prompt;
  these characters are then inserted in the decrypted file's buffer
  (see `epa-file-insert-file-contents`)
- let TRAMP fetch Google Drive credentials from .authinfo.gpg
- icomplete's C-j does not choose the first completion as advertised
  on empty input; it chooses ".", which AFAICT comes from the fact
  that icomplete-exhibit calls completion-pcm--filename-try-filter
  while icomplete-force-complete-and-exit simply calls
  minibuffer-force-complete-and-exit
    - likewise, if a folder contains foo.c and foo.o, "C-x C-f foo"
      hides foo.o, yet C-j completes to foo.o
- calendar uses default X resources when run in its own frame; see
  `calendar-frame-parameters`, `x-handle-named-frame-geometry`,
  `(make-frame '((name . "")))` vs `(make-frame '((title . "")))`
- use compilation-mode-line-… faces for compilation-num-… indicators
- "é" is not erased with a single DEL stroke, despite [Unicode
  conventions]
- sort tar archive members by name; serving suggestion:

    ``` elisp
    (defun my/tar-sort (info)
      (sort info (lambda (a b) (string< (tar-header-name a) (tar-header-name b)))))
    ;; Apply to tar-parse-info in tar-summarize-buffer.
    ```

- add a command or minor mode to highlight marks; serving suggestion:

    ``` elisp
    (save-excursion
      (dolist (m mark-ring)
        (goto-char (marker-position m))
        (pulse-momentary-highlight-region (point) (point-at-eol))
        (sit-for 0.1)))
    ```

- StackOverflow-like suggestions when reporting bugs
- match data vs. `:eval` during redisplay: cf. [bug#31586]

[bug#30008]: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=30008
[bug#31586]: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=31586
[Unicode conventions]: https://lists.gnu.org/archive/html/emacs-devel/2018-07/msg00961.html

## Make " Narrow" lighter customizable

The " Narrow" string comes from `src/xdisp.c:decode_mode_spec`:

``` c
case 'n':
  if (BUF_BEGV (b) > BUF_BEG (b) || BUF_ZV (b) < BUF_Z (b))
    return " Narrow";
```

This is probably just a matter of returning the contents of a Lisp
variable instead of this constant string.

TODO:

1. get the string value of a variable in C
2. define a customizable string variable
3. write a news entry
4. write a patch
5. extra credits: display string properties

### Get the string value of a variable in C

`decode_mode_spec` has some relevant snippets:

- Given a `Lisp_Object obj`, `SSDATA(obj)` gives the string value as a
  `char*`.

- How to get a variable's `Lisp_Object`?
    - `BVAR` works for buffer-local variables
    - `V${lispname//-/_}`

### Define a customizable string variable

#### Defining variables visible to C code

The C macro `DEFVAR_LISP(string-name, field-name)` does the following:

    define a static `Lisp_Objfwd` variable v
    get the address of globals._f##field-name &f

    defvar_lisp(v, string-name, &f)

As explained in the comments above `DEFVAR_LISP`, `globals` is a
global variable defined in `globals.h`, which is "auto-generated by
make-docfile" and exposes fields, `#define`s and `Lisp_Object`s for
every global variable.

make-docfile (`lib-src/make-docfile.c`) takes C files as input and
searches all occurences of `^ +DEFSYM[ \t(]`, `^ +DEFVAR_[ILB]` or
`^DEFU`, analyses what comes after and generates appropriate
definitions for `globals.h`.

`defvar_lisp` allocates a symbol using `Fmake_symbol`.

#### Making it customizable

`lisp/cus-start.el` defines customizable properties of symbols defined
by C code.

AFAICT, there is no need to assign the default value right after
defining the variable with `DEFVAR_LISP`: e.g. `shell-file-name` is
`DEFVAR_LISP`ed in `src/callproc.c` and its default value is set in…
Mmm.  Not in `cus-start.el`.  There is this snippet in
`callproc.c:init_callproc`:

  ``` c
sh = getenv ("SHELL");
Vshell_file_name = build_string (sh ? sh : "/bin/sh");
  ```

But when starting with `SHELL=rofl emacs -Q`, Custom says that the
value "has been changed outside Customize".  Changed from what to
what?

`cus-start.el` may contain a hint:

``` elisp
;; Elements of this list have the form:
;; …
;; REST is a set of :KEYWORD VALUE pairs.  Accepted :KEYWORDs are:
;; :standard - standard value for SYMBOL (else use current value)
;; …
```

Except that nope, this does not work.  Giving `:standard " Narrow"`
and looking at the variable in Custom yields

    narrow-lighter: nil
        [State]: CHANGED outside Customize. (mismatch)

A better example might be `overlay-arrow-string`, whose default value
is set right after `DEFVAR_LISP` by calling `build_pure_c_string`.

Why `build_pure_c_string` and not `build_string`?  From "(elisp) Pure
Storage":

> Emacs Lisp uses two kinds of storage for user-created Lisp objects:
> “normal storage” and “pure storage”.  Normal storage is where all
> the new data created during an Emacs session are kept (see Garbage
> Collection).  Pure storage is used for certain data in the preloaded
> standard Lisp files—data that should never change during actual use
> of Emacs.
>
> Pure storage is allocated only while ‘temacs’ is loading the
> standard preloaded Lisp libraries.  In the file ‘emacs’, it is
> marked as read-only (on operating systems that permit this), so that
> the memory space can be shared by all the Emacs jobs running on the
> machine at once.

"(elisp) Building Emacs" explains that "temacs" is the minimal Elisp
interpreter built by compiling all C files in `src/`; temacs then
loads Elisp sources and creates the "emacs" executable by dumping its
current state into a file.

### Debug stuff

#### Unicode characters represented as octal sequences

Trying to customize the new variable to any string with non-ASCII
characters fails: they show up as sequences of backslash-octal codes.
For some reason they show up fine in the Help and Custom buffers.

Things to investigate:

1. Should the `Lisp_Object` be created with something other than
   `build_pure_c_string`? 🙅
2. What does the code calling `decode_mode_spec` do with the returned
   string? **🎉**
3. (Does `SSDATA` make some transformation before returning the
   string? 🤷)
4. (Should a specialized Custom setter be defined? 🤷)

##### Should the `Lisp_Object` be created with something other than    `build_pure_c_string`?

Maybe this would work?

``` c
Vnarrow_lighter = make_multibyte_string(" Narrow", strlen(" Narrow"),
                                        strlen(" Narrow)");
```

That looks too ugly though, let's try something else.

Maybe `STRING_SET_MULTIBYTE(Vnarrow_lighter)` would help?

*compiles and tries*

… Nope, it does not.

##### What does the code calling `decode_mode_spec` do with the returned string?

``` c
spec = decode_mode_spec (it->w, c, field, &string);
multibyte = STRINGP (string) && STRING_MULTIBYTE (string);
```

*slowly turns around*

*finds `string` standing right there with a blank stare*

Gah!  How long have you been there?

``` c
/* Return a string for the output of a mode line %-spec for window W,
   generated by character C.  […]  Return a Lisp string in
   *STRING if the resulting string is taken from that Lisp string.
   […] */
static const char *
decode_mode_spec (struct window *w, register int c, int field_width,
                  Lisp_Object *string)
{
  Lisp_Object obj;
  /* … */
  obj = Qnil;
  *string = Qnil;

  switch (c)
    {
    /* … */
    }

  if (STRINGP (obj))
    {
      *string = obj;
      return SSDATA (obj);
    }
  else
    return "";
}
```

Alright then:

``` c
case 'n':
  if (BUF_BEGV (b) > BUF_BEG (b) || BUF_ZV (b) < BUF_Z (b))
      obj = Vnarrow_lighter;
  break;
```

#### Why do string properties not show up?

🤷

### Extra credit

Maybe it would be simpler to have the narrowing lighter work like the
" Compiling" lighter (cf. `compilation-in-progress` variable), i.e. adding an entry to `minor-mode-alist`.

## Better out-of-the-box display for FORM FEED

By default, FORM FEED is displayed as a dumb `^L` glyph.  This is
surprising considering it shows up in so many places: Emacs source
files, help buffers (e.g. `describe-mode`)…  You can even see it in
source files of other GNU projects, like GCC.

"Pages" are important enough to have their own navigation and
narrowing commands, yet their default delimiter is displayed as an
unassuming control character.

I like [`page-break-lines`]'s approach; having this kind of display by
default would make it more obvious that this character serves an
actual purpose.  As it stands, it looks no different from some stray
CARRIAGE RETURN.

This could be re-used by e.g.:

- `describe-symbol`, which uses the following ~~method~~ hack to
  visually break up multiple symbol definitions:

  ``` lisp
  (insert "\n\n"
          (eval-when-compile
            (propertize "\n" 'face '(:height 0.1 :inverse-video t)))
          "\n")
  ```

- Custom buffers, where sections are delimited visually with a
  999-character wide underlined space.

Full disclosure
:   This reflection started because moving over this underlined space
    with `truncate-lines` on causes the screen to jump horizontally.
    This specific problem should be fixable without dragging FORM FEED
    display into the discussion, but I feel like the latter is the
    more interesting issue ([who on Earth] enables `truncate-lines` by
    default anyway).

[`page-break-lines`]: https://github.com/purcell/page-break-lines
[who on Earth]: https://gitlab.com/peniblec/dotfiles/blob/master/.emacs-custom.el

## ERC

- move timestamp to a better position (see `stamp` module)
- play well with whitespace-mode

## Org

- dissociate sub- and super-script fontification from everything else
  in org-toggle-pretty-entities

- org-clocktable trips on DST:

    ``` org
    #+BEGIN: clocktable :scope file :maxlevel 2 :step day :stepskip0 t :tstart "[2018-10-15]" :tend "[2018-11-15]"
    #+END:

    * foo
    :LOGBOOK:
    CLOCK: [2018-10-26 Fri 08:00]--[2018-10-26 Fri 17:00] =>  9:00
    :END:

    * bar
    :LOGBOOK:
    CLOCK: [2018-10-29 Mon 08:00]--[2018-10-29 Mon 17:00] =>  9:00
    :END:
    ```

## Language support

- fix builtin/keyword distinction for Bash & Python3

## read-passwd

- prevent kills from ending up in the clipboard
- add command to temporarily reveal password

## External libraries

### adaptive-wrap

- whitespace-mode highlights the adaptive-wrap prefix (although
  weirdly enough the whitespace faces are not applied); I'd rather the
  extra space stayed unadorned.

- a commented-out line with no space between the comment delimite and
  its text will get padded with the comment delimiter:

        ;(some very long line)
        ;; ⇒ wrapped with adaptive-wrap-extra-indent set to 4:
        ;(some very
        ;;;;;long line)

### magit

- customize current-tag function so that one can add `--first-parent`
- prevent section highlight overlay from hiding tag face background
- fix copy-pasted docstring for magit-diff-context-highlight
- figure out why magit-blame-echo does not echo

### markdown-mode

- support [shortcut reference links]
- move point past header after C-c C-t !/@
- update sub-superscript regex to allow L~i+1~
- make justification work with indented blockquotes
- add "ini ↦ conf-mode" to markdown-code-lang-modes

[shortcut reference links]: http://spec.commonmark.org/0.27/#shortcut-reference-link

### rg-mode

- make -project DTRT in dired

### page-break-lines

- borked in magit-diff

### diff-hl

- colored fringe line is discontinued on lines featuring faces with
  heights greater than 1

  ``` shell
  $ git init
  $ echo "* foo" > README.org
  $ git add README.org ; git commit -m README.org README.org
  $ echo "* bar" >> README.org
  $ echo "* baz" >> README.org
  ```

  ``` elisp
  (load-file "…/diff-hl.el")
  (global-diff-hl-mode)
  (set-face-attribute 'org-level-1 nil :height 1.2)
  (find-file "README.org")
  ```

# XFCE

- xfwm: hide/remove titlebar/decorations

# Spell checkers

- update dictionaries?

# Conky

Cannot use `${eval $${somefunc ${gw_iface}}}` more than once:

    conky.text = [[
    ${eval ${gw_iface}}
    ${eval ${gw_iface}}
    ]]
    ⇒
    wlp20
    (null)

See [GitHub issue](https://github.com/brndnmtthws/conky/issues/461).

# Bunsenlabs

- use https for sources.list files
- manpages for bl-… utilities