From afd7868712d4a4f817829dc7e1868c337c5e5cff Mon Sep 17 00:00:00 2001 From: Christian Rocha Date: Wed, 31 May 2023 14:04:43 -0400 Subject: [PATCH] chore: filepicker edits (#382) * feat(filepicker): ignore messages from other filepicker instances * feat(filepicker): initialize default styles against a lipgloss renderer * chore(filepicker): swap global var for function with default keymap --- filepicker/filepicker.go | 80 ++++++++++++++++++++++++---------------- go.mod | 2 +- go.sum | 2 + 3 files changed, 51 insertions(+), 33 deletions(-) diff --git a/filepicker/filepicker.go b/filepicker/filepicker.go index 7c380ba..2df4032 100644 --- a/filepicker/filepicker.go +++ b/filepicker/filepicker.go @@ -45,8 +45,8 @@ func New() Model { selectedStack: newStack(), minStack: newStack(), maxStack: newStack(), - KeyMap: DefaultKeyMap, - Styles: DefaultStyles, + KeyMap: DefaultKeyMap(), + Styles: DefaultStyles(), } } @@ -54,7 +54,10 @@ type errorMsg struct { err error } -type readDirMsg []os.DirEntry +type readDirMsg struct { + id int + entries []os.DirEntry +} const ( marginBottom = 5 @@ -76,16 +79,18 @@ type KeyMap struct { } // DefaultKeyMap defines the default keybindings. -var DefaultKeyMap = KeyMap{ - GoToTop: key.NewBinding(key.WithKeys("g"), key.WithHelp("g", "first")), - GoToLast: key.NewBinding(key.WithKeys("G"), key.WithHelp("G", "last")), - Down: key.NewBinding(key.WithKeys("j", "down", "ctrl+n"), key.WithHelp("j", "down")), - Up: key.NewBinding(key.WithKeys("k", "up", "ctrl+p"), key.WithHelp("k", "up")), - PageUp: key.NewBinding(key.WithKeys("K", "pgup"), key.WithHelp("pgup", "page up")), - PageDown: key.NewBinding(key.WithKeys("J", "pgdown"), key.WithHelp("pgdown", "page down")), - Back: key.NewBinding(key.WithKeys("h", "backspace", "left", "esc"), key.WithHelp("h", "back")), - Open: key.NewBinding(key.WithKeys("l", "right", "enter"), key.WithHelp("l", "open")), - Select: key.NewBinding(key.WithKeys("enter"), key.WithHelp("enter", "select")), +func DefaultKeyMap() KeyMap { + return KeyMap{ + GoToTop: key.NewBinding(key.WithKeys("g"), key.WithHelp("g", "first")), + GoToLast: key.NewBinding(key.WithKeys("G"), key.WithHelp("G", "last")), + Down: key.NewBinding(key.WithKeys("j", "down", "ctrl+n"), key.WithHelp("j", "down")), + Up: key.NewBinding(key.WithKeys("k", "up", "ctrl+p"), key.WithHelp("k", "up")), + PageUp: key.NewBinding(key.WithKeys("K", "pgup"), key.WithHelp("pgup", "page up")), + PageDown: key.NewBinding(key.WithKeys("J", "pgdown"), key.WithHelp("pgdown", "page down")), + Back: key.NewBinding(key.WithKeys("h", "backspace", "left", "esc"), key.WithHelp("h", "back")), + Open: key.NewBinding(key.WithKeys("l", "right", "enter"), key.WithHelp("l", "open")), + Select: key.NewBinding(key.WithKeys("enter"), key.WithHelp("enter", "select")), + } } // Styles defines the possible customizations for styles in the file picker. @@ -104,18 +109,26 @@ type Styles struct { } // DefaultStyles defines the default styling for the file picker. -var DefaultStyles = Styles{ - DisabledCursor: lipgloss.NewStyle().Foreground(lipgloss.Color("247")), - Cursor: lipgloss.NewStyle().Foreground(lipgloss.Color("212")), - Symlink: lipgloss.NewStyle().Foreground(lipgloss.Color("36")), - Directory: lipgloss.NewStyle().Foreground(lipgloss.Color("99")), - File: lipgloss.NewStyle(), - DisabledFile: lipgloss.NewStyle().Foreground(lipgloss.Color("243")), - DisabledSelected: lipgloss.NewStyle().Foreground(lipgloss.Color("247")), - Permission: lipgloss.NewStyle().Foreground(lipgloss.Color("244")), - Selected: lipgloss.NewStyle().Foreground(lipgloss.Color("212")).Bold(true), - FileSize: lipgloss.NewStyle().Foreground(lipgloss.Color("240")).Width(fileSizeWidth).Align(lipgloss.Right), - EmptyDirectory: lipgloss.NewStyle().Foreground(lipgloss.Color("240")).PaddingLeft(paddingLeft).SetString("Bummer. No Files Found."), +func DefaultStyles() Styles { + return DefaultStylesWithRenderer(lipgloss.DefaultRenderer()) +} + +// DefaultStylesWithRenderer defines the default styling for the file picker, +// with a given Lip Gloss renderer. +func DefaultStylesWithRenderer(r *lipgloss.Renderer) Styles { + return Styles{ + DisabledCursor: r.NewStyle().Foreground(lipgloss.Color("247")), + Cursor: r.NewStyle().Foreground(lipgloss.Color("212")), + Symlink: r.NewStyle().Foreground(lipgloss.Color("36")), + Directory: r.NewStyle().Foreground(lipgloss.Color("99")), + File: r.NewStyle(), + DisabledFile: r.NewStyle().Foreground(lipgloss.Color("243")), + DisabledSelected: r.NewStyle().Foreground(lipgloss.Color("247")), + Permission: r.NewStyle().Foreground(lipgloss.Color("244")), + Selected: r.NewStyle().Foreground(lipgloss.Color("212")).Bold(true), + FileSize: r.NewStyle().Foreground(lipgloss.Color("240")).Width(fileSizeWidth).Align(lipgloss.Right), + EmptyDirectory: r.NewStyle().Foreground(lipgloss.Color("240")).PaddingLeft(paddingLeft).SetString("Bummer. No Files Found."), + } } // Model represents a file picker. @@ -187,7 +200,7 @@ func (m Model) popView() (int, int, int) { return m.selectedStack.Pop(), m.minStack.Pop(), m.maxStack.Pop() } -func readDir(path string, showHidden bool) tea.Cmd { +func (m Model) readDir(path string, showHidden bool) tea.Cmd { return func() tea.Msg { dirEntries, err := os.ReadDir(path) if err != nil { @@ -202,7 +215,7 @@ func readDir(path string, showHidden bool) tea.Cmd { }) if showHidden { - return readDirMsg(dirEntries) + return readDirMsg{id: m.id, entries: dirEntries} } var sanitizedDirEntries []os.DirEntry @@ -213,20 +226,23 @@ func readDir(path string, showHidden bool) tea.Cmd { } sanitizedDirEntries = append(sanitizedDirEntries, dirEntry) } - return readDirMsg(sanitizedDirEntries) + return readDirMsg{id: m.id, entries: sanitizedDirEntries} } } // Init initializes the file picker model. func (m Model) Init() tea.Cmd { - return readDir(m.CurrentDirectory, m.ShowHidden) + return m.readDir(m.CurrentDirectory, m.ShowHidden) } // Update handles user interactions within the file picker model. func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) { switch msg := msg.(type) { case readDirMsg: - m.files = msg + if msg.id != m.id { + break + } + m.files = msg.entries m.max = m.Height - 1 case tea.WindowSizeMsg: if m.AutoHeight { @@ -294,7 +310,7 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) { m.min = 0 m.max = m.Height - 1 } - return m, readDir(m.CurrentDirectory, m.ShowHidden) + return m, m.readDir(m.CurrentDirectory, m.ShowHidden) case key.Matches(msg, m.KeyMap.Open): if len(m.files) == 0 { break @@ -335,7 +351,7 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) { m.selected = 0 m.min = 0 m.max = m.Height - 1 - return m, readDir(m.CurrentDirectory, m.ShowHidden) + return m, m.readDir(m.CurrentDirectory, m.ShowHidden) } } return m, nil diff --git a/go.mod b/go.mod index fc062ba..74d130f 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/atotto/clipboard v0.1.4 github.com/charmbracelet/bubbletea v0.24.1 github.com/charmbracelet/harmonica v0.2.0 - github.com/charmbracelet/lipgloss v0.6.0 + github.com/charmbracelet/lipgloss v0.7.1 github.com/dustin/go-humanize v1.0.1 github.com/lucasb-eyer/go-colorful v1.2.0 github.com/mattn/go-runewidth v0.0.14 diff --git a/go.sum b/go.sum index b7c1c1b..982b120 100644 --- a/go.sum +++ b/go.sum @@ -8,6 +8,8 @@ github.com/charmbracelet/harmonica v0.2.0 h1:8NxJWRWg/bzKqqEaaeFNipOu77YR5t8aSwG github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao= github.com/charmbracelet/lipgloss v0.6.0 h1:1StyZB9vBSOyuZxQUcUwGr17JmojPNm87inij9N3wJY= github.com/charmbracelet/lipgloss v0.6.0/go.mod h1:tHh2wr34xcHjC2HCXIlGSG1jaDF0S0atAUvBMP6Ppuk= +github.com/charmbracelet/lipgloss v0.7.1 h1:17WMwi7N1b1rVWOjMT+rCh7sQkvDU75B2hbZpc5Kc1E= +github.com/charmbracelet/lipgloss v0.7.1/go.mod h1:yG0k3giv8Qj8edTCbbg6AlQ5e8KNWpFujkNawKNhE2c= github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 h1:q2hJAaP1k2wIvVRd/hEHD7lacgqrCPS+k8g1MndzfWY= github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=