charmbracelet / charmbracelet/bubbles
Initial loading of Filepicker isn't working
- Dominant language
- Go
- Stars
- 8.9k
- Forks
- 457
- Avg merge
- 1d 18h
- Merged PRs (30d)
- 5
Description
**Describe the bug**
Working on a tui http client [Muninn](https://github.com/9-Realms-Dev/muninn) and I'm using the filepicker bubble to find the `.http` files on my system. Well when the application initialize I get a "no files found" this isn't the same behaivor I get when working on the example you guys have built. I've rewritten the example using all the same steps I use in my code and it produces list of directory as expected but if I copy that code into my code base it still shows "no files found".
**Setup**
Please complete the following information along with version numbers, if applicable.
- OS: Pop-os
- Shell: Fish
- Terminal Emulator: Alacritty
- Terminal Multiplexer: Zellij
- Locale: en_US.UTF-8
**To Reproduce**
Steps to reproduce the behavior:
1. Clone Muninn
2. Start muninn `go run main.go`
3. Notice that it shows the filepicker is empty
4. Hit `h` to go back a directory and see that the filepicker is working fine from there
**Source Code**
Please include source code if needed to reproduce the behavior.
muninn filepicker: `/internal/tui/filepicker_view.go`
```go
package tui
import (
"errors"
"strings"
"time"
"github.com/charmbracelet/bubbles/filepicker"
tea "github.com/charmbracelet/bubbletea"
)
type clearErrorMsg struct{}
func clearErrorAfter(t time.Duration) tea.Cmd {
return tea.Tick(t, func(_ time.Time) tea.Msg {
return clearErrorMsg{}
})
}
type filepickerModel struct {
picker filepicker.Model
selected string
quitting bool
err error
}
func initFilepicker(path string) filepickerModel {
fp := filepicker.New()
fp.AllowedTypes = []string{".http"}
fp.CurrentDirectory = path
fp.ShowPermissions = false
fp.ShowSize = false
fp.AutoHeight = false
return filepickerModel{
picker: fp,
}
}
func (m filepickerModel) Init() tea.Cmd {
return m.picker.Init()
}
func (m filepickerModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.WindowSizeMsg:
m.picker.Height = msg.Height / 4
case tea.KeyMsg:
switch msg.String() {
case "ctrl+c", "q":
m.quitting = true
return m, tea.Quit
}
case clearErrorMsg:
m.err = nil
}
var cmd tea.Cmd
m.picker, cmd = m.picker.Update(msg)
// Did the user select a file?
if didSelect, path := m.picker.DidSelectFile(msg); didSelect {
// Get the path of the selected file.
m.selected = path
}
// Did the user select a disabled file?
// This is only necessary to display an error to the user.
if didSelect, path := m.picker.DidSelectDisabledFile(msg); didSelect {
// Let's clear the selectedFile and display an error.
m.err = errors.New(path + " is not valid.")
m.selected = ""
return m, tea.Batch(cmd, clearErrorAfter(2*time.Second))
}
return m, cmd
}
func (m filepickerModel) View() string {
if m.quitting {
return ""
}
var s strings.Builder
s.WriteString("\n ")
if m.err != nil {
s.WriteString(m.picker.Styles.DisabledFile.Render(m.err.Error()))
} else if m.selected == "" {
s.WriteString("Pick a file:")
} else {
s.WriteString("Selected file: " + m.picker.Styles.Selected.Render(m.selected))
}
s.WriteString("\n\n" + m.picker.View() + "\n")
return s.String()
}
```
Minimal standalone file
```go
package main
import (
"errors"
"fmt"
"os"
"strings"
"time"
"github.com/charmbracelet/bubbles/filepicker"
tea "github.com/charmbracelet/bubbletea"
)
type model struct {
filepicker filepicker.Model
selectedFile string
quitting bool
err error
}
type clearErrorMsg struct{}
func clearErrorAfter(t time.Duration) tea.Cmd {
return tea.Tick(t, func(_ time.Time) tea.Msg {
return clearErrorMsg{}
})
}
func (m model) Init() tea.Cmd {
return m.filepicker.Init()
}
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.WindowSizeMsg:
m.filepicker.Height = msg.Height / 4
case tea.KeyMsg:
switch msg.String() {
case "ctrl+c", "q":
m.quitting = true
return m, tea.Quit
}
case clearErrorMsg:
m.err = nil
}
var cmd tea.Cmd
m.filepicker, cmd = m.filepicker.Update(msg)
// Did the user select a file?
if didSelect, path := m.filepicker.DidSelectFile(msg); didSelect {
// Get the path of the selected file.
m.selectedFile = path
}
// Did the user select a disabled file?
// This is only necessary to display an error to the user.
if didSelect, path := m.filepicker.DidSelectDisabledFile(msg); didSelect {
// Let's clear the selectedFile and display an error.
m.err = errors.New(path + " is not valid.")
m.selectedFile = ""
return m, tea.Batch(cmd, clearErrorAfter(2*time.Second))
}
return m, cmd
}
func (m model) View() string {
if m.quitting {
return ""
}
var s strings.Builder
s.WriteString("\n ")
if m.err != nil {
s.WriteString(m.filepicker.Styles.DisabledFile.Render(m.err.Error()))
} else if m.selectedFile == "" {
s.WriteString("Pick a file:")
} else {
s.WriteString("Selected file: " + m.filepicker.Styles.Selected.Render(m.selectedFile))
}
s.WriteString("\n\n" + m.filepicker.View() + "\n")
return s.String()
}
func main() {
fp := filepicker.New()
path, _ := os.UserHomeDir()
fp.AllowedTypes = []string{".http"}
fp.CurrentDirectory = path
fp.ShowPermissions = false
fp.ShowSize = false
fp.AutoHeight = false
m := model{
filepicker: fp,
}
tm, _ := tea.NewProgram(&m).Run()
mm := tm.(model)
fmt.Println("\n You selected: " + m.filepicker.Styles.Selected.Render(mm.selectedFile) + "\n")
}
```
**Expected behavior**
When my application starts I expect the files and directories to appear just like the minimal example
**Screenshots**
What my application renders

What I expect it to render in the first box

Contributor guide
Assessment
This issue has not been assessed yet.