Skip to content

Commit afd7868

Browse files
authored
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
1 parent 2eaa8e3 commit afd7868

File tree

3 files changed

+51
-33
lines changed

3 files changed

+51
-33
lines changed

filepicker/filepicker.go

Lines changed: 48 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -45,16 +45,19 @@ func New() Model {
4545
selectedStack: newStack(),
4646
minStack: newStack(),
4747
maxStack: newStack(),
48-
KeyMap: DefaultKeyMap,
49-
Styles: DefaultStyles,
48+
KeyMap: DefaultKeyMap(),
49+
Styles: DefaultStyles(),
5050
}
5151
}
5252

5353
type errorMsg struct {
5454
err error
5555
}
5656

57-
type readDirMsg []os.DirEntry
57+
type readDirMsg struct {
58+
id int
59+
entries []os.DirEntry
60+
}
5861

5962
const (
6063
marginBottom = 5
@@ -76,16 +79,18 @@ type KeyMap struct {
7679
}
7780

7881
// DefaultKeyMap defines the default keybindings.
79-
var DefaultKeyMap = KeyMap{
80-
GoToTop: key.NewBinding(key.WithKeys("g"), key.WithHelp("g", "first")),
81-
GoToLast: key.NewBinding(key.WithKeys("G"), key.WithHelp("G", "last")),
82-
Down: key.NewBinding(key.WithKeys("j", "down", "ctrl+n"), key.WithHelp("j", "down")),
83-
Up: key.NewBinding(key.WithKeys("k", "up", "ctrl+p"), key.WithHelp("k", "up")),
84-
PageUp: key.NewBinding(key.WithKeys("K", "pgup"), key.WithHelp("pgup", "page up")),
85-
PageDown: key.NewBinding(key.WithKeys("J", "pgdown"), key.WithHelp("pgdown", "page down")),
86-
Back: key.NewBinding(key.WithKeys("h", "backspace", "left", "esc"), key.WithHelp("h", "back")),
87-
Open: key.NewBinding(key.WithKeys("l", "right", "enter"), key.WithHelp("l", "open")),
88-
Select: key.NewBinding(key.WithKeys("enter"), key.WithHelp("enter", "select")),
82+
func DefaultKeyMap() KeyMap {
83+
return KeyMap{
84+
GoToTop: key.NewBinding(key.WithKeys("g"), key.WithHelp("g", "first")),
85+
GoToLast: key.NewBinding(key.WithKeys("G"), key.WithHelp("G", "last")),
86+
Down: key.NewBinding(key.WithKeys("j", "down", "ctrl+n"), key.WithHelp("j", "down")),
87+
Up: key.NewBinding(key.WithKeys("k", "up", "ctrl+p"), key.WithHelp("k", "up")),
88+
PageUp: key.NewBinding(key.WithKeys("K", "pgup"), key.WithHelp("pgup", "page up")),
89+
PageDown: key.NewBinding(key.WithKeys("J", "pgdown"), key.WithHelp("pgdown", "page down")),
90+
Back: key.NewBinding(key.WithKeys("h", "backspace", "left", "esc"), key.WithHelp("h", "back")),
91+
Open: key.NewBinding(key.WithKeys("l", "right", "enter"), key.WithHelp("l", "open")),
92+
Select: key.NewBinding(key.WithKeys("enter"), key.WithHelp("enter", "select")),
93+
}
8994
}
9095

9196
// Styles defines the possible customizations for styles in the file picker.
@@ -104,18 +109,26 @@ type Styles struct {
104109
}
105110

106111
// DefaultStyles defines the default styling for the file picker.
107-
var DefaultStyles = Styles{
108-
DisabledCursor: lipgloss.NewStyle().Foreground(lipgloss.Color("247")),
109-
Cursor: lipgloss.NewStyle().Foreground(lipgloss.Color("212")),
110-
Symlink: lipgloss.NewStyle().Foreground(lipgloss.Color("36")),
111-
Directory: lipgloss.NewStyle().Foreground(lipgloss.Color("99")),
112-
File: lipgloss.NewStyle(),
113-
DisabledFile: lipgloss.NewStyle().Foreground(lipgloss.Color("243")),
114-
DisabledSelected: lipgloss.NewStyle().Foreground(lipgloss.Color("247")),
115-
Permission: lipgloss.NewStyle().Foreground(lipgloss.Color("244")),
116-
Selected: lipgloss.NewStyle().Foreground(lipgloss.Color("212")).Bold(true),
117-
FileSize: lipgloss.NewStyle().Foreground(lipgloss.Color("240")).Width(fileSizeWidth).Align(lipgloss.Right),
118-
EmptyDirectory: lipgloss.NewStyle().Foreground(lipgloss.Color("240")).PaddingLeft(paddingLeft).SetString("Bummer. No Files Found."),
112+
func DefaultStyles() Styles {
113+
return DefaultStylesWithRenderer(lipgloss.DefaultRenderer())
114+
}
115+
116+
// DefaultStylesWithRenderer defines the default styling for the file picker,
117+
// with a given Lip Gloss renderer.
118+
func DefaultStylesWithRenderer(r *lipgloss.Renderer) Styles {
119+
return Styles{
120+
DisabledCursor: r.NewStyle().Foreground(lipgloss.Color("247")),
121+
Cursor: r.NewStyle().Foreground(lipgloss.Color("212")),
122+
Symlink: r.NewStyle().Foreground(lipgloss.Color("36")),
123+
Directory: r.NewStyle().Foreground(lipgloss.Color("99")),
124+
File: r.NewStyle(),
125+
DisabledFile: r.NewStyle().Foreground(lipgloss.Color("243")),
126+
DisabledSelected: r.NewStyle().Foreground(lipgloss.Color("247")),
127+
Permission: r.NewStyle().Foreground(lipgloss.Color("244")),
128+
Selected: r.NewStyle().Foreground(lipgloss.Color("212")).Bold(true),
129+
FileSize: r.NewStyle().Foreground(lipgloss.Color("240")).Width(fileSizeWidth).Align(lipgloss.Right),
130+
EmptyDirectory: r.NewStyle().Foreground(lipgloss.Color("240")).PaddingLeft(paddingLeft).SetString("Bummer. No Files Found."),
131+
}
119132
}
120133

121134
// Model represents a file picker.
@@ -187,7 +200,7 @@ func (m Model) popView() (int, int, int) {
187200
return m.selectedStack.Pop(), m.minStack.Pop(), m.maxStack.Pop()
188201
}
189202

190-
func readDir(path string, showHidden bool) tea.Cmd {
203+
func (m Model) readDir(path string, showHidden bool) tea.Cmd {
191204
return func() tea.Msg {
192205
dirEntries, err := os.ReadDir(path)
193206
if err != nil {
@@ -202,7 +215,7 @@ func readDir(path string, showHidden bool) tea.Cmd {
202215
})
203216

204217
if showHidden {
205-
return readDirMsg(dirEntries)
218+
return readDirMsg{id: m.id, entries: dirEntries}
206219
}
207220

208221
var sanitizedDirEntries []os.DirEntry
@@ -213,20 +226,23 @@ func readDir(path string, showHidden bool) tea.Cmd {
213226
}
214227
sanitizedDirEntries = append(sanitizedDirEntries, dirEntry)
215228
}
216-
return readDirMsg(sanitizedDirEntries)
229+
return readDirMsg{id: m.id, entries: sanitizedDirEntries}
217230
}
218231
}
219232

220233
// Init initializes the file picker model.
221234
func (m Model) Init() tea.Cmd {
222-
return readDir(m.CurrentDirectory, m.ShowHidden)
235+
return m.readDir(m.CurrentDirectory, m.ShowHidden)
223236
}
224237

225238
// Update handles user interactions within the file picker model.
226239
func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
227240
switch msg := msg.(type) {
228241
case readDirMsg:
229-
m.files = msg
242+
if msg.id != m.id {
243+
break
244+
}
245+
m.files = msg.entries
230246
m.max = m.Height - 1
231247
case tea.WindowSizeMsg:
232248
if m.AutoHeight {
@@ -294,7 +310,7 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
294310
m.min = 0
295311
m.max = m.Height - 1
296312
}
297-
return m, readDir(m.CurrentDirectory, m.ShowHidden)
313+
return m, m.readDir(m.CurrentDirectory, m.ShowHidden)
298314
case key.Matches(msg, m.KeyMap.Open):
299315
if len(m.files) == 0 {
300316
break
@@ -335,7 +351,7 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
335351
m.selected = 0
336352
m.min = 0
337353
m.max = m.Height - 1
338-
return m, readDir(m.CurrentDirectory, m.ShowHidden)
354+
return m, m.readDir(m.CurrentDirectory, m.ShowHidden)
339355
}
340356
}
341357
return m, nil

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ require (
66
github.com/atotto/clipboard v0.1.4
77
github.com/charmbracelet/bubbletea v0.24.1
88
github.com/charmbracelet/harmonica v0.2.0
9-
github.com/charmbracelet/lipgloss v0.6.0
9+
github.com/charmbracelet/lipgloss v0.7.1
1010
github.com/dustin/go-humanize v1.0.1
1111
github.com/lucasb-eyer/go-colorful v1.2.0
1212
github.com/mattn/go-runewidth v0.0.14

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ github.com/charmbracelet/harmonica v0.2.0 h1:8NxJWRWg/bzKqqEaaeFNipOu77YR5t8aSwG
88
github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao=
99
github.com/charmbracelet/lipgloss v0.6.0 h1:1StyZB9vBSOyuZxQUcUwGr17JmojPNm87inij9N3wJY=
1010
github.com/charmbracelet/lipgloss v0.6.0/go.mod h1:tHh2wr34xcHjC2HCXIlGSG1jaDF0S0atAUvBMP6Ppuk=
11+
github.com/charmbracelet/lipgloss v0.7.1 h1:17WMwi7N1b1rVWOjMT+rCh7sQkvDU75B2hbZpc5Kc1E=
12+
github.com/charmbracelet/lipgloss v0.7.1/go.mod h1:yG0k3giv8Qj8edTCbbg6AlQ5e8KNWpFujkNawKNhE2c=
1113
github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 h1:q2hJAaP1k2wIvVRd/hEHD7lacgqrCPS+k8g1MndzfWY=
1214
github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk=
1315
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=

0 commit comments

Comments
 (0)