From 218931d6ba6f33f023aa9dc921d0aa0aca5a9f12 Mon Sep 17 00:00:00 2001 From: Benjamin Chausse Date: Sun, 24 Nov 2024 13:04:11 -0500 Subject: feat: add help at the bottom (#5) * Attemp at using goreleaser * Fix syntax error in .goreleaser.yml * fix: Check roadmap feature for clipboard (README) * feat: add help menu at the bottom (#4) * MVP for a help menu * fix: commented code is evil --- README.md | 2 +- assets/vhs.tape | 7 ++++-- internal/picker/keys.go | 10 ++++++--- internal/preview/preview.go | 12 +++------- internal/slider/keys.go | 13 +++++------ internal/switcher/keys.go | 40 +++++++++++++++++++++++++-------- internal/switcher/switcher.go | 51 +++++++++++++++++++++++++++++++++---------- 7 files changed, 93 insertions(+), 42 deletions(-) diff --git a/README.md b/README.md index 6e8d4ac..47c6ce3 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Here is a quick demo of what has been done so far: Here is my roadmap to reach what I would consider a finished state: -- [ ] Implement copying to clipboard for various formats (rgb, hex, hsl, cymk, etc...) +- [x] Implement copying to clipboard for various formats (rgb, hex, hsl, cymk, etc...) - [ ] Make the tabs interface prettier with [lipgloss][1] (similar to tabs in [soft-serve][2]) - [ ] Add a [help bubble][3] at the bottom of the interface to show available keybindings - [ ] Add some form of stdout cli flag to output to stdout instead of copying colors diff --git a/assets/vhs.tape b/assets/vhs.tape index 49b43a1..ecb1e4e 100644 --- a/assets/vhs.tape +++ b/assets/vhs.tape @@ -4,10 +4,10 @@ Require termpicker Set FontSize 18 Set Width 800 -Set Height 480 +# Set Height 480 +Set Height 600 Set Margin 15 -# Set MarginFill "#674EFF" Set MarginFill "#6F4624" Set BorderRadius 10 @@ -26,6 +26,9 @@ Sleep 500ms Type "jkllllljhhklhkhh" Sleep 1s +Type "?" +Sleep 500ms + Tab Sleep 500ms Type "jklllllljhhklhkhh" diff --git a/internal/picker/keys.go b/internal/picker/keys.go index f5b7135..26b7e80 100644 --- a/internal/picker/keys.go +++ b/internal/picker/keys.go @@ -10,7 +10,7 @@ func newKeybinds() keybinds { return keybinds{ next: key.NewBinding( key.WithKeys("j", "down"), - key.WithHelp("j", "previous slider"), + key.WithHelp("j", "prev. slider"), ), prev: key.NewBinding( key.WithKeys("k", "up"), @@ -24,6 +24,10 @@ func Keys() []key.Binding { return []key.Binding{k.next, k.prev} } -func (m Model) AllKeys() []key.Binding { - return append(Keys(), m.sliders[m.active].AllKeys()...) +func (m Model) AllKeys() [][]key.Binding { + keys := make([][]key.Binding, len(m.sliders[m.active].AllKeys())+1) + keys[0] = Keys() + copy(keys[1:], m.sliders[m.active].AllKeys()) + return keys + // return append(m.sliders[m.active].AllKeys(), Keys()) } diff --git a/internal/preview/preview.go b/internal/preview/preview.go index ef4c9f0..eb7d344 100644 --- a/internal/preview/preview.go +++ b/internal/preview/preview.go @@ -14,9 +14,7 @@ type Model struct { hex string } -func (m *Model) Color(hex string) { - m.hex = hex -} +func (m *Model) Color(hex string) { m.hex = hex } func New(hex string) *Model { return &Model{ @@ -25,13 +23,9 @@ func New(hex string) *Model { } } -func (m Model) Init() tea.Cmd { - return nil -} +func (m Model) Init() tea.Cmd { return nil } -func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - return m, nil -} +func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { return m, nil } func (m Model) View() string { style := lipgloss.NewStyle().Foreground(lipgloss.Color(m.hex)) diff --git a/internal/slider/keys.go b/internal/slider/keys.go index 9f96903..026ea1b 100644 --- a/internal/slider/keys.go +++ b/internal/slider/keys.go @@ -7,26 +7,25 @@ type keybinds struct { decRegular key.Binding incPrecise key.Binding decPrecise key.Binding - // quitApp key.Binding } func newKeybinds() keybinds { return keybinds{ incRegular: key.NewBinding( key.WithKeys("right", "l"), - key.WithHelp("l", "Increase (coarse)"), + key.WithHelp("l", "inc. (coarse)"), ), decRegular: key.NewBinding( key.WithKeys("left", "h"), - key.WithHelp("h", "Decrease (coarse)"), + key.WithHelp("h", "dec. (coarse)"), ), incPrecise: key.NewBinding( key.WithKeys("shift+right", "L"), - key.WithHelp("L", "Increase (fine)"), + key.WithHelp("L", "inc. (fine)"), ), decPrecise: key.NewBinding( key.WithKeys("shift+left", "H"), - key.WithHelp("H", "Decrease (fine)"), + key.WithHelp("H", "dec. (fine)"), ), } } @@ -47,6 +46,6 @@ func Keys() []key.Binding { // AllKeys returns key.Bindings for the Model // and all of its active children. The parent // can use this to generate help text. -func (m Model) AllKeys() []key.Binding { - return Keys() +func (m Model) AllKeys() [][]key.Binding { + return [][]key.Binding{Keys()} } diff --git a/internal/switcher/keys.go b/internal/switcher/keys.go index e019ba1..215a8e2 100644 --- a/internal/switcher/keys.go +++ b/internal/switcher/keys.go @@ -3,7 +3,7 @@ package switcher import "github.com/charmbracelet/bubbles/key" type keybinds struct { - next, prev, cpHex, cpRgb, cpHsl, cpCmyk, quit key.Binding + next, prev, cpHex, cpRgb, cpHsl, cpCmyk, help, quit key.Binding } func newKeybinds() keybinds { @@ -14,23 +14,27 @@ func newKeybinds() keybinds { ), prev: key.NewBinding( key.WithKeys("shift+tab"), - key.WithHelp("shift+tab", "previous picker"), + key.WithHelp("shift+tab", "prev. picker"), ), cpHex: key.NewBinding( key.WithKeys("x"), - key.WithHelp("x", "yank/copy hex value"), + key.WithHelp("x", "copy hex"), ), cpRgb: key.NewBinding( key.WithKeys("r"), - key.WithHelp("r", "yank/copy RGB value"), + key.WithHelp("r", "copy rgb"), ), cpHsl: key.NewBinding( key.WithKeys("s"), - key.WithHelp("s", "yank/copy HSL value"), + key.WithHelp("s", "copy hsl"), ), cpCmyk: key.NewBinding( key.WithKeys("c"), - key.WithHelp("c", "yank/copy CMYK value"), + key.WithHelp("c", "copy cmyk"), + ), + help: key.NewBinding( + key.WithKeys("?"), + key.WithHelp("?", "help"), ), quit: key.NewBinding( key.WithKeys("q", "ctrl+c"), @@ -41,9 +45,27 @@ func newKeybinds() keybinds { func Keys() []key.Binding { k := newKeybinds() - return []key.Binding{k.next, k.prev, k.cpHex, k.cpRgb, k.cpHsl, k.cpCmyk, k.quit} + return []key.Binding{k.next, k.prev, k.cpHex, k.cpRgb, k.cpHsl, k.cpCmyk, k.help, k.quit} +} + +func shortKeys() [][]key.Binding { + keys := make([][]key.Binding, 2) + rows := 2 + cRow := 0 + for i := 0; i < len(Keys()); i++ { + keys[cRow] = append(keys[cRow], Keys()[i]) + cRow++ + if cRow == rows { + cRow = 0 + } + } + return keys } -func (m Model) AllKeys() []key.Binding { - return append(Keys(), m.pickers[m.active].AllKeys()...) +func (m Model) AllKeys() [][]key.Binding { + keys := make([][]key.Binding, len(m.pickers[m.active].AllKeys())+1) + keys[0] = Keys() + copy(keys[1:], m.pickers[m.active].AllKeys()) + return keys + // return append(m.pickers[m.active].AllKeys(), Keys()) } diff --git a/internal/switcher/switcher.go b/internal/switcher/switcher.go index c470557..fdf91af 100644 --- a/internal/switcher/switcher.go +++ b/internal/switcher/switcher.go @@ -9,21 +9,27 @@ import ( "github.com/ChausseBenjamin/termpicker/internal/preview" "github.com/ChausseBenjamin/termpicker/internal/quit" "github.com/ChausseBenjamin/termpicker/internal/util" + "github.com/charmbracelet/bubbles/help" "github.com/charmbracelet/bubbles/key" tea "github.com/charmbracelet/bubbletea" + "github.com/charmbracelet/lipgloss" ) type Model struct { - active int - pickers []picker.Model - preview preview.Model + active int + pickers []picker.Model + preview preview.Model + help help.Model + fullHelp bool // When false, only show help for the switcher (not children) } func New(pickers []picker.Model) Model { return Model{ - active: 0, - pickers: pickers, - preview: *preview.New(colors.Hex(pickers[0].GetColor())), + active: 0, + pickers: pickers, + preview: *preview.New(colors.Hex(pickers[0].GetColor())), + help: help.New(), + fullHelp: false, } } @@ -51,15 +57,36 @@ func (m Model) Init() tea.Cmd { } func (m Model) View() string { - v := "|" + tabs := "|" for i, p := range m.pickers { if i == m.active { - v += fmt.Sprintf(">%s<|", p.Title()) + tabs += fmt.Sprintf(">%s<|", p.Title()) } else { - v += fmt.Sprintf(" %s |", p.Title()) + tabs += fmt.Sprintf(" %s |", p.Title()) } } - return fmt.Sprintf("%s\n%s\n%s", v, m.pickers[m.active].View(), m.preview.View()) + + pickerView := m.pickers[m.active].View() + w := lipgloss.Width(pickerView) + + m.help.Styles.ShortKey.Width(w) + var helpstr string + if m.fullHelp { + helpstr = m.help.FullHelpView(m.AllKeys()) + } else { + // This is a hack since the current view has too many keys + // and the horizontal "ShortHelpView" gets too wide. + // "FullHelpView" seperates keys by columns (and we only show the first). + // helpstr = m.help.FullHelpView([][]key.Binding{m.AllKeys()[0]}) + helpstr = m.help.FullHelpView(shortKeys()) + } + + return fmt.Sprintf("%s\n%s\n%s\n%v", + tabs, + pickerView, + m.preview.View(), + helpstr, + ) } func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { @@ -97,6 +124,9 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { cmyk := colors.CMYK{}.FromPrecise(pc).(colors.CMYK) util.Copy(cmyk.String()) + case key.Matches(msg, keys.help): + m.fullHelp = !m.fullHelp + case key.Matches(msg, keys.quit): return quit.Model{}, tea.Quit @@ -112,7 +142,6 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { return m, tea.Batch(cmds...) } default: - // fmt.Printf("\nmsg: %T\n", msg) } for i, p := range m.pickers { newActive, cmd := p.Update(msg) -- cgit v1.2.3