@@ -3,8 +3,10 @@ package tui
33import (
44 "fmt"
55 "sort"
6+ "strings"
67
78 "github.com/charmbracelet/bubbles/table"
9+ "github.com/charmbracelet/bubbles/textinput"
810 tea "github.com/charmbracelet/bubbletea"
911 "github.com/charmbracelet/lipgloss"
1012 "github.com/Bharath-code/git-scope/internal/config"
@@ -18,6 +20,7 @@ const (
1820 StateLoading State = iota
1921 StateReady
2022 StateError
23+ StateSearching
2124)
2225
2326// SortMode represents different sorting options
@@ -30,24 +33,37 @@ const (
3033 SortByLastCommit
3134)
3235
36+ // FilterMode represents different filter options
37+ type FilterMode int
38+
39+ const (
40+ FilterAll FilterMode = iota
41+ FilterDirty
42+ FilterClean
43+ )
44+
3345// Model is the Bubbletea model for the TUI
3446type Model struct {
35- cfg * config.Config
36- table table.Model
37- repos []model.Repo
38- sortedRepos []model.Repo // Sorted copy for display
39- state State
40- err error
41- statusMsg string
42- width int
43- height int
44- sortMode SortMode
47+ cfg * config.Config
48+ table table.Model
49+ textInput textinput.Model
50+ repos []model.Repo
51+ filteredRepos []model.Repo // After filter applied
52+ sortedRepos []model.Repo // After sort applied
53+ state State
54+ err error
55+ statusMsg string
56+ width int
57+ height int
58+ sortMode SortMode
59+ filterMode FilterMode
60+ searchQuery string
4561}
4662
4763// NewModel creates a new TUI model
4864func NewModel (cfg * config.Config ) Model {
4965 columns := []table.Column {
50- {Title : "Status" , Width : 6 },
66+ {Title : "Status" , Width : 8 },
5167 {Title : "Repository" , Width : 18 },
5268 {Title : "Branch" , Width : 14 },
5369 {Title : "Staged" , Width : 6 },
@@ -85,11 +101,19 @@ func NewModel(cfg *config.Config) Model {
85101
86102 t .SetStyles (s )
87103
104+ // Create text input for search
105+ ti := textinput .New ()
106+ ti .Placeholder = "Search repos..."
107+ ti .CharLimit = 50
108+ ti .Width = 30
109+
88110 return Model {
89- cfg : cfg ,
90- table : t ,
91- state : StateLoading ,
92- sortMode : SortByDirty ,
111+ cfg : cfg ,
112+ table : t ,
113+ textInput : ti ,
114+ state : StateLoading ,
115+ sortMode : SortByDirty ,
116+ filterMode : FilterAll ,
93117 }
94118}
95119
@@ -111,10 +135,45 @@ func (m Model) GetSelectedRepo() *model.Repo {
111135 return nil
112136}
113137
114- // sortRepos sorts repos based on current sort mode
138+ // applyFilter filters repos based on current filter mode and search query
139+ func (m * Model ) applyFilter () {
140+ m .filteredRepos = make ([]model.Repo , 0 , len (m .repos ))
141+
142+ for _ , r := range m .repos {
143+ // Apply filter mode
144+ switch m .filterMode {
145+ case FilterDirty :
146+ if ! r .Status .IsDirty {
147+ continue
148+ }
149+ case FilterClean :
150+ if r .Status .IsDirty {
151+ continue
152+ }
153+ }
154+
155+ // Apply search query
156+ if m .searchQuery != "" {
157+ query := strings .ToLower (m .searchQuery )
158+ name := strings .ToLower (r .Name )
159+ path := strings .ToLower (r .Path )
160+ branch := strings .ToLower (r .Status .Branch )
161+
162+ if ! strings .Contains (name , query ) &&
163+ ! strings .Contains (path , query ) &&
164+ ! strings .Contains (branch , query ) {
165+ continue
166+ }
167+ }
168+
169+ m .filteredRepos = append (m .filteredRepos , r )
170+ }
171+ }
172+
173+ // sortRepos sorts the filtered repos based on current sort mode
115174func (m * Model ) sortRepos () {
116- m .sortedRepos = make ([]model.Repo , len (m .repos ))
117- copy (m .sortedRepos , m .repos )
175+ m .sortedRepos = make ([]model.Repo , len (m .filteredRepos ))
176+ copy (m .sortedRepos , m .filteredRepos )
118177
119178 switch m .sortMode {
120179 case SortByDirty :
@@ -139,8 +198,9 @@ func (m *Model) sortRepos() {
139198 }
140199}
141200
142- // updateTable refreshes the table with current sorted repos
201+ // updateTable refreshes the table with current filtered and sorted repos
143202func (m * Model ) updateTable () {
203+ m .applyFilter ()
144204 m .sortRepos ()
145205 m .table .SetRows (reposToRows (m .sortedRepos ))
146206}
@@ -160,6 +220,19 @@ func (m Model) GetSortModeName() string {
160220 return "Unknown"
161221}
162222
223+ // GetFilterModeName returns the display name of current filter mode
224+ func (m Model ) GetFilterModeName () string {
225+ switch m .filterMode {
226+ case FilterAll :
227+ return "All"
228+ case FilterDirty :
229+ return "Dirty Only"
230+ case FilterClean :
231+ return "Clean Only"
232+ }
233+ return "All"
234+ }
235+
163236// reposToRows converts repos to table rows with status indicators
164237func reposToRows (repos []model.Repo ) []table.Row {
165238 rows := make ([]table.Row , 0 , len (repos ))
0 commit comments