mirror of
https://github.com/jesseduffield/lazygit.git
synced 2024-12-12 11:15:00 +02:00
967 lines
32 KiB
Go
967 lines
32 KiB
Go
package gui
|
|
|
|
import (
|
|
"log"
|
|
"strings"
|
|
"unicode/utf8"
|
|
|
|
"github.com/jesseduffield/gocui"
|
|
"github.com/jesseduffield/lazygit/pkg/constants"
|
|
"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/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() {
|
|
return nil
|
|
}
|
|
|
|
return f()
|
|
}
|
|
}
|
|
|
|
// only to be called from the cheatsheet generate script. This mutates the Gui struct.
|
|
func (self *Gui) GetCheatsheetKeybindings() []*types.Binding {
|
|
self.helpers = helpers.NewStubHelpers()
|
|
self.State = &GuiRepoState{}
|
|
self.State.Contexts = self.contextTree()
|
|
self.resetControllers()
|
|
bindings, _ := self.GetInitialKeybindings()
|
|
return bindings
|
|
}
|
|
|
|
// renaming receiver to 'self' to aid refactoring. Will probably end up moving all Gui handlers to this pattern eventually.
|
|
func (self *Gui) GetInitialKeybindings() ([]*types.Binding, []*gocui.ViewMouseBinding) {
|
|
config := self.c.UserConfig.Keybinding
|
|
|
|
guards := types.KeybindingGuards{
|
|
OutsideFilterMode: self.outsideFilterMode,
|
|
NoPopupPanel: self.noPopupPanel,
|
|
}
|
|
|
|
opts := types.KeybindingsOpts{
|
|
GetKey: self.getKey,
|
|
Config: config,
|
|
Guards: guards,
|
|
}
|
|
|
|
bindings := []*types.Binding{
|
|
{
|
|
ViewName: "",
|
|
Key: opts.GetKey(opts.Config.Universal.Quit),
|
|
Modifier: gocui.ModNone,
|
|
Handler: self.handleQuit,
|
|
},
|
|
{
|
|
ViewName: "",
|
|
Key: opts.GetKey(opts.Config.Universal.QuitWithoutChangingDirectory),
|
|
Modifier: gocui.ModNone,
|
|
Handler: self.handleQuitWithoutChangingDirectory,
|
|
},
|
|
{
|
|
ViewName: "",
|
|
Key: opts.GetKey(opts.Config.Universal.QuitAlt1),
|
|
Modifier: gocui.ModNone,
|
|
Handler: self.handleQuit,
|
|
},
|
|
{
|
|
ViewName: "",
|
|
Key: opts.GetKey(opts.Config.Universal.Return),
|
|
Modifier: gocui.ModNone,
|
|
Handler: self.handleTopLevelReturn,
|
|
},
|
|
{
|
|
ViewName: "",
|
|
Key: opts.GetKey(opts.Config.Universal.OpenRecentRepos),
|
|
Handler: self.handleCreateRecentReposMenu,
|
|
Description: self.c.Tr.SwitchRepo,
|
|
},
|
|
{
|
|
ViewName: "",
|
|
Key: opts.GetKey(opts.Config.Universal.ScrollUpMain),
|
|
Handler: self.scrollUpMain,
|
|
Alternative: "fn+up/shift+k",
|
|
Description: self.c.Tr.LcScrollUpMainPanel,
|
|
},
|
|
{
|
|
ViewName: "",
|
|
Key: opts.GetKey(opts.Config.Universal.ScrollDownMain),
|
|
Handler: self.scrollDownMain,
|
|
Alternative: "fn+down/shift+j",
|
|
Description: self.c.Tr.LcScrollDownMainPanel,
|
|
},
|
|
{
|
|
ViewName: "",
|
|
Key: opts.GetKey(opts.Config.Universal.ScrollUpMainAlt1),
|
|
Modifier: gocui.ModNone,
|
|
Handler: self.scrollUpMain,
|
|
},
|
|
{
|
|
ViewName: "",
|
|
Key: opts.GetKey(opts.Config.Universal.ScrollDownMainAlt1),
|
|
Modifier: gocui.ModNone,
|
|
Handler: self.scrollDownMain,
|
|
},
|
|
{
|
|
ViewName: "",
|
|
Key: opts.GetKey(opts.Config.Universal.ScrollUpMainAlt2),
|
|
Modifier: gocui.ModNone,
|
|
Handler: self.scrollUpMain,
|
|
},
|
|
{
|
|
ViewName: "",
|
|
Key: opts.GetKey(opts.Config.Universal.ScrollDownMainAlt2),
|
|
Modifier: gocui.ModNone,
|
|
Handler: self.scrollDownMain,
|
|
},
|
|
{
|
|
ViewName: "",
|
|
Key: opts.GetKey(opts.Config.Universal.CreateRebaseOptionsMenu),
|
|
Handler: self.helpers.MergeAndRebase.CreateRebaseOptionsMenu,
|
|
Description: self.c.Tr.ViewMergeRebaseOptions,
|
|
OpensMenu: true,
|
|
},
|
|
{
|
|
ViewName: "",
|
|
Key: opts.GetKey(opts.Config.Universal.CreatePatchOptionsMenu),
|
|
Handler: self.handleCreatePatchOptionsMenu,
|
|
Description: self.c.Tr.ViewPatchOptions,
|
|
OpensMenu: true,
|
|
},
|
|
{
|
|
ViewName: "",
|
|
Key: opts.GetKey(opts.Config.Universal.Refresh),
|
|
Handler: self.handleRefresh,
|
|
Description: self.c.Tr.LcRefresh,
|
|
},
|
|
{
|
|
ViewName: "",
|
|
Key: opts.GetKey(opts.Config.Universal.OptionMenu),
|
|
Handler: self.handleCreateOptionsMenu,
|
|
Description: self.c.Tr.LcOpenMenu,
|
|
OpensMenu: true,
|
|
},
|
|
{
|
|
ViewName: "",
|
|
Key: opts.GetKey(opts.Config.Universal.OptionMenuAlt1),
|
|
Modifier: gocui.ModNone,
|
|
Handler: self.handleCreateOptionsMenu,
|
|
},
|
|
{
|
|
ViewName: "status",
|
|
Contexts: []string{string(context.STATUS_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.Edit),
|
|
Handler: self.handleEditConfig,
|
|
Description: self.c.Tr.EditConfig,
|
|
},
|
|
{
|
|
ViewName: "",
|
|
Key: opts.GetKey(opts.Config.Universal.NextScreenMode),
|
|
Handler: self.nextScreenMode,
|
|
Description: self.c.Tr.LcNextScreenMode,
|
|
},
|
|
{
|
|
ViewName: "",
|
|
Key: opts.GetKey(opts.Config.Universal.PrevScreenMode),
|
|
Handler: self.prevScreenMode,
|
|
Description: self.c.Tr.LcPrevScreenMode,
|
|
},
|
|
{
|
|
ViewName: "status",
|
|
Contexts: []string{string(context.STATUS_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.OpenFile),
|
|
Handler: self.handleOpenConfig,
|
|
Description: self.c.Tr.OpenConfig,
|
|
},
|
|
{
|
|
ViewName: "status",
|
|
Contexts: []string{string(context.STATUS_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Status.CheckForUpdate),
|
|
Handler: self.handleCheckForUpdate,
|
|
Description: self.c.Tr.LcCheckForUpdate,
|
|
},
|
|
{
|
|
ViewName: "status",
|
|
Contexts: []string{string(context.STATUS_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Status.RecentRepos),
|
|
Handler: self.handleCreateRecentReposMenu,
|
|
Description: self.c.Tr.SwitchRepo,
|
|
},
|
|
{
|
|
ViewName: "status",
|
|
Contexts: []string{string(context.STATUS_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Status.AllBranchesLogGraph),
|
|
Handler: self.handleShowAllBranchLogs,
|
|
Description: self.c.Tr.LcAllBranchesLogGraph,
|
|
},
|
|
{
|
|
ViewName: "files",
|
|
Contexts: []string{string(context.FILES_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.CopyToClipboard),
|
|
Handler: self.handleCopySelectedSideContextItemToClipboard,
|
|
Description: self.c.Tr.LcCopyFileNameToClipboard,
|
|
},
|
|
{
|
|
ViewName: "branches",
|
|
Contexts: []string{string(context.LOCAL_BRANCHES_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.CopyToClipboard),
|
|
Handler: self.handleCopySelectedSideContextItemToClipboard,
|
|
Description: self.c.Tr.LcCopyBranchNameToClipboard,
|
|
},
|
|
{
|
|
ViewName: "commits",
|
|
Contexts: []string{string(context.LOCAL_COMMITS_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.CopyToClipboard),
|
|
Handler: self.handleCopySelectedSideContextItemToClipboard,
|
|
Description: self.c.Tr.LcCopyCommitShaToClipboard,
|
|
},
|
|
{
|
|
ViewName: "commits",
|
|
Contexts: []string{string(context.LOCAL_COMMITS_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Commits.ResetCherryPick),
|
|
Handler: self.helpers.CherryPick.Reset,
|
|
Description: self.c.Tr.LcResetCherryPick,
|
|
},
|
|
{
|
|
ViewName: "commits",
|
|
Contexts: []string{string(context.REFLOG_COMMITS_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.CopyToClipboard),
|
|
Handler: self.handleCopySelectedSideContextItemToClipboard,
|
|
Description: self.c.Tr.LcCopyCommitShaToClipboard,
|
|
},
|
|
{
|
|
ViewName: "subCommits",
|
|
Contexts: []string{string(context.SUB_COMMITS_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.CopyToClipboard),
|
|
Handler: self.handleCopySelectedSideContextItemToClipboard,
|
|
Description: self.c.Tr.LcCopyCommitShaToClipboard,
|
|
},
|
|
{
|
|
ViewName: "information",
|
|
Key: gocui.MouseLeft,
|
|
Modifier: gocui.ModNone,
|
|
Handler: self.handleInfoClick,
|
|
},
|
|
{
|
|
ViewName: "commitFiles",
|
|
Contexts: []string{string(context.COMMIT_FILES_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.CopyToClipboard),
|
|
Handler: self.handleCopySelectedSideContextItemToClipboard,
|
|
Description: self.c.Tr.LcCopyCommitFileNameToClipboard,
|
|
},
|
|
{
|
|
ViewName: "",
|
|
Key: opts.GetKey(opts.Config.Universal.FilteringMenu),
|
|
Handler: self.handleCreateFilteringMenuPanel,
|
|
Description: self.c.Tr.LcOpenFilteringMenu,
|
|
OpensMenu: true,
|
|
},
|
|
{
|
|
ViewName: "",
|
|
Key: opts.GetKey(opts.Config.Universal.DiffingMenu),
|
|
Handler: self.handleCreateDiffingMenuPanel,
|
|
Description: self.c.Tr.LcOpenDiffingMenu,
|
|
OpensMenu: true,
|
|
},
|
|
{
|
|
ViewName: "",
|
|
Key: opts.GetKey(opts.Config.Universal.DiffingMenuAlt),
|
|
Handler: self.handleCreateDiffingMenuPanel,
|
|
Description: self.c.Tr.LcOpenDiffingMenu,
|
|
OpensMenu: true,
|
|
},
|
|
{
|
|
ViewName: "",
|
|
Key: opts.GetKey(opts.Config.Universal.ExtrasMenu),
|
|
Handler: self.handleCreateExtrasMenuPanel,
|
|
Description: self.c.Tr.LcOpenExtrasMenu,
|
|
OpensMenu: true,
|
|
},
|
|
{
|
|
ViewName: "secondary",
|
|
Key: gocui.MouseWheelUp,
|
|
Modifier: gocui.ModNone,
|
|
Handler: self.scrollUpSecondary,
|
|
},
|
|
{
|
|
ViewName: "secondary",
|
|
Key: gocui.MouseWheelDown,
|
|
Modifier: gocui.ModNone,
|
|
Handler: self.scrollDownSecondary,
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_NORMAL_CONTEXT_KEY)},
|
|
Key: gocui.MouseWheelDown,
|
|
Handler: self.scrollDownMain,
|
|
Description: self.c.Tr.ScrollDown,
|
|
Alternative: "fn+up",
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_NORMAL_CONTEXT_KEY)},
|
|
Key: gocui.MouseWheelUp,
|
|
Handler: self.scrollUpMain,
|
|
Description: self.c.Tr.ScrollUp,
|
|
Alternative: "fn+down",
|
|
},
|
|
{
|
|
ViewName: "secondary",
|
|
Contexts: []string{string(context.MAIN_STAGING_CONTEXT_KEY)},
|
|
Key: gocui.MouseLeft,
|
|
Modifier: gocui.ModNone,
|
|
Handler: self.handleTogglePanelClick,
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_STAGING_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.Return),
|
|
Handler: self.handleStagingEscape,
|
|
Description: self.c.Tr.ReturnToFilesPanel,
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_STAGING_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.Select),
|
|
Handler: self.handleToggleStagedSelection,
|
|
Description: self.c.Tr.StageSelection,
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_STAGING_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.Remove),
|
|
Handler: self.handleResetSelection,
|
|
Description: self.c.Tr.ResetSelection,
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_STAGING_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.TogglePanel),
|
|
Handler: self.handleTogglePanel,
|
|
Description: self.c.Tr.TogglePanel,
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_PATCH_BUILDING_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.Return),
|
|
Handler: self.handleEscapePatchBuildingPanel,
|
|
Description: self.c.Tr.ExitLineByLineMode,
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_PATCH_BUILDING_CONTEXT_KEY), string(context.MAIN_STAGING_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.OpenFile),
|
|
Handler: self.handleOpenFileAtLine,
|
|
Description: self.c.Tr.LcOpenFile,
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_PATCH_BUILDING_CONTEXT_KEY), string(context.MAIN_STAGING_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.PrevItem),
|
|
Handler: self.handleSelectPrevLine,
|
|
Description: self.c.Tr.PrevLine,
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_PATCH_BUILDING_CONTEXT_KEY), string(context.MAIN_STAGING_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.NextItem),
|
|
Handler: self.handleSelectNextLine,
|
|
Description: self.c.Tr.NextLine,
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_PATCH_BUILDING_CONTEXT_KEY), string(context.MAIN_STAGING_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.PrevItemAlt),
|
|
Modifier: gocui.ModNone,
|
|
Handler: self.handleSelectPrevLine,
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_PATCH_BUILDING_CONTEXT_KEY), string(context.MAIN_STAGING_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.NextItemAlt),
|
|
Modifier: gocui.ModNone,
|
|
Handler: self.handleSelectNextLine,
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_PATCH_BUILDING_CONTEXT_KEY), string(context.MAIN_STAGING_CONTEXT_KEY)},
|
|
Key: gocui.MouseWheelUp,
|
|
Modifier: gocui.ModNone,
|
|
Handler: self.scrollUpMain,
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_PATCH_BUILDING_CONTEXT_KEY), string(context.MAIN_STAGING_CONTEXT_KEY)},
|
|
Key: gocui.MouseWheelDown,
|
|
Modifier: gocui.ModNone,
|
|
Handler: self.scrollDownMain,
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_PATCH_BUILDING_CONTEXT_KEY), string(context.MAIN_STAGING_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.PrevBlock),
|
|
Handler: self.handleSelectPrevHunk,
|
|
Description: self.c.Tr.PrevHunk,
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_PATCH_BUILDING_CONTEXT_KEY), string(context.MAIN_STAGING_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.PrevBlockAlt),
|
|
Modifier: gocui.ModNone,
|
|
Handler: self.handleSelectPrevHunk,
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_PATCH_BUILDING_CONTEXT_KEY), string(context.MAIN_STAGING_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.NextBlock),
|
|
Handler: self.handleSelectNextHunk,
|
|
Description: self.c.Tr.NextHunk,
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_PATCH_BUILDING_CONTEXT_KEY), string(context.MAIN_STAGING_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.NextBlockAlt),
|
|
Modifier: gocui.ModNone,
|
|
Handler: self.handleSelectNextHunk,
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_PATCH_BUILDING_CONTEXT_KEY), string(context.MAIN_STAGING_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.CopyToClipboard),
|
|
Modifier: gocui.ModNone,
|
|
Handler: self.copySelectedToClipboard,
|
|
Description: self.c.Tr.LcCopySelectedTexToClipboard,
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_STAGING_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.Edit),
|
|
Handler: self.handleLineByLineEdit,
|
|
Description: self.c.Tr.LcEditFile,
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_STAGING_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.OpenFile),
|
|
Handler: self.HandleOpenFile,
|
|
Description: self.c.Tr.LcOpenFile,
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_PATCH_BUILDING_CONTEXT_KEY), string(context.MAIN_STAGING_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.NextPage),
|
|
Modifier: gocui.ModNone,
|
|
Handler: self.handleLineByLineNextPage,
|
|
Description: self.c.Tr.LcNextPage,
|
|
Tag: "navigation",
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_PATCH_BUILDING_CONTEXT_KEY), string(context.MAIN_STAGING_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.PrevPage),
|
|
Modifier: gocui.ModNone,
|
|
Handler: self.handleLineByLinePrevPage,
|
|
Description: self.c.Tr.LcPrevPage,
|
|
Tag: "navigation",
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_PATCH_BUILDING_CONTEXT_KEY), string(context.MAIN_STAGING_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.GotoTop),
|
|
Modifier: gocui.ModNone,
|
|
Handler: self.handleLineByLineGotoTop,
|
|
Description: self.c.Tr.LcGotoTop,
|
|
Tag: "navigation",
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_PATCH_BUILDING_CONTEXT_KEY), string(context.MAIN_STAGING_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.GotoBottom),
|
|
Modifier: gocui.ModNone,
|
|
Handler: self.handleLineByLineGotoBottom,
|
|
Description: self.c.Tr.LcGotoBottom,
|
|
Tag: "navigation",
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_PATCH_BUILDING_CONTEXT_KEY), string(context.MAIN_STAGING_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.StartSearch),
|
|
Handler: func() error { return self.handleOpenSearch("main") },
|
|
Description: self.c.Tr.LcStartSearch,
|
|
Tag: "navigation",
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_PATCH_BUILDING_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.Select),
|
|
Handler: self.handleToggleSelectionForPatch,
|
|
Description: self.c.Tr.ToggleSelectionForPatch,
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_PATCH_BUILDING_CONTEXT_KEY), string(context.MAIN_STAGING_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Main.ToggleDragSelect),
|
|
Handler: self.handleToggleSelectRange,
|
|
Description: self.c.Tr.ToggleDragSelect,
|
|
},
|
|
// Alias 'V' -> 'v'
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_PATCH_BUILDING_CONTEXT_KEY), string(context.MAIN_STAGING_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Main.ToggleDragSelectAlt),
|
|
Handler: self.handleToggleSelectRange,
|
|
Description: self.c.Tr.ToggleDragSelect,
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_PATCH_BUILDING_CONTEXT_KEY), string(context.MAIN_STAGING_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Main.ToggleSelectHunk),
|
|
Handler: self.handleToggleSelectHunk,
|
|
Description: self.c.Tr.ToggleSelectHunk,
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_STAGING_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Main.EditSelectHunk),
|
|
Handler: self.handleEditHunk,
|
|
Description: self.c.Tr.EditHunk,
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_PATCH_BUILDING_CONTEXT_KEY), string(context.MAIN_STAGING_CONTEXT_KEY)},
|
|
Key: gocui.MouseLeft,
|
|
Modifier: gocui.ModNone,
|
|
Handler: self.handleLBLMouseDown,
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_PATCH_BUILDING_CONTEXT_KEY), string(context.MAIN_STAGING_CONTEXT_KEY)},
|
|
Key: gocui.MouseLeft,
|
|
Modifier: gocui.ModMotion,
|
|
Handler: self.handleMouseDrag,
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_PATCH_BUILDING_CONTEXT_KEY), string(context.MAIN_STAGING_CONTEXT_KEY)},
|
|
Key: gocui.MouseWheelUp,
|
|
Modifier: gocui.ModNone,
|
|
Handler: self.scrollUpMain,
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_PATCH_BUILDING_CONTEXT_KEY), string(context.MAIN_STAGING_CONTEXT_KEY)},
|
|
Key: gocui.MouseWheelDown,
|
|
Modifier: gocui.ModNone,
|
|
Handler: self.scrollDownMain,
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_PATCH_BUILDING_CONTEXT_KEY), string(context.MAIN_STAGING_CONTEXT_KEY), string(context.MAIN_MERGING_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.ScrollLeft),
|
|
Handler: self.scrollLeftMain,
|
|
Description: self.c.Tr.LcScrollLeft,
|
|
Tag: "navigation",
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_PATCH_BUILDING_CONTEXT_KEY), string(context.MAIN_STAGING_CONTEXT_KEY), string(context.MAIN_MERGING_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.ScrollRight),
|
|
Handler: self.scrollRightMain,
|
|
Description: self.c.Tr.LcScrollRight,
|
|
Tag: "navigation",
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_MERGING_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.Return),
|
|
Handler: self.handleEscapeMerge,
|
|
Description: self.c.Tr.ReturnToFilesPanel,
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_MERGING_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Files.OpenMergeTool),
|
|
Handler: self.helpers.WorkingTree.OpenMergeTool,
|
|
Description: self.c.Tr.LcOpenMergeTool,
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_MERGING_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.Select),
|
|
Handler: self.handlePickHunk,
|
|
Description: self.c.Tr.PickHunk,
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_MERGING_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Main.PickBothHunks),
|
|
Handler: self.handlePickAllHunks,
|
|
Description: self.c.Tr.PickAllHunks,
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_MERGING_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.PrevBlock),
|
|
Handler: self.handleSelectPrevConflict,
|
|
Description: self.c.Tr.PrevConflict,
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_MERGING_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.NextBlock),
|
|
Handler: self.handleSelectNextConflict,
|
|
Description: self.c.Tr.NextConflict,
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_MERGING_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.PrevItem),
|
|
Handler: self.handleSelectPrevConflictHunk,
|
|
Description: self.c.Tr.SelectPrevHunk,
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_MERGING_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.NextItem),
|
|
Handler: self.handleSelectNextConflictHunk,
|
|
Description: self.c.Tr.SelectNextHunk,
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_MERGING_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.PrevBlockAlt),
|
|
Modifier: gocui.ModNone,
|
|
Handler: self.handleSelectPrevConflict,
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_MERGING_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.NextBlockAlt),
|
|
Modifier: gocui.ModNone,
|
|
Handler: self.handleSelectNextConflict,
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_MERGING_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.PrevItemAlt),
|
|
Modifier: gocui.ModNone,
|
|
Handler: self.handleSelectPrevConflictHunk,
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_MERGING_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.NextItemAlt),
|
|
Modifier: gocui.ModNone,
|
|
Handler: self.handleSelectNextConflictHunk,
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_MERGING_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.Edit),
|
|
Handler: self.handleMergeConflictEditFileAtLine,
|
|
Description: self.c.Tr.LcEditFile,
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_MERGING_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.OpenFile),
|
|
Handler: self.handleMergeConflictOpenFileAtLine,
|
|
Description: self.c.Tr.LcOpenFile,
|
|
},
|
|
{
|
|
ViewName: "main",
|
|
Contexts: []string{string(context.MAIN_MERGING_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.Undo),
|
|
Handler: self.handleMergeConflictUndo,
|
|
Description: self.c.Tr.LcUndo,
|
|
},
|
|
{
|
|
ViewName: "status",
|
|
Key: gocui.MouseLeft,
|
|
Modifier: gocui.ModNone,
|
|
Handler: self.handleStatusClick,
|
|
},
|
|
{
|
|
ViewName: "search",
|
|
Key: opts.GetKey(opts.Config.Universal.Confirm),
|
|
Modifier: gocui.ModNone,
|
|
Handler: self.handleSearch,
|
|
},
|
|
{
|
|
ViewName: "search",
|
|
Key: opts.GetKey(opts.Config.Universal.Return),
|
|
Modifier: gocui.ModNone,
|
|
Handler: self.handleSearchEscape,
|
|
},
|
|
{
|
|
ViewName: "confirmation",
|
|
Key: opts.GetKey(opts.Config.Universal.PrevItem),
|
|
Modifier: gocui.ModNone,
|
|
Handler: self.scrollUpConfirmationPanel,
|
|
},
|
|
{
|
|
ViewName: "confirmation",
|
|
Key: opts.GetKey(opts.Config.Universal.NextItem),
|
|
Modifier: gocui.ModNone,
|
|
Handler: self.scrollDownConfirmationPanel,
|
|
},
|
|
{
|
|
ViewName: "confirmation",
|
|
Key: opts.GetKey(opts.Config.Universal.PrevItemAlt),
|
|
Modifier: gocui.ModNone,
|
|
Handler: self.scrollUpConfirmationPanel,
|
|
},
|
|
{
|
|
ViewName: "confirmation",
|
|
Key: opts.GetKey(opts.Config.Universal.NextItemAlt),
|
|
Modifier: gocui.ModNone,
|
|
Handler: self.scrollDownConfirmationPanel,
|
|
},
|
|
{
|
|
ViewName: "files",
|
|
Contexts: []string{string(context.SUBMODULES_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.CopyToClipboard),
|
|
Handler: self.handleCopySelectedSideContextItemToClipboard,
|
|
Description: self.c.Tr.LcCopySubmoduleNameToClipboard,
|
|
},
|
|
{
|
|
ViewName: "files",
|
|
Contexts: []string{string(context.FILES_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.ToggleWhitespaceInDiffView),
|
|
Handler: self.toggleWhitespaceInDiffView,
|
|
Description: self.c.Tr.ToggleWhitespaceInDiffView,
|
|
},
|
|
{
|
|
ViewName: "",
|
|
Key: opts.GetKey(opts.Config.Universal.IncreaseContextInDiffView),
|
|
Handler: self.IncreaseContextInDiffView,
|
|
Description: self.c.Tr.IncreaseContextInDiffView,
|
|
},
|
|
{
|
|
ViewName: "",
|
|
Key: opts.GetKey(opts.Config.Universal.DecreaseContextInDiffView),
|
|
Handler: self.DecreaseContextInDiffView,
|
|
Description: self.c.Tr.DecreaseContextInDiffView,
|
|
},
|
|
{
|
|
ViewName: "extras",
|
|
Key: gocui.MouseWheelUp,
|
|
Handler: self.scrollUpExtra,
|
|
},
|
|
{
|
|
ViewName: "extras",
|
|
Key: gocui.MouseWheelDown,
|
|
Handler: self.scrollDownExtra,
|
|
},
|
|
{
|
|
ViewName: "extras",
|
|
Key: opts.GetKey(opts.Config.Universal.ExtrasMenu),
|
|
Handler: self.handleCreateExtrasMenuPanel,
|
|
Description: self.c.Tr.LcOpenExtrasMenu,
|
|
OpensMenu: true,
|
|
},
|
|
{
|
|
ViewName: "extras",
|
|
Tag: "navigation",
|
|
Contexts: []string{string(context.COMMAND_LOG_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.PrevItemAlt),
|
|
Modifier: gocui.ModNone,
|
|
Handler: self.scrollUpExtra,
|
|
},
|
|
{
|
|
ViewName: "extras",
|
|
Tag: "navigation",
|
|
Contexts: []string{string(context.COMMAND_LOG_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.PrevItem),
|
|
Modifier: gocui.ModNone,
|
|
Handler: self.scrollUpExtra,
|
|
},
|
|
{
|
|
ViewName: "extras",
|
|
Tag: "navigation",
|
|
Contexts: []string{string(context.COMMAND_LOG_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.NextItem),
|
|
Modifier: gocui.ModNone,
|
|
Handler: self.scrollDownExtra,
|
|
},
|
|
{
|
|
ViewName: "extras",
|
|
Tag: "navigation",
|
|
Contexts: []string{string(context.COMMAND_LOG_CONTEXT_KEY)},
|
|
Key: opts.GetKey(opts.Config.Universal.NextItemAlt),
|
|
Modifier: gocui.ModNone,
|
|
Handler: self.scrollDownExtra,
|
|
},
|
|
{
|
|
ViewName: "extras",
|
|
Tag: "navigation",
|
|
Key: gocui.MouseLeft,
|
|
Modifier: gocui.ModNone,
|
|
Handler: self.handleFocusCommandLog,
|
|
},
|
|
}
|
|
|
|
mouseKeybindings := []*gocui.ViewMouseBinding{}
|
|
for _, c := range self.State.Contexts.Flatten() {
|
|
viewName := c.GetViewName()
|
|
contextKey := c.GetKey()
|
|
for _, binding := range c.GetKeybindings(opts) {
|
|
// TODO: move all mouse keybindings into the mouse keybindings approach below
|
|
if !gocui.IsMouseKey(binding.Key) && contextKey != context.GLOBAL_CONTEXT_KEY {
|
|
binding.Contexts = []string{string(contextKey)}
|
|
}
|
|
binding.ViewName = viewName
|
|
bindings = append(bindings, binding)
|
|
}
|
|
|
|
mouseKeybindings = append(mouseKeybindings, c.GetMouseKeybindings(opts)...)
|
|
}
|
|
|
|
for _, viewName := range []string{"status", "branches", "remoteBranches", "files", "commits", "commitFiles", "subCommits", "stash"} {
|
|
bindings = append(bindings, []*types.Binding{
|
|
{ViewName: viewName, Key: opts.GetKey(opts.Config.Universal.PrevBlock), Modifier: gocui.ModNone, Handler: self.previousSideWindow},
|
|
{ViewName: viewName, Key: opts.GetKey(opts.Config.Universal.NextBlock), Modifier: gocui.ModNone, Handler: self.nextSideWindow},
|
|
{ViewName: viewName, Key: opts.GetKey(opts.Config.Universal.PrevBlockAlt), Modifier: gocui.ModNone, Handler: self.previousSideWindow},
|
|
{ViewName: viewName, Key: opts.GetKey(opts.Config.Universal.NextBlockAlt), Modifier: gocui.ModNone, Handler: self.nextSideWindow},
|
|
{ViewName: viewName, Key: opts.GetKey(opts.Config.Universal.PrevBlockAlt2), Modifier: gocui.ModNone, Handler: self.previousSideWindow},
|
|
{ViewName: viewName, Key: opts.GetKey(opts.Config.Universal.NextBlockAlt2), Modifier: gocui.ModNone, Handler: self.nextSideWindow},
|
|
}...)
|
|
}
|
|
|
|
// Appends keybindings to jump to a particular sideView using numbers
|
|
windows := []string{"status", "files", "branches", "commits", "stash"}
|
|
|
|
if len(config.Universal.JumpToBlock) != len(windows) {
|
|
log.Fatal("Jump to block keybindings cannot be set. Exactly 5 keybindings must be supplied.")
|
|
} else {
|
|
for i, window := range windows {
|
|
bindings = append(bindings, &types.Binding{
|
|
ViewName: "",
|
|
Key: opts.GetKey(opts.Config.Universal.JumpToBlock[i]),
|
|
Modifier: gocui.ModNone,
|
|
Handler: self.goToSideWindow(window),
|
|
})
|
|
}
|
|
}
|
|
|
|
for viewName := range self.State.Contexts.InitialViewTabContextMap() {
|
|
bindings = append(bindings, []*types.Binding{
|
|
{
|
|
ViewName: viewName,
|
|
Key: opts.GetKey(opts.Config.Universal.NextTab),
|
|
Handler: self.handleNextTab,
|
|
Description: self.c.Tr.LcNextTab,
|
|
Tag: "navigation",
|
|
},
|
|
{
|
|
ViewName: viewName,
|
|
Key: opts.GetKey(opts.Config.Universal.PrevTab),
|
|
Handler: self.handlePrevTab,
|
|
Description: self.c.Tr.LcPrevTab,
|
|
Tag: "navigation",
|
|
},
|
|
}...)
|
|
}
|
|
|
|
return bindings, mouseKeybindings
|
|
}
|
|
|
|
func (gui *Gui) resetKeybindings() error {
|
|
gui.g.DeleteAllKeybindings()
|
|
|
|
bindings, mouseBindings := gui.GetInitialKeybindings()
|
|
|
|
// prepending because we want to give our custom keybindings precedence over default keybindings
|
|
customBindings, err := gui.CustomCommandsClient.GetCustomCommandKeybindings()
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
bindings = append(customBindings, bindings...)
|
|
|
|
for _, binding := range bindings {
|
|
if err := gui.SetKeybinding(binding); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
for _, binding := range mouseBindings {
|
|
if err := gui.SetMouseKeybinding(binding); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
for viewName := range gui.State.Contexts.InitialViewTabContextMap() {
|
|
viewName := viewName
|
|
tabClickCallback := func(tabIndex int) error { return gui.onViewTabClick(viewName, tabIndex) }
|
|
|
|
if err := gui.g.SetTabClickBinding(viewName, tabClickCallback); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (gui *Gui) wrappedHandler(f func() error) func(g *gocui.Gui, v *gocui.View) error {
|
|
return func(g *gocui.Gui, v *gocui.View) error {
|
|
return f()
|
|
}
|
|
}
|
|
|
|
func (gui *Gui) SetKeybinding(binding *types.Binding) error {
|
|
handler := binding.Handler
|
|
// TODO: move all mouse-ey stuff into new mouse approach
|
|
if gocui.IsMouseKey(binding.Key) {
|
|
handler = func() error {
|
|
// we ignore click events on views that aren't popup panels, when a popup panel is focused
|
|
if gui.popupPanelFocused() && gui.currentViewName() != binding.ViewName {
|
|
return nil
|
|
}
|
|
|
|
return binding.Handler()
|
|
}
|
|
}
|
|
|
|
return gui.g.SetKeybinding(binding.ViewName, binding.Contexts, binding.Key, binding.Modifier, gui.wrappedHandler(handler))
|
|
}
|
|
|
|
// warning: mutates the binding
|
|
func (gui *Gui) SetMouseKeybinding(binding *gocui.ViewMouseBinding) error {
|
|
baseHandler := binding.Handler
|
|
newHandler := func(opts gocui.ViewMouseBindingOpts) error {
|
|
// we ignore click events on views that aren't popup panels, when a popup panel is focused
|
|
if gui.popupPanelFocused() && gui.currentViewName() != binding.ViewName {
|
|
return nil
|
|
}
|
|
|
|
return baseHandler(opts)
|
|
}
|
|
binding.Handler = newHandler
|
|
|
|
return gui.g.SetViewClickBinding(binding)
|
|
}
|