package tui import ( "fmt" "strings" "github.com/charmbracelet/bubbles/list" "gitgud.io/mike/mpv-manager/pkg/hotkeys" ) // formatKeysForTUI formats hotkey keys for TUI display // Converts single uppercase letters to "Shift + lowercase" format // Handles special cases where + or / are the actual keys (at end of sequence) func formatKeysForTUI(keys string) string { parts := strings.Fields(keys) var result []string for i, part := range parts { // Check for separator tokens: / (or), + (connector), "or" // Only treat as separator if NOT at the last position // (if + or / is at the end, it's the actual key being pressed) if (part == "/" || part == "+" || part == "or") && i < len(parts)-1 { result = append(result, part) continue } // Check if this is a single uppercase letter (requires Shift) if len(part) == 1 && part[0] >= 'A' && part[0] <= 'Z' { // Convert to "Shift + lowercase" format result = append(result, "Shift + "+strings.ToLower(part)) } else if strings.Contains(part, "+") && len(part) > 1 { // Handle combined keys like "Ctrl+Shift+→" (but not standalone "+") subParts := strings.Split(part, "+") var formattedSubParts []string for _, subPart := range subParts { // If subPart is a single uppercase letter, convert to lowercase if len(subPart) == 1 && subPart[0] >= 'A' && subPart[0] <= 'Z' { subPart = strings.ToLower(subPart) } formattedSubParts = append(formattedSubParts, subPart) } result = append(result, strings.Join(formattedSubParts, "+")) } else { result = append(result, part) } } return strings.Join(result, " ") } // setupHotkeysCategoryList creates the category selection list for hotkeys func (m *Model) setupHotkeysCategoryList() { items := []list.Item{ hotkeyCategoryItem{id: "all", title: "All Shortcuts", count: hotkeys.GetHotkeysCount()}, } for _, cat := range hotkeys.Categories { catHotkeys := hotkeys.GetHotkeysByCategory(cat) if len(catHotkeys) > 0 { items = append(items, hotkeyCategoryItem{ id: cat, title: cat, count: len(catHotkeys), }) } } m.hotkeysCategoryList = m.createStyledList("Keyboard Shortcuts - Categories", items) } // setupHotkeysList creates the hotkeys list for a specific category func (m *Model) setupHotkeysList(category string) { var hks []hotkeys.Hotkey if category == "all" { hks = hotkeys.GetSortedHotkeys() } else { hks = hotkeys.GetHotkeysByCategory(category) } items := []list.Item{} for _, h := range hks { items = append(items, hotkeyItem{ keys: formatKeysForTUI(h.Keys), description: h.Description, category: h.Category, }) } title := "All Shortcuts" if category != "all" { title = category } m.hotkeysList = m.createStyledList(title, items) } // hotkeyCategoryItem implements list.Item for category selection type hotkeyCategoryItem struct { id string title string count int } func (h hotkeyCategoryItem) Title() string { return fmt.Sprintf("%s (%d)", h.title, h.count) } func (h hotkeyCategoryItem) Description() string { return "Press Enter to view shortcuts" } func (h hotkeyCategoryItem) FilterValue() string { return h.title } // hotkeyPresetItem implements list.Item for preset selection type hotkeyPresetItem struct { id string name string description string } func (i hotkeyPresetItem) Title() string { return i.name } func (i hotkeyPresetItem) Description() string { return i.description } func (i hotkeyPresetItem) FilterValue() string { return i.name + " " + i.description } // setupHotkeysPresetList creates the keybinding preset selection list func (m *Model) setupHotkeysPresetList() { presets := hotkeys.GetPresetList() var items []list.Item // Add preset items for _, p := range presets { items = append(items, hotkeyPresetItem{ id: p.ID, name: p.Name, description: p.Description, }) } // Add "View All Shortcuts" option to browse the default mpv keybindings reference items = append(items, hotkeyPresetItem{ id: "view-all", name: "📋 View All Shortcuts", description: "Browse the default mpv keybindings reference", }) m.hotkeysPresetList = m.createStyledList("Keybinding Presets", items) m.presetStatusMessage = "" } // hotkeysCategoryListView renders the category selection list func (m Model) hotkeysCategoryListView() string { var content strings.Builder content.WriteString(titleStyle.Render("⌨️ Keyboard Shortcuts")) content.WriteString("\n") content.WriteString(subtitleStyle.Render("══════════════════════")) content.WriteString("\n\n") content.WriteString(infoStyle.Render("Select a category to view shortcuts")) content.WriteString("\n\n") content.WriteString(m.hotkeysCategoryList.View()) content.WriteString("\n\n") content.WriteString(infoStyle.Render("Press ")) content.WriteString(subtitleStyle.Render("Enter")) content.WriteString(infoStyle.Render(" to select, ")) content.WriteString(subtitleStyle.Render("Esc")) content.WriteString(infoStyle.Render(" to go back")) return content.String() } // hotkeysListView renders the hotkeys list for a category func (m Model) hotkeysListView() string { var content strings.Builder content.WriteString(titleStyle.Render("⌨️ Keyboard Shortcuts")) content.WriteString("\n") content.WriteString(subtitleStyle.Render("══════════════════════")) content.WriteString("\n\n") content.WriteString(m.hotkeysList.View()) content.WriteString("\n\n") content.WriteString(infoStyle.Render("Press ")) content.WriteString(subtitleStyle.Render("/")) content.WriteString(infoStyle.Render(" to search, ")) content.WriteString(subtitleStyle.Render("Esc")) content.WriteString(infoStyle.Render(" to go back")) return content.String() } // hotkeysPresetListView renders the keybinding preset selection list func (m Model) hotkeysPresetListView() string { var content strings.Builder content.WriteString(titleStyle.Render("⌨️ Keybinding Presets")) content.WriteString("\n") content.WriteString(subtitleStyle.Render("══════════════════════")) content.WriteString("\n\n") content.WriteString(infoStyle.Render("Select a keybinding preset to apply.")) content.WriteString("\n") content.WriteString(infoStyle.Render("Your current keybindings will be backed up automatically.")) content.WriteString("\n\n") if m.presetStatusMessage != "" { if strings.HasPrefix(m.presetStatusMessage, "✓") { content.WriteString(successStyle.Render(m.presetStatusMessage)) } else { content.WriteString(errorStyle.Render(m.presetStatusMessage)) } content.WriteString("\n\n") } content.WriteString(m.hotkeysPresetList.View()) content.WriteString("\n\n") content.WriteString(infoStyle.Render("Press ")) content.WriteString(subtitleStyle.Render("Enter")) content.WriteString(infoStyle.Render(" to select, ")) content.WriteString(subtitleStyle.Render("Esc")) content.WriteString(infoStyle.Render(" to go back")) return content.String() }