Files
roam/azosemacs.org
T
2026-10-11 00:08:44 +03:00

3.1 KiB

azos/emacs

Gotchas

  • async-shell-command spawns subprocesses with TERM=dumb and no real controlling tty (confirmed: no INSIDE_EMACS, pty exists but curses can't use it). Any gpg/pinentry prompt triggered from such a process (e.g. signed git commits) fails with "Inappropriate ioctl for device" once the pinentry PIN cache expires — pinentry-emacs mode silently isn't engaged either, since gpg only requests it when INSIDE_EMACS is set, which async-shell-command doesn't set (unlike M-x shell=/comint, which does). Fix: run the command in a real pty via =vterm instead (confirmed working — vterm-term-environment-variable is set to xterm-256color). Fixed in azos/roam/backup (features/lauretta/emacs/config.org) 2026-10-04.
  • A nix rebuild (azos-lauretta-update) only regenerates files on disk (e.g. config.org) — it never reloads anything into an already-running Emacs session. setq=/=defvar forms evaluated at startup (e.g. mu4e-contexts) stay stale until that exact top-level form is re-evaluated, e.g. via emacsclient -e '(load-file "/tmp/x.el")' on a file containing just that extracted sexp (match parens exactly — an off-by-one line range truncates the form and errors "End of file during parsing" instead of warning about staleness). Discovered via mu4e context drift, see azos/mail Gotchas for the full incident.
  • org-babel emacs-lisp source blocks evaluate with dynamic binding by default (ob-emacs-lisp.el defaults :lexical to "no"), and config.org sets no :lexical header anywhere (file-wide or per-block). This silently breaks closures in async code: a pattern like (let ((output "")) (make-process :filter (lambda (_p chunk) (setq output ...)) :sentinel (lambda (_p _e) ... output ...))) fails because the let-bound output unwinds before the async filter/sentinel callbacks run — they don't lexically close over it. The failure is silent: errors like "Symbol's value as variable is void: output" only appear in *Messages*, not as visible UI errors, and whatever the sentinel was supposed to set (e.g. elfeed-feeds) just stays nil. This hit the elfeed-protocol Nextcloud News auth block (fetches a pass(1) password asynchronously via make-process to avoid blocking Emacs's command loop and deadlocking with pinentry-emacs, then sets elfeed-feeds from the sentinel) — elfeed-update appeared to "do nothing" because of this exact bug. Fix/convention: for any async Emacs Lisp in this repo's org-babel blocks (process filters/sentinels, timers, callbacks) that needs to carry state across the async boundary, don't rely on closures over let-bound locals unless the block explicitly sets :lexical yes. Instead store state on the process object itself via process-put=/=process-get (works regardless of lexical/dynamic binding) — this is the pattern now used in the elfeed-protocol block. Fixed in features/lauretta/emacs/config.org (Elfeed Nextcloud News Sync section) 2026-10-05.

azos