diff options
author | Jesse Duffield <jessedduffield@gmail.com> | 2022-08-06 18:50:52 +1000 |
---|---|---|
committer | Jesse Duffield <jessedduffield@gmail.com> | 2022-08-07 11:16:03 +1000 |
commit | 7410acd1aaa97f678295a328264360802346b33a (patch) | |
tree | 51dc6b5dfc8c0b67711ff644a6bc32480e6eaea8 /pkg/gui | |
parent | 445a625b56a79be6cee7ec1ee35fe9f4fcc2daad (diff) |
move merge conflicts code into controller
Diffstat (limited to 'pkg/gui')
36 files changed, 675 insertions, 646 deletions
diff --git a/pkg/gui/app_status_manager.go b/pkg/gui/app_status_manager.go index 2c5a8b1ec..21cf353a4 100644 --- a/pkg/gui/app_status_manager.go +++ b/pkg/gui/app_status_manager.go @@ -94,7 +94,7 @@ func (gui *Gui) renderAppStatus() { defer ticker.Stop() for range ticker.C { appStatus := gui.statusManager.getStatusString() - gui.OnUIThread(func() error { + gui.c.OnUIThread(func() error { return gui.renderString(gui.Views.AppStatus, appStatus) }) @@ -117,7 +117,7 @@ func (gui *Gui) withWaitingStatus(message string, f func() error) error { gui.renderAppStatus() if err := f(); err != nil { - gui.OnUIThread(func() error { + gui.c.OnUIThread(func() error { return gui.c.Error(err) }) } diff --git a/pkg/gui/command_log_panel.go b/pkg/gui/command_log_panel.go index 33f410043..dbee7febb 100644 --- a/pkg/gui/command_log_panel.go +++ b/pkg/gui/command_log_panel.go @@ -7,6 +7,7 @@ import ( "time" "github.com/jesseduffield/lazygit/pkg/constants" + "github.com/jesseduffield/lazygit/pkg/gui/keybindings" "github.com/jesseduffield/lazygit/pkg/gui/style" "github.com/jesseduffield/lazygit/pkg/theme" ) @@ -53,7 +54,7 @@ func (gui *Gui) LogCommand(cmdStr string, commandLine bool) { func (gui *Gui) printCommandLogHeader() { introStr := fmt.Sprintf( gui.c.Tr.CommandLogHeader, - gui.getKeyDisplay(gui.c.UserConfig.Keybinding.Universal.ExtrasMenu), + keybindings.Label(gui.c.UserConfig.Keybinding.Universal.ExtrasMenu), ) fmt.Fprintln(gui.Views.Extras, style.FgCyan.Sprint(introStr)) @@ -71,7 +72,7 @@ func (gui *Gui) getRandomTip() string { config := gui.c.UserConfig.Keybinding formattedKey := func(key string) string { - return gui.getKeyDisplay(key) + return keybindings.Label(key) } tips := []string{ diff --git a/pkg/gui/commit_message_panel.go b/pkg/gui/commit_message_panel.go index 35ffc822f..4c8ddae2b 100644 --- a/pkg/gui/commit_message_panel.go +++ b/pkg/gui/commit_message_panel.go @@ -5,6 +5,7 @@ import ( "strings" "github.com/jesseduffield/gocui" + "github.com/jesseduffield/lazygit/pkg/gui/keybindings" "github.com/jesseduffield/lazygit/pkg/utils" ) @@ -12,9 +13,9 @@ func (gui *Gui) handleCommitMessageFocused() error { message := utils.ResolvePlaceholderString( gui.c.Tr.CommitMessageConfirm, map[string]string{ - "keyBindClose": gui.getKeyDisplay(gui.c.UserConfig.Keybinding.Universal.Return), - "keyBindConfirm": gui.getKeyDisplay(gui.c.UserConfig.Keybinding.Universal.Confirm), - "keyBindNewLine": gui.getKeyDisplay(gui.c.UserConfig.Keybinding.Universal.AppendNewline), + "keyBindClose": keybindings.Label(gui.c.UserConfig.Keybinding.Universal.Return), + "keyBindConfirm": keybindings.Label(gui.c.UserConfig.Keybinding.Universal.Confirm), + "keyBindNewLine": keybindings.Label(gui.c.UserConfig.Keybinding.Universal.AppendNewline), }, ) diff --git a/pkg/gui/confirmation_panel.go b/pkg/gui/confirmation_panel.go index 86ae41812..1ad724ad5 100644 --- a/pkg/gui/confirmation_panel.go +++ b/pkg/gui/confirmation_panel.go @@ -5,6 +5,7 @@ import ( "strings" "github.com/jesseduffield/gocui" + "github.com/jesseduffield/lazygit/pkg/gui/keybindings" "github.com/jesseduffield/lazygit/pkg/gui/style" "github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/theme" @@ -220,22 +221,22 @@ func (gui *Gui) setKeyBindings(opts types.CreatePopupPanelOpts) error { bindings := []*types.Binding{ { ViewName: "confirmation", - Key: gui.getKey(keybindingConfig.Universal.Confirm), + Key: keybindings.GetKey(keybindingConfig.Universal.Confirm), Handler: onConfirm, }, { ViewName: "confirmation", - Key: gui.getKey(keybindingConfig.Universal.ConfirmAlt1), + Key: keybindings.GetKey(keybindingConfig.Universal.ConfirmAlt1), Handler: onConfirm, }, { ViewName: "confirmation", - Key: gui.getKey(keybindingConfig.Universal.Return), + Key: keybindings.GetKey(keybindingConfig.Universal.Return), Handler: gui.wrappedConfirmationFunction(opts.HandleClose), }, { ViewName: "confirmation", - Key: gui.getKey(keybindingConfig.Universal.TogglePanel), + Key: keybindings.GetKey(keybindingConfig.Universal.TogglePanel), Handler: func() error { if len(gui.State.Suggestions) > 0 { return gui.replaceContext(gui.State.Contexts.Suggestions) @@ -245,22 +246,22 @@ func (gui *Gui) setKeyBindings(opts types.CreatePopupPanelOpts) error { }, { ViewName: "suggestions", - Key: gui.getKey(keybindingConfig.Universal.Confirm), + Key: keybindings.GetKey(keybindingConfig.Universal.Confirm), Handler: onSuggestionConfirm, }, { ViewName: "suggestions", - Key: gui.getKey(keybindingConfig.Universal.ConfirmAlt1), + Key: keybindings.GetKey(keybindingConfig.Universal.ConfirmAlt1), Handler: onSuggestionConfirm, }, { ViewName: "suggestions", - Key: gui.getKey(keybindingConfig.Universal.Return), + Key: keybindings.GetKey(keybindingConfig.Universal.Return), Handler: gui.wrappedConfirmationFunction(opts.HandleClose), }, { ViewName: "suggestions", - Key: gui.getKey(keybindingConfig.Universal.TogglePanel), + Key: keybindings.GetKey(keybindingConfig.Universal.TogglePanel), Handler: func() error { return gui.replaceContext(gui.State.Contexts.Confirmation) }, }, } @@ -276,12 +277,12 @@ func (gui *Gui) setKeyBindings(opts types.CreatePopupPanelOpts) error { func (gui *Gui) clearConfirmationViewKeyBindings() { keybindingConfig := gui.c.UserConfig.Keybinding - _ = gui.g.DeleteKeybinding("confirmation", gui.getKey(keybindingConfig.Universal.Confirm), gocui.ModNone) - _ = gui.g.DeleteKeybinding("confirmation", gui.getKey(keybindingConfig.Universal.ConfirmAlt1), gocui.ModNone) - _ = gui.g.DeleteKeybinding("confirmation", gui.getKey(keybindingConfig.Universal.Return), gocui.ModNone) - _ = gui.g.DeleteKeybinding("suggestions", gui.getKey(keybindingConfig.Universal.Confirm), gocui.ModNone) - _ = gui.g.DeleteKeybinding("suggestions", gui.getKey(keybindingConfig.Universal.ConfirmAlt1), gocui.ModNone) - _ = gui.g.DeleteKeybinding("suggestions", gui.getKey(keybindingConfig.Universal.Return), gocui.ModNone) + _ = gui.g.DeleteKeybinding("confirmation", keybindings.GetKey(keybindingConfig.Universal.Confirm), gocui.ModNone) + _ = gui.g.DeleteKeybinding("confirmation", keybindings.GetKey(keybindingConfig.Universal.ConfirmAlt1), gocui.ModNone) + _ = gui.g.DeleteKeybinding("confirmation", keybindings.GetKey(keybindingConfig.Universal.Return), gocui.ModNone) + _ = gui.g.DeleteKeybinding("suggestions", keybindings.GetKey(keybindingConfig.Universal.Confirm), gocui.ModNone) + _ = gui.g.DeleteKeybinding("suggestions", keybindings.GetKey(keybindingConfig.Universal.ConfirmAlt1), gocui.ModNone) + _ = gui.g.DeleteKeybinding("suggestions", keybindings.GetKey(keybindingConfig.Universal.Return), gocui.ModNone) } func (gui *Gui) refreshSuggestions() { @@ -297,8 +298,8 @@ func (gui *Gui) handleAskFocused() error { message := utils.ResolvePlaceholderString( gui.c.Tr.CloseConfirm, map[string]string{ - "keyBindClose": gui.getKeyDisplay(keybindingConfig.Universal.Return), - "keyBindConfirm": gui.getKeyDisplay(keybindingConfig.Universal.Confirm), + "keyBindClose": keybindings.Label(keybindingConfig.Universal.Return), + "keyBindConfirm": keybindings.Label(keybindingConfig.Universal.Confirm), }, ) diff --git a/pkg/gui/context/menu_context.go b/pkg/gui/context/menu_context.go index 7754d02ae..780c35660 100644 --- a/pkg/gui/context/menu_context.go +++ b/pkg/gui/context/menu_context.go @@ -89,7 +89,7 @@ func (self *MenuViewModel) GetDisplayStrings(_startIdx int, _length int) [][]str return slices.Map(self.menuItems, func(item *types.MenuItem) []string { displayStrings := item.LabelColumns if showKeys { - displayStrings = slices.Prepend(displayStrings, style.FgCyan.Sprint(keybindings.GetKeyDisplay(item.Key))) + displayStrings = slices.Prepend(displayStrings, style.FgCyan.Sprint(keybindings.LabelFromKey(item.Key))) } return displayStrings }) diff --git a/pkg/gui/context/merge_conflicts_context.go b/pkg/gui/context/merge_conflicts_context.go index 48749373c..b49bf2c65 100644 --- a/pkg/gui/context/merge_conflicts_context.go +++ b/pkg/gui/context/merge_conflicts_context.go @@ -1,15 +1,20 @@ package context import ( + "math" + "sync" + "github.com/jesseduffield/gocui" "github.com/jesseduffield/lazygit/pkg/gui/mergeconflicts" "github.com/jesseduffield/lazygit/pkg/gui/types" + "github.com/sasha-s/go-deadlock" ) type MergeConflictsContext struct { types.Context viewModel *ConflictsViewModel c *types.HelperCommon + mutex *sync.Mutex } type ConflictsViewModel struct { @@ -35,6 +40,7 @@ func NewMergeConflictsContext( return &MergeConflictsContext{ viewModel: viewModel, + mutex: &sync.Mutex{}, Context: NewSimpleContext( NewBaseContext(NewBaseContextOpts{ Kind: types.MAIN_CONTEXT, @@ -50,6 +56,18 @@ func NewMergeConflictsContext( } } +func (self *MergeConflictsContext) GetState() *mergeconflicts.State { + return self.viewModel.state +} + +func (self *MergeConflictsContext) SetState(state *mergeconflicts.State) { + self.viewModel.state = state +} + +func (self *MergeConflictsContext) GetMutex() *sync.Mutex { + return self.mutex +} + func (self *MergeConflictsContext) SetUserScrolling(isScrolling bool) { self.viewModel.userVerticalScrolling = isScrolling } @@ -58,6 +76,43 @@ func (self *MergeConflictsContext) IsUserScrolling() bool { return self.viewModel.userVerticalScrolling } -func (self *MergeConflictsContext) State() *mergeconflicts.State { - return self.viewModel.state +func (self *MergeConflictsContext) RenderAndFocus(isFocused bool) error { + self.setContent(isFocused) + self.focusSelection() + + self.c.Render() + + return nil +} + +func (self *MergeConflictsContext) Render(isFocused bool) error { + self.setContent(isFocused) + + self.c.Render() + + return nil +} + +func (self *MergeConflictsContext) GetContentToRender(isFocused bool) string { + if self.GetState() == nil { + return "" + } + + return mergeconflicts.ColoredConflictFile(self.GetState(), isFocused) +} + +func (self *MergeConflictsContext) setContent(isFocused bool) { + self.GetView().SetContent(self.GetContentToRender(isFocused)) +} + +func (self *MergeConflictsContext) focusSelection() { + if !self.IsUserScrolling() { + _ = self.GetView().SetOrigin(self.GetView().OriginX(), self.GetOriginY()) + } +} + +func (self *MergeConflictsContext) GetOriginY() int { + view := self.GetView() + conflictMiddle := self.GetState().GetConflictMiddle() + return int(math.Max(0, float64(conflictMiddle-(view.Height()/2)))) } diff --git a/pkg/gui/context/patch_explorer_context.go b/pkg/gui/context/patch_explorer_context.go index 626c0be84..a8ad45bbb 100644 --- a/pkg/gui/context/patch_explorer_context.go +++ b/pkg/gui/context/patch_explorer_context.go @@ -67,19 +67,16 @@ func (self *PatchExplorerContext) GetIncludedLineIndices() []int { } func (self *PatchExplorerContext) RenderAndFocus(isFocused bool) error { - self.GetView().SetContent(self.GetContentToRender(isFocused)) - - if err := self.focusSelection(); err != nil { - return err - } + self.setContent(isFocused) + self.focusSelection() self.c.Render() return nil } func (self *PatchExplorerContext) Render(isFocused bool) error { - self.GetView().SetContent(self.GetContentToRender(isFocused)) + self.setContent(isFocused) self.c.Render() @@ -87,16 +84,17 @@ func (self *PatchExplorerContext) Render(isFocused bool) error { } func (self *PatchExplorerContext) Focus() error { - if err := self.focusSelection(); err != nil { - return err - } - + self.focusSelection() self.c.Render() return nil } -func (self *PatchExplorerContext) focusSelection() error { +func (self *PatchExplorerContext) setContent(isFocused bool) { + self.GetView().SetContent(self.GetContentToRender(isFocused)) +} + +func (self *PatchExplorerContext) focusSelection() { view := self.GetView() state := self.GetState() _, viewHeight := view.Size() @@ -107,11 +105,8 @@ func (self *PatchExplorerContext) focusSelection() error { newOrigin := state.CalculateOrigin(origin, bufferHeight) - if err := view.SetOriginY(newOrigin); err != nil { - return err - } - - return view.SetCursor(0, selectedLineIdx-newOrigin) + _ = view.SetOriginY(newOrigin) + _ = view.SetCursor(0, selectedLineIdx-newOrigin) } func (self *PatchExplorerContext) GetContentToRender(isFocused bool) string { diff --git a/pkg/gui/context_config.go b/pkg/gui/context_config.go index 79f14c68c..7bd0ca7f8 100644 --- a/pkg/gui/context_config.go +++ b/pkg/gui/context_config.go @@ -164,16 +164,21 @@ func (gui *Gui) contextTree() *context.ContextTree { OnFocus: OnFocusWrapper(func() error { gui.Views.MergeConflicts.Wrap = false - return gui.renderConflictsWithLock(true) + return gui.refreshMergePanel(true) }), - OnFocusLost: func(types.OnFocusLostOpts) error { + OnFocusLost: func(opts types.OnFocusLostOpts) error { + gui.State.Contexts.MergeConflicts.SetUserScrolling(false) + gui.State.Contexts.MergeConflicts.GetState().ResetConflictSelection() gui.Views.MergeConflicts.Wrap = true return nil }, }, gui.c, - gui.getMergingOptions, + func() map[string]string { + // wrapping in a function because contexts are initialized before helpers + return gui.helpers.MergeConflicts.GetMergingOptions() + }, ), Confirmation: context.NewSimpleContext( context.NewBaseContext(context.NewBaseContextOpts{ @@ -217,12 +222,11 @@ func (gui *Gui) contextTree() *context.ContextTree { ), CommandLog: context.NewSimpleContext( context.NewBaseContext(context.NewBaseContextOpts{ - Kind: types.EXTRAS_CONTEXT, - View: gui.Views.Extras, - WindowName: "extras", - Key: context.COMMAND_LOG_CONTEXT_KEY, - OnGetOptionsMap: gui.getMergingOptions, - Focusable: true, + Kind: types.EXTRAS_CONTEXT, + View: gui.Views.Extras, + WindowName: "extras", + Key: context.COMMAND_LOG_CONTEXT_KEY, + Focusable: true, }), context.ContextCallbackOpts{ OnFocusLost: func(opts types.OnFocusLostOpts) error { diff --git a/pkg/gui/controllers.go b/pkg/gui/controllers.go index e0c2d5eb6..4efb5e1ff 100644 --- a/pkg/gui/controllers.go +++ b/pkg/gui/controllers.go @@ -35,6 +35,7 @@ func (gui *Gui) resetControllers() { Tags: helpers.NewTagsHelper(helperCommon, gui.git), GPG: helpers.NewGpgHelper(helperCommon, gui.os, gui.git), MergeAndRebase: rebaseHelper, + MergeConflicts: helpers.NewMergeConflictsHelper(helperCommon, gui.State.Contexts, gui.git), CherryPick: helpers.NewCherryPickHelper( helperCommon, gui.git, @@ -51,7 +52,6 @@ func (gui *Gui) resetControllers() { gui.git, gui.State.Contexts, gui.helpers, - gui.getKey, ) common := controllers.NewControllerCommon( @@ -112,8 +112,8 @@ func (gui *Gui) resetControllers() { gui.enterSubmodule, setCommitMessage, getSavedCommitMessage, - gui.switchToMerge, ) + mergeConflictsController := controllers.NewMergeConflictsController(common) remotesController := controllers.NewRemotesController( common, func(branches []*models.RemoteBranch) { gui.State.Model.RemoteBranches = branches }, @@ -187,6 +187,10 @@ func (gui *Gui) resetControllers() { verticalScrollControllerFactory.Create(gui.State.Contexts.CustomPatchBuilder), ) + controllers.AttachControllers(gui.State.Contexts.MergeConflicts, + mergeConflictsController, + ) + controllers.AttachControllers(gui.State.Contexts.Files, filesController, filesRemoveController, diff --git a/pkg/gui/controllers/files_controller.go b/pkg/gui/controllers/files_controller.go index ba5e49ad9..20a802169 100644 --- a/pkg/gui/controllers/files_controller.go +++ b/pkg/gui/controllers/files_controller.go @@ -22,7 +22,6 @@ type FilesController struct { enterSubmodule func(submodule *models.SubmoduleConfig) error setCommitMessage func(message string) getSavedCommitMessage func() string - switchToMergeFn func(path string) error } var _ types.IController = &FilesController{} @@ -32,14 +31,12 @@ func NewFilesController( enterSubmodule func(submodule *models.SubmoduleConfig) error, setCommitMessage func(message string), getSavedCommitMessage func() string, - switchToMergeFn func(path string) error, ) *FilesController { return &FilesController{ controllerCommon: common, enterSubmodule: enterSubmodule, setCommitMessage: setCommitMessage, getSavedCommitMessage: getSavedCommitMessage, - switchToMergeFn: switchToMergeFn, } } @@ -268,10 +265,6 @@ func (self *FilesController) pressWithLock(node *filetree.FileNode) error { if node.IsFile() { file := node.File - if file.HasInlineMergeConflicts { - return self.c.PushContext(self.contexts.MergeConflicts) - } - if file.HasUnstagedChanges { self.c.LogAction(self.c.Tr.Actions.StageFile) @@ -328,6 +321,10 @@ func (self *FilesController) pressWithLock(node *filetree.FileNode) error { } func (self *FilesController) press(node *filetree.FileNode) error { + if node.IsFile() && node.File.HasInlineMergeConflicts { + return self.switchToMerge() + } + if err := self.pressWithLock(node); err != nil { return err } @@ -750,7 +747,7 @@ func (self *FilesController) switchToMerge() error { return nil } - return self.switchToMergeFn(file.Name) + return self.helpers.MergeConflicts.SwitchToMerge(file.Name) } func (self *FilesController) createStashMenu() error { diff --git a/pkg/gui/controllers/helpers/helpers.go b/pkg/gui/controllers/helpers/helpers.go index 61fdedf46..b8c279fac 100644 --- a/pkg/gui/controllers/helpers/helpers.go +++ b/pkg/gui/controllers/helpers/helpers.go @@ -8,6 +8,7 @@ type Helpers struct { WorkingTree *WorkingTreeHelper Tags *TagsHelper MergeAndRebase *MergeAndRebaseHelper + MergeConflicts *MergeConflictsHelper CherryPick *CherryPickHelper Host *HostHelper PatchBuilding *PatchBuildingHelper @@ -24,6 +25,7 @@ func NewStubHelpers() *Helpers { WorkingTree: &WorkingTreeHelper{}, Tags: &TagsHelper{}, MergeAndRebase: &MergeAndRebaseHelper{}, + MergeConflicts: &MergeConflictsHelper{}, CherryPick: &CherryPickHelper{}, Host: &HostHelper{}, PatchBuilding: &PatchBuildingHelper{}, diff --git a/pkg/gui/controllers/helpers/merge_and_rebase_helper.go b/pkg/gui/controllers/helpers/merge_and_rebase_helper.go index 4666f103d..21c02d6f4 100644 --- a/pkg/gui/controllers/helpers/merge_and_rebase_helper.go +++ b/pkg/gui/controllers/helpers/merge_and_rebase_helper.go @@ -186,8 +186,6 @@ func (self *MergeAndRebaseHelper) workingTreeStateNoun() string { // PromptToContinueRebase asks the user if they want to continue the rebase/merge that's in progress func (self *MergeAndRebaseHelper) PromptToContinueRebase() error { - self.contexts.MergeConflicts.SetUserScrolling(false) - return self.c.Confirm(types.ConfirmOpts{ Title: "continue", Prompt: self.c.Tr.ConflictsResolved, diff --git a/pkg/gui/controllers/helpers/merge_conflicts_helper.go b/pkg/gui/controllers/helpers/merge_conflicts_helper.go new file mode 100644 index 000000000..d7f7aa747 --- /dev/null +++ b/pkg/gui/controllers/helpers/merge_conflicts_helper.go @@ -0,0 +1,115 @@ +package helpers + +import ( + "fmt" + + "github.com/jesseduffield/lazygit/pkg/commands" + "github.com/jesseduffield/lazygit/pkg/gui/context" + "github.com/jesseduffield/lazygit/pkg/gui/keybindings" + "github.com/jesseduffield/lazygit/pkg/gui/types" +) + +type MergeConflictsHelper struct { + c *types.HelperCommon + contexts *context.ContextTree + git *commands.GitCommand +} + +func NewMergeConflictsHelper( + c *types.HelperCommon, + contexts *context.ContextTree, + git *commands.GitCommand, +) *MergeConflictsHelper { + return &MergeConflictsHelper{ + c: c, + contexts: contexts, + git: git, + } +} + +func (self *MergeConflictsHelper) GetMergingOptions() map[string]string { + keybindingConfig := self.c.UserConfig.Keybinding + + return map[string]string{ + fmt.Sprintf("%s %s", keybindings.Label(keybindingConfig.Universal.PrevItem), keybindings.Label(keybindingConfig.Universal.NextItem)): self.c.Tr.LcSelectHunk, + fmt.Sprintf("%s %s", keybindings.Label(keybindingConfig.Universal.PrevBlock), keybindings.Label(keybindingConfig.Universal.NextBlock)): self.c.Tr.LcNavigateConflicts, + keybindings.Label(keybindingConfig.Universal.Select): self.c.Tr.LcPickHunk, + keybindings.Label(keybindingConfig.Main.PickBothHunks): self.c.Tr.LcPickAllHunks, + keybindings.Label(keybindingConfig.Universal.Undo): self.c.Tr.LcUndo, + } +} + +func (self *MergeConflictsHelper) SetMergeState(path string) (bool, error) { + self.context().GetMutex().Lock() + defer self.context().GetMutex().Unlock() + + return self.setMergeStateWithoutLock(path) +} + +func (self *MergeConflictsHelper) setMergeStateWithoutLock(path string) (bool, error) { + content, err := self.git.File.Cat(path) |