From bd470888b49eb7852c35db8ea7622bcf06a8a94f Mon Sep 17 00:00:00 2001 From: sahil-singh1107 Date: Sun, 31 May 2026 01:12:42 +0530 Subject: [PATCH 1/2] add interactive file filtering --- filepicker/filepicker.go | 50 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/filepicker/filepicker.go b/filepicker/filepicker.go index 1d2a1cc2..16e54c42 100644 --- a/filepicker/filepicker.go +++ b/filepicker/filepicker.go @@ -27,6 +27,7 @@ func nextID() int { func New() Model { return Model{ id: nextID(), + filter: "", CurrentDirectory: ".", Cursor: ">", AllowedTypes: []string{}, @@ -37,6 +38,7 @@ func New() Model { DirAllowed: false, FileAllowed: true, AutoHeight: true, + SearchMode: false, height: 0, maxIdx: 0, minIdx: 0, @@ -74,6 +76,7 @@ type KeyMap struct { Back key.Binding Open key.Binding Select key.Binding + Search key.Binding } // DefaultKeyMap defines the default keybindings. @@ -88,6 +91,10 @@ func DefaultKeyMap() KeyMap { 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")), + Search: key.NewBinding( + key.WithKeys("/"), + key.WithHelp("/", "search"), + ), } } @@ -127,6 +134,7 @@ func DefaultStyles() Styles { type Model struct { id int + filter string // Path is the path which the user has selected with the file picker. Path string @@ -139,11 +147,13 @@ type Model struct { KeyMap KeyMap files []os.DirEntry + filteredFiles []os.DirEntry ShowPermissions bool ShowSize bool ShowHidden bool DirAllowed bool FileAllowed bool + SearchMode bool FileSelected string selected int @@ -195,6 +205,7 @@ func (m *Model) popView() (int, int, int) { } func (m Model) readDir(path string, showHidden bool) tea.Cmd { + return func() tea.Msg { dirEntries, err := os.ReadDir(path) if err != nil { @@ -218,6 +229,11 @@ func (m Model) readDir(path string, showHidden bool) tea.Cmd { if isHidden { continue } + + if !strings.HasPrefix(dirEntry.Name(), m.filter) { + continue + } + sanitizedDirEntries = append(sanitizedDirEntries, dirEntry) } return readDirMsg{id: m.id, entries: sanitizedDirEntries} @@ -232,6 +248,10 @@ func (m *Model) SetHeight(h int) { } } +func (m Model) Filter() string { + return m.filter +} + // Height returns the height of the file picker. func (m Model) Height() int { return m.height @@ -239,11 +259,13 @@ func (m Model) Height() int { // Init initializes the file picker model. func (m Model) Init() tea.Cmd { + 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: if msg.id != m.id { @@ -257,7 +279,28 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) { } m.maxIdx = m.Height() - 1 case tea.KeyPressMsg: + if m.SearchMode { + switch msg.Code { + case tea.KeyEsc: + m.SearchMode = false + return m, m.readDir(m.CurrentDirectory, m.ShowHidden) + + case tea.KeyBackspace: + r := []rune(m.filter) + if len(r) > 0 { + m.filter = string(r[:len(r)-1]) + } + return m, m.readDir(m.CurrentDirectory, m.ShowHidden) + } + + if msg.Text != "" { + m.filter += msg.Text + return m, m.readDir(m.CurrentDirectory, m.ShowHidden) + } + } switch { + case key.Matches(msg, m.KeyMap.Search): + m.SearchMode = true case key.Matches(msg, m.KeyMap.GoToTop): m.selected = 0 m.minIdx = 0 @@ -309,6 +352,12 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) { m.maxIdx = m.minIdx + m.Height() } case key.Matches(msg, m.KeyMap.Back): + + if m.SearchMode { + m.SearchMode = false + return m, nil + } + m.CurrentDirectory = filepath.Dir(m.CurrentDirectory) if m.selectedStack.Length() > 0 { m.selected, m.minIdx, m.maxIdx = m.popView() @@ -360,6 +409,7 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) { m.maxIdx = m.Height() - 1 return m, m.readDir(m.CurrentDirectory, m.ShowHidden) } + } return m, nil } From a3af38fd06884f92f9c2129767daba9403fd32b2 Mon Sep 17 00:00:00 2001 From: sahil-singh1107 Date: Sun, 31 May 2026 01:23:00 +0530 Subject: [PATCH 2/2] adjust the indexes --- filepicker/filepicker.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/filepicker/filepicker.go b/filepicker/filepicker.go index 16e54c42..dc1ea0fc 100644 --- a/filepicker/filepicker.go +++ b/filepicker/filepicker.go @@ -286,15 +286,20 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) { return m, m.readDir(m.CurrentDirectory, m.ShowHidden) case tea.KeyBackspace: - r := []rune(m.filter) - if len(r) > 0 { - m.filter = string(r[:len(r)-1]) + m.selected = 0 + m.minIdx = 0 + m.maxIdx = m.Height() - 1 + if len(m.filter) > 0 { + m.filter = m.filter[:len(m.filter)-1] } return m, m.readDir(m.CurrentDirectory, m.ShowHidden) } if msg.Text != "" { m.filter += msg.Text + m.selected = 0 + m.minIdx = 0 + m.maxIdx = m.Height() - 1 return m, m.readDir(m.CurrentDirectory, m.ShowHidden) } }