aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-06-08 11:17:49 -0500
committerCraig Jennings <c@cjennings.net>2026-06-08 11:17:49 -0500
commit84e5cdb277b8e96f730139e77d3ce7f5206c8b87 (patch)
tree0f86bfc3ff37c51b868cde78e79dc695288d397b
parent560cacd91f0120225c4b795aaabebbf0598df918 (diff)
downloaddotemacs-84e5cdb277b8e96f730139e77d3ce7f5206c8b87.tar.gz
dotemacs-84e5cdb277b8e96f730139e77d3ce7f5206c8b87.zip
feat(term): open the agenda with F8 from inside ghostel buffers
F8 is bound globally to cj/main-agenda-display, but ghostel's semi-char mode forwarded it to the terminal program, so it did nothing inside a ghostel buffer. I added F8 to ghostel-keymap-exceptions and rebuilt the semi-char map, which lets it fall through to the global map, the path F10 and the F9 family already take.
-rw-r--r--modules/term-config.el10
-rw-r--r--tests/test-term-config--f8-in-term.el42
-rw-r--r--todo.org5
3 files changed, 52 insertions, 5 deletions
diff --git a/modules/term-config.el b/modules/term-config.el
index 2daebe9b..f9c12635 100644
--- a/modules/term-config.el
+++ b/modules/term-config.el
@@ -237,12 +237,12 @@ run its own project-named tmux session instead of a bare, auto-named one.
;; rebuild is what actually lets the key through to `ghostel-mode-map' / the
;; global map. C-; and F12 are the prefix + toggle; the modified arrows are
;; windmove (S-arrows, focus) and buffer-move (C-M-arrows, swap), which the
- ;; ai-term workflow expects to work from inside an agent buffer. F10 and
- ;; C-F10 are global bindings (music-playlist toggle, server shutdown) that
- ;; reach Emacs by falling through to the global map once the semi-char map
- ;; stops forwarding them.
+ ;; ai-term workflow expects to work from inside an agent buffer. F8, F10 and
+ ;; C-F10 are global bindings (org agenda, music-playlist toggle, server
+ ;; shutdown) that reach Emacs by falling through to the global map once the
+ ;; semi-char map stops forwarding them.
(with-eval-after-load 'ghostel
- (dolist (key '("C-;" "<f12>" "<f10>" "C-<f10>"
+ (dolist (key '("C-;" "<f8>" "<f12>" "<f10>" "C-<f10>"
"S-<up>" "S-<down>" "S-<left>" "S-<right>"
"C-M-<up>" "C-M-<down>" "C-M-<left>" "C-M-<right>"))
(add-to-list 'ghostel-keymap-exceptions key))
diff --git a/tests/test-term-config--f8-in-term.el b/tests/test-term-config--f8-in-term.el
new file mode 100644
index 00000000..6cee4ff4
--- /dev/null
+++ b/tests/test-term-config--f8-in-term.el
@@ -0,0 +1,42 @@
+;;; test-term-config--f8-in-term.el --- F8 reaches Emacs from inside a ghostel buffer -*- lexical-binding: t; -*-
+
+;;; Commentary:
+;; <f8> is a global binding (`cj/main-agenda-display', set in org-agenda-config).
+;; ghostel's semi-char mode forwards every key NOT in `ghostel-keymap-exceptions'
+;; to the terminal program, so a plain <f8> typed while point is in a ghostel
+;; buffer would be sent to the program instead of opening the agenda. Unlike the
+;; F9 family, F8 is NOT re-bound in `ghostel-mode-map' -- it simply falls through
+;; to the global map once the semi-char map stops forwarding it, so the only
+;; wiring term-config.el adds is the keymap-exceptions entry plus the rebuild.
+;; These tests require ghostel (so term-config's `with-eval-after-load' fires)
+;; BEFORE term-config, then confirm the exception landed and the rebuilt
+;; semi-char map no longer forwards <f8>. `(require 'ghostel)' does not load the
+;; native module, so this stays light.
+
+;;; Code:
+
+(require 'ert)
+(require 'package)
+
+(setq package-user-dir (expand-file-name "elpa" user-emacs-directory))
+(package-initialize)
+(add-to-list 'load-path (expand-file-name "modules" user-emacs-directory))
+(require 'ghostel)
+(require 'term-config)
+
+(ert-deftest test-term-config-f8-in-keymap-exceptions ()
+ "Regression: <f8> is in `ghostel-keymap-exceptions' so semi-char mode lets it
+reach Emacs instead of forwarding it to the terminal program. This is what lets
+the global agenda binding work from inside a ghostel buffer."
+ (should (member "<f8>" ghostel-keymap-exceptions)))
+
+(ert-deftest test-term-config-f8-not-forwarded-by-semi-char-map ()
+ "Regression: the rebuilt semi-char map must no longer forward <f8> to the pty.
+`add-to-list' updates the exceptions list but not the already-built map -- only
+`ghostel--rebuild-semi-char-keymap' (run in term-config's :init) drops the
+forwarding binding so <f8> falls through to the global agenda command."
+ (should-not (eq (keymap-lookup ghostel-semi-char-mode-map "<f8>")
+ 'ghostel--send-event)))
+
+(provide 'test-term-config--f8-in-term)
+;;; test-term-config--f8-in-term.el ends here
diff --git a/todo.org b/todo.org
index 642a69e3..df76a599 100644
--- a/todo.org
+++ b/todo.org
@@ -132,6 +132,11 @@ What we're verifying: org's ~88-face and magit's ~111-face tables stay navigable
- Type "agenda" in the filter
- Reassign one face and watch the preview
Expected: rows are grouped, the filter narrows them, and a reassignment updates the preview live.
+*** TODO F8 opens the agenda from inside a ghostel buffer
+What we're verifying: F8 reaches Emacs (not the pty) inside a ghostel terminal, so it opens the main agenda like everywhere else. Verified at the source/data-structure level (=<f8>= is now a ghostel-keymap-exception and the rebuilt semi-char map no longer forwards it); only the live keypress needs a human.
+- Open a ghostel terminal (=F12=, or an ai-term agent with =F9=) and click into it so point is inside the terminal
+- Press F8
+Expected: =cj/main-agenda-display= runs and the agenda opens; the keypress is NOT echoed into the shell/terminal program.
** TODO [#B] Dashboard keybinding changes :quick:
:PROPERTIES:
:LAST_REVIEWED: 2026-06-06