keys.go

  1package models
  2
  3import (
  4	"charm.land/bubbles/v2/key"
  5)
  6
  7type KeyMap struct {
  8	Select,
  9	Next,
 10	Previous,
 11	Choose,
 12	Tab,
 13	Close key.Binding
 14
 15	isAPIKeyHelp  bool
 16	isAPIKeyValid bool
 17
 18	isHyperDeviceFlow bool
 19
 20	isClaudeAuthChoiceHelp    bool
 21	isClaudeOAuthHelp         bool
 22	isClaudeOAuthURLState     bool
 23	isClaudeOAuthHelpComplete bool
 24}
 25
 26func DefaultKeyMap() KeyMap {
 27	return KeyMap{
 28		Select: key.NewBinding(
 29			key.WithKeys("enter", "ctrl+y"),
 30			key.WithHelp("enter", "choose"),
 31		),
 32		Next: key.NewBinding(
 33			key.WithKeys("down", "ctrl+n"),
 34			key.WithHelp("↓", "next item"),
 35		),
 36		Previous: key.NewBinding(
 37			key.WithKeys("up", "ctrl+p"),
 38			key.WithHelp("↑", "previous item"),
 39		),
 40		Choose: key.NewBinding(
 41			key.WithKeys("left", "right", "h", "l"),
 42			key.WithHelp("←→", "choose"),
 43		),
 44		Tab: key.NewBinding(
 45			key.WithKeys("tab"),
 46			key.WithHelp("tab", "toggle type"),
 47		),
 48		Close: key.NewBinding(
 49			key.WithKeys("esc", "alt+esc"),
 50			key.WithHelp("esc", "exit"),
 51		),
 52	}
 53}
 54
 55// KeyBindings implements layout.KeyMapProvider
 56func (k KeyMap) KeyBindings() []key.Binding {
 57	return []key.Binding{
 58		k.Select,
 59		k.Next,
 60		k.Previous,
 61		k.Tab,
 62		k.Close,
 63	}
 64}
 65
 66// FullHelp implements help.KeyMap.
 67func (k KeyMap) FullHelp() [][]key.Binding {
 68	m := [][]key.Binding{}
 69	slice := k.KeyBindings()
 70	for i := 0; i < len(slice); i += 4 {
 71		end := min(i+4, len(slice))
 72		m = append(m, slice[i:end])
 73	}
 74	return m
 75}
 76
 77// ShortHelp implements help.KeyMap.
 78func (k KeyMap) ShortHelp() []key.Binding {
 79	if k.isHyperDeviceFlow {
 80		return []key.Binding{
 81			key.NewBinding(
 82				key.WithKeys("c"),
 83				key.WithHelp("c", "copy code"),
 84			),
 85			key.NewBinding(
 86				key.WithKeys("enter"),
 87				key.WithHelp("enter", "copy & open"),
 88			),
 89			k.Close,
 90		}
 91	}
 92	if k.isClaudeAuthChoiceHelp {
 93		return []key.Binding{
 94			key.NewBinding(
 95				key.WithKeys("left", "right", "h", "l"),
 96				key.WithHelp("←→", "choose"),
 97			),
 98			key.NewBinding(
 99				key.WithKeys("enter"),
100				key.WithHelp("enter", "accept"),
101			),
102			key.NewBinding(
103				key.WithKeys("esc"),
104				key.WithHelp("esc", "back"),
105			),
106		}
107	}
108	if k.isClaudeOAuthHelp {
109		if k.isClaudeOAuthHelpComplete {
110			return []key.Binding{
111				key.NewBinding(
112					key.WithKeys("enter"),
113					key.WithHelp("enter", "close"),
114				),
115			}
116		}
117
118		enterHelp := "submit"
119		if k.isClaudeOAuthURLState {
120			enterHelp = "open"
121		}
122
123		bindings := []key.Binding{
124			key.NewBinding(
125				key.WithKeys("enter"),
126				key.WithHelp("enter", enterHelp),
127			),
128		}
129
130		if k.isClaudeOAuthURLState {
131			bindings = append(bindings, key.NewBinding(
132				key.WithKeys("c"),
133				key.WithHelp("c", "copy url"),
134			))
135		}
136
137		bindings = append(bindings, key.NewBinding(
138			key.WithKeys("esc"),
139			key.WithHelp("esc", "back"),
140		))
141
142		return bindings
143	}
144	if k.isAPIKeyHelp && !k.isAPIKeyValid {
145		return []key.Binding{
146			key.NewBinding(
147				key.WithKeys("enter"),
148				key.WithHelp("enter", "submit"),
149			),
150			k.Close,
151		}
152	} else if k.isAPIKeyValid {
153		return []key.Binding{
154			k.Select,
155		}
156	}
157	return []key.Binding{
158		key.NewBinding(
159			key.WithKeys("down", "up"),
160			key.WithHelp("↑↓", "choose"),
161		),
162		k.Tab,
163		k.Select,
164		k.Close,
165	}
166}