charmbracelet/bubbletea
Keyboard
Active contributors: aymanbagabas, meowgorithm
Purpose
Bubble Tea's keyboard layer aims to capture every key you can press on every terminal that Go can run on. It supports the basic xterm protocol, xterm modifyOtherKeys=2, and the Kitty keyboard protocol for terminals that opt in.
Working with key messages
case tea.KeyPressMsg:
switch msg.String() {
case "ctrl+c", "q":
return m, tea.Quit
case "up", "k":
m.cursor--
case "enter", "space":
m.toggle()
}Or by inspecting the Key directly:
case tea.KeyPressMsg:
k := msg.Key()
switch k.Code {
case tea.KeyEnter:
...
}
if k.Mod.Contains(tea.ModCtrl) && k.Code == 'c' {
return m, tea.Quit
}KeyMsg (the interface) covers both presses and releases:
case tea.KeyMsg:
switch k := msg.(type) {
case tea.KeyPressMsg: // ...
case tea.KeyReleaseMsg: // ...
}The Key struct
type Key struct {
Text string // printable text or ""
Mod KeyMod // modifier bitmask
Code rune // KeyEnter, 'a', etc.
ShiftedCode rune // 'A' for shift+a (Kitty / Win console only)
BaseCode rune // base key on US PC-101 layout (Kitty / Win console only)
IsRepeat bool // auto-repeat (Kitty / Win console only)
}Key constants
key.go exports a large family of constants pulled in from ultraviolet:
- Movement:
KeyUp,KeyDown,KeyLeft,KeyRight,KeyHome,KeyEnd,KeyPgUp,KeyPgDown,KeyBegin,KeyFind,KeyInsert,KeyDelete,KeySelect. - Function:
KeyF1throughKeyF63(Kitty supports the full range). - Keypad:
KeyKpEnter,KeyKpEqual,KeyKp0–KeyKp9,KeyKpUp/Down/Left/Right, etc. - Locks/media:
KeyCapsLock,KeyNumLock,KeyScrollLock,KeyPause,KeyMediaPlay,KeyMediaPause,KeyLowerVol,KeyRaiseVol,KeyMute, etc. - Modifier keys as keys:
KeyLeftShift,KeyRightCtrl,KeyLeftSuper, etc. - C0/G0:
KeyBackspace,KeyTab,KeyEnter,KeyReturn,KeyEscape,KeyEsc,KeySpace. - Special:
KeyExtendedfor events that carry multiple runes.
Modifiers
mod.go:
const (
ModShift KeyMod = ...
ModAlt KeyMod = ...
ModCtrl KeyMod = ...
ModMeta KeyMod = ...
ModHyper KeyMod = ... // Kitty
ModSuper KeyMod = ... // Win/Cmd
ModCapsLock KeyMod = ...
ModNumLock KeyMod = ...
ModScrollLock KeyMod = ... // Windows API only
)Key.Keystroke() always emits modifiers in the order ctrl → alt → shift → meta → hyper → super, so matching against literal strings like "ctrl+shift+a" is safe.
Kitty keyboard enhancements
Set View.KeyboardEnhancements to opt into extended reporting:
func (m model) View() tea.View {
v := tea.NewView("...")
v.KeyboardEnhancements.ReportEventTypes = true
v.KeyboardEnhancements.ReportAlternateKeys = true
return v
}Available flags (tea.go):
| Flag | What it does |
|---|---|
ReportEventTypes |
Emits KeyReleaseMsg and sets Key.IsRepeat. |
ReportAlternateKeys |
Sends shifted/base alternates for non-printable keys. |
ReportAllKeysAsEscapeCodes |
Encodes every key, including printable text, as escape codes. |
ReportAssociatedText |
Together with the above, reports the text associated with each key. |
After the terminal acknowledges via a KeyboardEnhancementsMsg, the model can ask which features are live with SupportsEventTypes(), SupportsAlternateKeys(), etc. (keyboard.go).
The renderer also unconditionally enables xterm modifyOtherKeys=2, which provides a Kitty-like fidelity boost on terminals that don't support the full Kitty protocol but do support modifyOtherKeys.
Caveats
- Apple Terminal does not support
modifyOtherKeys, the Kitty protocol, or true color. It is explicitly excluded from synchronized output detection intea.go. - Tmux strips many of these features unless explicitly configured. Users may need to set
set -g extended-keys onfor modifier passthrough. - Space bar in v2 returns
"space"fromString()even thoughCode == ' 'andText == " ". The migration guide highlights this.
Related pages
- Input handling — how key bytes become messages.
- Declarative views —
KeyboardEnhancementsis aViewfield. - Reference / messages —
KeyPressMsg,KeyReleaseMsg,KeyboardEnhancementsMsg.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.