Control: tags 1134281 + patch Control: tags 1134281 + pending Dear maintainer,
I've prepared an NMU for golang-code.rocketnine-tslocum-cbind (versioned as 0.1.5-3.1) and uploaded it to DELAYED/2. Please feel free to tell me if I should cancel it. I have seen #1139314, this is a short-term fix. cu Adrian
diffstat for golang-code.rocketnine-tslocum-cbind-0.1.5 golang-code.rocketnine-tslocum-cbind-0.1.5 changelog | 7 control | 2 patches/0001-Support-CSI-u-mode-introduced-in-tcell-v2.10.0.patch | 212 ++++++++++ patches/series | 1 4 files changed, 221 insertions(+), 1 deletion(-) diff -Nru golang-code.rocketnine-tslocum-cbind-0.1.5/debian/changelog golang-code.rocketnine-tslocum-cbind-0.1.5/debian/changelog --- golang-code.rocketnine-tslocum-cbind-0.1.5/debian/changelog 2021-06-25 11:43:38.000000000 +0300 +++ golang-code.rocketnine-tslocum-cbind-0.1.5/debian/changelog 2026-06-19 18:28:47.000000000 +0300 @@ -1,3 +1,10 @@ +golang-code.rocketnine-tslocum-cbind (0.1.5-3.1) unstable; urgency=medium + + * Non-maintainer upload. + * Backport upstream fix for FTBFS with tcell >= 2.10. (Closes: #1134281) + + -- Adrian Bunk <[email protected]> Fri, 19 Jun 2026 18:28:47 +0300 + golang-code.rocketnine-tslocum-cbind (0.1.5-3) unstable; urgency=medium * Team Upload. diff -Nru golang-code.rocketnine-tslocum-cbind-0.1.5/debian/control golang-code.rocketnine-tslocum-cbind-0.1.5/debian/control --- golang-code.rocketnine-tslocum-cbind-0.1.5/debian/control 2021-04-05 12:58:47.000000000 +0300 +++ golang-code.rocketnine-tslocum-cbind-0.1.5/debian/control 2026-06-19 18:20:41.000000000 +0300 @@ -6,7 +6,7 @@ Build-Depends: debhelper-compat (= 13), dh-golang, golang-any, - golang-github-gdamore-tcell.v2-dev + golang-github-gdamore-tcell.v2-dev (>= 2.12) Standards-Version: 4.5.1 Homepage: https://code.rocketnine.space/tslocum/cbind Vcs-Browser: https://salsa.debian.org/go-team/packages/golang-code.rocketnine-tslocum-cbind diff -Nru golang-code.rocketnine-tslocum-cbind-0.1.5/debian/patches/0001-Support-CSI-u-mode-introduced-in-tcell-v2.10.0.patch golang-code.rocketnine-tslocum-cbind-0.1.5/debian/patches/0001-Support-CSI-u-mode-introduced-in-tcell-v2.10.0.patch --- golang-code.rocketnine-tslocum-cbind-0.1.5/debian/patches/0001-Support-CSI-u-mode-introduced-in-tcell-v2.10.0.patch 1970-01-01 02:00:00.000000000 +0200 +++ golang-code.rocketnine-tslocum-cbind-0.1.5/debian/patches/0001-Support-CSI-u-mode-introduced-in-tcell-v2.10.0.patch 2026-06-19 18:19:53.000000000 +0300 @@ -0,0 +1,212 @@ +From 30873c5326cba1b1f127e037f4e1c3e1ba1ca119 Mon Sep 17 00:00:00 2001 +From: Noboru Saito <[email protected]> +Date: Wed, 26 Nov 2025 09:24:07 +0900 +Subject: Support CSI u mode introduced in tcell v2.10.0 + +Fixes #1 + +Starting from tcell v2.10.0, CSI u mode support was added which changes +how Ctrl+letter key events are reported. Previously, Ctrl+C was reported +as KeyCtrlC (key code 3), but now it's reported as ModCtrl + KeyRune + 'c'. + +This commit adapts cbind to handle both the legacy KeyCtrlA-Z format and +the new CSI u format: + +- Modified Capture() to convert KeyCtrlA-Z events to the new rune-based + format (ModCtrl + KeyRune + 'a'-'z') for consistent internal handling +- Modified Encode() to convert KeyCtrlA-Z to rune format when encoding +- Modified Decode() to normalize Ctrl+letter keys to lowercase +- Removed old ctrlKeys mapping logic from SetKey() and SetRune() that is + no longer needed with the new approach +- Updated tests to use Set() method for consistent handler registration +- Simplified TestConfiguration by removing tcell event normalization + checks that were causing false failures +- Updated test cases to reflect the new rune-based Ctrl key format +- Commented out KeyCtrlRightSq test due to upstream tcell bug (PR #853) +--- + configuration.go | 37 ++++++++++++++++--------------------- + configuration_test.go | 29 ++++++----------------------- + key.go | 18 ++++++++---------- + key_test.go | 11 ++++++----- + 4 files changed, 36 insertions(+), 59 deletions(-) + +diff --git a/configuration.go b/configuration.go +index 2b42a93..57d2519 100644 +--- a/configuration.go ++++ b/configuration.go +@@ -3,7 +3,6 @@ package cbind + import ( + "fmt" + "sync" +- "unicode" + + "github.com/gdamore/tcell/v2" + ) +@@ -51,15 +50,6 @@ func (c *Configuration) SetKey(mod tcell.ModMask, key tcell.Key, handler func(ev + key = tcell.KeyBacktab + } + +- if mod&tcell.ModCtrl == 0 && key != tcell.KeyBackspace && key != tcell.KeyTab && key != tcell.KeyEnter { +- for _, ctrlKey := range ctrlKeys { +- if key == ctrlKey { +- mod |= tcell.ModCtrl +- break +- } +- } +- } +- + c.handlers[fmt.Sprintf("%d-%d", mod, key)] = handler + } + +@@ -76,14 +66,6 @@ func (c *Configuration) SetRune(mod tcell.ModMask, ch rune, handler func(ev *tce + return + } + +- if mod&tcell.ModCtrl != 0 { +- k, ok := ctrlKeys[unicode.ToLower(ch)] +- if ok { +- c.SetKey(mod, k, handler) +- return +- } +- } +- + c.mutex.Lock() + defer c.mutex.Unlock() + +@@ -99,11 +81,24 @@ func (c *Configuration) Capture(ev *tcell.EventKey) *tcell.EventKey { + return nil + } + ++ mod := ev.Modifiers() ++ key := ev.Key() ++ ch := ev.Rune() ++ ++ if key != tcell.KeyRune && key != tcell.KeyBackspace && key != tcell.KeyTab && key != tcell.KeyEnter && key != tcell.KeyEscape { ++ // Convert KeyCtrlA-Z to rune format, but skip special keys first ++ if key >= tcell.KeyCtrlA && key <= tcell.KeyCtrlZ { ++ mod |= tcell.ModCtrl ++ ch = rune('a' + (key - tcell.KeyCtrlA)) ++ key = tcell.KeyRune ++ } ++ } ++ + var keyName string +- if ev.Key() != tcell.KeyRune { +- keyName = fmt.Sprintf("%d-%d", ev.Modifiers(), ev.Key()) ++ if key != tcell.KeyRune { ++ keyName = fmt.Sprintf("%d-%d", mod, key) + } else { +- keyName = fmt.Sprintf("%d:%d", ev.Modifiers(), ev.Rune()) ++ keyName = fmt.Sprintf("%d:%d", mod, ch) + } + + handler := c.handlers[keyName] +diff --git a/configuration_test.go b/configuration_test.go +index d6c98fa..68830ca 100644 +--- a/configuration_test.go ++++ b/configuration_test.go +@@ -23,18 +23,13 @@ func TestConfiguration(t *testing.T) { + wg[i].Add(pressTimes) + + i := i // Capture +- if c.key != tcell.KeyRune { +- config.SetKey(c.mod, c.key, func(ev *tcell.EventKey) *tcell.EventKey { +- wg[i].Done() +- return nil +- }) +- } else { +- config.SetRune(c.mod, c.ch, func(ev *tcell.EventKey) *tcell.EventKey { +- wg[i].Done() +- return nil +- }) ++ err := config.Set(c.encoded, func(ev *tcell.EventKey) *tcell.EventKey { ++ wg[i].Done() ++ return nil ++ }) ++ if err != nil { ++ t.Fatalf("failed to set keybind for %s: %s", c.encoded, err) + } +- + } + + done := make(chan struct{}) +@@ -53,18 +48,6 @@ func TestConfiguration(t *testing.T) { + for i, c := range testCases { + i, c := i, c // Capture + go func() { +- k := tcell.NewEventKey(c.key, c.ch, c.mod) +- if k.Key() != c.key { +- errs <- fmt.Errorf("failed to test capturing keybinds: tcell modified EventKey.Key: expected %d, got %d", c.key, k.Key()) +- return +- } else if k.Rune() != c.ch { +- errs <- fmt.Errorf("failed to test capturing keybinds: tcell modified EventKey.Rune: expected %d, got %d", c.ch, k.Rune()) +- return +- } else if k.Modifiers() != c.mod { +- errs <- fmt.Errorf("failed to test capturing keybinds: tcell modified EventKey.Modifiers: expected %d, got %d", c.mod, k.Modifiers()) +- return +- } +- + ev := config.Capture(tcell.NewEventKey(c.key, c.ch, c.mod)) + if ev != nil { + errs <- fmt.Errorf("failed to test capturing keybinds: failed to register case %d event %d %d %d", i, c.mod, c.key, c.ch) +diff --git a/key.go b/key.go +index b30fec8..1465242 100644 +--- a/key.go ++++ b/key.go +@@ -140,16 +140,9 @@ DECODEPIECE: + ch = rune(piece[0]) + } + +- if mod&tcell.ModCtrl != 0 { +- k, ok := ctrlKeys[unicode.ToLower(ch)] +- if ok { +- key = k +- if UnifyEnterKeys && key == ctrlKeys['j'] { +- key = tcell.KeyEnter +- } else if key < 0x80 { +- ch = rune(key) +- } +- } ++ // Normalize Ctrl+A-Z to lowercase ++ if mod&tcell.ModCtrl != 0 && key == tcell.KeyRune { ++ ch = unicode.ToLower(ch) + } + + return mod, key, ch, nil +@@ -164,6 +157,11 @@ func Encode(mod tcell.ModMask, key tcell.Key, ch rune) (string, error) { + if key == tcell.KeyBackspace || key == tcell.KeyTab || key == tcell.KeyEnter { + mod ^= tcell.ModCtrl + } else { ++ if key >= tcell.KeyCtrlA && key <= tcell.KeyCtrlZ { ++ mod |= tcell.ModCtrl ++ ch = rune('a' + (key - tcell.KeyCtrlA)) ++ key = tcell.KeyRune ++ } + for _, ctrlKey := range ctrlKeys { + if key == ctrlKey { + mod ^= tcell.ModCtrl +diff --git a/key_test.go b/key_test.go +index 7063583..8271fa0 100644 +--- a/key_test.go ++++ b/key_test.go +@@ -27,11 +27,12 @@ var testCases = []testCase{ + {mod: tcell.ModAlt, key: tcell.KeyRune, ch: '1', encoded: "Alt+1"}, + {mod: tcell.ModAlt, key: tcell.KeyTab, ch: rune(tcell.KeyTab), encoded: "Alt+Tab"}, + {mod: tcell.ModAlt, key: tcell.KeyEnter, ch: rune(tcell.KeyEnter), encoded: "Alt+Enter"}, +- {mod: tcell.ModAlt, key: tcell.KeyBackspace2, ch: rune(tcell.KeyBackspace2), encoded: "Alt+Backspace"}, +- {mod: tcell.ModCtrl, key: tcell.KeyCtrlC, ch: rune(tcell.KeyCtrlC), encoded: "Ctrl+C"}, +- {mod: tcell.ModCtrl, key: tcell.KeyCtrlD, ch: rune(tcell.KeyCtrlD), encoded: "Ctrl+D"}, +- {mod: tcell.ModCtrl, key: tcell.KeyCtrlSpace, ch: rune(tcell.KeyCtrlSpace), encoded: "Ctrl+Space"}, +- {mod: tcell.ModCtrl, key: tcell.KeyCtrlRightSq, ch: rune(tcell.KeyCtrlRightSq), encoded: "Ctrl+]"}, ++ {mod: tcell.ModAlt, key: tcell.KeyDelete, ch: 0, encoded: "Alt+Delete"}, ++ {mod: tcell.ModCtrl, key: tcell.KeyRune, ch: 'c', encoded: "Ctrl+c"}, ++ {mod: tcell.ModCtrl, key: tcell.KeyRune, ch: 'd', encoded: "Ctrl+d"}, ++ {mod: tcell.ModCtrl, key: tcell.KeyRune, ch: ' ', encoded: "Ctrl+Space"}, ++ // The test for tcell.KeyCtrlRightSq has been avoided due to a problem with tcell (#853). ++ //{mod: tcell.ModCtrl, key: tcell.KeyCtrlRightSq, ch: rune(tcell.KeyCtrlRightSq), encoded: "Ctrl+]"}, + {mod: tcell.ModCtrl | tcell.ModAlt, key: tcell.KeyRune, ch: '+', encoded: "Ctrl+Alt++"}, + {mod: tcell.ModCtrl | tcell.ModShift, key: tcell.KeyRune, ch: '+', encoded: "Ctrl+Shift++"}, + } +-- +2.47.3 + diff -Nru golang-code.rocketnine-tslocum-cbind-0.1.5/debian/patches/series golang-code.rocketnine-tslocum-cbind-0.1.5/debian/patches/series --- golang-code.rocketnine-tslocum-cbind-0.1.5/debian/patches/series 1970-01-01 02:00:00.000000000 +0200 +++ golang-code.rocketnine-tslocum-cbind-0.1.5/debian/patches/series 2026-06-19 18:20:07.000000000 +0300 @@ -0,0 +1 @@ +0001-Support-CSI-u-mode-introduced-in-tcell-v2.10.0.patch

