Skip to content

Commit

Permalink
feat: add kitty keyboard uniform key layout support
Browse files Browse the repository at this point in the history
This uses kitty keyboard protocol "Report alternate keys" and "Report
all keys as escape codes" to report key events as though they were on a
PC-101 layout. This is useful for uniform key event reporting across
different keyboard layouts.
  • Loading branch information
aymanbagabas committed Sep 20, 2024
1 parent a039baa commit a1ff722
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 2 deletions.
24 changes: 24 additions & 0 deletions keyboard.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,17 @@ func WithKeyReleases(k *keyboardEnhancements) {
k.kittyFlags |= ansi.KittyReportEventTypes
}

// WithUniformKeyLayout enables support for reporting key events as though they
// were on a PC-101 layout. This is useful for uniform key event reporting
// across different keyboard layouts. This is equivalent to the Kitty keyboard
// protocol "Report alternate keys" and "Report all keys as escape codes"
// progressive enhancement features.
//
// Note that not all terminals support this feature.
func WithUniformKeyLayout(k *keyboardEnhancements) {
k.kittyFlags |= ansi.KittyReportAlternateKeys | ansi.KittyReportAllKeysAsEscapeCodes
}

// withKeyDisambiguation enables support for disambiguating keyboard escape
// codes. This is useful for terminals that support the Kitty keyboard protocol
// "Disambiguate escape codes" progressive enhancement feature or the XTerm
Expand Down Expand Up @@ -102,3 +113,16 @@ func (k KeyboardEnhancementsMsg) SupportsKeyReleases() bool {
}
return k.kittyFlags&ansi.KittyReportEventTypes != 0
}

// SupportsKeyBaseLayout returns whether the terminal supports reporting key
// events as though they were on a PC-101 layout.
func (k KeyboardEnhancementsMsg) SupportsUniformKeyLayout() bool {
if runtime.GOOS == "windows" {
// We use Windows Console API which supports reporting key events as
// though they were on a PC-101 layout.
return true
}
return k.SupportsKeyDisambiguation() &&
k.kittyFlags&ansi.KittyReportAlternateKeys != 0 &&
k.kittyFlags&ansi.KittyReportAllKeysAsEscapeCodes != 0
}
8 changes: 7 additions & 1 deletion kitty.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ func fromKittyMod(mod int) KeyMod {
// CSI unicode-key-code:alternate-key-codes ; modifiers:event-type ; text-as-codepoints u
//
// See https://sw.kovidgoyal.net/kitty/keyboard-protocol/
func parseKittyKeyboard(csi *ansi.CsiSequence) Msg {
func parseKittyKeyboard(csi *ansi.CsiSequence) (msg Msg) {
var isRelease bool
key := Key{}

Expand Down Expand Up @@ -253,6 +253,12 @@ func parseKittyKeyboard(csi *ansi.CsiSequence) Msg {
}
}

if key.Mod == ModShift && key.ShiftedCode == 0 {
if unicode.IsLower(key.Code) {
key.ShiftedCode = unicode.ToUpper(key.Code)
}
}

noneOrShifted := key.Mod <= ModShift && key.Code != KeyLeftShift && key.Code != KeyRightShift
if len(key.Text) == 0 && noneOrShifted {
if key.ShiftedCode != 0 && unicode.IsPrint(key.ShiftedCode) {
Expand Down
18 changes: 17 additions & 1 deletion tea.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"io"
"os"
"os/signal"
"runtime"
"runtime/debug"
"sync"
"sync/atomic"
Expand Down Expand Up @@ -476,6 +477,12 @@ func (p *Program) eventLoop(model Model, cmds chan Cmd) (Model, error) {
}

case enableKeyboardEnhancementsMsg:
if runtime.GOOS == "windows" {
// We use the Windows Console API which supports keyboard
// enhancements.
break
}

var ke keyboardEnhancements
for _, e := range msg {
e(&ke)
Expand All @@ -494,6 +501,12 @@ func (p *Program) eventLoop(model Model, cmds chan Cmd) (Model, error) {
}

case disableKeyboardEnhancementsMsg:
if runtime.GOOS == "windows" {
// We use the Windows Console API which supports keyboard
// enhancements.
break
}

if p.keyboard.modifyOtherKeys > 0 {
p.execute(ansi.DisableModifyOtherKeys)
p.keyboard.modifyOtherKeys = 0
Expand Down Expand Up @@ -706,7 +719,10 @@ func (p *Program) Run() (Model, error) {
p.execute(ansi.EnableReportFocus)
p.modes[ansi.ReportFocusMode] = true
}
if p.startupOptions&withKeyboardEnhancements != 0 {
if p.startupOptions&withKeyboardEnhancements != 0 && runtime.GOOS != "windows" {
// We use the Windows Console API which supports keyboard
// enhancements.

if p.keyboard.modifyOtherKeys > 0 {
p.execute(ansi.ModifyOtherKeys(p.keyboard.modifyOtherKeys))
p.execute(ansi.RequestModifyOtherKeys)
Expand Down

0 comments on commit a1ff722

Please sign in to comment.