summaryrefslogtreecommitdiffstats
path: root/pkg/gui/context
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/gui/context')
-rw-r--r--pkg/gui/context/branches_context.go13
-rw-r--r--pkg/gui/context/commit_files_context.go11
-rw-r--r--pkg/gui/context/filtered_list.go93
-rw-r--r--pkg/gui/context/filtered_list_view_model.go33
-rw-r--r--pkg/gui/context/list_view_model.go (renamed from pkg/gui/context/basic_view_model.go)14
-rw-r--r--pkg/gui/context/local_commits_context.go15
-rw-r--r--pkg/gui/context/menu_context.go13
-rw-r--r--pkg/gui/context/patch_explorer_context.go14
-rw-r--r--pkg/gui/context/reflog_commits_context.go13
-rw-r--r--pkg/gui/context/remote_branches_context.go15
-rw-r--r--pkg/gui/context/remotes_context.go13
-rw-r--r--pkg/gui/context/search_trait.go74
-rw-r--r--pkg/gui/context/stash_context.go13
-rw-r--r--pkg/gui/context/sub_commits_context.go18
-rw-r--r--pkg/gui/context/submodules_context.go13
-rw-r--r--pkg/gui/context/suggestions_context.go8
-rw-r--r--pkg/gui/context/tags_context.go13
-rw-r--r--pkg/gui/context/working_tree_context.go11
18 files changed, 346 insertions, 51 deletions
diff --git a/pkg/gui/context/branches_context.go b/pkg/gui/context/branches_context.go
index c2463ad20..497b3a2c4 100644
--- a/pkg/gui/context/branches_context.go
+++ b/pkg/gui/context/branches_context.go
@@ -7,7 +7,7 @@ import (
)
type BranchesContext struct {
- *BasicViewModel[*models.Branch]
+ *FilteredListViewModel[*models.Branch]
*ListContextTrait
}
@@ -17,11 +17,16 @@ var (
)
func NewBranchesContext(c *ContextCommon) *BranchesContext {
- viewModel := NewBasicViewModel(func() []*models.Branch { return c.Model().Branches })
+ viewModel := NewFilteredListViewModel(
+ func() []*models.Branch { return c.Model().Branches },
+ func(branch *models.Branch) []string {
+ return []string{branch.Name}
+ },
+ )
getDisplayStrings := func(startIdx int, length int) [][]string {
return presentation.GetBranchListDisplayStrings(
- c.Model().Branches,
+ viewModel.GetItems(),
c.State().GetRepoState().GetScreenMode() != types.SCREEN_NORMAL,
c.Modes().Diffing.Ref,
c.Tr,
@@ -30,7 +35,7 @@ func NewBranchesContext(c *ContextCommon) *BranchesContext {
}
self := &BranchesContext{
- BasicViewModel: viewModel,
+ FilteredListViewModel: viewModel,
ListContextTrait: &ListContextTrait{
Context: NewSimpleContext(NewBaseContext(NewBaseContextOpts{
View: c.Views().Branches,
diff --git a/pkg/gui/context/commit_files_context.go b/pkg/gui/context/commit_files_context.go
index 96b6f2fcf..5cb11d9cc 100644
--- a/pkg/gui/context/commit_files_context.go
+++ b/pkg/gui/context/commit_files_context.go
@@ -13,6 +13,7 @@ type CommitFilesContext struct {
*filetree.CommitFileTreeViewModel
*ListContextTrait
*DynamicTitleBuilder
+ *SearchTrait
}
var (
@@ -38,9 +39,10 @@ func NewCommitFilesContext(c *ContextCommon) *CommitFilesContext {
})
}
- return &CommitFilesContext{
+ ctx := &CommitFilesContext{
CommitFileTreeViewModel: viewModel,
DynamicTitleBuilder: NewDynamicTitleBuilder(c.Tr.CommitFilesDynamicTitle),
+ SearchTrait: NewSearchTrait(c),
ListContextTrait: &ListContextTrait{
Context: NewSimpleContext(
NewBaseContext(NewBaseContextOpts{
@@ -57,6 +59,13 @@ func NewCommitFilesContext(c *ContextCommon) *CommitFilesContext {
c: c,
},
}
+
+ ctx.GetView().SetOnSelectItem(ctx.SearchTrait.onSelectItemWrapper(func(selectedLineIdx int) error {
+ ctx.GetList().SetSelectedLineIdx(selectedLineIdx)
+ return ctx.HandleFocus(types.OnFocusOpts{})
+ }))
+
+ return ctx
}
func (self *CommitFilesContext) GetSelectedItemId() string {
diff --git a/pkg/gui/context/filtered_list.go b/pkg/gui/context/filtered_list.go
new file mode 100644
index 000000000..298d3d615
--- /dev/null
+++ b/pkg/gui/context/filtered_list.go
@@ -0,0 +1,93 @@
+package context
+
+import (
+ "github.com/jesseduffield/lazygit/pkg/utils"
+ "github.com/sasha-s/go-deadlock"
+)
+
+type FilteredList[T any] struct {
+ filteredIndices []int // if nil, we are not filtering
+
+ getList func() []T
+ getFilterFields func(T) []string
+ filter string
+
+ mutex *deadlock.Mutex
+}
+
+func NewFilteredList[T any](getList func() []T, getFilterFields func(T) []string) *FilteredList[T] {
+ return &FilteredList[T]{
+ getList: getList,
+ getFilterFields: getFilterFields,
+ mutex: &deadlock.Mutex{},
+ }
+}
+
+func (self *FilteredList[T]) GetFilter() string {
+ return self.filter
+}
+
+func (self *FilteredList[T]) SetFilter(filter string) {
+ self.filter = filter
+
+ self.applyFilter()
+}
+
+func (self *FilteredList[T]) ClearFilter() {
+ self.SetFilter("")
+}
+
+func (self *FilteredList[T]) IsFiltering() bool {
+ return self.filter != ""
+}
+
+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())
+}
+
+func (self *FilteredList[T]) applyFilter() {
+ self.mutex.Lock()
+ defer self.mutex.Unlock()
+
+ if self.filter == "" {
+ self.filteredIndices = nil
+ } else {
+ self.filteredIndices = []int{}
+ for i, item := range self.getList() {
+ for _, field := range self.getFilterFields(item) {
+ if self.match(field, self.filter) {
+ self.filteredIndices = append(self.filteredIndices, i)
+ break
+ }
+ }
+ }
+ }
+}
+
+func (self *FilteredList[T]) match(haystack string, needle string) bool {
+ return utils.CaseAwareContains(haystack, needle)
+}
+
+func (self *FilteredList[T]) UnfilteredIndex(index int) int {
+ self.mutex.Lock()
+ defer self.mutex.Unlock()
+
+ if self.filteredIndices == nil {
+ return index
+ }
+
+ // we use -1 when there are no items
+ if index == -1 {
+ return -1
+ }
+
+ return self.filteredIndices[index]
+}
diff --git a/pkg/gui/context/filtered_list_view_model.go b/pkg/gui/context/filtered_list_view_model.go
new file mode 100644
index 000000000..77f6e1174
--- /dev/null
+++ b/pkg/gui/context/filtered_list_view_model.go
@@ -0,0 +1,33 @@
+package context
+
+type FilteredListViewModel[T any] struct {
+ *FilteredList[T]
+ *ListViewModel[T]
+}
+
+func NewFilteredListViewModel[T any](getList func() []T, getFilterFields func(T) []string) *FilteredListViewModel[T] {
+ filteredList := NewFilteredList(getList, getFilterFields)
+
+ self := &FilteredListViewModel[T]{
+ FilteredList: filteredList,
+ }
+
+ listViewModel := NewListViewModel(filteredList.GetFilteredList)
+
+ self.ListViewModel = listViewModel
+
+ return self
+}
+
+// used for type switch
+func (self *FilteredListViewModel[T]) IsFilterableContext() {}
+
+func (self *FilteredListViewModel[T]) ClearFilter() {
+ // Set the selected line index to the unfiltered index of the currently selected line,
+ // so that the current item is still selected after the filter is cleared.
+ unfilteredIndex := self.FilteredList.UnfilteredIndex(self.GetSelectedLineIdx())
+
+ self.FilteredList.ClearFilter()
+
+ self.SetSelectedLineIdx(unfilteredIndex)
+}
diff --git a/pkg/gui/context/basic_view_model.go b/pkg/gui/context/list_view_model.go
index a53be4d91..b70330d7d 100644
--- a/pkg/gui/context/basic_view_model.go
+++ b/pkg/gui/context/list_view_model.go
@@ -2,13 +2,13 @@ package context
import "github.com/jesseduffield/lazygit/pkg/gui/context/traits"
-type BasicViewModel[T any] struct {
+type ListViewModel[T any] struct {
*traits.ListCursor
getModel func() []T
}
-func NewBasicViewModel[T any](getModel func() []T) *BasicViewModel[T] {
- self := &BasicViewModel[T]{
+func NewListViewModel[T any](getModel func() []T) *ListViewModel[T] {
+ self := &ListViewModel[T]{
getModel: getModel,
}
@@ -17,11 +17,11 @@ func NewBasicViewModel[T any](getModel func() []T) *BasicViewModel[T] {
return self
}
-func (self *BasicViewModel[T]) Len() int {
+func (self *ListViewModel[T]) Len() int {
return len(self.getModel())
}
-func (self *BasicViewModel[T]) GetSelected() T {
+func (self *ListViewModel[T]) GetSelected() T {
if self.Len() == 0 {
return Zero[T]()
}
@@ -29,6 +29,10 @@ func (self *BasicViewModel[T]) GetSelected() T {
return self.getModel()[self.GetSelectedLineIdx()]
}
+func (self *ListViewModel[T]) GetItems() []T {
+ return self.getModel()
+}
+
func Zero[T any]() T {
return *new(T)
}
diff --git a/pkg/gui/context/local_commits_context.go b/pkg/gui/context/local_commits_context.go
index 74363c52f..84204591c 100644
--- a/pkg/gui/context/local_commits_context.go
+++ b/pkg/gui/context/local_commits_context.go
@@ -13,6 +13,7 @@ import (
type LocalCommitsContext struct {
*LocalCommitsViewModel
*ListContextTrait
+ *SearchTrait
}
var (
@@ -57,8 +58,9 @@ func NewLocalCommitsContext(c *ContextCommon) *LocalCommitsContext {
)
}
- return &LocalCommitsContext{
+ ctx := &LocalCommitsContext{
LocalCommitsViewModel: viewModel,
+ SearchTrait: NewSearchTrait(c),
ListContextTrait: &ListContextTrait{
Context: NewSimpleContext(NewBaseContext(NewBaseContextOpts{
View: c.Views().Commits,
@@ -73,6 +75,13 @@ func NewLocalCommitsContext(c *ContextCommon) *LocalCommitsContext {
refreshViewportOnChange: true,
},
}
+
+ ctx.GetView().SetOnSelectItem(ctx.SearchTrait.onSelectItemWrapper(func(selectedLineIdx int) error {
+ ctx.GetList().SetSelectedLineIdx(selectedLineIdx)
+ return ctx.HandleFocus(types.OnFocusOpts{})
+ }))
+
+ return ctx
}
func (self *LocalCommitsContext) GetSelectedItemId() string {
@@ -85,7 +94,7 @@ func (self *LocalCommitsContext) GetSelectedItemId() string {
}
type LocalCommitsViewModel struct {
- *BasicViewModel[*models.Commit]
+ *ListViewModel[*models.Commit]
// If this is true we limit the amount of commits we load, for the sake of keeping things fast.
// If the user attempts to scroll past the end of the list, we will load more commits.
@@ -97,7 +106,7 @@ type LocalCommitsViewModel struct {
func NewLocalCommitsViewModel(getModel func() []*models.Commit, c *ContextCommon) *LocalCommitsViewModel {
self := &LocalCommitsViewModel{
- BasicViewModel: NewBasicViewModel(getModel),
+ ListViewModel: NewListViewModel(getModel),
limitCommits: true,
showWholeGitGraph: c.UserConfig.Git.Log.ShowWholeGraph,
}
diff --git a/pkg/gui/context/menu_context.go b/pkg/gui/context/menu_context.go
index 6f84a8274..088640ea0 100644
--- a/pkg/gui/context/menu_context.go
+++ b/pkg/gui/context/menu_context.go
@@ -56,7 +56,7 @@ func (self *MenuContext) GetSelectedItemId() string {
type MenuViewModel struct {
c *ContextCommon
menuItems []*types.MenuItem
- *BasicViewModel[*types.MenuItem]
+ *FilteredListViewModel[*types.MenuItem]
}
func NewMenuViewModel(c *ContextCommon) *MenuViewModel {
@@ -65,7 +65,10 @@ func NewMenuViewModel(c *ContextCommon) *MenuViewModel {
c: c,
}
- self.BasicViewModel = NewBasicViewModel(func() []*types.MenuItem { return self.menuItems })
+ self.FilteredListViewModel = NewFilteredListViewModel(
+ func() []*types.MenuItem { return self.menuItems },
+ func(item *types.MenuItem) []string { return item.LabelColumns },
+ )
return self
}
@@ -76,11 +79,12 @@ func (self *MenuViewModel) SetMenuItems(items []*types.MenuItem) {
// TODO: move into presentation package
func (self *MenuViewModel) GetDisplayStrings(_startIdx int, _length int) [][]string {
- showKeys := slices.Some(self.menuItems, func(item *types.MenuItem) bool {
+ menuItems := self.FilteredListViewModel.GetItems()
+ showKeys := slices.Some(menuItems, func(item *types.MenuItem) bool {
return item.Key != nil
})
- return slices.Map(self.menuItems, func(item *types.MenuItem) []string {
+ return slices.Map(menuItems, func(item *types.MenuItem) []string {
displayStrings := item.LabelColumns
if !showKeys {
@@ -93,6 +97,7 @@ func (self *MenuViewModel) GetDisplayStrings(_startIdx int, _length int) [][]str
self.c.UserConfig.Keybinding.Universal.Confirm,
self.c.UserConfig.Keybinding.Universal.Select,
self.c.UserConfig.Keybinding.Universal.Return,
+ self.c.UserConfig.Keybinding.Universal.StartSearch,
}
keyLabel := keybindings.LabelFromKey(item.Key)
keyStyle := style.FgCyan
diff --git a/pkg/gui/context/patch_explorer_context.go b/pkg/gui/context/patch_explorer_context.go
index 1c986ee1d..17ecae4ae 100644
--- a/pkg/gui/context/patch_explorer_context.go
+++ b/pkg/gui/context/patch_explorer_context.go
@@ -9,6 +9,7 @@ import (
type PatchExplorerContext struct {
*SimpleContext
+ *SearchTrait
state *patch_exploring.State
viewTrait *ViewTrait
@@ -28,7 +29,7 @@ func NewPatchExplorerContext(
c *ContextCommon,
) *PatchExplorerContext {
- return &PatchExplorerContext{
+ ctx := &PatchExplorerContext{
state: nil,
viewTrait: NewViewTrait(view),
c: c,
@@ -42,7 +43,18 @@ func NewPatchExplorerContext(
Focusable: true,
HighlightOnFocus: true,
})),
+ SearchTrait: NewSearchTrait(c),
}
+
+ ctx.GetView().SetOnSelectItem(ctx.SearchTrait.onSelectItemWrapper(
+ func(selectedLineIdx int) error {
+ ctx.GetMutex().Lock()
+ defer ctx.GetMutex().Unlock()
+ return ctx.NavigateTo(ctx.c.IsCurrentContext(ctx), selectedLineIdx)
+ }),
+ )
+
+ return ctx
}
func (self *PatchExplorerContext) IsPatchExplorerContext() {}
diff --git a/pkg/gui/context/reflog_commits_context.go b/pkg/gui/context/reflog_commits_context.go
index a92d605c8..421a7c8d5 100644
--- a/pkg/gui/context/reflog_commits_context.go
+++ b/pkg/gui/context/reflog_commits_context.go
@@ -9,7 +9,7 @@ import (
)
type ReflogCommitsContext struct {
- *BasicViewModel[*models.Commit]
+ *FilteredListViewModel[*models.Commit]
*ListContextTrait
}
@@ -19,11 +19,16 @@ var (
)
func NewReflogCommitsContext(c *ContextCommon) *ReflogCommitsContext {
- viewModel := NewBasicViewModel(func() []*models.Commit { return c.Model().FilteredReflogCommits })
+ viewModel := NewFilteredListViewModel(
+ func() []*models.Commit { return c.Model().FilteredReflogCommits },
+ func(commit *models.Commit) []string {
+ return []string{commit.ShortSha(), commit.Name}
+ },
+ )
getDisplayStrings := func(startIdx int, length int) [][]string {
return presentation.GetReflogCommitListDisplayStrings(
- c.Model().FilteredReflogCommits,
+ viewModel.GetItems(),
c.State().GetRepoState().GetScreenMode() != types.SCREEN_NORMAL,
c.Modes().CherryPicking.SelectedShaSet(),
c.Modes().Diffing.Ref,
@@ -35,7 +40,7 @@ func NewReflogCommitsContext(c *ContextCommon) *ReflogCommitsContext {
}
return &ReflogCommitsContext{
- BasicViewModel: viewModel,
+ FilteredListViewModel: viewModel,
ListContextTrait: &ListContextTrait{
Context: NewSimpleContext(NewBaseContext(NewBaseContextOpts{
View: c.Views().ReflogCommits,
diff --git a/pkg/gui/context/remote_branches_context.go b/pkg/gui/context/remote_branches_context.go
index a085c18cc..602a19a65 100644
--- a/pkg/gui/context/remote_branches_context.go
+++ b/pkg/gui/context/remote_branches_context.go
@@ -7,7 +7,7 @@ import (
)
type RemoteBranchesContext struct {
- *BasicViewModel[*models.RemoteBranch]
+ *FilteredListViewModel[*models.RemoteBranch]
*ListContextTrait
*DynamicTitleBuilder
}
@@ -20,15 +20,20 @@ var (
func NewRemoteBranchesContext(
c *ContextCommon,
) *RemoteBranchesContext {
- viewModel := NewBasicViewModel(func() []*models.RemoteBranch { return c.Model().RemoteBranches })
+ viewModel := NewFilteredListViewModel(
+ func() []*models.RemoteBranch { return c.Model().RemoteBranches },
+ func(remoteBranch *models.RemoteBranch) []string {
+ return []string{remoteBranch.Name}
+ },
+ )
getDisplayStrings := func(startIdx int, length int) [][]string {
- return presentation.GetRemoteBranchListDisplayStrings(c.Model().RemoteBranches, c.Modes().Diffing.Ref)
+ return presentation.GetRemoteBranchListDisplayStrings(viewModel.GetItems(), c.Modes().Diffing.Ref)
}
return &RemoteBranchesContext{
- BasicViewModel: viewModel,
- DynamicTitleBuilder: NewDynamicTitleBuilder(c.Tr.RemoteBranchesDynamicTitle),
+ FilteredListViewModel: viewModel,
+ DynamicTitleBuilder: NewDynamicTitleBuilder(c.Tr.RemoteBranchesDynamicTitle),
ListContextTrait: &ListContextTrait{
Context: NewSimpleContext(NewBaseContext(NewBaseContextOpts{
View: c.Views().RemoteBranches,
diff --git a/pkg/gui/context/remotes_context.go b/pkg/gui/context/remotes_context.go
index d1082ab52..f5e2a97ab 100644
--- a/pkg/gui/context/remotes_context.go
+++ b/pkg/gui/context/remotes_context.go
@@ -7,7 +7,7 @@ import (
)
type RemotesContext struct {
- *BasicViewModel[*models.Remote]
+ *FilteredListViewModel[*models.Remote]
*ListContextTrait
}
@@ -17,14 +17,19 @@ var (
)
func NewRemotesContext(c *ContextCommon) *RemotesContext {
- viewModel := NewBasicViewModel(func() []*models.Remote { return c.Model().Remotes })
+ viewModel := NewFilteredListViewModel(
+ func() []*models.Remote { return c.Model().Remotes },
+ func(remote *models.Remote) []string {
+ return []string{remote.Name}
+ },
+ )
getDisplayStrings := func(startIdx int, length int) [][]string {
- return presentation.GetRemoteListDisplayStrings(c.Model().Remotes, c.Modes().Diffing.Ref)
+ return presentation.GetRemoteListDisplayStrings(viewModel.GetItems(), c.Modes().Diffing.Ref)
}
return &RemotesContext{
- BasicViewModel: viewModel,
+ FilteredListViewModel: viewModel,
ListContextTrait: &ListContextTrait{
Context: NewSimpleContext(NewBaseContext(NewBaseContextOpts{
View: c.Views().Remotes,
diff --git a/pkg/gui/context/search_trait.go b/pkg/gui/context/search_trait.go
new file mode 100644
index 000000000..fad68d794
--- /dev/null
+++ b/pkg/gui/context/search_trait.go
@@ -0,0 +1,74 @@
+package context
+
+import (
+ "fmt"
+
+ "github.com/jesseduffield/lazygit/pkg/gui/keybindings"
+ "github.com/jesseduffield/lazygit/pkg/theme"
+)
+
+type SearchTrait struct {
+ c *ContextCommon
+
+ searchString string
+}
+
+func NewSearchTrait(c *ContextCommon) *SearchTrait {
+ return &SearchTrait{c: c}
+}
+
+func (self *SearchTrait) GetSearchString() string {
+ return self.searchString
+}
+
+func (self *SearchTrait) SetSearchString(searchString string) {
+ self.searchString = searchString
+}
+
+func (self *SearchTrait) ClearSearchString() {
+ self.SetSearchString("")
+}
+
+// used for type switch
+func (self *SearchTrait) IsSearchableContext() {}
+
+func (self *SearchTrait) onSelectItemWrapper(innerFunc func(int) error) func(int, int, int) error {
+ keybindingConfig := self.c.UserConfig.Keybinding
+
+ return func(y int, index int, total int) error {
+ if total == 0 {
+ self.c.SetViewContent(
+ self.c.Views().Search,
+ fmt.Sprintf(
+ self.c.Tr.NoMatchesFor,
+ self.searchString,
+ theme.OptionsFgColor.Sprintf(self.c.Tr.ExitSearchMode, keybindings.Label(keybindingConfig.Universal.Return)),
+ ),
+ )
+ return nil
+ }
+ self.c.SetViewContent(
+ self.c.Views().Search,
+ fmt.Sprintf(
+ self.c.Tr.MatchesFor,
+ self.searchString,
+ index+1,
+ total,
+ theme.OptionsFgColor.Sprintf(
+ self.c.Tr.SearchKeybindings,
+ keybindings.Label(keybindingConfig.Universal.NextMatch),
+ keybindings.Label(keybindingConfig.Universal.PrevMatch),
+ keybindings.Label(keybindingConfig.Universal.Return),
+ ),
+ ),
+ )
+ if err := innerFunc(y); err != nil {
+ return err
+ }
+ return nil
+ }
+}
+
+func (self *SearchTrait) IsSearching() bool {
+ return self.searchString != ""
+}
diff --git a/pkg/gui/context/stash_context.go b/pkg/gui/context/stash_context.go
index 386292c00..7bd4740f8 100644
--- a/pkg/gui/context/stash_context.go
+++ b/pkg/gui/context/stash_context.go
@@ -7,7 +7,7 @@ import (
)
type StashContext struct {
- *BasicViewModel[*models.StashEntry]
+ *FilteredListViewModel[*models.StashEntry]
*ListContextTrait
}
@@ -19,14 +19,19 @@ var (
func NewStashContext(
c *ContextCommon,
) *StashContext {
- viewModel := NewBasicViewModel(func() []*models.StashEntry { return c.Model().StashEntries })
+ viewModel := NewFilteredListViewModel(
+ func() []*models.StashEntry { return c.Model().StashEntries },
+ func(stashEntry *models.StashEntry) []string {
+ return []string{stashEntry.Name}
+ },
+ )
getDisplayStrings := func(startIdx int, length int) [][]string {
- return presentation.GetStashEntryListDisplayStrings(c.Model().StashEntries, c.Modes().Diffing.Ref)
+ return presentation.GetStashEntryListDisplayStrings(viewModel.GetItems(), c.Modes().Diffing.Ref)
}
return &StashContext{
- BasicViewModel: viewModel,
+ FilteredListViewModel: viewModel,
ListContextTrait: &ListContextTrait{
Context: NewSimpleContext(NewBaseContext(NewBaseContextOpts{
View: c.Views().Stash,
diff --git a/pkg/gui/context/sub_commits_context.go b/pkg/gui/context/sub_commits_context.go
index e2c89aa14..0cf884589 100644
--- a/pkg/gui/context/sub_commits_context.go
+++ b/pkg/gui/context/sub_commits_context.go
@@ -12,9 +12,12 @@ import (
)
type SubCommitsContext struct {
+ c *ContextCommon
+
*SubCommitsViewModel
*ListContextTrait
*DynamicTitleBuilder
+ *SearchTrait
}
var (
@@ -26,7 +29,7 @@ func NewSubCommitsContext(
c *ContextCommon,
) *SubCommitsContext {
viewModel := &SubCommitsViewModel{
- BasicViewModel: NewBasicViewModel(
+ ListViewModel: NewListViewModel(
func() []*models.Commit { return c.Model().SubCommits },
),
ref: nil,
@@ -60,8 +63,10 @@ func NewSubCommitsContext(
)
}
- return &SubCommitsContext{
+ ctx := &SubCommitsContext{
+ c: c,
SubCommitsViewModel: viewModel,
+ SearchTrait: NewSearchTrait(c),
DynamicTitleBuilder: NewDynamicTitleBuilder(c.Tr.SubCommitsDynamicTitle),
ListContextTrait: &ListContextTrait{
Context: NewSimpleContext(NewBaseContext(NewBaseContextOpts{
@@ -78,12 +83,19 @@ func NewSubCommitsContext(
refreshViewportOnChange: true,
},
}
+
+ ctx.GetView().SetOnSelectItem(ctx.SearchTrait.onSelectItemWrapper(func(selectedLineIdx int) error {
+ ctx.GetList().SetSelectedLineIdx(selectedLineIdx)
+ return ctx.HandleFocus(types.OnFocusOpts{})
+ }))
+
+ return ctx
}
type SubCommitsViewModel struct {
// name of the ref that the sub-commits are shown for
ref types.Ref
- *BasicViewModel[*models.Commit]
+ *ListViewModel[*models.Commit]
limitCommits bool
}
diff --git a/pkg/gui/context/submodules_context.go b/pkg/gui/context/submodules_context.go
index 675e01cd1..e97fa4f5c 100644
--- a/pkg/gui/context/submodules_context.go
+++ b/pkg/gui/context/submodules_context.go
@@ -7,21 +7,26 @@ import (
)
type SubmodulesContext struct {
- *BasicViewModel[*models.SubmoduleConfig]
+ *FilteredListViewModel[*models.SubmoduleConfig]
*ListContextTrait
}
var _ types.IListContext = (*SubmodulesContext)(nil)
func NewSubmodulesContext(c *ContextCommon) *SubmodulesContext {
- viewModel := NewBasicViewModel(func() []*models.SubmoduleConfig { return c.Model().Submodules })
+ viewModel := NewFilteredListViewModel(
+ func() []*models.SubmoduleConfig { return c.Model().Submodules },
+ func(submodule *models.SubmoduleConfig) []string {
+ return []string{submodule.Name}
+ },
+ )
getDisplayStrings := func(startIdx int, length int) [][]string {
- return presentation.GetSubmoduleListDisplayStrings(c.Model().Submodules)
+ return presentation.GetSubmoduleListDisplayStrings(viewModel.GetItems())
}
return &SubmodulesContext{
- BasicViewModel: viewModel,
+ FilteredListViewModel: viewModel,
ListContextTrait: &ListContextTrait{
Context: NewSimpleContext(NewBaseContext(NewBaseContextOpts{
View: c.Views().Submodules,
diff --git a/pkg/gui/context/suggestions_context.go b/pkg/gui/context/suggestions_context.go
index 022e96daf..58b2205a4 100644
--- a/pkg/gui/context/suggestions_context.go
+++ b/pkg/gui/context/suggestions_context.go
@@ -7,7 +7,7 @@ import (
)
type SuggestionsContext struct {
- *BasicViewModel[*types.Suggestion]
+ *ListViewModel[*types.Suggestion]
*ListContextTrait
State *SuggestionsContextState
@@ -40,11 +40,11 @@ func NewSuggestionsContext(
return presentation.GetSuggestionListDisplayStrings(state.Suggestions)
}
- viewModel := NewBasicViewModel(getModel)
+ viewModel := NewListViewModel(getModel)
return &SuggestionsContext{
- State: state,
- BasicViewModel: viewModel,
+ State: state,
+ ListViewModel: viewModel,
ListContextTrait: &ListContextTrait{
Context: NewSimpleContext(NewBaseContext(NewBaseContextOpts{
View: c.Views().Suggestions,
diff --git a/pkg/gui/context/tags_context.go b/pkg/gui/context/tags_context.go
index e49cdad9b..71ea36981 100644
--- a/pkg/gui/context/tags_context.go
+++ b/pkg/gui/context/tags_context.go
@@ -7,7 +7,7 @@ import (
)
type TagsContext struct {
- *BasicViewModel[*models.Tag]
+ *FilteredListViewModel[*models.Tag]
*ListContextTrait
}
@@ -19,14 +19,19 @@ var (
func NewTagsContext(
c *ContextCommon,
) *TagsContext {
- viewModel := NewBasicViewModel(func() []*models.Tag { return c.Model().Tags })
+ viewModel := NewFilteredListViewModel(
+ func() []*models.Tag { return c.Model().Tags },
+ func(tag *models.Tag) []string {
+ return []string{tag.Name, tag.Message}
+ },
+ )
getDisplayStrings := func(startIdx int, length int) [][]string {
- return presentation.GetTagListDisplayStrings(c.Model().Tags, c.Modes().Diffing.Ref)
+ return presentation.GetTagListDisplayStrings(viewModel.GetItems(), c.Modes().Diffing.Ref)
}
return &TagsContext{
- BasicViewModel: viewModel,
+ FilteredListViewModel: viewModel,
ListContextTrait: &ListContextTrait{
Context: NewSimpleContext(NewBaseContext(NewBaseContextOpts{
View: c.Views().Tags,
diff --git a/pkg/gui/context/working_tree_context.go b/pkg/gui/context/working_tree_context.go
index 45502eb60..107228ee8 100644
--- a/pkg/gui/context/working_tree_context.go
+++ b/pkg/gui/context/working_tree_context.go
@@ -11,6 +11,7 @@ import (
type WorkingTreeContext struct {
*filetree.FileTreeViewModel
*ListContextTrait
+ *SearchTrait
}
var _ types.IListContext = (*WorkingTreeContext)(nil)
@@ -29,7 +30,8 @@ func NewWorkingTreeContext(c *ContextCommon) *WorkingTreeContext {
})
}
- return &WorkingTreeContext{
+ ctx := &WorkingTreeContext{
+ SearchTrait: NewSearchTrait(c),
FileTreeViewModel: viewModel,
ListContextTrait: &ListContextTrait{
Context: NewSimpleContext(NewBaseContext(NewBaseContextOpts{
@@ -44,6 +46,13 @@ func NewWorkingTreeContext(c *ContextCommon) *WorkingTreeContext {
c: c,
},
}
+
+ ctx.GetView().SetOnSelectItem(ctx.SearchTrait.onSelectItemWrapper(func(selectedLineIdx int) error {
+ ctx.GetList().SetSelectedLineIdx(selectedLineIdx)
+ return ctx.HandleFocus(types.OnFocusOpts{})
+ }))
+
+ return ctx
}
func (self *WorkingTreeContext) GetSelectedItemId() string {