summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Duffield <jessedduffield@gmail.com>2023-05-27 19:58:48 +1000
committerJesse Duffield <jessedduffield@gmail.com>2023-07-03 12:54:13 +1000
commit13326344f092e23d4a54887505c92060377adeb6 (patch)
treea7e6f0ab69717657f978b25f5cbcc21473fc4837
parent84870d45038e206a71aa3160d681a2b9d9827aa9 (diff)
Support filtering files
-rw-r--r--pkg/commands/models/commit_file.go4
-rw-r--r--pkg/gui/context/commit_files_context.go23
-rw-r--r--pkg/gui/context/filtered_list.go10
-rw-r--r--pkg/gui/context/filtered_list_view_model.go7
-rw-r--r--pkg/gui/context/working_tree_context.go29
-rw-r--r--pkg/gui/controllers/files_controller.go2
-rw-r--r--pkg/gui/controllers/helpers/refresh_helper.go4
-rw-r--r--pkg/gui/filetree/file_tree.go6
-rw-r--r--pkg/gui/filetree/file_tree_view_model.go6
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)
}