@@ -9,18 +9,21 @@ import (
99 "github.com/charmbracelet/huh"
1010 "github.com/charmbracelet/lipgloss"
1111
12- "github.com/xinnjie/onekeymap-cli/internal/keymap"
1312 "github.com/xinnjie/onekeymap-cli/internal/mappings"
14- "github.com/xinnjie/onekeymap-cli/internal/platform"
1513 keymapv1 "github.com/xinnjie/onekeymap-cli/protogen/keymap/v1"
1614)
1715
1816const (
1917 columnWidthActionName = 48
2018 columnWidthKeybinding = 30
21- minViewHeight = 6
19+ minViewHeight = 10 // Need space for header + rows
2220 categoryPanelWidth = 25
23- viewHeightMargin = 7
21+ viewHeightMargin = 10 // Space for help text + details
22+ detailsHeight = 8 // Estimated height for action details
23+ defaultInitialWidth = 120
24+ defaultInitialHeight = 30
25+ tablePaddingWidth = 6 // Padding for borders and spacing
26+ panelBorderWidth = 4 // Width adjustment for panel borders
2427)
2528
2629var _ tea.Model = (* KeymapViewModel )(nil )
@@ -43,6 +46,8 @@ func NewKeymapViewModel(setting *keymapv1.Keymap, mc *mappings.MappingConfig) te
4346 m := & KeymapViewModel {
4447 setting : setting ,
4548 mc : mc ,
49+ width : defaultInitialWidth ,
50+ height : defaultInitialHeight ,
4651 }
4752 m .initCategories ()
4853 m .selectedCategory = "All"
@@ -57,6 +62,13 @@ func NewKeymapViewModel(setting *keymapv1.Keymap, mc *mappings.MappingConfig) te
5762 Options (options ... ).
5863 Value (& m .selectedCategory )
5964
65+ // Calculate initial table dimensions
66+ initialTableWidth := m .width - categoryPanelWidth - tablePaddingWidth
67+ initialTableHeight := m .height - viewHeightMargin - detailsHeight
68+ if initialTableHeight < minViewHeight {
69+ initialTableHeight = minViewHeight
70+ }
71+
6072 m .actionTable = table .New (
6173 table .WithColumns (
6274 []table.Column {
@@ -66,6 +78,8 @@ func NewKeymapViewModel(setting *keymapv1.Keymap, mc *mappings.MappingConfig) te
6678 ),
6779 table .WithRows (m .keybindingRows ()),
6880 table .WithFocused (true ),
81+ table .WithHeight (initialTableHeight ),
82+ table .WithWidth (initialTableWidth ),
6983 )
7084 return m
7185}
@@ -93,12 +107,20 @@ func (m *KeymapViewModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
93107 m .actionTable .SetRows (m .keybindingRows ())
94108 }
95109 case tea.WindowSizeMsg :
96- h := msg .Height - viewHeightMargin
97- if h < minViewHeight {
98- h = minViewHeight
110+ m .width , m .height = msg .Width , msg .Height
111+
112+ // Calculate available width for table (total - category panel)
113+ tableWidth := m .width - categoryPanelWidth - tablePaddingWidth
114+
115+ // Calculate available height for table (total - help - details - margins)
116+ tableHeight := m .height - viewHeightMargin - detailsHeight
117+ if tableHeight < minViewHeight {
118+ tableHeight = minViewHeight
99119 }
100- m .width , m .height = msg .Width , h
101- m .actionTable .SetHeight (h )
120+
121+ // Update table dimensions
122+ m .actionTable .SetHeight (tableHeight )
123+ m .actionTable .SetWidth (tableWidth )
102124 }
103125
104126 var tableCmd tea.Cmd
@@ -109,7 +131,10 @@ func (m *KeymapViewModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
109131}
110132
111133func (m * KeymapViewModel ) View () string {
112- help := "OneKeymap Viewer (read-only) — Use ↑/↓ navigate, Tab/Shift+Tab to switch category, q to quit\n \n "
134+ // Help text at the top
135+ help := lipgloss .NewStyle ().
136+ Foreground (lipgloss .Color ("241" )).
137+ Render ("OneKeymap Viewer (read-only) — Use ↑/↓ navigate, Tab/Shift+Tab to switch category, q to quit" )
113138
114139 // Left panel: category select
115140 categoryPanel := lipgloss .NewStyle ().
@@ -119,35 +144,44 @@ func (m *KeymapViewModel) View() string {
119144 Render (m .categorySelect .View ())
120145
121146 // Right panel: table and details
122- rightPanelContent := m .actionTable .View () + "\n "
123- selectedID := m .selectedActionID ()
124- if selectedID != "" {
125- details := newActionDetailsViewModel (selectedID , m .mc )
126- rightPanelContent += details .View ()
147+ var rightPanelContent string
148+ if m .width > 0 && m .height > 0 {
149+ rightPanelContent = m .actionTable .View ()
150+ selectedID := m .selectedActionID ()
151+ if selectedID != "" {
152+ details := newActionDetailsViewModel (selectedID , m .mc )
153+ rightPanelContent += "\n " + details .View ()
154+ }
127155 }
128156
129157 rightPanel := lipgloss .NewStyle ().
130- Width (m .width - categoryPanelWidth ).
158+ Width (m .width - categoryPanelWidth - panelBorderWidth ).
131159 Render (rightPanelContent )
132160
133- body := lipgloss . JoinHorizontal ( lipgloss . Top , categoryPanel , rightPanel )
134- body = lipgloss .JoinVertical (lipgloss .Top , body , help )
161+ // Combine panels horizontally
162+ mainContent : = lipgloss .JoinHorizontal (lipgloss .Top , categoryPanel , rightPanel )
135163
136- return body
164+ // Combine help and main content vertically
165+ return lipgloss .JoinVertical (lipgloss .Left , help , "" , mainContent )
137166}
138167
139168func (m * KeymapViewModel ) selectedActionID () string {
140169 row := m .actionTable .SelectedRow ()
141170 if len (row ) == 0 {
142171 return ""
143172 }
144- return row [0 ]
173+ for _ , actionName := range m .mc .Mappings {
174+ if actionName .Name == row [0 ] {
175+ return actionName .ID
176+ }
177+ }
178+ return ""
145179}
146180
147181func (m * KeymapViewModel ) initCategories () {
148182 catSet := map [string ]struct {}{}
149183 for _ , kb := range m .setting .GetActions () {
150- if mapping := m .mc .FindByUniversalAction (kb .GetName ()); mapping != nil {
184+ if mapping := m .mc .Get (kb .GetName ()); mapping != nil {
151185 if mapping .Category != "" {
152186 catSet [mapping .Category ] = struct {}{}
153187 }
@@ -189,7 +223,7 @@ func (m *KeymapViewModel) includeAction(actionID string) bool {
189223 if m .selectedCategory == "All" {
190224 return true
191225 }
192- if mapping := m .mc .FindByUniversalAction (actionID ); mapping != nil {
226+ if mapping := m .mc .Get (actionID ); mapping != nil {
193227 return mapping .Category == m .selectedCategory
194228 }
195229 return false
@@ -203,24 +237,29 @@ func (m *KeymapViewModel) keybindingRows() []table.Row {
203237 continue
204238 }
205239 for _ , b := range ab .GetBindings () {
206- k := keybindingToString ( b )
240+ k := b . GetKeyChordsReadable ( )
207241 if k == "" {
208242 continue
209243 }
210244 agg [ab .GetName ()] = append (agg [ab .GetName ()], k )
211245 }
212246 }
213- ids := make ([]string , 0 , len (agg ))
214- for id := range agg {
247+
248+ return m .sortDeterministic (agg )
249+ }
250+
251+ func (m * KeymapViewModel ) sortDeterministic (action2keybindings map [string ][]string ) []table.Row {
252+ ids := make ([]string , 0 , len (action2keybindings ))
253+ for id := range action2keybindings {
215254 ids = append (ids , id )
216255 }
217256 sort .Strings (ids )
218257
219258 rows := make ([]table.Row , 0 , len (ids ))
220259 for _ , id := range ids {
221- keys := dedup (agg [id ])
260+ keys := dedup (action2keybindings [id ])
222261
223- mapping := m .mc .FindByUniversalAction (id )
262+ mapping := m .mc .Get (id )
224263 d := func () string {
225264 if mapping == nil {
226265 return id
@@ -244,14 +283,3 @@ func dedup(in []string) []string {
244283 }
245284 return out
246285}
247-
248- func keybindingToString (kb * keymapv1.KeybindingReadable ) string {
249- if kb == nil {
250- return ""
251- }
252- f , err := keymap .NewKeyBinding (kb ).Format (platform .PlatformMacOS , "+" )
253- if err != nil {
254- return ""
255- }
256- return f
257- }
0 commit comments