summaryrefslogtreecommitdiff
path: root/modules/system-commands.el
Commit message (Collapse)AuthorAgeFilesLines
* fix(system-commands): make Emacs restart and destructive confirms defensiveCraig Jennings13 days1-19/+47
| | | | | | 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.
* fix(system-commands): require keybindings at load time, not just compile timeCraig Jennings2026-05-151-1/+6
| | | | | | | | | | | | | | | | 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.
* refactor(system-commands): use string interactive spec so undercover instrumentsCraig Jennings2026-05-141-2/+9
| | | | | | | | | | | | | | | | `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.
* fix: keep C-; ! as system command prefixCraig Jennings2026-05-031-13/+21
| | | | | | | | 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.
* refactor: Rename custom-file-buffer to custom-buffer-fileCraig Jennings2025-10-271-0/+138
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'.