diff options
| -rw-r--r-- | modules/video-audio-recording.el | 41 | ||||
| -rw-r--r-- | tests/test-video-audio-recording--keybindings.el | 133 |
2 files changed, 60 insertions, 114 deletions
diff --git a/modules/video-audio-recording.el b/modules/video-audio-recording.el index 65a8612f..8fd3d23b 100644 --- a/modules/video-audio-recording.el +++ b/modules/video-audio-recording.el @@ -300,40 +300,13 @@ Changes take effect on the next recording (not the current one)." (cj/register-prefix-map "r" cj/record-map) -;; Fast chords for the two toggles, alongside C-; r v and C-; r a. F9 is free: -;; ai-term vacated the F9 family when its swap moved to M-SPC, and -;; `test-ai-term-f9-family-removed-globally' keeps it vacated. Both commands -;; still take a prefix argument, so C-u F9 prompts for the recording location. -(keymap-global-set "<f9>" #'cj/video-recording-toggle) -(keymap-global-set "S-<f9>" #'cj/audio-recording-toggle) - -(defvar eat-mode-map) -(defvar eat-semi-char-mode-map) -(defvar eat-char-mode-map) -(defvar eat-eshell-char-mode-map) - -;; EAT builds each input mode's keymap from key categories, and which categories -;; a mode claims is what decides whether a chord reaches Emacs at all. -;; -;; Semi-char mode -- the default, and where every agent buffer sits -- is built -;; from :ascii, :arrow and :navigation. It never claims function keys, so F9 -;; already fell through to the global map. The semi-char entry below is -;; belt-and-braces rather than the fix, which is why it reads as redundant. -;; -;; Char mode is the one that swallows F9. It adds :function, binding f1 through -;; f63 to eat-self-input, and it is a minor mode, so its map outranks -;; eat-mode-map. Without an entry here the pair splits in the worst possible -;; way: :function claims only the unmodified keys, so S-F9 would toggle audio in -;; a char-mode buffer while F9 went to the program under the cursor. That is a -;; recording you believe you started and didn't. -;; -;; Claiming both costs a char-mode program the use of F9. I would rather pay -;; that than ship a toggle that works for audio and silently fails for video. -(with-eval-after-load 'eat - (dolist (map (list eat-semi-char-mode-map eat-mode-map - eat-char-mode-map eat-eshell-char-mode-map)) - (keymap-set map "<f9>" #'cj/video-recording-toggle) - (keymap-set map "S-<f9>" #'cj/audio-recording-toggle))) +;; The toggles live only under C-; r. They had a fast chord (F9 video, S-F9 +;; audio, claimed in every EAT map too) until 2026-09-22: with Fn Lock on the +;; Framework 13 the F-key row sends plain function keys, and a bare F9 press +;; started a screen recording. Both chords went together, because a lone S-F9 +;; on a live F-key row is one fat-finger from an unwanted audio recording. +;; Both commands still take a prefix argument, so C-u C-; r v prompts for the +;; recording location. (with-eval-after-load 'which-key (which-key-add-key-based-replacements diff --git a/tests/test-video-audio-recording--keybindings.el b/tests/test-video-audio-recording--keybindings.el index cdb6493a..9ddce661 100644 --- a/tests/test-video-audio-recording--keybindings.el +++ b/tests/test-video-audio-recording--keybindings.el @@ -1,25 +1,21 @@ ;;; test-video-audio-recording--keybindings.el --- recording toggle keybinding placement -*- lexical-binding: t; -*- ;;; Commentary: -;; The two recording toggles get a fast chord alongside the C-; r prefix: F9 -;; starts/stops video, S-F9 starts/stops audio. +;; The two recording toggles live only under the C-; r prefix. They used to +;; have a fast chord too: F9 for video, S-F9 for audio, claimed globally and in +;; every EAT map so char mode's :function category could not swallow them. ;; -;; Reaching them from inside an EAT buffer turns on which key categories each -;; input mode claims. Semi-char mode -- the default, and where agent buffers -;; sit -- is built from (:ascii :arrow :navigation) and never claims function -;; keys, so F9 already fell through to the global map there. Char mode adds -;; :function, binding f1 through f63 to `eat-self-input', and it is a minor -;; mode, so its map outranks `eat-mode-map'. The char-mode entries are the -;; load-bearing ones; the semi-char entry is belt-and-braces. +;; That chord went away on 2026-09-22. With Fn Lock on the Framework 13, the +;; F-key row sends plain function keys, so a bare F9 press started a screen +;; recording. The pair is removed as a unit: a lone S-F9 audio chord on a live +;; F-key row is one fat-finger from an unwanted recording, and the module +;; treated the two as one feature. ;; -;; :function claims only the unmodified keys, which is why getting this wrong -;; split the pair rather than breaking it outright: S-F9 toggled audio in a -;; char-mode buffer while F9 went to the program under the cursor. -;; -;; These tests require eat first so the module's `with-eval-after-load' fires. -;; The char-mode cases resolve through `key-binding' in a fixture that -;; reproduces minor-mode precedence, because reading a binding back out of the -;; map the module just wrote proves nothing about which map wins on a keypress. +;; These tests pin the removal. The char-mode case resolves through +;; `key-binding' in a fixture that reproduces minor-mode precedence, because +;; reading a map the module no longer writes proves nothing about which map wins +;; on a keypress. They require eat first so any `with-eval-after-load' the +;; module still carries would have fired. ;;; Code: @@ -32,56 +28,41 @@ (require 'eat) (require 'video-audio-recording) +(defconst test-video-audio-recording--toggles + '(cj/video-recording-toggle cj/audio-recording-toggle) + "The two commands the retired F9 chords used to reach.") + +(defun test-video-audio-recording--bound-to-toggle-p (binding) + "Return non-nil when BINDING is one of the recording toggles." + (memq binding test-video-audio-recording--toggles)) + ;;; Normal -(ert-deftest test-video-audio-recording-f9-bound-globally () - "Normal: F9 toggles video recording, S-F9 toggles audio recording." - (should (eq (lookup-key (current-global-map) (kbd "<f9>")) - #'cj/video-recording-toggle)) - (should (eq (lookup-key (current-global-map) (kbd "S-<f9>")) - #'cj/audio-recording-toggle))) - -(ert-deftest test-video-audio-recording-f9-bound-in-eat-semi-char-mode-map () - "Normal: both chords are bound in `eat-semi-char-mode-map'. -Redundant rather than load-bearing: semi-char is built without :function, so a -function key already falls through to the global map. Asserted anyway so the -entry cannot be dropped silently while the comment explaining it stays." - (should (eq (keymap-lookup eat-semi-char-mode-map "<f9>") - #'cj/video-recording-toggle)) - (should (eq (keymap-lookup eat-semi-char-mode-map "S-<f9>") - #'cj/audio-recording-toggle))) - -(ert-deftest test-video-audio-recording-f9-bound-in-eat-mode-map () - "Normal: both chords are bound in `eat-mode-map', the major-mode map every -EAT buffer carries regardless of input mode." - (should (eq (keymap-lookup eat-mode-map "<f9>") - #'cj/video-recording-toggle)) - (should (eq (keymap-lookup eat-mode-map "S-<f9>") - #'cj/audio-recording-toggle))) - -(ert-deftest test-video-audio-recording-f9-bound-in-eat-char-mode-maps () - "Normal: both chords are bound in the two char-mode maps. -Char mode is built with EAT's :function category, which binds f1 through f63 -to `eat-self-input'. These entries are what override that." - (dolist (map (list eat-char-mode-map eat-eshell-char-mode-map)) - (should (eq (keymap-lookup map "<f9>") #'cj/video-recording-toggle)) - (should (eq (keymap-lookup map "S-<f9>") #'cj/audio-recording-toggle)))) +(ert-deftest test-video-audio-recording-f9-not-bound-globally () + "Normal/regression: neither F9 nor S-F9 reaches a recording toggle globally." + (should-not (test-video-audio-recording--bound-to-toggle-p + (lookup-key (current-global-map) (kbd "<f9>")))) + (should-not (test-video-audio-recording--bound-to-toggle-p + (lookup-key (current-global-map) (kbd "S-<f9>"))))) + +(ert-deftest test-video-audio-recording-f9-not-bound-in-eat-maps () + "Normal/regression: none of the four EAT maps carries a recording toggle on +F9 or S-F9. The module used to write all four so the chord survived char +mode; the removal has to reach every one of them." + (dolist (map (list eat-semi-char-mode-map eat-mode-map + eat-char-mode-map eat-eshell-char-mode-map)) + (should-not (test-video-audio-recording--bound-to-toggle-p + (keymap-lookup map "<f9>"))) + (should-not (test-video-audio-recording--bound-to-toggle-p + (keymap-lookup map "S-<f9>"))))) ;;; Boundary -(ert-deftest test-video-audio-recording-f9-chords-are-distinct () - "Boundary: the shifted and unshifted chords resolve to different commands. -A copy-paste binding both to the same toggle would satisfy every -binding-is-present assertion above, so assert the difference directly." - (should-not (eq (lookup-key (current-global-map) (kbd "<f9>")) - (lookup-key (current-global-map) (kbd "S-<f9>"))))) - (defun test-video-audio-recording--in-char-mode (body) "Run BODY in a buffer wired the way a live EAT char-mode buffer is. `eat--char-mode' is a minor mode, so its map is consulted ahead of the -major-mode map. Reproducing that ordering is the point: reading a binding -back out of the map the module just wrote proves nothing about which map wins -when a key is actually pressed." +major-mode map. Reproducing that ordering is the point: the assertion is +about which map wins when a key is actually pressed." (with-temp-buffer (use-local-map eat-mode-map) (let ((minor-mode-overriding-map-alist @@ -89,42 +70,34 @@ when a key is actually pressed." (eat--char-mode t)) (funcall body)))) -(ert-deftest test-video-audio-recording-f9-resolves-in-char-mode () - "Boundary: both chords resolve to the toggles through the real precedence -chain in a char-mode buffer. Before this override F9 resolved to -`eat-self-input' and went to the program under the cursor, while S-F9 reached -Emacs — so the pair silently split, audio recording and video not." +(ert-deftest test-video-audio-recording-f9-reaches-program-in-char-mode () + "Boundary: in a char-mode buffer F9 goes to the program under the cursor +again. EAT's :function category binds f1 through f63 to `eat-self-input'; +the module's override used to sit in front of it, and now nothing does." (test-video-audio-recording--in-char-mode (lambda () - (should (eq (key-binding (kbd "<f9>")) #'cj/video-recording-toggle)) - (should (eq (key-binding (kbd "S-<f9>")) #'cj/audio-recording-toggle))))) + (should (eq (key-binding (kbd "<f9>")) #'eat-self-input))))) ;;; Error (ert-deftest test-video-audio-recording-char-mode-fixture-really-is-char-mode () "Error (positive control): the char-mode fixture genuinely puts EAT's map in front. F8 sits in the same :function category as F9 and this module never -touches it, so it must still reach `eat-self-input'. If it resolves anywhere -else the fixture is inert, and the resolution test above would pass without -ever consulting `eat-char-mode-map' — which is precisely how the first cut of -this file missed that F9 was being swallowed there." +touched it, so it must reach `eat-self-input'. If it resolves anywhere else +the fixture is inert and the F9 assertion above passes for the wrong reason." (test-video-audio-recording--in-char-mode (lambda () (should (eq (key-binding (kbd "<f8>")) #'eat-self-input))))) -(ert-deftest test-video-audio-recording-f9-targets-are-commands () - "Error: a key bound to a non-interactive function fails at press time with a -`commandp' error rather than at load, so assert both targets are real commands." - (should (commandp (lookup-key (current-global-map) (kbd "<f9>")))) - (should (commandp (lookup-key (current-global-map) (kbd "S-<f9>"))))) - (ert-deftest test-video-audio-recording-prefix-bindings-still-reachable () - "Error/regression (positive control): the fast chords must not disturb the -C-; r prefix path. Without this, deleting the prefix map outright would leave -every assertion above green." + "Error/regression (positive control): removing the fast chords must leave +the C-; r prefix path intact. Without this, deleting the toggles outright +would leave every not-bound assertion above green." (should (eq (keymap-lookup cj/record-map "v") #'cj/video-recording-toggle)) (should (eq (keymap-lookup cj/record-map "a") #'cj/audio-recording-toggle)) - (should (eq (keymap-lookup cj/custom-keymap "r") cj/record-map))) + (should (eq (keymap-lookup cj/custom-keymap "r") cj/record-map)) + (should (commandp #'cj/video-recording-toggle)) + (should (commandp #'cj/audio-recording-toggle))) (provide 'test-video-audio-recording--keybindings) ;;; test-video-audio-recording--keybindings.el ends here |
