mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-04-23 12:18:51 +02:00
When exiting filtering mode, we currently keep the selection index the same in the commits panel. This doesn't make sense at all, since the index in the filtered view has no relation to the index in the unfiltered view. I often use filtering mode (either by path or by author) to find a given commit faster than I would otherwise be able to. When exiting filtering mode, it's useful to keep the same commit selected, so that I can look at the surrounding commits, see which branch it was a part of, etc. So reselect the commit again after exiting filtering mode. Sometimes this is not possible, most likely when the commit is so long ago that it's outside of the initial 300 range. In that case, at least select the commit again that was selected before I entered filtering; this is still better than arbitrarily keeping the same selection index.
197 lines
5.0 KiB
Go
197 lines
5.0 KiB
Go
package context
|
|
|
|
import (
|
|
"log"
|
|
"time"
|
|
|
|
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
|
"github.com/jesseduffield/lazygit/pkg/commands/types/enums"
|
|
"github.com/jesseduffield/lazygit/pkg/gui/presentation"
|
|
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
|
"github.com/samber/lo"
|
|
)
|
|
|
|
type LocalCommitsContext struct {
|
|
*LocalCommitsViewModel
|
|
*ListContextTrait
|
|
*SearchTrait
|
|
}
|
|
|
|
var (
|
|
_ types.IListContext = (*LocalCommitsContext)(nil)
|
|
_ types.DiffableContext = (*LocalCommitsContext)(nil)
|
|
)
|
|
|
|
func NewLocalCommitsContext(c *ContextCommon) *LocalCommitsContext {
|
|
viewModel := NewLocalCommitsViewModel(
|
|
func() []*models.Commit { return c.Model().Commits },
|
|
c,
|
|
)
|
|
|
|
getDisplayStrings := func(startIdx int, endIdx int) [][]string {
|
|
selectedCommitSha := ""
|
|
|
|
if c.CurrentContext().GetKey() == LOCAL_COMMITS_CONTEXT_KEY {
|
|
selectedCommit := viewModel.GetSelected()
|
|
if selectedCommit != nil {
|
|
selectedCommitSha = selectedCommit.Sha
|
|
}
|
|
}
|
|
|
|
showYouAreHereLabel := c.Model().WorkingTreeStateAtLastCommitRefresh == enums.REBASE_MODE_REBASING
|
|
hasRebaseUpdateRefsConfig := c.Git().Config.GetRebaseUpdateRefs()
|
|
|
|
return presentation.GetCommitListDisplayStrings(
|
|
c.Common,
|
|
c.Model().Commits,
|
|
c.Model().Branches,
|
|
c.Model().CheckedOutBranch,
|
|
hasRebaseUpdateRefsConfig,
|
|
c.State().GetRepoState().GetScreenMode() != types.SCREEN_NORMAL,
|
|
c.Modes().CherryPicking.SelectedShaSet(),
|
|
c.Modes().Diffing.Ref,
|
|
c.Modes().MarkedBaseCommit.GetSha(),
|
|
c.UserConfig.Gui.TimeFormat,
|
|
c.UserConfig.Gui.ShortTimeFormat,
|
|
time.Now(),
|
|
c.UserConfig.Git.ParseEmoji,
|
|
selectedCommitSha,
|
|
startIdx,
|
|
endIdx,
|
|
shouldShowGraph(c),
|
|
c.Model().BisectInfo,
|
|
showYouAreHereLabel,
|
|
)
|
|
}
|
|
|
|
ctx := &LocalCommitsContext{
|
|
LocalCommitsViewModel: viewModel,
|
|
SearchTrait: NewSearchTrait(c),
|
|
ListContextTrait: &ListContextTrait{
|
|
Context: NewSimpleContext(NewBaseContext(NewBaseContextOpts{
|
|
View: c.Views().Commits,
|
|
WindowName: "commits",
|
|
Key: LOCAL_COMMITS_CONTEXT_KEY,
|
|
Kind: types.SIDE_CONTEXT,
|
|
Focusable: true,
|
|
NeedsRerenderOnWidthChange: true,
|
|
})),
|
|
ListRenderer: ListRenderer{
|
|
list: viewModel,
|
|
getDisplayStrings: getDisplayStrings,
|
|
},
|
|
c: c,
|
|
refreshViewportOnChange: true,
|
|
},
|
|
}
|
|
|
|
ctx.GetView().SetOnSelectItem(ctx.SearchTrait.onSelectItemWrapper(func(selectedLineIdx int) error {
|
|
ctx.GetList().SetSelection(selectedLineIdx)
|
|
return ctx.HandleFocus(types.OnFocusOpts{})
|
|
}))
|
|
|
|
return ctx
|
|
}
|
|
|
|
type LocalCommitsViewModel struct {
|
|
*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.
|
|
limitCommits bool
|
|
|
|
// If this is true we'll use git log --all when fetching the commits.
|
|
showWholeGitGraph bool
|
|
}
|
|
|
|
func NewLocalCommitsViewModel(getModel func() []*models.Commit, c *ContextCommon) *LocalCommitsViewModel {
|
|
self := &LocalCommitsViewModel{
|
|
ListViewModel: NewListViewModel(getModel),
|
|
limitCommits: true,
|
|
showWholeGitGraph: c.UserConfig.Git.Log.ShowWholeGraph,
|
|
}
|
|
|
|
return self
|
|
}
|
|
|
|
func (self *LocalCommitsContext) CanRebase() bool {
|
|
return true
|
|
}
|
|
|
|
func (self *LocalCommitsContext) GetSelectedRef() types.Ref {
|
|
commit := self.GetSelected()
|
|
if commit == nil {
|
|
return nil
|
|
}
|
|
return commit
|
|
}
|
|
|
|
// Returns the commit hash of the selected commit, or an empty string if no
|
|
// commit is selected
|
|
func (self *LocalCommitsContext) GetSelectedCommitHash() string {
|
|
commit := self.GetSelected()
|
|
if commit == nil {
|
|
return ""
|
|
}
|
|
return commit.Sha
|
|
}
|
|
|
|
func (self *LocalCommitsContext) SelectCommitByHash(hash string) bool {
|
|
if hash == "" {
|
|
return false
|
|
}
|
|
|
|
if _, idx, found := lo.FindIndexOf(self.GetItems(), func(c *models.Commit) bool { return c.Sha == hash }); found {
|
|
self.SetSelection(idx)
|
|
return true
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
func (self *LocalCommitsContext) GetDiffTerminals() []string {
|
|
itemId := self.GetSelectedItemId()
|
|
|
|
return []string{itemId}
|
|
}
|
|
|
|
func (self *LocalCommitsViewModel) SetLimitCommits(value bool) {
|
|
self.limitCommits = value
|
|
}
|
|
|
|
func (self *LocalCommitsViewModel) GetLimitCommits() bool {
|
|
return self.limitCommits
|
|
}
|
|
|
|
func (self *LocalCommitsViewModel) SetShowWholeGitGraph(value bool) {
|
|
self.showWholeGitGraph = value
|
|
}
|
|
|
|
func (self *LocalCommitsViewModel) GetShowWholeGitGraph() bool {
|
|
return self.showWholeGitGraph
|
|
}
|
|
|
|
func (self *LocalCommitsViewModel) GetCommits() []*models.Commit {
|
|
return self.getModel()
|
|
}
|
|
|
|
func shouldShowGraph(c *ContextCommon) bool {
|
|
if c.Modes().Filtering.Active() {
|
|
return false
|
|
}
|
|
|
|
value := c.GetAppState().GitLogShowGraph
|
|
|
|
switch value {
|
|
case "always":
|
|
return true
|
|
case "never":
|
|
return false
|
|
case "when-maximised":
|
|
return c.State().GetRepoState().GetScreenMode() != types.SCREEN_NORMAL
|
|
}
|
|
|
|
log.Fatalf("Unknown value for git.log.showGraph: %s. Expected one of: 'always', 'never', 'when-maximised'", value)
|
|
return false
|
|
}
|