charmbracelet / bubbletea

A powerful little TUI framework 🏗

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Inconsistent key inputs between terminal apps on Mac (Terminal and iTerm2)

blackmann opened this issue · comments

I'm confident they may be having separate underlying implementations on how key inputs are handled but I don't know how to [think or] approach it as a TUI app.

For my particular case, I have set up a keybind like this:

func NewViewport() Model {
	tabs := []string{"Headers (q)", "Request Body (w)", "Response (e)"}
	keybinds := keymap{
		nextTab:     key.NewBinding(key.WithKeys("alt+f"), key.WithHelp("⌥→", "Next tab")),
		previousTab: key.NewBinding(key.WithKeys("alt+b"), key.WithHelp("⌥←", "Prev tab")),
	}

	return Model{
		tabs:     tabs,
		keybinds: keybinds,
	}
}

So alt+f for example is used for switching to the next tab but if I enter option+forward (which I assume is alt+f in bubbletea land) in iTerm and log the key, I get

Key is alt+�

"Key is" is my logging prefix. This effectively allows the switch case to not match my binding. However on iTerm, I get alt+f.

What's the general approach for such cases apart from considering alternate keybinds?

As a secondary request, is there a list/file of all the keys in their string representation for reference for bubbletea?

Hi! So terminals don't have a notion of the option key. On macOS Terminal and iTerm2 you need to tick a box in settings to have option send alt (which is often called meta). What it sounds like is happening is that one of your terminals is sending alt/meta from the option key and the other is not.

On a personal note, when I'm on a Mac I setup Kitty so that I my left option key is bound to alt/meta while the right option remains bound to option so I still have access to the system-wide, option-based keybindings—particularly those that let me enter special characters.


Separately, per your question about string representations for keys, there's no official reference for string representations of keys at the moment, but you can get an idea what they look like below. Not listed are basic latin characters like "a", "b", and so on as well as " " which is the literal space key. Also keep in mind that many of these can receive an "alt+" modifier, but not all because of limitations of terminal emulators for a variety of reasons.

bubbletea/key.go

Lines 225 to 293 in 515ef02

// Mapping for control keys to friendly consts.
var keyNames = map[KeyType]string{
keyNUL: "ctrl+@", // also ctrl+`
keySOH: "ctrl+a",
keySTX: "ctrl+b",
keyETX: "ctrl+c",
keyEOT: "ctrl+d",
keyENQ: "ctrl+e",
keyACK: "ctrl+f",
keyBEL: "ctrl+g",
keyBS: "ctrl+h",
keyHT: "tab", // also ctrl+i
keyLF: "ctrl+j",
keyVT: "ctrl+k",
keyFF: "ctrl+l",
keyCR: "enter",
keySO: "ctrl+n",
keySI: "ctrl+o",
keyDLE: "ctrl+p",
keyDC1: "ctrl+q",
keyDC2: "ctrl+r",
keyDC3: "ctrl+s",
keyDC4: "ctrl+t",
keyNAK: "ctrl+u",
keySYN: "ctrl+v",
keyETB: "ctrl+w",
keyCAN: "ctrl+x",
keyEM: "ctrl+y",
keySUB: "ctrl+z",
keyESC: "esc",
keyFS: "ctrl+\\",
keyGS: "ctrl+]",
keyRS: "ctrl+^",
keyUS: "ctrl+_",
keySP: "space",
keyDEL: "backspace",
KeyRunes: "runes",
KeyUp: "up",
KeyDown: "down",
KeyRight: "right",
KeyLeft: "left",
KeyShiftTab: "shift+tab",
KeyHome: "home",
KeyEnd: "end",
KeyPgUp: "pgup",
KeyPgDown: "pgdown",
KeyDelete: "delete",
KeyF1: "f1",
KeyF2: "f2",
KeyF3: "f3",
KeyF4: "f4",
KeyF5: "f5",
KeyF6: "f6",
KeyF7: "f7",
KeyF8: "f8",
KeyF9: "f9",
KeyF10: "f10",
KeyF11: "f11",
KeyF12: "f12",
KeyF13: "f13",
KeyF14: "f14",
KeyF15: "f15",
KeyF16: "f16",
KeyF17: "f17",
KeyF18: "f18",
KeyF19: "f19",
KeyF20: "f20",
}

Thanks @meowgorithm. This answer is helpful.