diff options
Diffstat (limited to 'pkg/gui/context')
-rw-r--r-- | pkg/gui/context/branches_context.go | 13 | ||||
-rw-r--r-- | pkg/gui/context/commit_files_context.go | 11 | ||||
-rw-r--r-- | pkg/gui/context/filtered_list.go | 93 | ||||
-rw-r--r-- | pkg/gui/context/filtered_list_view_model.go | 33 | ||||
-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.go | 15 | ||||
-rw-r--r-- | pkg/gui/context/menu_context.go | 13 | ||||
-rw-r--r-- | pkg/gui/context/patch_explorer_context.go | 14 | ||||
-rw-r--r-- | pkg/gui/context/reflog_commits_context.go | 13 | ||||
-rw-r--r-- | pkg/gui/context/remote_branches_context.go | 15 | ||||
-rw-r--r-- | pkg/gui/context/remotes_context.go | 13 | ||||
-rw-r--r-- | pkg/gui/context/search_trait.go | 74 | ||||
-rw-r--r-- | pkg/gui/context/stash_context.go | 13 | ||||
-rw-r--r-- | pkg/gui/context/sub_commits_context.go | 18 | ||||
-rw-r--r-- | pkg/gui/context/submodules_context.go | 13 | ||||
-rw-r--r-- | pkg/gui/context/suggestions_context.go | 8 | ||||
-rw-r--r-- | pkg/gui/context/tags_context.go | 13 | ||||
-rw-r--r-- | pkg/gui/context/working_tree_context.go | 11 |
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 { |