diff options
author | Jesse Duffield <jessedduffield@gmail.com> | 2023-05-27 19:58:48 +1000 |
---|---|---|
committer | Jesse Duffield <jessedduffield@gmail.com> | 2023-07-03 12:54:13 +1000 |
commit | 13326344f092e23d4a54887505c92060377adeb6 (patch) | |
tree | a7e6f0ab69717657f978b25f5cbcc21473fc4837 | |
parent | 84870d45038e206a71aa3160d681a2b9d9827aa9 (diff) |
Support filtering files
-rw-r--r-- | pkg/commands/models/commit_file.go | 4 | ||||
-rw-r--r-- | pkg/gui/context/commit_files_context.go | 23 | ||||
-rw-r--r-- | pkg/gui/context/filtered_list.go | 10 | ||||
-rw-r--r-- | pkg/gui/context/filtered_list_view_model.go | 7 | ||||
-rw-r--r-- | pkg/gui/context/working_tree_context.go | 29 | ||||
-rw-r--r-- | pkg/gui/controllers/files_controller.go | 2 | ||||
-rw-r--r-- | pkg/gui/controllers/helpers/refresh_helper.go | 4 | ||||
-rw-r--r-- | pkg/gui/filetree/file_tree.go | 6 | ||||
-rw-r--r-- | pkg/gui/filetree/file_tree_view_model.go | 6 |
9 files changed, 72 insertions, 19 deletions
diff --git a/pkg/commands/models/commit_file.go b/pkg/commands/models/commit_file.go index 45b56d2dd..d05b5b3fd 100644 --- a/pkg/commands/models/commit_file.go +++ b/pkg/commands/models/commit_file.go @@ -23,3 +23,7 @@ func (f *CommitFile) Added() bool { func (f *CommitFile) Deleted() bool { return f.ChangeStatus == "D" } + +func (f *CommitFile) GetPath() string { + return f.Name +} diff --git a/pkg/gui/context/commit_files_context.go b/pkg/gui/context/commit_files_context.go index 96b6f2fcf..54d2a02e3 100644 --- a/pkg/gui/context/commit_files_context.go +++ b/pkg/gui/context/commit_files_context.go @@ -10,6 +10,7 @@ import ( ) type CommitFilesContext struct { + *FilteredList[*models.CommitFile] *filetree.CommitFileTreeViewModel *ListContextTrait *DynamicTitleBuilder @@ -21,8 +22,13 @@ var ( ) func NewCommitFilesContext(c *ContextCommon) *CommitFilesContext { - viewModel := filetree.NewCommitFileTreeViewModel( + filteredList := NewFilteredList( func() []*models.CommitFile { return c.Model().CommitFiles }, + func(file *models.CommitFile) []string { return []string{file.GetPath()} }, + ) + + viewModel := filetree.NewCommitFileTreeViewModel( + func() []*models.CommitFile { return filteredList.GetFilteredList() }, c.Log, c.UserConfig.Gui.ShowFileTree, ) @@ -39,6 +45,7 @@ func NewCommitFilesContext(c *ContextCommon) *CommitFilesContext { } return &CommitFilesContext{ + FilteredList: filteredList, CommitFileTreeViewModel: viewModel, DynamicTitleBuilder: NewDynamicTitleBuilder(c.Tr.CommitFilesDynamicTitle), ListContextTrait: &ListContextTrait{ @@ -71,3 +78,17 @@ func (self *CommitFilesContext) GetSelectedItemId() string { func (self *CommitFilesContext) GetDiffTerminals() []string { return []string{self.GetRef().RefName()} } + +// used for type switch +func (self *CommitFilesContext) IsFilterableContext() {} + +// TODO: see if we can just call SetTree() within HandleRender(). It doesn't seem +// right that we need to imperatively refresh the view model like this +func (self *CommitFilesContext) SetFilter(filter string) { + self.FilteredList.SetFilter(filter) + self.SetTree() +} + +func (self *CommitFilesContext) ClearFilter() { + self.SetFilter("") +} diff --git a/pkg/gui/context/filtered_list.go b/pkg/gui/context/filtered_list.go index 1317924ad..5a7257388 100644 --- a/pkg/gui/context/filtered_list.go +++ b/pkg/gui/context/filtered_list.go @@ -14,6 +14,13 @@ type FilteredList[T any] struct { filter string } +func NewFilteredList[T any](getList func() []T, getFilterFields func(T) []string) *FilteredList[T] { + return &FilteredList[T]{ + getList: getList, + getFilterFields: getFilterFields, + } +} + func (self *FilteredList[T]) GetFilter() string { return self.filter } @@ -28,13 +35,14 @@ func (self *FilteredList[T]) ClearFilter() { self.SetFilter("") } -func (self *FilteredList[T]) GetList() []T { +func (self *FilteredList[T]) GetFilteredList() []T { if self.filteredIndices == nil { return self.getList() } return utils.ValuesAtIndices(self.getList(), self.filteredIndices) } +// TODO: update to just 'Len' func (self *FilteredList[T]) UnfilteredLen() int { return len(self.getList()) } diff --git a/pkg/gui/context/filtered_list_view_model.go b/pkg/gui/context/filtered_list_view_model.go index 01b020841..6196ed180 100644 --- a/pkg/gui/context/filtered_list_view_model.go +++ b/pkg/gui/context/filtered_list_view_model.go @@ -6,16 +6,13 @@ type FilteredListViewModel[T any] struct { } func NewFilteredListViewModel[T any](getList func() []T, getFilterFields func(T) []string) *FilteredListViewModel[T] { - filteredList := &FilteredList[T]{ - getList: getList, - getFilterFields: getFilterFields, - } + filteredList := NewFilteredList(getList, getFilterFields) self := &FilteredListViewModel[T]{ FilteredList: filteredList, } - listViewModel := NewListViewModel(filteredList.GetList) + listViewModel := NewListViewModel(filteredList.GetFilteredList) self.ListViewModel = listViewModel diff --git a/pkg/gui/context/working_tree_context.go b/pkg/gui/context/working_tree_context.go index 45502eb60..0c8c2bc5e 100644 --- a/pkg/gui/context/working_tree_context.go +++ b/pkg/gui/context/working_tree_context.go @@ -9,20 +9,30 @@ import ( ) type WorkingTreeContext struct { + *FilteredList[*models.File] *filetree.FileTreeViewModel *ListContextTrait } -var _ types.IListContext = (*WorkingTreeContext)(nil) +var ( + _ types.IListContext = (*WorkingTreeContext)(nil) + _ types.IFilterableContext = (*WorkingTreeContext)(nil) +) func NewWorkingTreeContext(c *ContextCommon) *WorkingTreeContext { - viewModel := filetree.NewFileTreeViewModel( + filteredList := NewFilteredList( func() []*models.File { return c.Model().Files }, + func(file *models.File) []string { return []string{file.GetPath()} }, + ) + + viewModel := filetree.NewFileTreeViewModel( + func() []*models.File { return filteredList.GetFilteredList() }, c.Log, c.UserConfig.Gui.ShowFileTree, ) getDisplayStrings := func(startIdx int, length int) [][]string { + c.Log.Warn("in get display strings") lines := presentation.RenderFileTree(viewModel, c.Modes().Diffing.Ref, c.Model().Submodules) return slices.Map(lines, func(line string) []string { return []string{line} @@ -30,6 +40,7 @@ func NewWorkingTreeContext(c *ContextCommon) *WorkingTreeContext { } return &WorkingTreeContext{ + FilteredList: filteredList, FileTreeViewModel: viewModel, ListContextTrait: &ListContextTrait{ Context: NewSimpleContext(NewBaseContext(NewBaseContextOpts{ @@ -54,3 +65,17 @@ func (self *WorkingTreeContext) GetSelectedItemId() string { return item.ID() } + +// used for type switch +func (self *WorkingTreeContext) IsFilterableContext() {} + +// TODO: see if we can just call SetTree() within HandleRender(). It doesn't seem +// right that we need to imperatively refresh the view model like this +func (self *WorkingTreeContext) SetFilter(filter string) { + self.FilteredList.SetFilter(filter) + self.SetTree() +} + +func (self *WorkingTreeContext) ClearFilter() { + self.SetFilter("") +} diff --git a/pkg/gui/controllers/files_controller.go b/pkg/gui/controllers/files_controller.go index 11d39ee9f..93e52c192 100644 --- a/pkg/gui/controllers/files_controller.go +++ b/pkg/gui/controllers/files_controller.go @@ -658,7 +658,7 @@ func (self *FilesController) handleStatusFilterPressed() error { } func (self *FilesController) setStatusFiltering(filter filetree.FileTreeDisplayFilter) error { - self.context().FileTreeViewModel.SetFilter(filter) + self.context().FileTreeViewModel.SetStatusFilter(filter) return self.c.PostRefreshUpdate(self.context()) } diff --git a/pkg/gui/controllers/helpers/refresh_helper.go b/pkg/gui/controllers/helpers/refresh_helper.go index 7b37585a5..f0827dc41 100644 --- a/pkg/gui/controllers/helpers/refresh_helper.go +++ b/pkg/gui/controllers/helpers/refresh_helper.go @@ -464,10 +464,10 @@ func (self *RefreshHelper) refreshStateFiles() error { // I'd prefer to maintain as little state as possible. if conflictFileCount > 0 { if fileTreeViewModel.GetFilter() == filetree.DisplayAll { - fileTreeViewModel.SetFilter(filetree.DisplayConflicted) + fileTreeViewModel.SetStatusFilter(filetree.DisplayConflicted) } } else if fileTreeViewModel.GetFilter() == filetree.DisplayConflicted { - fileTreeViewModel.SetFilter(filetree.DisplayAll) + fileTreeViewModel.SetStatusFilter(filetree.DisplayAll) } self.c.Model().Files = files diff --git a/pkg/gui/filetree/file_tree.go b/pkg/gui/filetree/file_tree.go index 950bf24be..3f244edfe 100644 --- a/pkg/gui/filetree/file_tree.go +++ b/pkg/gui/filetree/file_tree.go @@ -34,7 +34,7 @@ type IFileTree interface { ITree[models.File] FilterFiles(test func(*models.File) bool) []*models.File - SetFilter(filter FileTreeDisplayFilter) + SetStatusFilter(filter FileTreeDisplayFilter) Get(index int) *FileNode GetFile(path string) *models.File GetAllItems() []*FileNode @@ -91,7 +91,7 @@ func (self *FileTree) FilterFiles(test func(*models.File) bool) []*models.File { return slices.Filter(self.getFiles(), test) } -func (self *FileTree) SetFilter(filter FileTreeDisplayFilter) { +func (self *FileTree) SetStatusFilter(filter FileTreeDisplayFilter) { self.filter = filter self.SetTree() } @@ -102,7 +102,7 @@ func (self *FileTree) ToggleShowTree() { } func (self *FileTree) Get(index int) *FileNode { - // need to traverse the three depth first until we get to the index. + // need to traverse the tree depth first until we get to the index. return NewFileNode(self.tree.GetNodeAtIndex(index+1, self.collapsedPaths)) // ignoring root } diff --git a/pkg/gui/filetree/file_tree_view_model.go b/pkg/gui/filetree/file_tree_view_model.go index b48aaffab..547b62b91 100644 --- a/pkg/gui/filetree/file_tree_view_model.go +++ b/pkg/gui/filetree/file_tree_view_model.go @@ -26,8 +26,6 @@ type FileTreeViewModel struct { var _ IFileTreeViewModel = &FileTreeViewModel{} -// how to tackle this? We could just filter down the list of files at a high point and then the rest will take care of itself. - func NewFileTreeViewModel(getFiles func() []*models.File, log *logrus.Entry, showTree bool) *FileTreeViewModel { fileTree := NewFileTree(getFiles, log, showTree) listCursor := traits.NewListCursor(fileTree) @@ -128,8 +126,8 @@ func (self *FileTreeViewModel) findNewSelectedIdx(prevNodes []*FileNode, currNod return -1 } -func (self *FileTreeViewModel) SetFilter(filter FileTreeDisplayFilter) { - self.IFileTree.SetFilter(filter) +func (self *FileTreeViewModel) SetStatusFilter(filter FileTreeDisplayFilter) { + self.IFileTree.SetStatusFilter(filter) self.IListCursor.SetSelectedLineIdx(0) } |