mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-02-01 13:17:53 +02:00
move merge conflicts code into controller
This commit is contained in:
parent
445a625b56
commit
7410acd1aa
@ -142,7 +142,7 @@ func getBindingSections(bindings []*types.Binding, tr *i18n.TranslationSet) []*b
|
||||
bindingsByHeader,
|
||||
func(header header, hBindings []*types.Binding) headerWithBindings {
|
||||
uniqBindings := lo.UniqBy(hBindings, func(binding *types.Binding) string {
|
||||
return binding.Description + keybindings.GetKeyDisplay(binding.Key)
|
||||
return binding.Description + keybindings.LabelFromKey(binding.Key)
|
||||
})
|
||||
|
||||
return headerWithBindings{
|
||||
@ -202,10 +202,10 @@ func formatBinding(binding *types.Binding) string {
|
||||
if binding.Alternative != "" {
|
||||
return fmt.Sprintf(
|
||||
" <kbd>%s</kbd>: %s (%s)\n",
|
||||
keybindings.GetKeyDisplay(binding.Key),
|
||||
keybindings.LabelFromKey(binding.Key),
|
||||
binding.Description,
|
||||
binding.Alternative,
|
||||
)
|
||||
}
|
||||
return fmt.Sprintf(" <kbd>%s</kbd>: %s\n", keybindings.GetKeyDisplay(binding.Key), binding.Description)
|
||||
return fmt.Sprintf(" <kbd>%s</kbd>: %s\n", keybindings.LabelFromKey(binding.Key), binding.Description)
|
||||
}
|
||||
|
@ -7,7 +7,8 @@ import (
|
||||
"bytes"
|
||||
"io"
|
||||
"os/exec"
|
||||
"sync"
|
||||
|
||||
"github.com/sasha-s/go-deadlock"
|
||||
)
|
||||
|
||||
type Buffer struct {
|
||||
|
@ -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)
|
||||
})
|
||||
}
|
||||
|
@ -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{
|
||||
|
@ -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),
|
||||
},
|
||||
)
|
||||
|
||||
|
@ -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),
|
||||
},
|
||||
)
|
||||
|
||||
|
@ -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
|
||||
})
|
||||
|
@ -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))))
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
|
@ -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 {
|
||||
|
@ -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{},
|
||||
|
@ -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,
|
||||
|
115
pkg/gui/controllers/helpers/merge_conflicts_helper.go
Normal file
115
pkg/gui/controllers/helpers/merge_conflicts_helper.go
Normal file
@ -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)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if path != self.context().GetState().GetPath() {
|
||||
self.context().SetUserScrolling(false)
|
||||
}
|
||||
|
||||
self.context().GetState().SetContent(content, path)
|
||||
|
||||
return !self.context().GetState().NoConflicts(), nil
|
||||
}
|
||||
|
||||
func (self *MergeConflictsHelper) ResetMergeState() {
|
||||
self.context().GetMutex().Lock()
|
||||
defer self.context().GetMutex().Unlock()
|
||||
|
||||
self.resetMergeState()
|
||||
}
|
||||
|
||||
func (self *MergeConflictsHelper) resetMergeState() {
|
||||
self.context().SetUserScrolling(false)
|
||||
self.context().GetState().Reset()
|
||||
}
|
||||
|
||||
func (self *MergeConflictsHelper) EscapeMerge() error {
|
||||
self.resetMergeState()
|
||||
|
||||
// doing this in separate UI thread so that we're not still holding the lock by the time refresh the file
|
||||
self.c.OnUIThread(func() error {
|
||||
return self.c.PushContext(self.contexts.Files)
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *MergeConflictsHelper) SetConflictsAndRender(path string, isFocused bool) (bool, error) {
|
||||
hasConflicts, err := self.setMergeStateWithoutLock(path)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if hasConflicts {
|
||||
return true, self.context().Render(isFocused)
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (self *MergeConflictsHelper) SwitchToMerge(path string) error {
|
||||
if self.context().GetState().GetPath() != path {
|
||||
hasConflicts, err := self.SetMergeState(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !hasConflicts {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return self.c.PushContext(self.contexts.MergeConflicts)
|
||||
}
|
||||
|
||||
func (self *MergeConflictsHelper) context() *context.MergeConflictsContext {
|
||||
return self.contexts.MergeConflicts
|
||||
}
|
@ -1,7 +1,11 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/jesseduffield/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/mergeconflicts"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
)
|
||||
|
||||
@ -25,14 +29,125 @@ func (self *MergeConflictsController) GetKeybindings(opts types.KeybindingsOpts)
|
||||
bindings := []*types.Binding{
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.Edit),
|
||||
Handler: self.EditFile,
|
||||
Handler: self.HandleEditFile,
|
||||
Description: self.c.Tr.LcEditFile,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.OpenFile),
|
||||
Handler: self.HandleOpenFile,
|
||||
Description: self.c.Tr.LcOpenFile,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.PrevBlock),
|
||||
Handler: self.withRenderAndFocus(self.PrevConflict),
|
||||
Description: self.c.Tr.PrevConflict,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.NextBlock),
|
||||
Handler: self.withRenderAndFocus(self.NextConflict),
|
||||
Description: self.c.Tr.NextConflict,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.PrevItem),
|
||||
Handler: self.withRenderAndFocus(self.PrevConflictHunk),
|
||||
Description: self.c.Tr.SelectPrevHunk,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.NextItem),
|
||||
Handler: self.withRenderAndFocus(self.NextConflictHunk),
|
||||
Description: self.c.Tr.SelectNextHunk,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.PrevBlockAlt),
|
||||
Handler: self.withRenderAndFocus(self.PrevConflict),
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.NextBlockAlt),
|
||||
Handler: self.withRenderAndFocus(self.NextConflict),
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.PrevItemAlt),
|
||||
Handler: self.withRenderAndFocus(self.PrevConflictHunk),
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.NextItemAlt),
|
||||
Handler: self.withRenderAndFocus(self.NextConflictHunk),
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.ScrollLeft),
|
||||
Handler: self.withRenderAndFocus(self.HandleScrollLeft),
|
||||
Description: self.c.Tr.LcScrollLeft,
|
||||
Tag: "navigation",
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.ScrollRight),
|
||||
Handler: self.withRenderAndFocus(self.HandleScrollRight),
|
||||
Description: self.c.Tr.LcScrollRight,
|
||||
Tag: "navigation",
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.Undo),
|
||||
Handler: self.withRenderAndFocus(self.HandleUndo),
|
||||
Description: self.c.Tr.LcUndo,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Files.OpenMergeTool),
|
||||
Handler: self.helpers.WorkingTree.OpenMergeTool,
|
||||
Description: self.c.Tr.LcOpenMergeTool,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.Select),
|
||||
Handler: self.withRenderAndFocus(self.HandlePickHunk),
|
||||
Description: self.c.Tr.PickHunk,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Main.PickBothHunks),
|
||||
Handler: self.withRenderAndFocus(self.HandlePickAllHunks),
|
||||
Description: self.c.Tr.PickAllHunks,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.Return),
|
||||
Handler: self.Escape,
|
||||
Description: self.c.Tr.ReturnToFilesPanel,
|
||||
},
|
||||
}
|
||||
|
||||
return bindings
|
||||
}
|
||||
|
||||
func (self *MergeConflictsController) GetMouseKeybindings(opts types.KeybindingsOpts) []*gocui.ViewMouseBinding {
|
||||
return []*gocui.ViewMouseBinding{
|
||||
{
|
||||
ViewName: self.context().GetViewName(),
|
||||
Key: gocui.MouseWheelUp,
|
||||
Handler: func(gocui.ViewMouseBindingOpts) error {
|
||||
return self.HandleScrollUp()
|
||||
},
|
||||
},
|
||||
{
|
||||
ViewName: self.context().GetViewName(),
|
||||
Key: gocui.MouseWheelDown,
|
||||
Handler: func(gocui.ViewMouseBindingOpts) error {
|
||||
return self.HandleScrollDown()
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (self *MergeConflictsController) HandleScrollUp() error {
|
||||
self.context().SetUserScrolling(true)
|
||||
self.context().GetViewTrait().ScrollUp(self.c.UserConfig.Gui.ScrollHeight)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *MergeConflictsController) HandleScrollDown() error {
|
||||
self.context().SetUserScrolling(true)
|
||||
self.context().GetViewTrait().ScrollDown(self.c.UserConfig.Gui.ScrollHeight)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *MergeConflictsController) Context() types.Context {
|
||||
return self.context()
|
||||
}
|
||||
@ -41,14 +156,162 @@ func (self *MergeConflictsController) context() *context.MergeConflictsContext {
|
||||
return self.contexts.MergeConflicts
|
||||
}
|
||||
|
||||
func (self *MergeConflictsController) EditFile() error {
|
||||
lineNumber := self.context().State().GetSelectedLine()
|
||||
return self.helpers.Files.EditFileAtLine(self.context().State().GetPath(), lineNumber)
|
||||
func (self *MergeConflictsController) Escape() error {
|
||||
return self.c.PushContext(self.contexts.Files)
|
||||
}
|
||||
|
||||
func (self *MergeConflictsController) withMergeConflictLock(f func() error) error {
|
||||
self.context().State().Lock()
|
||||
defer self.context().State().Unlock()
|
||||
|
||||
return f()
|
||||
func (self *MergeConflictsController) HandleEditFile() error {
|
||||
lineNumber := self.context().GetState().GetSelectedLine()
|
||||
return self.helpers.Files.EditFileAtLine(self.context().GetState().GetPath(), lineNumber)
|
||||
}
|
||||
|
||||
func (self *MergeConflictsController) HandleOpenFile() error {
|
||||
lineNumber := self.context().GetState().GetSelectedLine()
|
||||
return self.helpers.Files.OpenFileAtLine(self.context().GetState().GetPath(), lineNumber)
|
||||
}
|
||||
|
||||
func (self *MergeConflictsController) HandleScrollLeft() error {
|
||||
self.context().GetViewTrait().ScrollLeft()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *MergeConflictsController) HandleScrollRight() error {
|
||||
self.context().GetViewTrait().ScrollRight()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *MergeConflictsController) HandleUndo() error {
|
||||
state := self.context().GetState()
|
||||
|
||||
ok := state.Undo()
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
self.c.LogAction("Restoring file to previous state")
|
||||
self.c.LogCommand("Undoing last conflict resolution", false)
|
||||
if err := ioutil.WriteFile(state.GetPath(), []byte(state.GetContent()), 0o644); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *MergeConflictsController) PrevConflictHunk() error {
|
||||
self.context().SetUserScrolling(false)
|
||||
self.context().GetState().SelectPrevConflictHunk()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *MergeConflictsController) NextConflictHunk() error {
|
||||
self.context().SetUserScrolling(false)
|
||||
self.context().GetState().SelectNextConflictHunk()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *MergeConflictsController) NextConflict() error {
|
||||
self.context().SetUserScrolling(false)
|
||||
self.context().GetState().SelectNextConflict()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *MergeConflictsController) PrevConflict() error {
|
||||
self.context().SetUserScrolling(false)
|
||||
self.context().GetState().SelectPrevConflict()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *MergeConflictsController) HandlePickHunk() error {
|
||||
return self.pickSelection(self.context().GetState().Selection())
|
||||
}
|
||||
|
||||
func (self *MergeConflictsController) HandlePickAllHunks() error {
|
||||
return self.pickSelection(mergeconflicts.ALL)
|
||||
}
|
||||
|
||||
func (self *MergeConflictsController) pickSelection(selection mergeconflicts.Selection) error {
|
||||
ok, err := self.resolveConflict(selection)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
if self.context().GetState().AllConflictsResolved() {
|
||||
return self.onLastConflictResolved()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *MergeConflictsController) resolveConflict(selection mergeconflicts.Selection) (bool, error) {
|
||||
self.context().SetUserScrolling(false)
|
||||
|
||||
state := self.context().GetState()
|
||||
|
||||
ok, content, err := state.ContentAfterConflictResolve(selection)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if !ok {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
var logStr string
|
||||
switch selection {
|
||||
case mergeconflicts.TOP:
|
||||
logStr = "Picking top hunk"
|
||||
case mergeconflicts.MIDDLE:
|
||||
logStr = "Picking middle hunk"
|
||||
case mergeconflicts.BOTTOM:
|
||||
logStr = "Picking bottom hunk"
|
||||
case mergeconflicts.ALL:
|
||||
logStr = "Picking all hunks"
|
||||
}
|
||||
self.c.LogAction("Resolve merge conflict")
|
||||
self.c.LogCommand(logStr, false)
|
||||
state.PushContent(content)
|
||||
return true, ioutil.WriteFile(state.GetPath(), []byte(content), 0o644)
|
||||
}
|
||||
|
||||
func (self *MergeConflictsController) onLastConflictResolved() error {
|
||||
// as part of refreshing files, we handle the situation where a file has had
|
||||
// its merge conflicts resolved.
|
||||
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.FILES}})
|
||||
}
|
||||
|
||||
func (self *MergeConflictsController) isFocused() bool {
|
||||
return self.c.CurrentContext().GetKey() == self.context().GetKey()
|
||||
}
|
||||
|
||||
func (self *MergeConflictsController) withRenderAndFocus(f func() error) func() error {
|
||||
return self.withLock(func() error {
|
||||
if err := f(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return self.context().RenderAndFocus(self.isFocused())
|
||||
})
|
||||
}
|
||||
|
||||
func (self *MergeConflictsController) withLock(f func() error) func() error {
|
||||
return func() error {
|
||||
self.context().GetMutex().Lock()
|
||||
defer self.context().GetMutex().Unlock()
|
||||
|
||||
if self.context().GetState() == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return f()
|
||||
}
|
||||
}
|
||||
|
@ -4,10 +4,11 @@ import (
|
||||
"unicode"
|
||||
|
||||
"github.com/jesseduffield/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/keybindings"
|
||||
)
|
||||
|
||||
func (gui *Gui) handleEditorKeypress(textArea *gocui.TextArea, key gocui.Key, ch rune, mod gocui.Modifier, allowMultiline bool) bool {
|
||||
newlineKey, ok := gui.getKey(gui.c.UserConfig.Keybinding.Universal.AppendNewline).(gocui.Key)
|
||||
newlineKey, ok := keybindings.GetKey(gui.c.UserConfig.Keybinding.Universal.AppendNewline).(gocui.Key)
|
||||
if !ok {
|
||||
newlineKey = gocui.KeyAltEnter
|
||||
}
|
||||
|
@ -6,8 +6,6 @@ import (
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/filetree"
|
||||
)
|
||||
|
||||
// list panel functions
|
||||
|
||||
func (gui *Gui) getSelectedFileNode() *filetree.FileNode {
|
||||
return gui.State.Contexts.Files.GetSelected()
|
||||
}
|
||||
@ -20,15 +18,6 @@ func (gui *Gui) getSelectedFile() *models.File {
|
||||
return node.File
|
||||
}
|
||||
|
||||
func (gui *Gui) getSelectedPath() string {
|
||||
node := gui.getSelectedFileNode()
|
||||
if node == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
return node.GetPath()
|
||||
}
|
||||
|
||||
func (gui *Gui) filesRenderToMain() error {
|
||||
node := gui.getSelectedFileNode()
|
||||
|
||||
@ -43,16 +32,17 @@ func (gui *Gui) filesRenderToMain() error {
|
||||
}
|
||||
|
||||
if node.File != nil && node.File.HasInlineMergeConflicts {
|
||||
ok, err := gui.setConflictsAndRenderWithLock(node.GetPath(), false)
|
||||
hasConflicts, err := gui.helpers.MergeConflicts.SetMergeState(node.GetPath())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if ok {
|
||||
return nil
|
||||
|
||||
if hasConflicts {
|
||||
return gui.refreshMergePanel(false)
|
||||
}
|
||||
}
|
||||
|
||||
gui.resetMergeStateWithLock()
|
||||
gui.helpers.MergeConflicts.ResetMergeState()
|
||||
|
||||
pair := gui.normalMainContextPair()
|
||||
if node.File != nil {
|
||||
@ -92,13 +82,6 @@ func (gui *Gui) filesRenderToMain() error {
|
||||
return gui.refreshMainViews(refreshOpts)
|
||||
}
|
||||
|
||||
func (gui *Gui) onFocusFile() error {
|
||||
gui.State.Contexts.MergeConflicts.SetUserScrolling(false)
|
||||
return nil
|
||||
}
|
||||
|
||||
// test
|
||||
|
||||
func (gui *Gui) getSetTextareaTextFn(getView func() *gocui.View) func(string) {
|
||||
return func(text string) {
|
||||
// using a getView function so that we don't need to worry about when the view is created
|
||||
@ -108,5 +91,3 @@ func (gui *Gui) getSetTextareaTextFn(getView func() *gocui.View) func(string) {
|
||||
view.RenderTextArea()
|
||||
}
|
||||
}
|
||||
|
||||
// test
|
||||
|
@ -75,10 +75,6 @@ func (gui *Gui) scrollDownView(view *gocui.View) {
|
||||
}
|
||||
|
||||
func (gui *Gui) scrollUpMain() error {
|
||||
if gui.renderingConflicts() {
|
||||
gui.State.Contexts.MergeConflicts.SetUserScrolling(true)
|
||||
}
|
||||
|
||||
var view *gocui.View
|
||||
if gui.c.CurrentContext().GetWindowName() == "secondary" {
|
||||
view = gui.secondaryView()
|
||||
@ -86,16 +82,20 @@ func (gui *Gui) scrollUpMain() error {
|
||||
view = gui.mainView()
|
||||
}
|
||||
|
||||
if view.Name() == "mergeConflicts" {
|
||||
// although we have this same logic in the controller, this method can be invoked
|
||||
// via the global scroll up/down keybindings, as opposed to just the mouse wheel keybinding.
|
||||
// It would be nice to have a concept of a global keybinding that runs on the top context in a
|
||||
// window but that might be overkill for this one use case.
|
||||
gui.State.Contexts.MergeConflicts.SetUserScrolling(true)
|
||||
}
|
||||
|
||||
gui.scrollUpView(view)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (gui *Gui) scrollDownMain() error {
|
||||
if gui.renderingConflicts() {
|
||||
gui.State.Contexts.MergeConflicts.SetUserScrolling(true)
|
||||
}
|
||||
|
||||
var view *gocui.View
|
||||
if gui.c.CurrentContext().GetWindowName() == "secondary" {
|
||||
view = gui.secondaryView()
|
||||
@ -103,6 +103,10 @@ func (gui *Gui) scrollDownMain() error {
|
||||
view = gui.mainView()
|
||||
}
|
||||
|
||||
if view.Name() == "mergeConflicts" {
|
||||
gui.State.Contexts.MergeConflicts.SetUserScrolling(true)
|
||||
}
|
||||
|
||||
gui.scrollDownView(view)
|
||||
|
||||
return nil
|
||||
@ -120,27 +124,6 @@ func (gui *Gui) secondaryView() *gocui.View {
|
||||
return view
|
||||
}
|
||||
|
||||
func (gui *Gui) scrollLeftMain() error {
|
||||
gui.scrollLeft(gui.mainView())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (gui *Gui) scrollRightMain() error {
|
||||
gui.scrollRight(gui.mainView())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (gui *Gui) scrollLeft(view *gocui.View) {
|
||||
newOriginX := utils.Max(view.OriginX()-view.InnerWidth()/HORIZONTAL_SCROLL_FACTOR, 0)
|
||||
_ = view.SetOriginX(newOriginX)
|
||||
}
|
||||
|
||||
func (gui *Gui) scrollRight(view *gocui.View) {
|
||||
_ = view.SetOriginX(view.OriginX() + view.InnerWidth()/HORIZONTAL_SCROLL_FACTOR)
|
||||
}
|
||||
|
||||
func (gui *Gui) scrollUpSecondary() error {
|
||||
gui.scrollUpView(gui.secondaryView())
|
||||
|
||||
|
@ -19,6 +19,7 @@ import (
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/keybindings"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/modes/cherrypicking"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/modes/diffing"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/modes/filtering"
|
||||
@ -481,6 +482,13 @@ func (gui *Gui) Run(startArgs types.StartArgs) error {
|
||||
gui.g = g
|
||||
defer gui.g.Close()
|
||||
|
||||
// if the deadlock package wants to report a deadlock, we first need to
|
||||
// close the gui so that we can actually read what it prints.
|
||||
deadlock.Opts.LogBuf = utils.NewOnceWriter(os.Stderr, func() {
|
||||
gui.g.Close()
|
||||
})
|
||||
deadlock.Opts.Disable = !gui.Debug
|
||||
|
||||
if replaying() {
|
||||
gui.g.RecordingConfig = gocui.RecordingConfig{
|
||||
Speed: getRecordingSpeed(),
|
||||
@ -504,9 +512,9 @@ func (gui *Gui) Run(startArgs types.StartArgs) error {
|
||||
return nil
|
||||
}
|
||||
userConfig := gui.UserConfig
|
||||
gui.g.SearchEscapeKey = gui.getKey(userConfig.Keybinding.Universal.Return)
|
||||
gui.g.NextSearchMatchKey = gui.getKey(userConfig.Keybinding.Universal.NextMatch)
|
||||
gui.g.PrevSearchMatchKey = gui.getKey(userConfig.Keybinding.Universal.PrevMatch)
|
||||
gui.g.SearchEscapeKey = keybindings.GetKey(userConfig.Keybinding.Universal.Return)
|
||||
gui.g.NextSearchMatchKey = keybindings.GetKey(userConfig.Keybinding.Universal.NextMatch)
|
||||
gui.g.PrevSearchMatchKey = keybindings.GetKey(userConfig.Keybinding.Universal.PrevMatch)
|
||||
|
||||
gui.g.ShowListFooter = userConfig.Gui.ShowListFooter
|
||||
|
||||
@ -771,7 +779,7 @@ func (gui *Gui) setColorScheme() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (gui *Gui) OnUIThread(f func() error) {
|
||||
func (gui *Gui) onUIThread(f func() error) {
|
||||
gui.g.Update(func(*gocui.Gui) error {
|
||||
return f()
|
||||
})
|
||||
|
@ -87,5 +87,5 @@ func (self *guiCommon) OpenSearch() {
|
||||
}
|
||||
|
||||
func (self *guiCommon) OnUIThread(f func() error) {
|
||||
self.gui.OnUIThread(f)
|
||||
self.gui.onUIThread(f)
|
||||
}
|
||||
|
@ -2,37 +2,13 @@ package gui
|
||||
|
||||
import (
|
||||
"log"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/jesseduffield/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/constants"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/keybindings"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
)
|
||||
|
||||
func (gui *Gui) getKeyDisplay(name string) string {
|
||||
key := gui.getKey(name)
|
||||
return keybindings.GetKeyDisplay(key)
|
||||
}
|
||||
|
||||
func (gui *Gui) getKey(key string) types.Key {
|
||||
runeCount := utf8.RuneCountInString(key)
|
||||
if runeCount > 1 {
|
||||
binding := keybindings.Keymap[strings.ToLower(key)]
|
||||
if binding == nil {
|
||||
log.Fatalf("Unrecognized key %s for keybinding. For permitted values see %s", strings.ToLower(key), constants.Links.Docs.CustomKeybindings)
|
||||
} else {
|
||||
return binding
|
||||
}
|
||||
} else if runeCount == 1 {
|
||||
return []rune(key)[0]
|
||||
}
|
||||
log.Fatal("Key empty for keybinding: " + strings.ToLower(key))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (gui *Gui) noPopupPanel(f func() error) func() error {
|
||||
return func() error {
|
||||
if gui.popupPanelFocused() {
|
||||
@ -68,7 +44,7 @@ func (self *Gui) GetInitialKeybindings() ([]*types.Binding, []*gocui.ViewMouseBi
|
||||
}
|
||||
|
||||
opts := types.KeybindingsOpts{
|
||||
GetKey: self.getKey,
|
||||
GetKey: keybindings.GetKey,
|
||||
Config: config,
|
||||
Guards: guards,
|
||||
}
|
||||
@ -325,110 +301,6 @@ func (self *Gui) GetInitialKeybindings() ([]*types.Binding, []*gocui.ViewMouseBi
|
||||
Modifier: gocui.ModNone,
|
||||
Handler: self.scrollUpSecondary,
|
||||
},
|
||||
{
|
||||
ViewName: "mergeConflicts",
|
||||
Key: opts.GetKey(opts.Config.Universal.ScrollLeft),
|
||||
Handler: self.scrollLeftMain,
|
||||
Description: self.c.Tr.LcScrollLeft,
|
||||
Tag: "navigation",
|
||||
},
|
||||
{
|
||||
ViewName: "mergeConflicts",
|
||||
Key: opts.GetKey(opts.Config.Universal.ScrollRight),
|
||||
Handler: self.scrollRightMain,
|
||||
Description: self.c.Tr.LcScrollRight,
|
||||
Tag: "navigation",
|
||||
},
|
||||
{
|
||||
ViewName: "mergeConflicts",
|
||||
Key: opts.GetKey(opts.Config.Universal.Return),
|
||||
Handler: self.handleEscapeMerge,
|
||||
Description: self.c.Tr.ReturnToFilesPanel,
|
||||
},
|
||||
{
|
||||
ViewName: "mergeConflicts",
|
||||
Key: opts.GetKey(opts.Config.Files.OpenMergeTool),
|
||||
Handler: self.helpers.WorkingTree.OpenMergeTool,
|
||||
Description: self.c.Tr.LcOpenMergeTool,
|
||||
},
|
||||
{
|
||||
ViewName: "mergeConflicts",
|
||||
Key: opts.GetKey(opts.Config.Universal.Select),
|
||||
Handler: self.handlePickHunk,
|
||||
Description: self.c.Tr.PickHunk,
|
||||
},
|
||||
{
|
||||
ViewName: "mergeConflicts",
|
||||
Key: opts.GetKey(opts.Config.Main.PickBothHunks),
|
||||
Handler: self.handlePickAllHunks,
|
||||
Description: self.c.Tr.PickAllHunks,
|
||||
},
|
||||
{
|
||||
ViewName: "mergeConflicts",
|
||||
Key: opts.GetKey(opts.Config.Universal.PrevBlock),
|
||||
Handler: self.handleSelectPrevConflict,
|
||||
Description: self.c.Tr.PrevConflict,
|
||||
},
|
||||
{
|
||||
ViewName: "mergeConflicts",
|
||||
Key: opts.GetKey(opts.Config.Universal.NextBlock),
|
||||
Handler: self.handleSelectNextConflict,
|
||||
Description: self.c.Tr.NextConflict,
|
||||
},
|
||||
{
|
||||
ViewName: "mergeConflicts",
|
||||
Key: opts.GetKey(opts.Config.Universal.PrevItem),
|
||||
Handler: self.handleSelectPrevConflictHunk,
|
||||
Description: self.c.Tr.SelectPrevHunk,
|
||||
},
|
||||
{
|
||||
ViewName: "mergeConflicts",
|
||||
Key: opts.GetKey(opts.Config.Universal.NextItem),
|
||||
Handler: self.handleSelectNextConflictHunk,
|
||||
Description: self.c.Tr.SelectNextHunk,
|
||||
},
|
||||
{
|
||||
ViewName: "mergeConflicts",
|
||||
Key: opts.GetKey(opts.Config.Universal.PrevBlockAlt),
|
||||
Modifier: gocui.ModNone,
|
||||
Handler: self.handleSelectPrevConflict,
|
||||
},
|
||||
{
|
||||
ViewName: "mergeConflicts",
|
||||
Key: opts.GetKey(opts.Config.Universal.NextBlockAlt),
|
||||
Modifier: gocui.ModNone,
|
||||
Handler: self.handleSelectNextConflict,
|
||||
},
|
||||
{
|
||||
ViewName: "mergeConflicts",
|
||||
Key: opts.GetKey(opts.Config.Universal.PrevItemAlt),
|
||||
Modifier: gocui.ModNone,
|
||||
Handler: self.handleSelectPrevConflictHunk,
|
||||
},
|
||||
{
|
||||
ViewName: "mergeConflicts",
|
||||
Key: opts.GetKey(opts.Config.Universal.NextItemAlt),
|
||||
Modifier: gocui.ModNone,
|
||||
Handler: self.handleSelectNextConflictHunk,
|
||||
},
|
||||
{
|
||||
ViewName: "mergeConflicts",
|
||||
Key: opts.GetKey(opts.Config.Universal.Edit),
|
||||
Handler: self.handleMergeConflictEditFileAtLine,
|
||||
Description: self.c.Tr.LcEditFile,
|
||||
},
|
||||
{
|
||||
ViewName: "mergeConflicts",
|
||||
Key: opts.GetKey(opts.Config.Universal.OpenFile),
|
||||
Handler: self.handleMergeConflictOpenFileAtLine,
|
||||
Description: self.c.Tr.LcOpenFile,
|
||||
},
|
||||
{
|
||||
ViewName: "mergeConflicts",
|
||||
Key: opts.GetKey(opts.Config.Universal.Undo),
|
||||
Handler: self.handleMergeConflictUndo,
|
||||
Description: self.c.Tr.LcUndo,
|
||||
},
|
||||
{
|
||||
ViewName: "status",
|
||||
Key: gocui.MouseLeft,
|
||||
|
@ -2,12 +2,16 @@ package keybindings
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/jesseduffield/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/constants"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
)
|
||||
|
||||
var KeyMapReversed = map[gocui.Key]string{
|
||||
var keyMapReversed = map[gocui.Key]string{
|
||||
gocui.KeyF1: "f1",
|
||||
gocui.KeyF2: "f2",
|
||||
gocui.KeyF3: "f3",
|
||||
@ -66,11 +70,11 @@ var KeyMapReversed = map[gocui.Key]string{
|
||||
gocui.KeyCtrl5: "ctrl+5", // ctrl+]
|
||||
gocui.KeyCtrl6: "ctrl+6",
|
||||
gocui.KeyCtrl8: "ctrl+8",
|
||||
gocui.MouseWheelUp: "mouse wheel up",
|
||||
gocui.MouseWheelDown: "mouse wheel down",
|
||||
gocui.MouseWheelUp: "mouse wheel ▲",
|
||||
gocui.MouseWheelDown: "mouse wheel ▼",
|
||||
}
|
||||
|
||||
var Keymap = map[string]types.Key{
|
||||
var keyMap = map[string]types.Key{
|
||||
"<c-a>": gocui.KeyCtrlA,
|
||||
"<c-b>": gocui.KeyCtrlB,
|
||||
"<c-c>": gocui.KeyCtrlC,
|
||||
@ -142,14 +146,18 @@ var Keymap = map[string]types.Key{
|
||||
"<right>": gocui.KeyArrowRight,
|
||||
}
|
||||
|
||||
func GetKeyDisplay(key types.Key) string {
|
||||
func Label(name string) string {
|
||||
return LabelFromKey(GetKey(name))
|
||||
}
|
||||
|
||||
func LabelFromKey(key types.Key) string {
|
||||
keyInt := 0
|
||||
|
||||
switch key := key.(type) {
|
||||
case rune:
|
||||
keyInt = int(key)
|
||||
case gocui.Key:
|
||||
value, ok := KeyMapReversed[key]
|
||||
value, ok := keyMapReversed[key]
|
||||
if ok {
|
||||
return value
|
||||
}
|
||||
@ -158,3 +166,19 @@ func GetKeyDisplay(key types.Key) string {
|
||||
|
||||
return fmt.Sprintf("%c", keyInt)
|
||||
}
|
||||
|
||||
func GetKey(key string) types.Key {
|
||||
runeCount := utf8.RuneCountInString(key)
|
||||
if runeCount > 1 {
|
||||
binding := keyMap[strings.ToLower(key)]
|
||||
if binding == nil {
|
||||
log.Fatalf("Unrecognized key %s for keybinding. For permitted values see %s", strings.ToLower(key), constants.Links.Docs.CustomKeybindings)
|
||||
} else {
|
||||
return binding
|
||||
}
|
||||
} else if runeCount == 1 {
|
||||
return []rune(key)[0]
|
||||
}
|
||||
log.Fatal("Key empty for keybinding: " + strings.ToLower(key))
|
||||
return nil
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ func (gui *Gui) filesListContext() *context.WorkingTreeContext {
|
||||
return []string{line}
|
||||
})
|
||||
},
|
||||
OnFocusWrapper(gui.onFocusFile),
|
||||
nil,
|
||||
gui.withDiffModeCheck(gui.filesRenderToMain),
|
||||
nil,
|
||||
gui.c,
|
||||
|
@ -43,6 +43,18 @@ func NewRenderStringWithoutScrollTask(str string) *renderStringWithoutScrollTask
|
||||
return &renderStringWithoutScrollTask{str: str}
|
||||
}
|
||||
|
||||
type renderStringWithScrollTask struct {
|
||||
str string
|
||||
originX int
|
||||
originY int
|
||||
}
|
||||
|
||||
func (t *renderStringWithScrollTask) IsUpdateTask() {}
|
||||
|
||||
func NewRenderStringWithScrollTask(str string, originX int, originY int) *renderStringWithScrollTask {
|
||||
return &renderStringWithScrollTask{str: str, originX: originX, originY: originY}
|
||||
}
|
||||
|
||||
type runCommandTask struct {
|
||||
cmd *exec.Cmd
|
||||
prefix string
|
||||
@ -69,11 +81,6 @@ func NewRunPtyTask(cmd *exec.Cmd) *runPtyTask {
|
||||
return &runPtyTask{cmd: cmd}
|
||||
}
|
||||
|
||||
// currently unused
|
||||
// func (gui *Gui) createRunPtyTaskWithPrefix(cmd *exec.Cmd, prefix string) *runPtyTask {
|
||||
// return &runPtyTask{cmd: cmd, prefix: prefix}
|
||||
// }
|
||||
|
||||
func (gui *Gui) runTaskForView(view *gocui.View, task updateTask) error {
|
||||
switch v := task.(type) {
|
||||
case *renderStringTask:
|
||||
@ -82,6 +89,9 @@ func (gui *Gui) runTaskForView(view *gocui.View, task updateTask) error {
|
||||
case *renderStringWithoutScrollTask:
|
||||
return gui.newStringTaskWithoutScroll(view, v.str)
|
||||
|
||||
case *renderStringWithScrollTask:
|
||||
return gui.newStringTaskWithScroll(view, v.str, v.originX, v.originY)
|
||||
|
||||
case *runCommandTask:
|
||||
return gui.newCmdTask(view, v.cmd, v.prefix)
|
||||
|
||||
|
@ -3,6 +3,7 @@ package gui
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/keybindings"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/presentation"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
"github.com/jesseduffield/lazygit/pkg/theme"
|
||||
@ -13,9 +14,9 @@ func (gui *Gui) getMenuOptions() map[string]string {
|
||||
keybindingConfig := gui.c.UserConfig.Keybinding
|
||||
|
||||
return map[string]string{
|
||||
gui.getKeyDisplay(keybindingConfig.Universal.Return): gui.c.Tr.LcClose,
|
||||
fmt.Sprintf("%s %s", gui.getKeyDisplay(keybindingConfig.Universal.PrevItem), gui.getKeyDisplay(keybindingConfig.Universal.NextItem)): gui.c.Tr.LcNavigate,
|
||||
gui.getKeyDisplay(keybindingConfig.Universal.Select): gui.c.Tr.LcExecute,
|
||||
keybindings.Label(keybindingConfig.Universal.Return): gui.c.Tr.LcClose,
|
||||
fmt.Sprintf("%s %s", keybindings.Label(keybindingConfig.Universal.PrevItem), keybindings.Label(keybindingConfig.Universal.NextItem)): gui.c.Tr.LcNavigate,
|
||||
keybindings.Label(keybindingConfig.Universal.Select): gui.c.Tr.LcExecute,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,315 +0,0 @@
|
||||
// though this panel is called the merge panel, it's really going to use the main panel. This may change in the future
|
||||
|
||||
package gui
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"math"
|
||||
|
||||
"github.com/jesseduffield/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/mergeconflicts"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
)
|
||||
|
||||
func (gui *Gui) handleSelectPrevConflictHunk() error {
|
||||
return gui.withMergeConflictLock(func() error {
|
||||
gui.State.Contexts.MergeConflicts.SetUserScrolling(false)
|
||||
gui.State.Contexts.MergeConflicts.State().SelectPrevConflictHunk()
|
||||
return gui.renderConflictsWithFocus()
|
||||
})
|
||||
}
|
||||
|
||||
func (gui *Gui) handleSelectNextConflictHunk() error {
|
||||
return gui.withMergeConflictLock(func() error {
|
||||
gui.State.Contexts.MergeConflicts.SetUserScrolling(false)
|
||||
gui.State.Contexts.MergeConflicts.State().SelectNextConflictHunk()
|
||||
return gui.renderConflictsWithFocus()
|
||||
})
|
||||
}
|
||||
|
||||
func (gui *Gui) handleSelectNextConflict() error {
|
||||
return gui.withMergeConflictLock(func() error {
|
||||
gui.State.Contexts.MergeConflicts.SetUserScrolling(false)
|
||||
gui.State.Contexts.MergeConflicts.State().SelectNextConflict()
|
||||
return gui.renderConflictsWithFocus()
|
||||
})
|
||||
}
|
||||
|
||||
func (gui *Gui) handleSelectPrevConflict() error {
|
||||
return gui.withMergeConflictLock(func() error {
|
||||
gui.State.Contexts.MergeConflicts.SetUserScrolling(false)
|
||||
gui.State.Contexts.MergeConflicts.State().SelectPrevConflict()
|
||||
return gui.renderConflictsWithFocus()
|
||||
})
|
||||
}
|
||||
|
||||
func (gui *Gui) handleMergeConflictUndo() error {
|
||||
state := gui.State.Contexts.MergeConflicts.State()
|
||||
|
||||
ok := state.Undo()
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
gui.c.LogAction("Restoring file to previous state")
|
||||
gui.LogCommand("Undoing last conflict resolution", false)
|
||||
if err := ioutil.WriteFile(state.GetPath(), []byte(state.GetContent()), 0o644); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return gui.renderConflictsWithFocus()
|
||||
}
|
||||
|
||||
func (gui *Gui) handlePickHunk() error {
|
||||
return gui.withMergeConflictLock(func() error {
|
||||
ok, err := gui.resolveConflict(gui.State.Contexts.MergeConflicts.State().Selection())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
if gui.State.Contexts.MergeConflicts.State().AllConflictsResolved() {
|
||||
return gui.onLastConflictResolved()
|
||||
}
|
||||
|
||||
return gui.renderConflictsWithFocus()
|
||||
})
|
||||
}
|
||||
|
||||
func (gui *Gui) handlePickAllHunks() error {
|
||||
return gui.withMergeConflictLock(func() error {
|
||||
ok, err := gui.resolveConflict(mergeconflicts.ALL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
if gui.State.Contexts.MergeConflicts.State().AllConflictsResolved() {
|
||||
return gui.onLastConflictResolved()
|
||||
}
|
||||
|
||||
return gui.renderConflictsWithFocus()
|
||||
})
|
||||
}
|
||||
|
||||
func (gui *Gui) resolveConflict(selection mergeconflicts.Selection) (bool, error) {
|
||||
gui.State.Contexts.MergeConflicts.SetUserScrolling(false)
|
||||
|
||||
state := gui.State.Contexts.MergeConflicts.State()
|
||||
|
||||
ok, content, err := state.ContentAfterConflictResolve(selection)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if !ok {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
var logStr string
|
||||
switch selection {
|
||||
case mergeconflicts.TOP:
|
||||
logStr = "Picking top hunk"
|
||||
case mergeconflicts.MIDDLE:
|
||||
logStr = "Picking middle hunk"
|
||||
case mergeconflicts.BOTTOM:
|
||||
logStr = "Picking bottom hunk"
|
||||
case mergeconflicts.ALL:
|
||||
logStr = "Picking all hunks"
|
||||
}
|
||||
gui.c.LogAction("Resolve merge conflict")
|
||||
gui.LogCommand(logStr, false)
|
||||
state.PushContent(content)
|
||||
return true, ioutil.WriteFile(state.GetPath(), []byte(content), 0o644)
|
||||
}
|
||||
|
||||
// precondition: we actually have conflicts to render
|
||||
func (gui *Gui) renderConflicts(hasFocus bool) error {
|
||||
state := gui.State.Contexts.MergeConflicts.State()
|
||||
content := mergeconflicts.ColoredConflictFile(state, hasFocus)
|
||||
|
||||
if !gui.State.Contexts.MergeConflicts.IsUserScrolling() {
|
||||
// TODO: find a way to not have to do this OnUIThread thing. Why doesn't it work
|
||||
// without it given that we're calling the 'no scroll' variant below?
|
||||
gui.c.OnUIThread(func() error {
|
||||
gui.State.Contexts.MergeConflicts.State().Lock()
|
||||
defer gui.State.Contexts.MergeConflicts.State().Unlock()
|
||||
|
||||
if !state.Active() {
|
||||
return nil
|
||||
}
|
||||
|
||||
gui.centerYPos(gui.Views.MergeConflicts, state.GetConflictMiddle())
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
return gui.refreshMainViews(refreshMainOpts{
|
||||
pair: gui.mergingMainContextPair(),
|
||||
main: &viewUpdateOpts{
|
||||
task: NewRenderStringWithoutScrollTask(content),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (gui *Gui) renderConflictsWithFocus() error {
|
||||
return gui.renderConflicts(true)
|
||||
}
|
||||
|
||||
func (gui *Gui) renderConflictsWithLock(hasFocus bool) error {
|
||||
return gui.withMergeConflictLock(func() error {
|
||||
return gui.renderConflicts(hasFocus)
|
||||
})
|
||||
}
|
||||
|
||||
func (gui *Gui) centerYPos(view *gocui.View, y int) {
|
||||
ox, _ := view.Origin()
|
||||
_, height := view.Size()
|
||||
newOriginY := int(math.Max(0, float64(y-(height/2))))
|
||||
_ = view.SetOrigin(ox, newOriginY)
|
||||
}
|
||||
|
||||
func (gui *Gui) getMergingOptions() map[string]string {
|
||||
keybindingConfig := gui.c.UserConfig.Keybinding
|
||||
|
||||
return map[string]string{
|
||||
fmt.Sprintf("%s %s", gui.getKeyDisplay(keybindingConfig.Universal.PrevItem), gui.getKeyDisplay(keybindingConfig.Universal.NextItem)): gui.c.Tr.LcSelectHunk,
|
||||
fmt.Sprintf("%s %s", gui.getKeyDisplay(keybindingConfig.Universal.PrevBlock), gui.getKeyDisplay(keybindingConfig.Universal.NextBlock)): gui.c.Tr.LcNavigateConflicts,
|
||||
gui.getKeyDisplay(keybindingConfig.Universal.Select): gui.c.Tr.LcPickHunk,
|
||||
gui.getKeyDisplay(keybindingConfig.Main.PickBothHunks): gui.c.Tr.LcPickAllHunks,
|
||||
gui.getKeyDisplay(keybindingConfig.Universal.Undo): gui.c.Tr.LcUndo,
|
||||
}
|
||||
}
|
||||
|
||||
func (gui *Gui) handleEscapeMerge() error {
|
||||
if err := gui.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.FILES}}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return gui.escapeMerge()
|
||||
}
|
||||
|
||||
func (gui *Gui) onLastConflictResolved() error {
|
||||
// as part of refreshing files, we handle the situation where a file has had
|
||||
// its merge conflicts resolved.
|
||||
return gui.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.FILES}})
|
||||
}
|
||||
|
||||
func (gui *Gui) resetMergeState() {
|
||||
gui.State.Contexts.MergeConflicts.SetUserScrolling(false)
|
||||
gui.State.Contexts.MergeConflicts.State().Reset()
|
||||
}
|
||||
|
||||
func (gui *Gui) setMergeState(path string) (bool, error) {
|
||||
content, err := gui.git.File.Cat(path)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
gui.State.Contexts.MergeConflicts.State().SetContent(content, path)
|
||||
|
||||
return !gui.State.Contexts.MergeConflicts.State().NoConflicts(), nil
|
||||
}
|
||||
|
||||
func (gui *Gui) setMergeStateWithLock(path string) (bool, error) {
|
||||
gui.State.Contexts.MergeConflicts.State().Lock()
|
||||
defer gui.State.Contexts.MergeConflicts.State().Unlock()
|
||||
|
||||
return gui.setMergeState(path)
|
||||
}
|
||||
|
||||
func (gui *Gui) resetMergeStateWithLock() {
|
||||
gui.State.Contexts.MergeConflicts.State().Lock()
|
||||
defer gui.State.Contexts.MergeConflicts.State().Unlock()
|
||||
|
||||
gui.resetMergeState()
|
||||
}
|
||||
|
||||
func (gui *Gui) escapeMerge() error {
|
||||
gui.resetMergeState()
|
||||
|
||||
// doing this in separate UI thread so that we're not still holding the lock by the time refresh the file
|
||||
gui.OnUIThread(func() error {
|
||||
return gui.c.PushContext(gui.State.Contexts.Files)
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (gui *Gui) renderingConflicts() bool {
|
||||
currentView := gui.g.CurrentView()
|
||||
if currentView != gui.Views.MergeConflicts && currentView != gui.Views.Files {
|
||||
return false
|
||||
}
|
||||
|
||||
return gui.State.Contexts.MergeConflicts.State().Active()
|
||||
}
|
||||
|
||||
func (gui *Gui) withMergeConflictLock(f func() error) error {
|
||||
gui.State.Contexts.MergeConflicts.State().Lock()
|
||||
defer gui.State.Contexts.MergeConflicts.State().Unlock()
|
||||
|
||||
return f()
|
||||
}
|
||||
|
||||
func (gui *Gui) setConflictsAndRender(path string, hasFocus bool) (bool, error) {
|
||||
hasConflicts, err := gui.setMergeState(path)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if hasConflicts {
|
||||
return true, gui.renderConflicts(hasFocus)
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (gui *Gui) setConflictsAndRenderWithLock(path string, hasFocus bool) (bool, error) {
|
||||
gui.State.Contexts.MergeConflicts.State().Lock()
|
||||
defer gui.State.Contexts.MergeConflicts.State().Unlock()
|
||||
|
||||
return gui.setConflictsAndRender(path, hasFocus)
|
||||
}
|
||||
|
||||
func (gui *Gui) switchToMerge(path string) error {
|
||||
gui.State.Contexts.MergeConflicts.SetUserScrolling(false)
|
||||
|
||||
if gui.State.Contexts.MergeConflicts.State().GetPath() != path {
|
||||
hasConflicts, err := gui.setMergeStateWithLock(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !hasConflicts {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return gui.c.PushContext(gui.State.Contexts.MergeConflicts)
|
||||
}
|
||||
|
||||
func (gui *Gui) handleMergeConflictEditFileAtLine() error {
|
||||
file := gui.getSelectedFile()
|
||||
if file == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
lineNumber := gui.State.Contexts.MergeConflicts.State().GetSelectedLine()
|
||||
return gui.helpers.Files.EditFileAtLine(file.GetPath(), lineNumber)
|
||||
}
|
||||
|
||||
func (gui *Gui) handleMergeConflictOpenFileAtLine() error {
|
||||
file := gui.getSelectedFile()
|
||||
if file == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
lineNumber := gui.State.Contexts.MergeConflicts.State().GetSelectedLine()
|
||||
return gui.helpers.Files.OpenFileAtLine(file.GetPath(), lineNumber)
|
||||
}
|
@ -1,15 +1,11 @@
|
||||
package mergeconflicts
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
)
|
||||
|
||||
// State represents the selection state of the merge conflict context.
|
||||
type State struct {
|
||||
sync.Mutex
|
||||
|
||||
// path of the file with the conflicts
|
||||
path string
|
||||
|
||||
@ -28,7 +24,6 @@ type State struct {
|
||||
|
||||
func NewState() *State {
|
||||
return &State{
|
||||
Mutex: sync.Mutex{},
|
||||
conflictIndex: 0,
|
||||
selectionIndex: 0,
|
||||
conflicts: []*mergeConflict{},
|
||||
@ -151,6 +146,12 @@ func (s *State) Reset() {
|
||||
s.path = ""
|
||||
}
|
||||
|
||||
// we're not resetting selectedIndex here because the user typically would want
|
||||
// to pick either all top hunks or all bottom hunks so we retain that selection
|
||||
func (s *State) ResetConflictSelection() {
|
||||
s.conflictIndex = 0
|
||||
}
|
||||
|
||||
func (s *State) Active() bool {
|
||||
return s.path != ""
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ func (gui *Gui) getBindings(context types.Context) []*types.Binding {
|
||||
bindings = append(customBindings, bindings...)
|
||||
|
||||
for _, binding := range bindings {
|
||||
if keybindings.GetKeyDisplay(binding.Key) != "" && binding.Description != "" {
|
||||
if keybindings.LabelFromKey(binding.Key) != "" && binding.Description != "" {
|
||||
if binding.ViewName == "" {
|
||||
bindingsGlobal = append(bindingsGlobal, binding)
|
||||
} else if binding.Tag == "navigation" {
|
||||
|
@ -22,17 +22,18 @@ import (
|
||||
|
||||
func getScopeNames(scopes []types.RefreshableView) []string {
|
||||
scopeNameMap := map[types.RefreshableView]string{
|
||||
types.COMMITS: "commits",
|
||||
types.BRANCHES: "branches",
|
||||
types.FILES: "files",
|
||||
types.SUBMODULES: "submodules",
|
||||
types.STASH: "stash",
|
||||
types.REFLOG: "reflog",
|
||||
types.TAGS: "tags",
|
||||
types.REMOTES: "remotes",
|
||||
types.STATUS: "status",
|
||||
types.BISECT_INFO: "bisect",
|
||||
types.STAGING: "staging",
|
||||
types.COMMITS: "commits",
|
||||
types.BRANCHES: "branches",
|
||||
types.FILES: "files",
|
||||
types.SUBMODULES: "submodules",
|
||||
types.STASH: "stash",
|
||||
types.REFLOG: "reflog",
|
||||
types.TAGS: "tags",
|
||||
types.REMOTES: "remotes",
|
||||
types.STATUS: "status",
|
||||
types.BISECT_INFO: "bisect",
|
||||
types.STAGING: "staging",
|
||||
types.MERGE_CONFLICTS: "mergeConflicts",
|
||||
}
|
||||
|
||||
return slices.Map(scopes, func(scope types.RefreshableView) string {
|
||||
@ -138,6 +139,10 @@ func (gui *Gui) Refresh(options types.RefreshOptions) error {
|
||||
refresh(func() { _ = gui.refreshPatchBuildingPanel(types.OnFocusOpts{}) })
|
||||
}
|
||||
|
||||
if scopeSet.Includes(types.MERGE_CONFLICTS) || scopeSet.Includes(types.FILES) {
|
||||
refresh(func() { _ = gui.refreshMergeState() })
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
|
||||
gui.refreshStatus()
|
||||
@ -148,7 +153,7 @@ func (gui *Gui) Refresh(options types.RefreshOptions) error {
|
||||
}
|
||||
|
||||
if options.Mode == types.BLOCK_UI {
|
||||
gui.OnUIThread(func() error {
|
||||
gui.c.OnUIThread(func() error {
|
||||
f()
|
||||
return nil
|
||||
})
|
||||
@ -323,21 +328,15 @@ func (gui *Gui) refreshFilesAndSubmodules() error {
|
||||
gui.Mutexes.RefreshingFilesMutex.Unlock()
|
||||
}()
|
||||
|
||||
prevSelectedPath := gui.getSelectedPath()
|
||||
|
||||
if err := gui.refreshStateSubmoduleConfigs(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := gui.refreshMergeState(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := gui.refreshStateFiles(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
gui.OnUIThread(func() error {
|
||||
gui.c.OnUIThread(func() error {
|
||||
if err := gui.c.PostRefreshUpdate(gui.State.Contexts.Submodules); err != nil {
|
||||
gui.c.Log.Error(err)
|
||||
}
|
||||
@ -346,14 +345,6 @@ func (gui *Gui) refreshFilesAndSubmodules() error {
|
||||
gui.c.Log.Error(err)
|
||||
}
|
||||
|
||||
if gui.currentContext().GetKey() == context.FILES_CONTEXT_KEY {
|
||||
currentSelectedPath := gui.getSelectedPath()
|
||||
alreadySelected := prevSelectedPath != "" && currentSelectedPath == prevSelectedPath
|
||||
if !alreadySelected {
|
||||
gui.State.Contexts.MergeConflicts.SetUserScrolling(false)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
@ -361,20 +352,20 @@ func (gui *Gui) refreshFilesAndSubmodules() error {
|
||||
}
|
||||
|
||||
func (gui *Gui) refreshMergeState() error {
|
||||
gui.State.Contexts.MergeConflicts.State().Lock()
|
||||
defer gui.State.Contexts.MergeConflicts.State().Unlock()
|
||||
gui.State.Contexts.MergeConflicts.GetMutex().Lock()
|
||||
defer gui.State.Contexts.MergeConflicts.GetMutex().Unlock()
|
||||
|
||||
if gui.currentContext().GetKey() != context.MERGE_CONFLICTS_CONTEXT_KEY {
|
||||
return nil
|
||||
}
|
||||
|
||||
hasConflicts, err := gui.setConflictsAndRender(gui.State.Contexts.MergeConflicts.State().GetPath(), true)
|
||||
hasConflicts, err := gui.helpers.MergeConflicts.SetConflictsAndRender(gui.State.Contexts.MergeConflicts.GetState().GetPath(), true)
|
||||
if err != nil {
|
||||
return gui.c.Error(err)
|
||||
}
|
||||
|
||||
if !hasConflicts {
|
||||
return gui.escapeMerge()
|
||||
return gui.helpers.MergeConflicts.EscapeMerge()
|
||||
}
|
||||
|
||||
return nil
|
||||
@ -426,7 +417,7 @@ func (gui *Gui) refreshStateFiles() error {
|
||||
}
|
||||
|
||||
if gui.git.Status.WorkingTreeState() != enums.REBASE_MODE_NONE && conflictFileCount == 0 && prevConflictFileCount > 0 {
|
||||
gui.OnUIThread(func() error { return gui.helpers.MergeAndRebase.PromptToContinueRebase() })
|
||||
gui.c.OnUIThread(func() error { return gui.helpers.MergeAndRebase.PromptToContinueRebase() })
|
||||
}
|
||||
|
||||
fileTreeViewModel.RWMutex.Lock()
|
||||
@ -701,3 +692,22 @@ func (gui *Gui) refreshPatchBuildingPanel(opts types.OnFocusOpts) error {
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (gui *Gui) refreshMergePanel(isFocused bool) error {
|
||||
content := gui.State.Contexts.MergeConflicts.GetContentToRender(isFocused)
|
||||
|
||||
var task updateTask
|
||||
if gui.State.Contexts.MergeConflicts.IsUserScrolling() {
|
||||
task = NewRenderStringWithoutScrollTask(content)
|
||||
} else {
|
||||
originY := gui.State.Contexts.MergeConflicts.GetOriginY()
|
||||
task = NewRenderStringWithScrollTask(content, 0, originY)
|
||||
}
|
||||
|
||||
return gui.refreshMainViews(refreshMainOpts{
|
||||
pair: gui.mergingMainContextPair(),
|
||||
main: &viewUpdateOpts{
|
||||
task: task,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package gui
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/keybindings"
|
||||
"github.com/jesseduffield/lazygit/pkg/theme"
|
||||
)
|
||||
|
||||
@ -52,7 +53,7 @@ func (gui *Gui) onSelectItemWrapper(innerFunc func(int) error) func(int, int, in
|
||||
fmt.Sprintf(
|
||||
"no matches for '%s' %s",
|
||||
gui.State.Searching.searchString,
|
||||
theme.OptionsFgColor.Sprintf("%s: exit search mode", gui.getKeyDisplay(keybindingConfig.Universal.Return)),
|
||||
theme.OptionsFgColor.Sprintf("%s: exit search mode", keybindings.Label(keybindingConfig.Universal.Return)),
|
||||
),
|
||||
)
|
||||
}
|
||||
@ -65,9 +66,9 @@ func (gui *Gui) onSelectItemWrapper(innerFunc func(int) error) func(int, int, in
|
||||
total,
|
||||
theme.OptionsFgColor.Sprintf(
|
||||
"%s: next match, %s: previous match, %s: exit search mode",
|
||||
gui.getKeyDisplay(keybindingConfig.Universal.NextMatch),
|
||||
gui.getKeyDisplay(keybindingConfig.Universal.PrevMatch),
|
||||
gui.getKeyDisplay(keybindingConfig.Universal.Return),
|
||||
keybindings.Label(keybindingConfig.Universal.NextMatch),
|
||||
keybindings.Label(keybindingConfig.Universal.PrevMatch),
|
||||
keybindings.Label(keybindingConfig.Universal.Return),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
@ -23,11 +23,10 @@ func NewClient(
|
||||
git *commands.GitCommand,
|
||||
contexts *context.ContextTree,
|
||||
helpers *helpers.Helpers,
|
||||
getKey func(string) types.Key,
|
||||
) *Client {
|
||||
sessionStateLoader := NewSessionStateLoader(contexts, helpers)
|
||||
handlerCreator := NewHandlerCreator(c, os, git, sessionStateLoader)
|
||||
keybindingCreator := NewKeybindingCreator(contexts, getKey)
|
||||
keybindingCreator := NewKeybindingCreator(contexts)
|
||||
customCommands := c.UserConfig.CustomCommands
|
||||
|
||||
return &Client{
|
||||
|
@ -8,19 +8,18 @@ import (
|
||||
"github.com/jesseduffield/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/keybindings"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
)
|
||||
|
||||
// KeybindingCreator takes a custom command along with its handler and returns a corresponding keybinding
|
||||
type KeybindingCreator struct {
|
||||
contexts *context.ContextTree
|
||||
getKey func(string) types.Key
|
||||
}
|
||||
|
||||
func NewKeybindingCreator(contexts *context.ContextTree, getKey func(string) types.Key) *KeybindingCreator {
|
||||
func NewKeybindingCreator(contexts *context.ContextTree) *KeybindingCreator {
|
||||
return &KeybindingCreator{
|
||||
contexts: contexts,
|
||||
getKey: getKey,
|
||||
}
|
||||
}
|
||||
|
||||
@ -41,7 +40,7 @@ func (self *KeybindingCreator) call(customCommand config.CustomCommand, handler
|
||||
|
||||
return &types.Binding{
|
||||
ViewName: viewName,
|
||||
Key: self.getKey(customCommand.Key),
|
||||
Key: keybindings.GetKey(customCommand.Key),
|
||||
Modifier: gocui.ModNone,
|
||||
Handler: handler,
|
||||
Description: description,
|
||||
|
@ -64,6 +64,22 @@ func (gui *Gui) newStringTaskWithoutScroll(view *gocui.View, str string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (gui *Gui) newStringTaskWithScroll(view *gocui.View, str string, originX int, originY int) error {
|
||||
manager := gui.getManager(view)
|
||||
|
||||
f := func(stop chan struct{}) error {
|
||||
gui.setViewContent(view, str)
|
||||
_ = view.SetOrigin(originX, originY)
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := manager.NewTask(f, ""); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (gui *Gui) newStringTaskWithKey(view *gocui.View, str string, key string) error {
|
||||
manager := gui.getManager(view)
|
||||
|
||||
|
@ -16,6 +16,7 @@ const (
|
||||
SUBMODULES
|
||||
STAGING
|
||||
PATCH_BUILDING
|
||||
MERGE_CONFLICTS
|
||||
COMMIT_FILES
|
||||
// not actually a view. Will refactor this later
|
||||
BISECT_INFO
|
||||
|
@ -58,7 +58,7 @@ func (gui *Gui) startUpdating(newVersion string) {
|
||||
func (gui *Gui) onUpdateFinish(statusId int, err error) error {
|
||||
gui.State.Updating = false
|
||||
gui.statusManager.removeStatus(statusId)
|
||||
gui.OnUIThread(func() error {
|
||||
gui.c.OnUIThread(func() error {
|
||||
_ = gui.renderString(gui.Views.AppStatus, "")
|
||||
if err != nil {
|
||||
errMessage := utils.ResolvePlaceholderString(
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/jesseduffield/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/keybindings"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
"github.com/spkg/bom"
|
||||
@ -99,13 +100,13 @@ func (gui *Gui) globalOptionsMap() map[string]string {
|
||||
keybindingConfig := gui.c.UserConfig.Keybinding
|
||||
|
||||
return map[string]string{
|
||||
fmt.Sprintf("%s/%s", gui.getKeyDisplay(keybindingConfig.Universal.ScrollUpMain), gui.getKeyDisplay(keybindingConfig.Universal.ScrollDownMain)): gui.c.Tr.LcScroll,
|
||||
fmt.Sprintf("%s %s %s %s", gui.getKeyDisplay(keybindingConfig.Universal.PrevBlock), gui.getKeyDisplay(keybindingConfig.Universal.NextBlock), gui.getKeyDisplay(keybindingConfig.Universal.PrevItem), gui.getKeyDisplay(keybindingConfig.Universal.NextItem)): gui.c.Tr.LcNavigate,
|
||||
gui.getKeyDisplay(keybindingConfig.Universal.Return): gui.c.Tr.LcCancel,
|
||||
gui.getKeyDisplay(keybindingConfig.Universal.Quit): gui.c.Tr.LcQuit,
|
||||
gui.getKeyDisplay(keybindingConfig.Universal.OptionMenu): gui.c.Tr.LcMenu,
|
||||
fmt.Sprintf("%s-%s", gui.getKeyDisplay(keybindingConfig.Universal.JumpToBlock[0]), gui.getKeyDisplay(keybindingConfig.Universal.JumpToBlock[len(keybindingConfig.Universal.JumpToBlock)-1])): gui.c.Tr.LcJump,
|
||||
fmt.Sprintf("%s/%s", gui.getKeyDisplay(keybindingConfig.Universal.ScrollLeft), gui.getKeyDisplay(keybindingConfig.Universal.ScrollRight)): gui.c.Tr.LcScrollLeftRight,
|
||||
fmt.Sprintf("%s/%s", keybindings.Label(keybindingConfig.Universal.ScrollUpMain), keybindings.Label(keybindingConfig.Universal.ScrollDownMain)): gui.c.Tr.LcScroll,
|
||||
fmt.Sprintf("%s %s %s %s", keybindings.Label(keybindingConfig.Universal.PrevBlock), keybindings.Label(keybindingConfig.Universal.NextBlock), keybindings.Label(keybindingConfig.Universal.PrevItem), keybindings.Label(keybindingConfig.Universal.NextItem)): gui.c.Tr.LcNavigate,
|
||||
keybindings.Label(keybindingConfig.Universal.Return): gui.c.Tr.LcCancel,
|
||||
keybindings.Label(keybindingConfig.Universal.Quit): gui.c.Tr.LcQuit,
|
||||
keybindings.Label(keybindingConfig.Universal.OptionMenu): gui.c.Tr.LcMenu,
|
||||
fmt.Sprintf("%s-%s", keybindings.Label(keybindingConfig.Universal.JumpToBlock[0]), keybindings.Label(keybindingConfig.Universal.JumpToBlock[len(keybindingConfig.Universal.JumpToBlock)-1])): gui.c.Tr.LcJump,
|
||||
fmt.Sprintf("%s/%s", keybindings.Label(keybindingConfig.Universal.ScrollLeft), keybindings.Label(keybindingConfig.Universal.ScrollRight)): gui.c.Tr.LcScrollLeftRight,
|
||||
}
|
||||
}
|
||||
|
||||
@ -192,5 +193,5 @@ func getTabbedView(gui *Gui) *gocui.View {
|
||||
}
|
||||
|
||||
func (gui *Gui) render() {
|
||||
gui.OnUIThread(func() error { return nil })
|
||||
gui.c.OnUIThread(func() error { return nil })
|
||||
}
|
||||
|
@ -202,7 +202,7 @@ func RunTests(
|
||||
|
||||
// validates that the actual and expected dirs have the same repo names (doesn't actually check the contents of the repos)
|
||||
func validateSameRepos(expectedDir string, actualDir string) error {
|
||||
// iterate through each repo in the expected dir and comparet to the corresponding repo in the actual dir
|
||||
// iterate through each repo in the expected dir and compare to the corresponding repo in the actual dir
|
||||
expectedFiles, err := ioutil.ReadDir(expectedDir)
|
||||
if err != nil {
|
||||
return err
|
||||
|
Loading…
x
Reference in New Issue
Block a user