aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--modules/eat-config.el27
-rw-r--r--tests/test-eat-config--charset-never-nil.el43
2 files changed, 70 insertions, 0 deletions
diff --git a/modules/eat-config.el b/modules/eat-config.el
index 1de24dc4..d66507c4 100644
--- a/modules/eat-config.el
+++ b/modules/eat-config.el
@@ -83,6 +83,33 @@ ARGS is (TERMINAL OUTPUT)."
(advice-add 'eat-term-process-output :filter-args #'cj/--eat-reset-sgr-at-newline)
+;; EAT 0.9.4 charset-designation bug. Its parser (eat--t-handle-output) accepts
+;; a wide set of final bytes for an `ESC ( x' charset designation, but the store
+;; step (eat--t-set-charset) only maps two of them: "0" -> dec-line-drawing and
+;; "B" -> us-ascii. Any other accepted byte (e.g. ESC ( A, the UK set) falls
+;; through the `pcase' to nil, and nil gets stored as that slot's charset. The
+;; next character written then trips (cl-assert charset) in eat--t-write, and
+;; because writes are driven by the eat--process-output-queue timer it errors
+;; once per output chunk -- the "cl-assertion-failed (charset) [N times]" storm.
+;; We can't patch the vendored pcase without a fork the next package update would
+;; revert, so guard the one function that injects the nil: coerce a nil charset
+;; to us-ascii (the safe default the byte would have mapped to) before it lands.
+
+(declare-function eat--t-set-charset "eat")
+
+(defun cj/--eat-charset-never-nil (args)
+ "`:filter-args' advice for `eat--t-set-charset'.
+ARGS is (SLOT CHARSET). Return it with a nil CHARSET replaced by
+`us-ascii', so EAT never stores nil for a charset designation it does
+not recognize (which would later trip (cl-assert charset) on write)."
+ (list (car args) (or (cadr args) 'us-ascii)))
+
+;; eat--t-set-charset is an internal function defined only once eat.el loads
+;; (the package is deferred), so add the advice after load rather than at top
+;; level.
+(with-eval-after-load 'eat
+ (advice-add 'eat--t-set-charset :filter-args #'cj/--eat-charset-never-nil))
+
;; ------------------------------- eat package ---------------------------------
(use-package eat
diff --git a/tests/test-eat-config--charset-never-nil.el b/tests/test-eat-config--charset-never-nil.el
new file mode 100644
index 00000000..dfd38cb5
--- /dev/null
+++ b/tests/test-eat-config--charset-never-nil.el
@@ -0,0 +1,43 @@
+;;; test-eat-config--charset-never-nil.el --- Tests for the EAT charset nil-guard -*- lexical-binding: t; -*-
+
+;;; Commentary:
+;; Unit tests for `cj/--eat-charset-never-nil', the `:filter-args' guard on
+;; `eat--t-set-charset'. eat 0.9.4 accepts more charset-designation final
+;; bytes in its parser than its store step maps, so an unmapped designation
+;; (e.g. ESC ( A) stores nil as that slot's charset; the next character write
+;; then trips (cl-assert charset) in `eat--t-write', repeatedly, via the
+;; output-queue timer. The guard coerces a nil charset to `us-ascii' before
+;; it is ever stored, so the assertion can't fire.
+
+;;; Code:
+
+(require 'ert)
+
+;; Stub keymap dep before loading the module (matches the other module tests).
+(defvar cj/custom-keymap (make-sparse-keymap)
+ "Stub keymap for testing.")
+
+(require 'eat-config)
+
+(ert-deftest test-eat-config-charset-never-nil-normal-real-charset-unchanged ()
+ "Normal: a real charset value passes through unchanged."
+ (should (equal (cj/--eat-charset-never-nil '(g0 us-ascii))
+ '(g0 us-ascii)))
+ (should (equal (cj/--eat-charset-never-nil '(g1 dec-line-drawing))
+ '(g1 dec-line-drawing))))
+
+(ert-deftest test-eat-config-charset-never-nil-error-nil-becomes-us-ascii ()
+ "Error: a nil charset (unmapped designation) is coerced to `us-ascii'."
+ (should (equal (cj/--eat-charset-never-nil '(g0 nil))
+ '(g0 us-ascii)))
+ (should (equal (cj/--eat-charset-never-nil '(g3 nil))
+ '(g3 us-ascii))))
+
+(ert-deftest test-eat-config-charset-never-nil-boundary-preserves-slot ()
+ "Boundary: the slot symbol is preserved for every slot, coerced or not."
+ (dolist (slot '(g0 g1 g2 g3))
+ (should (eq (car (cj/--eat-charset-never-nil (list slot nil))) slot))
+ (should (eq (cadr (cj/--eat-charset-never-nil (list slot nil))) 'us-ascii))))
+
+(provide 'test-eat-config--charset-never-nil)
+;;; test-eat-config--charset-never-nil.el ends here