Emacs Settings
Table of Contents
This page lists the Emacs variables you can change to adjust how Emanix behaves, with their defaults. It is for someone who has a consuming flake and wants a different status-bar rhythm, font or buffer group without patching the distribution.
These are Emacs variables, not Nix options. For the emanix.* options, see
Options.
1. Where to set them
Emacs loads ~/.config/emacs/personal.el last, after the distribution's
config.el, so a setting there overrides the default. Your consuming flake
writes that file through Home Manager. A missing file is ignored. An error in it
is logged and never stops the desktop from starting.
;; ~/.config/emacs/personal.el (setq emanix/modeline-threshold 50) (setq emanix-prose-width 100)
Each variable below is one of two kinds, and the kind decides how you set it:
- A
defcustomhas a type and works withsetq, withM-x customize-variableand with.dir-locals.el. - A
defvaris a plain variable. Usesetq, oradd-to-listfor a list.customizedoes not know it.
Know when a variable is read. Some are read on every use and take effect at once. Others are read once, when a mode turns on, and need a restart of that mode. The tables say which.
2. Status bar
EWM has no status bar, so Emacs draws one in the tab bar: volume, wifi, cpu, ram,
gpu, any segments you add, the clock and the battery. Everything but volume reads
/sys or /proc, so nothing forks at the render rate.
| Variable | Default | Kind | Meaning |
|---|---|---|---|
emanix/modeline-interval |
3 |
defcustom, integer | Seconds between refreshes of the bar. Every segment this timer drives reads sysfs or procfs; do not put a subprocess on it |
emanix/modeline-probe-interval |
15 |
defcustom, integer | Seconds between volume probes. Volume is the one segment that needs a subprocess (wpctl), and under EWM each subprocess also costs an activation token and a journal line. It changes only when you turn a knob, so it polls on its own slow timer |
emanix/modeline-threshold |
25 |
defcustom, integer | The cpu, ram and gpu segments appear only while their value is above this percent |
emanix/modeline-battery-hide-capacity |
99 |
defcustom, integer | The battery segment is hidden at or above this capacity when the battery is neither charging nor discharging. While it charges or discharges, it always shows |
emanix/modeline-extra-segments |
nil |
defcustom, list of functions | The consumer extension point. Each function takes no arguments and returns a string, or nil to show nothing. Segments draw after gpu and before the clock, so the clock and the battery stay at the right-hand end |
The two intervals are read when the mode turns on. emanix/modeline-mode is
already on when personal.el loads, so a setq of either interval changes
nothing until you restart the mode:
(setq emanix/modeline-interval 5) (emanix/modeline-mode -1) (emanix/modeline-mode 1)
The threshold, the battery capacity and the segment list are read at every refresh and take effect on the next one.
Register a segment with add-to-list, not by advising the renderer. The
renderer, emanix/modeline--render, is private and moves. A check in the
distribution holds the extension point stable:
(defun my/load-segment ()
(when (file-readable-p "/proc/loadavg")
(with-temp-buffer
(insert-file-contents "/proc/loadavg")
(format "load %s" (car (split-string (buffer-string)))))))
(add-to-list 'emanix/modeline-extra-segments #'my/load-segment)
A segment that signals is dropped, with a message in *Messages*, and the bar
still draws. Read /sys or /proc in a segment; do not start a process.
3. Theme
| Variable | Default | Kind | Meaning |
|---|---|---|---|
emanix/theme-state-dir |
~/.config/dotfiles |
defcustom, directory | Where Emacs keeps the runtime theme state: the active-theme marker and one last-<variant> marker per variant. Emacs writes here. The name predates Emacs owning the contents |
emanix/theme-apply-functions |
nil |
defcustom, list of functions | The consumer extension point for a theme switch. Each function receives the plan (:name, :dir, :variant, :emacs-theme, :links, :gtk). A function that signals is reported and skipped |
Theming explains the switch and the hook in full. The build-time theme is the
Nix option emanix.theme, not a variable here.
4. Prose rendering
Org buffers render as prose: a proportional body font, scaled headings and a
centred reading column. These are read when emanix-prose-mode turns on in a
buffer. A buffer that is already open keeps its old values until you toggle the
mode off and on.
| Variable | Default | Kind | Meaning |
|---|---|---|---|
emanix-prose-body-font |
IBM Plex Sans |
defcustom, string | Proportional family for body text |
emanix-prose-heading-font |
IBM Plex Serif |
defcustom, string | Family for headings |
emanix-prose-mono-font |
JetBrains Mono |
defcustom, string | Monospace family for code, tables and blocks |
emanix-prose-width |
90 |
defcustom, integer | Width in characters of the centred reading column |
emanix-prose-left-margin |
4 |
defcustom, integer | Left margin in characters |
emanix-prose-heading-scales |
(1.6 1.4 1.25 1.15 1.05 1.0) |
defcustom, list of numbers | Height multiplier for heading levels 1 to 6 |
A file opts out with the file-local variable eval: (emanix-prose-mode -1).
5. Buffers and windows
| Variable | Default | Kind | Meaning |
|---|---|---|---|
emanix/buffer-group-alist |
five groups: agenda, org, dired, files, * |
defvar, alist of (NAME . PREDICATE) |
The groups C-c K offers (emanix/kill-buffer-group). A predicate takes a buffer and returns non-nil to kill it. agenda is only what the last agenda run opened, org, dired and files are what they say, and * is everything not protected |
emanix/buffer-protect-names |
("*scratch*" "*Messages*") |
defvar, list of strings | Buffers no group kill ever reaches. Buffers whose name starts with a space are protected as well, with no setting |
emanix/windmove-active |
t |
defvar | Set it to nil, buffer-locally, to hand M-h M-j M-k M-l back to a major mode |
emanix/terminal-glyph-substitutions |
a list of (WIDE-CHAR . CELL-WIDTH-CHAR) pairs |
defvar, alist | Characters in terminal buffers that the font draws off the cell grid, replaced on screen by glyphs that fit. The text itself is untouched, so copy and search still see the original |
Add a group of your own. Every kill still goes through kill-buffer, so a
modified file still asks to save, and a protected buffer is filtered out before
any predicate runs:
(add-to-list 'emanix/buffer-group-alist
(cons "notes"
(lambda (buf) (emanix/buffer-under-p buf "~/notes"))))
emanix/buffer-under-p is the helper for path-specific groups.
6. Tools
| Variable | Default | Kind | Meaning |
|---|---|---|---|
emanix/agent-shell-save-before-prompt |
t |
defcustom, boolean | Save modified project buffers before each prompt to an agent. The agent reads files from disk, so without this it cannot see unsaved edits. With it, every prompt commits your unsaved work and entangles your edits with the agent's. The formatter runs on save, so pressing RET in an agent shell can reformat a file you were editing in another window |
emanix/arc-capture-target |
~/docs/org/arc.org |
defcustom, file | The org file that w in an answer buffer files the answer into. The default is under your home directory; the distribution cannot know where your notes live |
emanix-web-djlint-profile |
jinja |
defcustom, string | The template language passed to djlint --profile. Set it per tree in .dir-locals.el; a command-line profile overrides one in the tree's own djlint config |
emanix-welcome-repo-candidates |
the $EMANIX_DOTFILES directory, ~/flake, /etc/nixos |
defcustom, list of directories | Where the welcome buffer looks for your configuration repository, in order. The first directory holding both a flake.nix and a .git wins. nil entries are ignored |
The default of emanix-welcome-repo-candidates is computed when the file loads,
so the EMANIX_DOTFILES variable must be in Emacs's environment by then. See
the environment variable table.
7. Read, do not set
emanix/init-errorisnilon a healthy start. Anything else is the error that stoppedconfig.el; see Keybindings.emanix/modeline-statusis the cached string the bar displays.
8. What you now know
Every setting above lives in personal.el. A defcustom takes setq or
customize; a defvar takes setq or add-to-list. Two of them,
emanix/modeline-interval and emanix/modeline-probe-interval, need
emanix/modeline-mode restarted. The extension points — a segment function or
a theme hook — take a function and never need a patch to the distribution.