<feed xmlns='http://www.w3.org/2005/Atom'>
<title>dotemacs/modules/system-commands.el, branch main</title>
<subtitle>My Emacs configuration
</subtitle>
<id>https://git.cjennings.net/dotemacs/atom?h=main</id>
<link rel='self' href='https://git.cjennings.net/dotemacs/atom?h=main'/>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/'/>
<updated>2026-05-25T00:59:28+00:00</updated>
<entry>
<title>refactor(load-graph): route C-; registration through the keymap API</title>
<updated>2026-05-25T00:59:28+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-25T00:59:28+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=08014b2f15e099a1c5e662a17a41290f37aeebf4'/>
<id>urn:sha1:08014b2f15e099a1c5e662a17a41290f37aeebf4</id>
<content type='text'>
Migrated all 31 cj/custom-keymap registration sites across 24 modules from direct (keymap-set cj/custom-keymap ...) calls to cj/register-prefix-map and cj/register-command. Consumers no longer reference cj/custom-keymap directly, so keybindings.el is the sole owner of the C-; prefix and modules reach it only through the API (each already requires keybindings from Phase 2).

Behavior-preserving: I dumped every C-; binding before and after the migration and they're identical: 279 bindings, each resolving to the same command. The which-key label blocks are untouched, since they use string key descriptions and never assumed the keymap existed. I byte-compiled all 24 files (no new free-variable warnings, because the cj/custom-keymap references are gone), and make test, validate-modules, and an init load all pass.
</content>
</entry>
<entry>
<title>docs(load-graph): classify remaining domain and optional modules</title>
<updated>2026-05-24T22:01:40+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-24T22:01:40+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=f84bba186dca1543f9c5f02c03af355188b6e87c'/>
<id>urn:sha1:f84bba186dca1543f9c5f02c03af355188b6e87c</id>
<content type='text'>
Final classification batch: the last 19 modules — linear-config, local-repository, lorem-optimum, mail-config, markdown-config, music-config, pdf-config, quick-video-capture, reconcile-open-repos, restclient-config, slack-config, system-commands, telega-config, tramp-config, transcription-config, video-audio-recording, vterm-config, weather-config, wrap-up. I annotated each header, added a Batch 9 table to the inventory, and extended the validation allowlist. 101 of 102 modules are now classified; only elfeed-config remains, deferred on its test fix.

Two more hidden dependencies turned up. video-audio-recording uses the boundp shim for its C-; r binding, and mail-config registers C-; e directly without requiring keybindings, so it errors standalone rather than degrading. Both recorded for Phase 2.
</content>
</entry>
<entry>
<title>fix(system-commands): make Emacs restart and destructive confirms defensive</title>
<updated>2026-05-24T09:15:30+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-24T09:15:30+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=f1dbec16531cd3d5f0b9124accedb8cb8e49dea3'/>
<id>urn:sha1:f1dbec16531cd3d5f0b9124accedb8cb8e49dea3</id>
<content type='text'>
Restart-Emacs scheduled an unconditional kill-emacs one second after firing the systemctl restart. If the service was missing or the restart failed, the session still got killed with nothing to replace it. Restart now guards on (daemonp) and a present emacs.service before doing anything, and drops the separate kill-emacs entirely — systemctl restart cycles the daemon itself, so a failed restart leaves the current Emacs alive. Added cj/system-cmd--emacs-service-available-p (systemctl --user cat) for the guard.

Shutdown and reboot now use a strong yes-or-no-p confirm instead of the quick (Y/n) read-char, where RET or space counted as yes — a stray Enter at the prompt could power off the machine. Logout and suspend keep the quick confirm since they are recoverable. The confirm tier rides on a property set by cj/defsystem-command. Tests cover service detection, both restart guards, and the strong-confirm accept/decline paths with the system primitives stubbed.
</content>
</entry>
<entry>
<title>fix(system-commands): require keybindings at load time, not just compile time</title>
<updated>2026-05-15T07:31:43+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-15T07:31:43+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=db522da5d27c9fe90cae64ab80c659068fbb29c2'/>
<id>urn:sha1:db522da5d27c9fe90cae64ab80c659068fbb29c2</id>
<content type='text'>
The module had `(eval-when-compile (require 'keybindings))`, which
silences the byte-compiler but doesn't make `cj/custom-keymap'
available when the module is required.  The top-level
`(keymap-set cj/custom-keymap "!" cj/system-command-map)' at the tail
of the file then fails with `void-variable cj/custom-keymap'.

Normal Emacs startup happened to work because `init.el' requires
`keybindings' before `system-commands'.  But requiring the module in
isolation -- including from `make test-file
FILE=test-system-commands-resolve-and-run.el' -- blows up.

Fix: use a plain `(require 'keybindings)' so the load-time
dependency matches the load-time reference.
</content>
</entry>
<entry>
<title>refactor(system-commands): use string interactive spec so undercover instruments</title>
<updated>2026-05-14T12:51:12+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-14T12:51:12+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=488da25c0f13b2401a7121fd3941aa649207f39e'/>
<id>urn:sha1:488da25c0f13b2401a7121fd3941aa649207f39e</id>
<content type='text'>
`cj/system-cmd' had `(interactive (list (read-shell-command "System
command: ")))' -- the destructured-list interactive spec.  Undercover.el
relies on edebug instrumentation, which doesn't see past that form, so
the entire function body registered as 0 hits under coverage even
though tests call the function directly.

Switch to the equivalent string spec `(interactive "sSystem command: ")'.
Same UX (prompt, history, single-string result), but the body now
instruments correctly and coverage moves from 34/49 to 50/51.

Add one more test that captures the `run-at-time' lambda in
`cj/system-cmd-restart-emacs' and invokes it directly so the inner
`call-process-shell-command' branch registers, taking coverage to 51/51.
</content>
</entry>
<entry>
<title>fix: keep C-; ! as system command prefix</title>
<updated>2026-05-04T00:10:50+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-04T00:10:50+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=c2f355bf601fd9b7db0107c163c64432a7ae9a80'/>
<id>urn:sha1:c2f355bf601fd9b7db0107c163c64432a7ae9a80</id>
<content type='text'>
The module was binding `cj/system-command-map` under `C-; !`, then a few lines later overwriting the same prefix with `cj/system-command-menu`. The second bind won, so every documented subkey, like `C-; ! r` for reboot and `C-; ! l` for lock, was unreachable.

I kept the prefix map and folded the completing-read menu into it at `C-; ! !`. So `C-; !` still opens the prefix, the menu is one extra `!` away, and the single-letter shortcuts work again. I also added which-key labels for every documented subkey so the popup actually says what each one does.

I added `tests/test-system-commands-keymap.el`. It asserts the prefix stays mounted and that every binding (`!`, `L`, `r`, `s`, `S`, `l`, `E`, `e`) resolves to the right command.
</content>
</entry>
<entry>
<title>refactor: Rename custom-file-buffer to custom-buffer-file</title>
<updated>2025-10-28T02:05:06+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2025-10-28T02:05:06+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=d77ca19cf7106a0eecbff1588c13b8b52b98b85f'/>
<id>urn:sha1:d77ca19cf7106a0eecbff1588c13b8b52b98b85f</id>
<content type='text'>
Renamed the module 'custom-file-buffer' to 'custom-buffer-file' to
ensure consistency across the codebase. This change affects module
imports and test files. Additionally, new module
'system-commands.el' has been created to handle system power and
session management commands, removing these functionalities from
'wip.el'.
</content>
</entry>
</feed>
