aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-06-16 09:41:58 -0500
committerCraig Jennings <c@cjennings.net>2026-06-16 09:41:58 -0500
commitbd35c3a74bfa329907f4ab15628197dd39e76c65 (patch)
tree4d7023e756caea5130d137c2e40c6e0cdac775a0
parent92538504f829ca49643ed0212e0af823cce9167a (diff)
downloaddotemacs-bd35c3a74bfa329907f4ab15628197dd39e76c65.tar.gz
dotemacs-bd35c3a74bfa329907f4ab15628197dd39e76c65.zip
feat(keybindings): mirror the C-; command family under C-c ;
C-; is GUI-only: terminals can't encode Control-semicolon, so the whole custom command family (calendar, AI, Slack, org, pearl, jump, and the rest) was unreachable in a terminal frame (emacs -nw, emacsclient -nw, or Emacs inside vterm/tmux). I bound the single cj/custom-keymap under C-c ; alongside C-;, so the same leaf keys reach the identical map in both GUI and TTY with no relearning and no per-module edits. C-c is the standard user prefix and always TTY-encodable. I audited every leaf key in the family and they're all TTY-safe (letters, digits, punctuation, SPC, and arrow keys), so nothing needed remapping.
-rw-r--r--modules/keybindings.el4
-rw-r--r--tests/test-keybindings-tty-mirror.el33
-rw-r--r--todo.org10
3 files changed, 46 insertions, 1 deletions
diff --git a/modules/keybindings.el b/modules/keybindings.el
index db4800876..b61c3f2b3 100644
--- a/modules/keybindings.el
+++ b/modules/keybindings.el
@@ -35,6 +35,10 @@
(defvar-keymap cj/custom-keymap
:doc "User custom prefix keymap base for nested keymaps.")
(keymap-global-set "C-;" cj/custom-keymap)
+;; C-; is GUI-only; terminals can't encode Control-semicolon. Mirror the same
+;; keymap under C-c ; (the standard user prefix, always TTY-encodable) so the
+;; whole command family works in a terminal frame with no leaf-key relearning.
+(keymap-global-set "C-c ;" cj/custom-keymap)
;; ------------------------ Custom Keymap Registration -------------------------
diff --git a/tests/test-keybindings-tty-mirror.el b/tests/test-keybindings-tty-mirror.el
new file mode 100644
index 000000000..f63024c0b
--- /dev/null
+++ b/tests/test-keybindings-tty-mirror.el
@@ -0,0 +1,33 @@
+;;; test-keybindings-tty-mirror.el --- TTY mirror prefix for the C-; family -*- lexical-binding: t; -*-
+
+;;; Commentary:
+;; The personal prefix C-; is GUI-only — terminals can't encode Control-semicolon,
+;; so the whole custom command family is unreachable in a TTY frame (emacs -nw,
+;; emacsclient -nw, Emacs inside vterm/tmux). keybindings.el binds the single
+;; `cj/custom-keymap' under a TTY-safe mirror prefix C-c ; alongside C-;, so the
+;; same leaf keys reach the identical map in both GUI and terminal. These tests
+;; pin that load-time global binding.
+
+;;; Code:
+
+(require 'ert)
+
+(add-to-list 'load-path (expand-file-name "modules" user-emacs-directory))
+(require 'keybindings)
+
+(ert-deftest test-keybindings-tty-mirror-gui-prefix-resolves ()
+ "Normal: the GUI prefix C-; resolves to cj/custom-keymap globally."
+ (should (eq (keymap-lookup (current-global-map) "C-;") cj/custom-keymap)))
+
+(ert-deftest test-keybindings-tty-mirror-tty-prefix-resolves ()
+ "Normal: the TTY mirror C-c ; resolves to the same cj/custom-keymap."
+ (should (eq (keymap-lookup (current-global-map) "C-c ;") cj/custom-keymap)))
+
+(ert-deftest test-keybindings-tty-mirror-both-prefixes-share-one-map ()
+ "Boundary: both prefixes point at the identical keymap object, so a leaf
+key registered once is reachable under either prefix."
+ (should (eq (keymap-lookup (current-global-map) "C-;")
+ (keymap-lookup (current-global-map) "C-c ;"))))
+
+(provide 'test-keybindings-tty-mirror)
+;;; test-keybindings-tty-mirror.el ends here
diff --git a/todo.org b/todo.org
index a78d17afc..38b2188bb 100644
--- a/todo.org
+++ b/todo.org
@@ -2519,10 +2519,12 @@ From the 2026-06 config audit, =modules/transcription-config.el=:
- =:210= — =make-process :stderr= with a file PATH creates a BUFFER named like the path (verified by probe); the "Errored. Logs in <file>" notification points at a log without the error text, and the hidden stderr buffer leaks per transcription. Route stderr into the process buffer or write it out in the sentinel.
- =:370-374= — video path derives txt/log from the temp mp3's /tmp path; the transcript lands in /tmp and dies on reboot, contradicting the "alongside the source" docstring. Pass the video's path as the output base.
-** TODO [#B] TTY-accessible personal C-; keymap :feature:solo:quick:
+** DONE [#B] TTY-accessible personal C-; keymap :feature:solo:quick:
+CLOSED: [2026-06-16 Tue]
:PROPERTIES:
:LAST_REVIEWED: 2026-06-05
:END:
+Done 2026-06-16: keybindings.el binds cj/custom-keymap under C-c ; alongside C-;, so the whole command family is reachable in a terminal frame with the same leaf keys (the single-point fix the body describes; no env-terminal-p branch). Audited every leaf key registered into the family — all are TTY-safe (letters, digits, punctuation, SPC, and arrow keys under C-; b, which terminals do encode); no C-RET, super, or hyper bindings, so nothing needed remapping. TDD: tests/test-keybindings-tty-mirror.el (3 tests, both prefixes share one map); full suite green; live-reloaded and confirmed C-c ; resolves to the family in the daemon. Commit pending. TTY-frame sign-off is a VERIFY under Manual testing and validation.
The personal prefix =C-;= (Control-semicolon) is GUI-only — terminals can't encode it, so the entire custom command family (=C-; g= calendar, =C-; a= AI, =C-; S= Slack, =C-; O= org, =C-; M= Signal, =C-; L= pearl, =C-; j= jump, …) is unreachable in a terminal frame (=emacsclient -nw=, Emacs inside vterm/tmux). Surfaced 2026-06-03 out of the pearl =C-; L= prefix discussion.
Goal: keep =C-;= in GUI and add a TTY-typable mirror prefix so the same leaf keys work in a terminal. The fix is a single point: =modules/keybindings.el= defines =cj/custom-keymap= once, binds it globally with =(keymap-global-set "C-;" cj/custom-keymap)=, and every module registers into it via =cj/bind-prefix= / =cj/bind-command=. Binding that one keymap under a second prefix mirrors the whole family for free — no per-module edits.
@@ -4587,6 +4589,12 @@ What we're verifying: with the mu4e modes excluded from global font-lock, mu4e's
- Open mu4e, look at the headers list and the main menu
- Open a message and read the body
Expected: headers list shows unread/flagged/date/subject in their theme colors (mu4e-unread-face gold, mu4e-header-face green, etc.); the main menu and the message-view headers (From/To/Subject) are themed; the message body still renders correctly (gnus does the body, so it's unaffected). NOTE: a plain "g" refresh in an already-open *mu4e-headers* won't fix it on its own unless font-lock is off there; a restart is the reliable check.
+*** VERIFY C-c ; reaches the custom command family in a real terminal frame
+What we're verifying: the TTY mirror prefix C-c ; reaches the same cj/custom-keymap as the GUI C-; prefix, so the whole command family works in a terminal. The unit tests + a live daemon eval already confirm both prefixes resolve to the one keymap; this is the end-to-end in an actual TTY frame, which the batch harness can't drive.
+- Open a terminal Emacs frame: emacsclient -nw (or emacs -nw, or Emacs inside vterm/tmux)
+- Press C-c ; L (pearl), C-c ; a (AI), C-c ; g (calendar) — the same leaf keys you use under C-; in GUI
+- Confirm which-key shows the custom prefix under C-c ;
+Expected: each C-c ; <leaf> runs the same command its C-; <leaf> counterpart runs in GUI; which-key lists the family under C-c ;. C-; itself stays working in GUI frames (unchanged).
*** VERIFY theme-studio gnus view package themes the article headers
What we're verifying: gnus is now its own view package in theme-studio (it drives the mu4e article view), so the bright-green article headers can be themed and exported. #gnustest confirms the package is registered and its preview emits only real gnus faces; this is the visual read plus the live-green retirement.
- Reload theme-studio (or make theme-studio-open)