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}