diff options
author | Jesse Duffield <jessedduffield@gmail.com> | 2020-08-22 11:44:03 +1000 |
---|---|---|
committer | Jesse Duffield <jessedduffield@gmail.com> | 2020-08-23 14:29:18 +1000 |
commit | c2b154acad4e1040bdc0e09cf44733ccd877923b (patch) | |
tree | d963fb7f4cdb405c8dfa610c94835d5c00822498 | |
parent | fbd61fcd17d495e9605bcf1f765663f861839cac (diff) |
better handling of our different modes and also cherry picking
-rw-r--r-- | pkg/gui/branches_panel.go | 2 | ||||
-rw-r--r-- | pkg/gui/cherry_picking.go | 103 | ||||
-rw-r--r-- | pkg/gui/diffing.go | 8 | ||||
-rw-r--r-- | pkg/gui/filtering.go | 6 | ||||
-rw-r--r-- | pkg/gui/filtering_menu_panel.go | 2 | ||||
-rw-r--r-- | pkg/gui/global_handlers.go | 4 | ||||
-rw-r--r-- | pkg/gui/gui.go | 18 | ||||
-rw-r--r-- | pkg/gui/keybindings.go | 2 | ||||
-rw-r--r-- | pkg/gui/layout.go | 21 | ||||
-rw-r--r-- | pkg/gui/list_context.go | 3 | ||||
-rw-r--r-- | pkg/gui/modes.go | 47 | ||||
-rw-r--r-- | pkg/gui/quitting.go | 13 | ||||
-rw-r--r-- | pkg/gui/reflog_panel.go | 2 |
13 files changed, 185 insertions, 46 deletions
diff --git a/pkg/gui/branches_panel.go b/pkg/gui/branches_panel.go index 7f7748834..360c10be6 100644 --- a/pkg/gui/branches_panel.go +++ b/pkg/gui/branches_panel.go @@ -48,7 +48,7 @@ func (gui *Gui) handleBranchSelect() error { // be sure there is a state.Branches array to pick the current branch from func (gui *Gui) refreshBranches() { reflogCommits := gui.State.FilteredReflogCommits - if gui.inFilterMode() { + if gui.State.Modes.Filtering.Active() { // in filter mode we filter our reflog commits to just those containing the path // however we need all the reflog entries to populate the recencies of our branches // which allows us to order them correctly. So if we're filtering we'll just diff --git a/pkg/gui/cherry_picking.go b/pkg/gui/cherry_picking.go index c87ba7a73..bd0ee5007 100644 --- a/pkg/gui/cherry_picking.go +++ b/pkg/gui/cherry_picking.go @@ -6,6 +6,20 @@ import ( // you can only copy from one context at a time, because the order and position of commits matter +func (gui *Gui) resetCherryPickingIfNecessary(context Context) error { + oldContextKey := gui.State.Modes.CherryPicking.ContextKey + + if oldContextKey != context.GetKey() { + // need to reset the cherry picking mode + gui.State.Modes.CherryPicking.ContextKey = context.GetKey() + gui.State.Modes.CherryPicking.CherryPickedCommits = make([]*commands.Commit, 0) + + return gui.rerenderContextViewIfPresent(oldContextKey) + } + + return nil +} + func (gui *Gui) handleCopyCommit() error { if ok, err := gui.validateNotInFilterMode(); err != nil || !ok { return err @@ -17,6 +31,10 @@ func (gui *Gui) handleCopyCommit() error { return nil } + if err := gui.resetCherryPickingIfNecessary(context); err != nil { + return err + } + commit, ok := context.SelectedItem().(*commands.Commit) if !ok { gui.Log.Error("type cast failed for handling copy commit") @@ -33,7 +51,7 @@ func (gui *Gui) handleCopyCommit() error { } } - gui.addCommitToCherryPickedCommits(gui.State.Panels.Commits.SelectedLineIdx) + gui.addCommitToCherryPickedCommits(context.GetPanelState().GetSelectedLineIdx()) return context.HandleRender() } @@ -45,12 +63,33 @@ func (gui *Gui) CherryPickedCommitShaMap() map[string]bool { return commitShaMap } +func (gui *Gui) commitsListForContext() []*commands.Commit { + context := gui.currentSideContext() + if context == nil { + return nil + } + + // using a switch statement, but we should use polymorphism + switch context.GetKey() { + case BRANCH_COMMITS_CONTEXT_KEY: + return gui.State.Commits + case REFLOG_COMMITS_CONTEXT_KEY: + return gui.State.FilteredReflogCommits + case SUB_COMMITS_CONTEXT_KEY: + return gui.State.SubCommits + default: + gui.Log.Errorf("no commit list for context %s", context.GetKey()) + return nil + } +} + func (gui *Gui) addCommitToCherryPickedCommits(index int) { commitShaMap := gui.CherryPickedCommitShaMap() - commitShaMap[gui.State.Commits[index].Sha] = true + commitsList := gui.commitsListForContext() + commitShaMap[commitsList[index].Sha] = true newCommits := []*commands.Commit{} - for _, commit := range gui.State.Commits { + for _, commit := range commitsList { if commitShaMap[commit.Sha] { // duplicating just the things we need to put in the rebase TODO list newCommits = append(newCommits, &commands.Commit{Name: commit.Name, Sha: commit.Sha}) @@ -65,18 +104,34 @@ func (gui *Gui) handleCopyCommitRange() error { return err } + // get currently selected commit, add the sha to state. + context := gui.currentSideContext() + if context == nil { + return nil + } + + gui.resetCherryPickingIfNecessary(context) + + commit, ok := context.SelectedItem().(*commands.Commit) + if !ok { + gui.Log.Error("type cast failed for handling copy commit") + } + if commit == nil { + return nil + } + commitShaMap := gui.CherryPickedCommitShaMap() // find the last commit that is copied that's above our position // if there are none, startIndex = 0 startIndex := 0 - for index, commit := range gui.State.Commits[0:gui.State.Panels.Commits.SelectedLineIdx] { + for index, commit := range gui.commitsListForContext()[0:context.GetPanelState().GetSelectedLineIdx()] { if commitShaMap[commit.Sha] { startIndex = index } } - for index := startIndex; index <= gui.State.Panels.Commits.SelectedLineIdx; index++ { + for index := startIndex; index <= context.GetPanelState().GetSelectedLineIdx(); index++ { gui.addCommitToCherryPickedCommits(index) } @@ -102,3 +157,41 @@ func (gui *Gui) HandlePasteCommits() error { }, }) } + +func (gui *Gui) exitCherryPickingMode() error { + contextKey := gui.State.Modes.CherryPicking.ContextKey + + gui.State.Modes.CherryPicking.ContextKey = "" + gui.State.Modes.CherryPicking.CherryPickedCommits = nil + + if contextKey == "" { + gui.Log.Warn("context key blank when trying to exit cherry picking mode") + return nil + } + + return gui.rerenderContextViewIfPresent(contextKey) +} + +func (gui *Gui) rerenderContextViewIfPresent(contextKey string) error { + if contextKey == "" { + return nil + } + + context := gui.contextForContextKey(contextKey) + + viewName := context.GetViewName() + + view, err := gui.g.View(viewName) + if err != nil { + gui.Log.Warn(err) + return nil + } + + if view.Context == contextKey { + if err := context.HandleRender(); err != nil { + return err + } + } + + return nil +} diff --git a/pkg/gui/diffing.go b/pkg/gui/diffing.go index 2093e1170..968887b30 100644 --- a/pkg/gui/diffing.go +++ b/pkg/gui/diffing.go @@ -7,10 +7,6 @@ import ( "github.com/jesseduffield/gocui" ) -func (gui *Gui) inDiffMode() bool { - return gui.State.Modes.Diffing.Ref != "" -} - func (gui *Gui) exitDiffMode() error { gui.State.Modes.Diffing = Diffing{} return gui.refreshSidePanels(refreshOptions{mode: ASYNC}) @@ -19,7 +15,7 @@ func (gui *Gui) exitDiffMode() error { func (gui *Gui) renderDiff() error { filterArg := "" - if gui.inFilterMode() { + if gui.State.Modes.Filtering.Active() { filterArg = fmt.Sprintf(" -- %s", gui.State.Modes.Filtering.Path) } @@ -126,7 +122,7 @@ func (gui *Gui) handleCreateDiffingMenuPanel(g *gocui.Gui, v *gocui.View) error }, }...) - if gui.inDiffMode() { + if gui.State.Modes.Diffing.Active() { menuItems = append(menuItems, []*menuItem{ { displayString: gui.Tr.SLocalize("swapDiff"), diff --git a/pkg/gui/filtering.go b/pkg/gui/filtering.go index 6f6968bdd..2faafe9f2 100644 --- a/pkg/gui/filtering.go +++ b/pkg/gui/filtering.go @@ -1,11 +1,7 @@ package gui -func (gui *Gui) inFilterMode() bool { - return gui.State.Modes.Filtering.Path != "" -} - func (gui *Gui) validateNotInFilterMode() (bool, error) { - if gui.inFilterMode() { + if gui.State.Modes.Filtering.Active() { err := gui.ask(askOpts{ returnToView: gui.g.CurrentView(), returnFocusOnClose: true, diff --git a/pkg/gui/filtering_menu_panel.go b/pkg/gui/filtering_menu_panel.go index 4d603a5bb..b70fc80b2 100644 --- a/pkg/gui/filtering_menu_panel.go +++ b/pkg/gui/filtering_menu_panel.go @@ -48,7 +48,7 @@ func (gui *Gui) handleCreateFilteringMenuPanel(g *gocui.Gui, v *gocui.View) erro }, }) - if gui.inFilterMode() { + if gui.State.Modes.Filtering.Active() { menuItems = append(menuItems, &menuItem{ displayString: gui.Tr.SLocalize("exitFilterMode"), onPress: func() error { diff --git a/pkg/gui/global_handlers.go b/pkg/gui/global_handlers.go index ee44a3c48..b1cedd63b 100644 --- a/pkg/gui/global_handlers.go +++ b/pkg/gui/global_handlers.go @@ -143,10 +143,10 @@ func (gui *Gui) handleInfoClick(g *gocui.Gui, v *gocui.View) error { // if we're in the normal context there will be a donate button here if width-cx <= len(gui.Tr.SLocalize("(reset)")) { - if gui.inFilterMode() { + if gui.State.Modes.Filtering.Active() { return gui.exitFilterMode() } - if gui.inDiffMode() { + if gui.State.Modes.Diffing.Active() { return gui.exitDiffMode() } if gui.GitCommand.PatchManager.Active() { diff --git a/pkg/gui/gui.go b/pkg/gui/gui.go index 7cebf5362..d7ae574e9 100644 --- a/pkg/gui/gui.go +++ b/pkg/gui/gui.go @@ -232,12 +232,27 @@ type Diffing struct { Reverse bool } +func (m *Diffing) Active() bool { + return m.Ref != "" +} + type Filtering struct { Path string // the filename that gets passed to git log } +func (m *Filtering) Active() bool { + return m.Path != "" +} + type CherryPicking struct { CherryPickedCommits []*commands.Commit + + // we only allow cherry picking from one context at a time, so you can't copy a commit from the local commits context and then also copy a commit in the reflog context + ContextKey string +} + +func (m *CherryPicking) Active() bool { + return len(m.CherryPickedCommits) > 0 } type Modes struct { @@ -309,6 +324,7 @@ func (gui *Gui) resetState() { }, CherryPicking: CherryPicking{ CherryPickedCommits: make([]*commands.Commit, 0), + ContextKey: "", }, Diffing: prevDiff, } @@ -383,7 +399,7 @@ func (gui *Gui) Run() error { } defer g.Close() - if gui.inFilterMode() { + if gui.State.Modes.Filtering.Active() { gui.State.ScreenMode = SCREEN_HALF } else { gui.State.ScreenMode = SCREEN_NORMAL diff --git a/pkg/gui/keybindings.go b/pkg/gui/keybindings.go index 23724f385..f9d6a777f 100644 --- a/pkg/gui/keybindings.go +++ b/pkg/gui/keybindings.go @@ -868,7 +868,7 @@ func (gui *Gui) GetInitialKeybindings() []*Binding { Description: gui.Tr.SLocalize("newBranch"), }, { - ViewName: "commits", + ViewName: "branches", Contexts: []string{SUB_COMMITS_CONTEXT_KEY}, Key: gui.getKey("commits.cherryPickCopy"), Handler: gui.wrappedHandler(gui.handleCopyCommit), diff --git a/pkg/gui/layout.go b/pkg/gui/layout.go index 8fb180e8b..33310fa6c 100644 --- a/pkg/gui/layout.go +++ b/pkg/gui/layout.go @@ -1,27 +1,22 @@ package gui import ( - "fmt" - "github.com/fatih/color" "github.com/jesseduffield/gocui" "github.com/jesseduffield/lazygit/pkg/theme" - "github.com/jesseduffield/lazygit/pkg/utils" ) const SEARCH_PREFIX = "search: " const INFO_SECTION_PADDING = " " func (gui *Gui) informationStr() string { - if gui.inDiffMode() { - return utils.ColoredString(fmt.Sprintf("%s %s %s", gui.Tr.SLocalize("showingGitDiff"), "git diff "+gui.diffStr(), utils.ColoredString(gui.Tr.SLocalize("(reset)"), color.Underline)), color.FgMagenta) - } else if gui.inFilterMode() { - return utils.ColoredString(fmt.Sprintf("%s '%s' %s", gui.Tr.SLocalize("filteringBy"), gui.State.Modes.Filtering.Path, utils.ColoredString(gui.Tr.SLocalize("(reset)"), color.Underline)), color.FgRed, color.Bold) - } else if gui.GitCommand.PatchManager.Active() { - return utils.ColoredString(fmt.Sprintf("%s %s", gui.Tr.SLocalize("buildingPatch"), utils.ColoredString(gui.Tr.SLocalize("(reset)"), color.Underline)), color.FgYellow, color.Bold) - } else if len(gui.State.Modes.CherryPicking.CherryPickedCommits) > 0 { - return utils.ColoredString(fmt.Sprintf("%d commits copied", len(gui.State.Modes.CherryPicking.CherryPickedCommits)), color.FgCyan) - } else if gui.g.Mouse { + for _, mode := range gui.modeStatuses() { + if mode.isActive() { + return mode.description() + } + } + + if gui.g.Mouse { donate := color.New(color.FgMagenta, color.Underline).Sprint(gui.Tr.SLocalize("Donate")) return donate + " " + gui.Config.GetVersion() } else { @@ -275,7 +270,7 @@ func (gui *Gui) layout(g *gocui.Gui) error { if gui.g.CurrentView() == nil { initialContext := gui.Contexts.Files.Context - if gui.inFilterMode() { + if gui.State.Modes.Filtering.Active() { initialContext = gui.Contexts.BranchCommits.Context } diff --git a/pkg/gui/list_context.go b/pkg/gui/list_context.go index 80eea1545..f97af7675 100644 --- a/pkg/gui/list_context.go +++ b/pkg/gui/list_context.go @@ -128,7 +128,7 @@ func (lc *ListContext) HandleFocus() error { view.FocusPoint(0, lc.GetPanelState().GetSelectedLineIdx()) - if lc.Gui.inDiffMode() { + if lc.Gui.State.Modes.Diffing.Active() { return lc.Gui.renderDiff() } @@ -403,6 +403,7 @@ func (gui *Gui) subCommitsListContext() *ListContext { RendersToMainView: true, Kind: SIDE_CONTEXT, GetDisplayStrings: func() [][]string { + gui.Log.Warn("getting display strings for sub commits") return presentation.GetCommitListDisplayStrings(gui.State.SubCommits, gui.State.ScreenMode != SCREEN_NORMAL, gui.CherryPickedCommitShaMap(), gui.State.Modes.Diffing.Ref) }, Contains: CONTAINS_COMMITS, diff --git a/pkg/gui/modes.go b/pkg/gui/modes.go new file mode 100644 index 000000000..f53a64d13 --- /dev/null +++ b/pkg/gui/modes.go @@ -0,0 +1,47 @@ +package gui + +import ( + "fmt" + + "github.com/fatih/color" + "github.com/jesseduffield/lazygit/pkg/utils" +) + +type modeStatus struct { + isActive func() bool + description func() string + onReset func() error +} + +func (gui *Gui) modeStatuses() []modeStatus { + return []modeStatus{ + { + isActive: gui.State.Modes.Diffing.Active, + description: func() string { + return utils.ColoredString(fmt.Sprintf("%s %s %s", gui.Tr.SLocalize("showingGitDiff"), "git diff "+gui.diffStr(), utils.ColoredString(gui.Tr.SLocalize("(reset)"), color.Underline)), color.FgMagenta) + }, + onReset: gui.exitDiffMode, + }, + { + isActive: gui.State.Modes.Filtering.Active, + description: func() string { + return utils.ColoredString(fmt.Sprintf("%s '%s' %s", gui.Tr.SLocalize("filteringBy"), gui.State.Modes.Filtering.Path, utils.ColoredString(gui.Tr.SLocalize("(reset)"), color.Underline)), color.FgRed, color.Bold) + }, + onReset: gui.exitFilterMode, + }, + { + isActive: gui.GitCommand.PatchManager.Active, + description: func() string { + return utils.ColoredString(fmt.Sprintf("%s %s", gui.Tr.SLocalize("buildingPatch"), utils.ColoredString(gui.Tr.SLocalize("(reset)"), color.Underline)), color.FgYellow, color.Bold) + }, + onReset: gui.handleResetPatch, + }, + { + isActive: gui.State.Modes.CherryPicking.Active, + description: func() string { + return utils.ColoredString(fmt.Sprintf("%d commits copied", len(gui.State.Modes.CherryPicking.CherryPickedCommits)), color.FgCyan) + }, + onReset: gui.exitCherryPickingMode, + }, + } +} diff --git a/pkg/gui/quitting.go b/pkg/gui/quitting.go index 6f1b77e29..da755c4dc 100644 --- a/pkg/gui/quitting.go +++ b/pkg/gui/quitting.go @@ -41,15 +41,10 @@ func (gui *Gui) handleTopLevelReturn(g *gocui.Gui, v *gocui.View) error { return gui.switchContext(currentContext.GetParentContext()) } - if gui.inDiffMode() { - return gui.exitDiffMode() - } - if gui.inFilterMode() { - return gui.exitFilterMode() - } - - if gui.GitCommand.PatchManager.Active() { - return gui.handleResetPatch() + for _, mode := range gui.modeStatuses() { + if mode.isActive() { + return mode.onReset() + } } if gui.Config.GetUserConfig().GetBool("quitOnTopLevelReturn") { diff --git a/pkg/gui/reflog_panel.go b/pkg/gui/reflog_panel.go index 35dfd542c..259c8f6ac 100644 --- a/pkg/gui/reflog_panel.go +++ b/pkg/gui/reflog_panel.go @@ -72,7 +72,7 @@ func (gui *Gui) refreshReflogCommits() error { return err } - if gui.inFilterMode() { + if gui.State.Modes.Filtering.Active() { if err := refresh(&state.FilteredReflogCommits, state.Modes.Filtering.Path); err != nil { return err } |