mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-07-30 03:23:08 +03:00
Enforce single-item selection in various actions
We want to show an error when the user tries to invoke an action that expects only a single item to be selected. We're using the GetDisabledReason field to enforce this (as well as DisabledReason on menu items). I've created a ListControllerTrait to store some shared convenience functions for this.
This commit is contained in:
@ -22,50 +22,61 @@ type ContainsCommits interface {
|
||||
|
||||
type BasicCommitsController struct {
|
||||
baseController
|
||||
*ListControllerTrait[*models.Commit]
|
||||
c *ControllerCommon
|
||||
context ContainsCommits
|
||||
}
|
||||
|
||||
func NewBasicCommitsController(controllerCommon *ControllerCommon, context ContainsCommits) *BasicCommitsController {
|
||||
func NewBasicCommitsController(c *ControllerCommon, context ContainsCommits) *BasicCommitsController {
|
||||
return &BasicCommitsController{
|
||||
baseController: baseController{},
|
||||
c: controllerCommon,
|
||||
c: c,
|
||||
context: context,
|
||||
ListControllerTrait: NewListControllerTrait[*models.Commit](
|
||||
c,
|
||||
context,
|
||||
context.GetSelected,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
func (self *BasicCommitsController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
||||
bindings := []*types.Binding{
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Commits.CheckoutCommit),
|
||||
Handler: self.checkSelected(self.checkout),
|
||||
Description: self.c.Tr.CheckoutCommit,
|
||||
Key: opts.GetKey(opts.Config.Commits.CheckoutCommit),
|
||||
Handler: self.withItem(self.checkout),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.CheckoutCommit,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Commits.CopyCommitAttributeToClipboard),
|
||||
Handler: self.checkSelected(self.copyCommitAttribute),
|
||||
Description: self.c.Tr.CopyCommitAttributeToClipboard,
|
||||
OpensMenu: true,
|
||||
Key: opts.GetKey(opts.Config.Commits.CopyCommitAttributeToClipboard),
|
||||
Handler: self.withItem(self.copyCommitAttribute),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.CopyCommitAttributeToClipboard,
|
||||
OpensMenu: true,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Commits.OpenInBrowser),
|
||||
Handler: self.checkSelected(self.openInBrowser),
|
||||
Description: self.c.Tr.OpenCommitInBrowser,
|
||||
Key: opts.GetKey(opts.Config.Commits.OpenInBrowser),
|
||||
Handler: self.withItem(self.openInBrowser),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.OpenCommitInBrowser,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.New),
|
||||
Handler: self.checkSelected(self.newBranch),
|
||||
Description: self.c.Tr.CreateNewBranchFromCommit,
|
||||
Key: opts.GetKey(opts.Config.Universal.New),
|
||||
Handler: self.withItem(self.newBranch),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.CreateNewBranchFromCommit,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Commits.ViewResetOptions),
|
||||
Handler: self.checkSelected(self.createResetMenu),
|
||||
Description: self.c.Tr.ViewResetOptions,
|
||||
OpensMenu: true,
|
||||
Key: opts.GetKey(opts.Config.Commits.ViewResetOptions),
|
||||
Handler: self.withItem(self.createResetMenu),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.ViewResetOptions,
|
||||
OpensMenu: true,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Commits.CherryPickCopy),
|
||||
Handler: self.checkSelected(self.copyRange),
|
||||
Handler: self.withItem(self.copyRange),
|
||||
Description: self.c.Tr.CherryPickCopy,
|
||||
},
|
||||
{
|
||||
@ -74,30 +85,16 @@ func (self *BasicCommitsController) GetKeybindings(opts types.KeybindingsOpts) [
|
||||
Description: self.c.Tr.ResetCherryPick,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.OpenDiffTool),
|
||||
Handler: self.checkSelected(self.openDiffTool),
|
||||
Description: self.c.Tr.OpenDiffTool,
|
||||
Key: opts.GetKey(opts.Config.Universal.OpenDiffTool),
|
||||
Handler: self.withItem(self.openDiffTool),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.OpenDiffTool,
|
||||
},
|
||||
}
|
||||
|
||||
return bindings
|
||||
}
|
||||
|
||||
func (self *BasicCommitsController) checkSelected(callback func(*models.Commit) error) func() error {
|
||||
return func() error {
|
||||
commit := self.context.GetSelected()
|
||||
if commit == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return callback(commit)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *BasicCommitsController) Context() types.Context {
|
||||
return self.context
|
||||
}
|
||||
|
||||
func (self *BasicCommitsController) copyCommitAttribute(commit *models.Commit) error {
|
||||
return self.c.Menu(types.CreateMenuOptions{
|
||||
Title: self.c.Tr.Actions.CopyCommitAttributeToClipboard,
|
||||
|
@ -14,17 +14,23 @@ import (
|
||||
|
||||
type BisectController struct {
|
||||
baseController
|
||||
*ListControllerTrait[*models.Commit]
|
||||
c *ControllerCommon
|
||||
}
|
||||
|
||||
var _ types.IController = &BisectController{}
|
||||
|
||||
func NewBisectController(
|
||||
common *ControllerCommon,
|
||||
c *ControllerCommon,
|
||||
) *BisectController {
|
||||
return &BisectController{
|
||||
baseController: baseController{},
|
||||
c: common,
|
||||
c: c,
|
||||
ListControllerTrait: NewListControllerTrait[*models.Commit](
|
||||
c,
|
||||
c.Contexts().LocalCommits,
|
||||
c.Contexts().LocalCommits.GetSelected,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,7 +38,7 @@ func (self *BisectController) GetKeybindings(opts types.KeybindingsOpts) []*type
|
||||
bindings := []*types.Binding{
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Commits.ViewBisectOptions),
|
||||
Handler: opts.Guards.OutsideFilterMode(self.checkSelected(self.openMenu)),
|
||||
Handler: opts.Guards.OutsideFilterMode(self.withItem(self.openMenu)),
|
||||
Description: self.c.Tr.ViewBisectOptions,
|
||||
OpensMenu: true,
|
||||
},
|
||||
@ -70,9 +76,19 @@ func (self *BisectController) openMidBisectMenu(info *git_commands.BisectInfo, c
|
||||
// If we have a current sha already, then we always want to use that one. If
|
||||
// not, we're still picking the initial commits before we really start, so
|
||||
// use the selected commit in that case.
|
||||
shaToMark := lo.Ternary(info.GetCurrentSha() != "", info.GetCurrentSha(), commit.Sha)
|
||||
|
||||
bisecting := info.GetCurrentSha() != ""
|
||||
shaToMark := lo.Ternary(bisecting, info.GetCurrentSha(), commit.Sha)
|
||||
shortShaToMark := utils.ShortSha(shaToMark)
|
||||
|
||||
// For marking a commit as bad, when we're not already bisecting, we require
|
||||
// a single item selected, but once we are bisecting, it doesn't matter because
|
||||
// the action applies to the HEAD commit rather than the selected commit.
|
||||
var singleItemIfNotBisecting *types.DisabledReason
|
||||
if !bisecting {
|
||||
singleItemIfNotBisecting = self.require(self.singleItemSelected())()
|
||||
}
|
||||
|
||||
menuItems := []*types.MenuItem{
|
||||
{
|
||||
Label: fmt.Sprintf(self.c.Tr.Bisect.Mark, shortShaToMark, info.NewTerm()),
|
||||
@ -84,7 +100,8 @@ func (self *BisectController) openMidBisectMenu(info *git_commands.BisectInfo, c
|
||||
|
||||
return self.afterMark(selectCurrentAfter, waitToReselect)
|
||||
},
|
||||
Key: 'b',
|
||||
DisabledReason: singleItemIfNotBisecting,
|
||||
Key: 'b',
|
||||
},
|
||||
{
|
||||
Label: fmt.Sprintf(self.c.Tr.Bisect.Mark, shortShaToMark, info.OldTerm()),
|
||||
@ -96,7 +113,8 @@ func (self *BisectController) openMidBisectMenu(info *git_commands.BisectInfo, c
|
||||
|
||||
return self.afterMark(selectCurrentAfter, waitToReselect)
|
||||
},
|
||||
Key: 'g',
|
||||
DisabledReason: singleItemIfNotBisecting,
|
||||
Key: 'g',
|
||||
},
|
||||
{
|
||||
Label: fmt.Sprintf(self.c.Tr.Bisect.SkipCurrent, shortShaToMark),
|
||||
@ -108,7 +126,8 @@ func (self *BisectController) openMidBisectMenu(info *git_commands.BisectInfo, c
|
||||
|
||||
return self.afterMark(selectCurrentAfter, waitToReselect)
|
||||
},
|
||||
Key: 's',
|
||||
DisabledReason: singleItemIfNotBisecting,
|
||||
Key: 's',
|
||||
},
|
||||
}
|
||||
if info.GetCurrentSha() != "" && info.GetCurrentSha() != commit.Sha {
|
||||
@ -122,7 +141,8 @@ func (self *BisectController) openMidBisectMenu(info *git_commands.BisectInfo, c
|
||||
|
||||
return self.afterMark(selectCurrentAfter, waitToReselect)
|
||||
},
|
||||
Key: 'S',
|
||||
DisabledReason: self.require(self.singleItemSelected())(),
|
||||
Key: 'S',
|
||||
}))
|
||||
}
|
||||
menuItems = append(menuItems, lo.ToPtr(types.MenuItem{
|
||||
@ -157,7 +177,8 @@ func (self *BisectController) openStartBisectMenu(info *git_commands.BisectInfo,
|
||||
|
||||
return self.c.Helpers().Bisect.PostBisectCommandRefresh()
|
||||
},
|
||||
Key: 'b',
|
||||
DisabledReason: self.require(self.singleItemSelected())(),
|
||||
Key: 'b',
|
||||
},
|
||||
{
|
||||
Label: fmt.Sprintf(self.c.Tr.Bisect.MarkStart, commit.ShortSha(), info.OldTerm()),
|
||||
@ -173,7 +194,8 @@ func (self *BisectController) openStartBisectMenu(info *git_commands.BisectInfo,
|
||||
|
||||
return self.c.Helpers().Bisect.PostBisectCommandRefresh()
|
||||
},
|
||||
Key: 'g',
|
||||
DisabledReason: self.require(self.singleItemSelected())(),
|
||||
Key: 'g',
|
||||
},
|
||||
{
|
||||
Label: self.c.Tr.Bisect.ChooseTerms,
|
||||
@ -273,21 +295,6 @@ func (self *BisectController) selectCurrentBisectCommit() {
|
||||
}
|
||||
}
|
||||
|
||||
func (self *BisectController) checkSelected(callback func(*models.Commit) error) func() error {
|
||||
return func() error {
|
||||
commit := self.context().GetSelected()
|
||||
if commit == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return callback(commit)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *BisectController) Context() types.Context {
|
||||
return self.context()
|
||||
}
|
||||
|
||||
func (self *BisectController) context() *context.LocalCommitsContext {
|
||||
return self.c.Contexts().LocalCommits
|
||||
}
|
||||
|
@ -17,48 +17,61 @@ import (
|
||||
|
||||
type BranchesController struct {
|
||||
baseController
|
||||
*ListControllerTrait[*models.Branch]
|
||||
c *ControllerCommon
|
||||
}
|
||||
|
||||
var _ types.IController = &BranchesController{}
|
||||
|
||||
func NewBranchesController(
|
||||
common *ControllerCommon,
|
||||
c *ControllerCommon,
|
||||
) *BranchesController {
|
||||
return &BranchesController{
|
||||
baseController: baseController{},
|
||||
c: common,
|
||||
c: c,
|
||||
ListControllerTrait: NewListControllerTrait[*models.Branch](
|
||||
c,
|
||||
c.Contexts().Branches,
|
||||
c.Contexts().Branches.GetSelected,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
func (self *BranchesController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
||||
return []*types.Binding{
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.Select),
|
||||
Handler: self.checkSelected(self.press),
|
||||
GetDisabledReason: self.getDisabledReasonForPress,
|
||||
Description: self.c.Tr.Checkout,
|
||||
Key: opts.GetKey(opts.Config.Universal.Select),
|
||||
Handler: self.withItem(self.press),
|
||||
GetDisabledReason: self.require(
|
||||
self.singleItemSelected(),
|
||||
self.notPulling,
|
||||
),
|
||||
Description: self.c.Tr.Checkout,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.New),
|
||||
Handler: self.checkSelected(self.newBranch),
|
||||
Description: self.c.Tr.NewBranch,
|
||||
Key: opts.GetKey(opts.Config.Universal.New),
|
||||
Handler: self.withItem(self.newBranch),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.NewBranch,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Branches.CreatePullRequest),
|
||||
Handler: self.checkSelected(self.handleCreatePullRequest),
|
||||
Description: self.c.Tr.CreatePullRequest,
|
||||
Key: opts.GetKey(opts.Config.Branches.CreatePullRequest),
|
||||
Handler: self.withItem(self.handleCreatePullRequest),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.CreatePullRequest,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Branches.ViewPullRequestOptions),
|
||||
Handler: self.checkSelected(self.handleCreatePullRequestMenu),
|
||||
Description: self.c.Tr.CreatePullRequestOptions,
|
||||
OpensMenu: true,
|
||||
Key: opts.GetKey(opts.Config.Branches.ViewPullRequestOptions),
|
||||
Handler: self.withItem(self.handleCreatePullRequestMenu),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.CreatePullRequestOptions,
|
||||
OpensMenu: true,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Branches.CopyPullRequestURL),
|
||||
Handler: self.copyPullRequestURL,
|
||||
Description: self.c.Tr.CopyPullRequestURL,
|
||||
Key: opts.GetKey(opts.Config.Branches.CopyPullRequestURL),
|
||||
Handler: self.copyPullRequestURL,
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.CopyPullRequestURL,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Branches.CheckoutBranchByName),
|
||||
@ -66,60 +79,69 @@ func (self *BranchesController) GetKeybindings(opts types.KeybindingsOpts) []*ty
|
||||
Description: self.c.Tr.CheckoutByName,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Branches.ForceCheckoutBranch),
|
||||
Handler: self.forceCheckout,
|
||||
Description: self.c.Tr.ForceCheckout,
|
||||
Key: opts.GetKey(opts.Config.Branches.ForceCheckoutBranch),
|
||||
Handler: self.forceCheckout,
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.ForceCheckout,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.Remove),
|
||||
Handler: self.checkSelectedAndReal(self.delete),
|
||||
Description: self.c.Tr.ViewDeleteOptions,
|
||||
OpensMenu: true,
|
||||
Key: opts.GetKey(opts.Config.Universal.Remove),
|
||||
Handler: self.withItem(self.delete),
|
||||
GetDisabledReason: self.require(self.singleItemSelected(self.branchIsReal)),
|
||||
Description: self.c.Tr.ViewDeleteOptions,
|
||||
OpensMenu: true,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Branches.RebaseBranch),
|
||||
Handler: opts.Guards.OutsideFilterMode(self.rebase),
|
||||
Description: self.c.Tr.RebaseBranch,
|
||||
GetDisabledReason: self.getDisabledReasonForRebase,
|
||||
Key: opts.GetKey(opts.Config.Branches.RebaseBranch),
|
||||
Handler: opts.Guards.OutsideFilterMode(self.rebase),
|
||||
GetDisabledReason: self.require(
|
||||
self.singleItemSelected(self.notRebasingOntoSelf),
|
||||
),
|
||||
Description: self.c.Tr.RebaseBranch,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Branches.MergeIntoCurrentBranch),
|
||||
Handler: opts.Guards.OutsideFilterMode(self.merge),
|
||||
Description: self.c.Tr.MergeIntoCurrentBranch,
|
||||
Key: opts.GetKey(opts.Config.Branches.MergeIntoCurrentBranch),
|
||||
Handler: opts.Guards.OutsideFilterMode(self.merge),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.MergeIntoCurrentBranch,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Branches.FastForward),
|
||||
Handler: self.checkSelectedAndReal(self.fastForward),
|
||||
Description: self.c.Tr.FastForward,
|
||||
Key: opts.GetKey(opts.Config.Branches.FastForward),
|
||||
Handler: self.withItem(self.fastForward),
|
||||
GetDisabledReason: self.require(self.singleItemSelected(self.branchIsReal)),
|
||||
Description: self.c.Tr.FastForward,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Branches.CreateTag),
|
||||
Handler: self.checkSelected(self.createTag),
|
||||
Description: self.c.Tr.CreateTag,
|
||||
Key: opts.GetKey(opts.Config.Branches.CreateTag),
|
||||
Handler: self.withItem(self.createTag),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.CreateTag,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Branches.SortOrder),
|
||||
Handler: self.createSortMenu,
|
||||
Description: self.c.Tr.SortOrder,
|
||||
OpensMenu: true,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Commits.ViewResetOptions),
|
||||
Handler: self.checkSelected(self.createResetMenu),
|
||||
Description: self.c.Tr.ViewResetOptions,
|
||||
OpensMenu: true,
|
||||
Key: opts.GetKey(opts.Config.Commits.ViewResetOptions),
|
||||
Handler: self.withItem(self.createResetMenu),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.ViewResetOptions,
|
||||
OpensMenu: true,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Branches.RenameBranch),
|
||||
Handler: self.checkSelectedAndReal(self.rename),
|
||||
Description: self.c.Tr.RenameBranch,
|
||||
Key: opts.GetKey(opts.Config.Branches.RenameBranch),
|
||||
Handler: self.withItem(self.rename),
|
||||
GetDisabledReason: self.require(self.singleItemSelected(self.branchIsReal)),
|
||||
Description: self.c.Tr.RenameBranch,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Branches.SetUpstream),
|
||||
Handler: self.checkSelected(self.viewUpstreamOptions),
|
||||
Description: self.c.Tr.ViewBranchUpstreamOptions,
|
||||
Tooltip: self.c.Tr.ViewBranchUpstreamOptionsTooltip,
|
||||
OpensMenu: true,
|
||||
Key: opts.GetKey(opts.Config.Branches.SetUpstream),
|
||||
Handler: self.withItem(self.viewUpstreamOptions),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.ViewBranchUpstreamOptions,
|
||||
Tooltip: self.c.Tr.ViewBranchUpstreamOptionsTooltip,
|
||||
OpensMenu: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -308,7 +330,7 @@ func (self *BranchesController) press(selectedBranch *models.Branch) error {
|
||||
return self.c.Helpers().Refs.CheckoutRef(selectedBranch.Name, types.CheckoutRefOptions{})
|
||||
}
|
||||
|
||||
func (self *BranchesController) getDisabledReasonForPress() *types.DisabledReason {
|
||||
func (self *BranchesController) notPulling() *types.DisabledReason {
|
||||
currentBranch := self.c.Helpers().Refs.GetCheckedOutRef()
|
||||
if currentBranch != nil {
|
||||
op := self.c.State().GetItemOperation(currentBranch)
|
||||
@ -561,8 +583,8 @@ func (self *BranchesController) rebase() error {
|
||||
return self.c.Helpers().MergeAndRebase.RebaseOntoRef(selectedBranchName)
|
||||
}
|
||||
|
||||
func (self *BranchesController) getDisabledReasonForRebase() *types.DisabledReason {
|
||||
selectedBranchName := self.context().GetSelected().Name
|
||||
func (self *BranchesController) notRebasingOntoSelf(branch *models.Branch) *types.DisabledReason {
|
||||
selectedBranchName := branch.Name
|
||||
checkedOutBranch := self.c.Helpers().Refs.GetCheckedOutRef().Name
|
||||
if selectedBranchName == checkedOutBranch {
|
||||
return &types.DisabledReason{Text: self.c.Tr.CantRebaseOntoSelf}
|
||||
@ -753,24 +775,10 @@ func (self *BranchesController) createPullRequest(from string, to string) error
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *BranchesController) checkSelected(callback func(*models.Branch) error) func() error {
|
||||
return func() error {
|
||||
selectedItem := self.context().GetSelected()
|
||||
if selectedItem == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return callback(selectedItem)
|
||||
func (self *BranchesController) branchIsReal(branch *models.Branch) *types.DisabledReason {
|
||||
if !branch.IsRealBranch() {
|
||||
return &types.DisabledReason{Text: self.c.Tr.SelectedItemIsNotABranch}
|
||||
}
|
||||
}
|
||||
|
||||
func (self *BranchesController) checkSelectedAndReal(callback func(*models.Branch) error) func() error {
|
||||
return func() error {
|
||||
selectedItem := self.context().GetSelected()
|
||||
if selectedItem == nil || !selectedItem.IsRealBranch() {
|
||||
return nil
|
||||
}
|
||||
|
||||
return callback(selectedItem)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -12,11 +12,11 @@ type CommandLogController struct {
|
||||
var _ types.IController = &CommandLogController{}
|
||||
|
||||
func NewCommandLogController(
|
||||
common *ControllerCommon,
|
||||
c *ControllerCommon,
|
||||
) *CommandLogController {
|
||||
return &CommandLogController{
|
||||
baseController: baseController{},
|
||||
c: common,
|
||||
c: c,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,11 +13,11 @@ type CommitDescriptionController struct {
|
||||
var _ types.IController = &CommitMessageController{}
|
||||
|
||||
func NewCommitDescriptionController(
|
||||
common *ControllerCommon,
|
||||
c *ControllerCommon,
|
||||
) *CommitDescriptionController {
|
||||
return &CommitDescriptionController{
|
||||
baseController: baseController{},
|
||||
c: common,
|
||||
c: c,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,11 +14,11 @@ type CommitMessageController struct {
|
||||
var _ types.IController = &CommitMessageController{}
|
||||
|
||||
func NewCommitMessageController(
|
||||
common *ControllerCommon,
|
||||
c *ControllerCommon,
|
||||
) *CommitMessageController {
|
||||
return &CommitMessageController{
|
||||
baseController: baseController{},
|
||||
c: common,
|
||||
c: c,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,61 +12,74 @@ import (
|
||||
|
||||
type CommitFilesController struct {
|
||||
baseController
|
||||
*ListControllerTrait[*filetree.CommitFileNode]
|
||||
c *ControllerCommon
|
||||
}
|
||||
|
||||
var _ types.IController = &CommitFilesController{}
|
||||
|
||||
func NewCommitFilesController(
|
||||
common *ControllerCommon,
|
||||
c *ControllerCommon,
|
||||
) *CommitFilesController {
|
||||
return &CommitFilesController{
|
||||
baseController: baseController{},
|
||||
c: common,
|
||||
c: c,
|
||||
ListControllerTrait: NewListControllerTrait[*filetree.CommitFileNode](
|
||||
c,
|
||||
c.Contexts().CommitFiles,
|
||||
c.Contexts().CommitFiles.GetSelected,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
func (self *CommitFilesController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
||||
bindings := []*types.Binding{
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.CommitFiles.CheckoutCommitFile),
|
||||
Handler: self.checkSelected(self.checkout),
|
||||
Description: self.c.Tr.CheckoutCommitFile,
|
||||
Key: opts.GetKey(opts.Config.CommitFiles.CheckoutCommitFile),
|
||||
Handler: self.withItem(self.checkout),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.CheckoutCommitFile,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.Remove),
|
||||
Handler: self.checkSelected(self.discard),
|
||||
Description: self.c.Tr.DiscardOldFileChange,
|
||||
Key: opts.GetKey(opts.Config.Universal.Remove),
|
||||
Handler: self.withItem(self.discard),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.DiscardOldFileChange,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.OpenFile),
|
||||
Handler: self.checkSelected(self.open),
|
||||
Description: self.c.Tr.OpenFile,
|
||||
Key: opts.GetKey(opts.Config.Universal.OpenFile),
|
||||
Handler: self.withItem(self.open),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.OpenFile,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.Edit),
|
||||
Handler: self.checkSelected(self.edit),
|
||||
Description: self.c.Tr.EditFile,
|
||||
Key: opts.GetKey(opts.Config.Universal.Edit),
|
||||
Handler: self.withItem(self.edit),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.EditFile,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.OpenDiffTool),
|
||||
Handler: self.checkSelected(self.openDiffTool),
|
||||
Description: self.c.Tr.OpenDiffTool,
|
||||
Key: opts.GetKey(opts.Config.Universal.OpenDiffTool),
|
||||
Handler: self.withItem(self.openDiffTool),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.OpenDiffTool,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.Select),
|
||||
Handler: self.checkSelected(self.toggleForPatch),
|
||||
Description: self.c.Tr.ToggleAddToPatch,
|
||||
Key: opts.GetKey(opts.Config.Universal.Select),
|
||||
Handler: self.withItem(self.toggleForPatch),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.ToggleAddToPatch,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Files.ToggleStagedAll),
|
||||
Handler: self.checkSelected(self.toggleAllForPatch),
|
||||
Handler: self.withItem(self.toggleAllForPatch),
|
||||
Description: self.c.Tr.ToggleAllInPatch,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.GoInto),
|
||||
Handler: self.checkSelected(self.enter),
|
||||
Description: self.c.Tr.EnterFile,
|
||||
Key: opts.GetKey(opts.Config.Universal.GoInto),
|
||||
Handler: self.withItem(self.enter),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.EnterFile,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Files.ToggleTreeView),
|
||||
@ -89,21 +102,6 @@ func (self *CommitFilesController) GetMouseKeybindings(opts types.KeybindingsOpt
|
||||
}
|
||||
}
|
||||
|
||||
func (self *CommitFilesController) checkSelected(callback func(*filetree.CommitFileNode) error) func() error {
|
||||
return func() error {
|
||||
selected := self.context().GetSelected()
|
||||
if selected == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return callback(selected)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *CommitFilesController) Context() types.Context {
|
||||
return self.context()
|
||||
}
|
||||
|
||||
func (self *CommitFilesController) context() *context.CommitFilesContext {
|
||||
return self.c.Contexts().CommitFiles
|
||||
}
|
||||
|
@ -13,11 +13,11 @@ type ConfirmationController struct {
|
||||
var _ types.IController = &ConfirmationController{}
|
||||
|
||||
func NewConfirmationController(
|
||||
common *ControllerCommon,
|
||||
c *ControllerCommon,
|
||||
) *ConfirmationController {
|
||||
return &ConfirmationController{
|
||||
baseController: baseController{},
|
||||
c: common,
|
||||
c: c,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,11 +31,11 @@ type ContextLinesController struct {
|
||||
var _ types.IController = &ContextLinesController{}
|
||||
|
||||
func NewContextLinesController(
|
||||
common *ControllerCommon,
|
||||
c *ControllerCommon,
|
||||
) *ContextLinesController {
|
||||
return &ContextLinesController{
|
||||
baseController: baseController{},
|
||||
c: common,
|
||||
c: c,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,15 +62,22 @@ func (self *CustomPatchOptionsMenuAction) Call() error {
|
||||
if self.c.CurrentContext().GetKey() == self.c.Contexts().LocalCommits.GetKey() {
|
||||
selectedCommit := self.c.Contexts().LocalCommits.GetSelected()
|
||||
if selectedCommit != nil && self.c.Git().Patch.PatchBuilder.To != selectedCommit.Sha {
|
||||
|
||||
var disabledReason *types.DisabledReason
|
||||
if self.c.Contexts().LocalCommits.AreMultipleItemsSelected() {
|
||||
disabledReason = &types.DisabledReason{Text: self.c.Tr.RangeSelectNotSupported}
|
||||
}
|
||||
|
||||
// adding this option to index 1
|
||||
menuItems = append(
|
||||
menuItems[:1],
|
||||
append(
|
||||
[]*types.MenuItem{
|
||||
{
|
||||
Label: fmt.Sprintf(self.c.Tr.MovePatchToSelectedCommit, selectedCommit.Sha),
|
||||
OnPress: self.handleMovePatchToSelectedCommit,
|
||||
Key: 'm',
|
||||
Label: fmt.Sprintf(self.c.Tr.MovePatchToSelectedCommit, selectedCommit.Sha),
|
||||
OnPress: self.handleMovePatchToSelectedCommit,
|
||||
Key: 'm',
|
||||
DisabledReason: disabledReason,
|
||||
},
|
||||
}, menuItems[1:]...,
|
||||
)...,
|
||||
|
@ -13,25 +13,32 @@ import (
|
||||
|
||||
type FilesController struct {
|
||||
baseController // nolint: unused
|
||||
c *ControllerCommon
|
||||
*ListControllerTrait[*filetree.FileNode]
|
||||
c *ControllerCommon
|
||||
}
|
||||
|
||||
var _ types.IController = &FilesController{}
|
||||
|
||||
func NewFilesController(
|
||||
common *ControllerCommon,
|
||||
c *ControllerCommon,
|
||||
) *FilesController {
|
||||
return &FilesController{
|
||||
c: common,
|
||||
c: c,
|
||||
ListControllerTrait: NewListControllerTrait[*filetree.FileNode](
|
||||
c,
|
||||
c.Contexts().Files,
|
||||
c.Contexts().Files.GetSelected,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
func (self *FilesController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
||||
return []*types.Binding{
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.Select),
|
||||
Handler: self.checkSelectedFileNode(self.press),
|
||||
Description: self.c.Tr.ToggleStaged,
|
||||
Key: opts.GetKey(opts.Config.Universal.Select),
|
||||
Handler: self.withItem(self.press),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.ToggleStaged,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Files.OpenStatusFilter),
|
||||
@ -71,20 +78,23 @@ func (self *FilesController) GetKeybindings(opts types.KeybindingsOpts) []*types
|
||||
Tooltip: self.c.Tr.FindBaseCommitForFixupTooltip,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.Edit),
|
||||
Handler: self.checkSelectedFileNode(self.edit),
|
||||
Description: self.c.Tr.EditFile,
|
||||
Key: opts.GetKey(opts.Config.Universal.Edit),
|
||||
Handler: self.withItem(self.edit),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.EditFile,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.OpenFile),
|
||||
Handler: self.Open,
|
||||
Description: self.c.Tr.OpenFile,
|
||||
Key: opts.GetKey(opts.Config.Universal.OpenFile),
|
||||
Handler: self.Open,
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.OpenFile,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Files.IgnoreFile),
|
||||
Handler: self.checkSelectedFileNode(self.ignoreOrExcludeMenu),
|
||||
Description: self.c.Tr.Actions.IgnoreExcludeFile,
|
||||
OpensMenu: true,
|
||||
Key: opts.GetKey(opts.Config.Files.IgnoreFile),
|
||||
Handler: self.withItem(self.ignoreOrExcludeMenu),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.Actions.IgnoreExcludeFile,
|
||||
OpensMenu: true,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Files.RefreshFiles),
|
||||
@ -108,9 +118,10 @@ func (self *FilesController) GetKeybindings(opts types.KeybindingsOpts) []*types
|
||||
Description: self.c.Tr.ToggleStagedAll,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.GoInto),
|
||||
Handler: self.enter,
|
||||
Description: self.c.Tr.FileEnter,
|
||||
Key: opts.GetKey(opts.Config.Universal.GoInto),
|
||||
Handler: self.enter,
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.FileEnter,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Commits.ViewResetOptions),
|
||||
@ -130,9 +141,10 @@ func (self *FilesController) GetKeybindings(opts types.KeybindingsOpts) []*types
|
||||
Description: self.c.Tr.ToggleTreeView,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.OpenDiffTool),
|
||||
Handler: self.checkSelectedFileNode(self.openDiffTool),
|
||||
Description: self.c.Tr.OpenDiffTool,
|
||||
Key: opts.GetKey(opts.Config.Universal.OpenDiffTool),
|
||||
Handler: self.withItem(self.openDiffTool),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.OpenDiffTool,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Files.OpenMergeTool),
|
||||
@ -254,7 +266,7 @@ func (self *FilesController) GetOnRenderToMain() func() error {
|
||||
}
|
||||
|
||||
func (self *FilesController) GetOnClick() func() error {
|
||||
return self.checkSelectedFileNode(self.press)
|
||||
return self.withItemGraceful(self.press)
|
||||
}
|
||||
|
||||
// if we are dealing with a status for which there is no key in this map,
|
||||
@ -411,17 +423,6 @@ func (self *FilesController) press(node *filetree.FileNode) error {
|
||||
return self.context().HandleFocus(types.OnFocusOpts{})
|
||||
}
|
||||
|
||||
func (self *FilesController) checkSelectedFileNode(callback func(*filetree.FileNode) error) func() error {
|
||||
return func() error {
|
||||
node := self.context().GetSelected()
|
||||
if node == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return callback(node)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *FilesController) Context() types.Context {
|
||||
return self.context()
|
||||
}
|
||||
@ -798,7 +799,8 @@ func (self *FilesController) openCopyMenu() error {
|
||||
self.c.Toast(self.c.Tr.FileNameCopiedToast)
|
||||
return nil
|
||||
},
|
||||
Key: 'n',
|
||||
DisabledReason: self.require(self.singleItemSelected())(),
|
||||
Key: 'n',
|
||||
}
|
||||
copyPathItem := &types.MenuItem{
|
||||
Label: self.c.Tr.CopyFilePath,
|
||||
@ -809,7 +811,8 @@ func (self *FilesController) openCopyMenu() error {
|
||||
self.c.Toast(self.c.Tr.FilePathCopiedToast)
|
||||
return nil
|
||||
},
|
||||
Key: 'p',
|
||||
DisabledReason: self.require(self.singleItemSelected())(),
|
||||
Key: 'p',
|
||||
}
|
||||
copyFileDiffItem := &types.MenuItem{
|
||||
Label: self.c.Tr.CopySelectedDiff,
|
||||
@ -827,6 +830,14 @@ func (self *FilesController) openCopyMenu() error {
|
||||
self.c.Toast(self.c.Tr.FileDiffCopiedToast)
|
||||
return nil
|
||||
},
|
||||
DisabledReason: self.require(self.singleItemSelected(
|
||||
func(file *filetree.FileNode) *types.DisabledReason {
|
||||
if !node.GetHasStagedOrTrackedChanges() {
|
||||
return &types.DisabledReason{Text: self.c.Tr.NoContentToCopyError}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
))(),
|
||||
Key: 's',
|
||||
}
|
||||
copyAllDiff := &types.MenuItem{
|
||||
@ -844,21 +855,17 @@ func (self *FilesController) openCopyMenu() error {
|
||||
self.c.Toast(self.c.Tr.AllFilesDiffCopiedToast)
|
||||
return nil
|
||||
},
|
||||
DisabledReason: self.require(
|
||||
func() *types.DisabledReason {
|
||||
if !self.anyStagedOrTrackedFile() {
|
||||
return &types.DisabledReason{Text: self.c.Tr.NoContentToCopyError}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
)(),
|
||||
Key: 'a',
|
||||
}
|
||||
|
||||
if node == nil {
|
||||
copyNameItem.DisabledReason = &types.DisabledReason{Text: self.c.Tr.NoContentToCopyError}
|
||||
copyPathItem.DisabledReason = &types.DisabledReason{Text: self.c.Tr.NoContentToCopyError}
|
||||
copyFileDiffItem.DisabledReason = &types.DisabledReason{Text: self.c.Tr.NoContentToCopyError}
|
||||
}
|
||||
if node != nil && !node.GetHasStagedOrTrackedChanges() {
|
||||
copyFileDiffItem.DisabledReason = &types.DisabledReason{Text: self.c.Tr.NoContentToCopyError}
|
||||
}
|
||||
if !self.anyStagedOrTrackedFile() {
|
||||
copyAllDiff.DisabledReason = &types.DisabledReason{Text: self.c.Tr.NoContentToCopyError}
|
||||
}
|
||||
|
||||
return self.c.Menu(types.CreateMenuOptions{
|
||||
Title: self.c.Tr.CopyToClipboardMenu,
|
||||
Items: []*types.MenuItem{
|
||||
|
@ -3,7 +3,6 @@ package controllers
|
||||
import (
|
||||
"github.com/jesseduffield/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/filetree"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
@ -13,27 +12,34 @@ import (
|
||||
|
||||
type FilesRemoveController struct {
|
||||
baseController
|
||||
*ListControllerTrait[*filetree.FileNode]
|
||||
c *ControllerCommon
|
||||
}
|
||||
|
||||
var _ types.IController = &FilesRemoveController{}
|
||||
|
||||
func NewFilesRemoveController(
|
||||
common *ControllerCommon,
|
||||
c *ControllerCommon,
|
||||
) *FilesRemoveController {
|
||||
return &FilesRemoveController{
|
||||
baseController: baseController{},
|
||||
c: common,
|
||||
c: c,
|
||||
ListControllerTrait: NewListControllerTrait[*filetree.FileNode](
|
||||
c,
|
||||
c.Contexts().Files,
|
||||
c.Contexts().Files.GetSelected,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
func (self *FilesRemoveController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
||||
bindings := []*types.Binding{
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.Remove),
|
||||
Handler: self.checkSelectedFileNode(self.remove),
|
||||
Description: self.c.Tr.ViewDiscardOptions,
|
||||
OpensMenu: true,
|
||||
Key: opts.GetKey(opts.Config.Universal.Remove),
|
||||
Handler: self.withItem(self.remove),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.ViewDiscardOptions,
|
||||
OpensMenu: true,
|
||||
},
|
||||
}
|
||||
|
||||
@ -166,22 +172,3 @@ func (self *FilesRemoveController) ResetSubmodule(submodule *models.SubmoduleCon
|
||||
return self.c.Refresh(types.RefreshOptions{Mode: types.ASYNC, Scope: []types.RefreshableView{types.FILES, types.SUBMODULES}})
|
||||
})
|
||||
}
|
||||
|
||||
func (self *FilesRemoveController) checkSelectedFileNode(callback func(*filetree.FileNode) error) func() error {
|
||||
return func() error {
|
||||
node := self.context().GetSelected()
|
||||
if node == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return callback(node)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *FilesRemoveController) Context() types.Context {
|
||||
return self.context()
|
||||
}
|
||||
|
||||
func (self *FilesRemoveController) context() *context.WorkingTreeContext {
|
||||
return self.c.Contexts().Files
|
||||
}
|
||||
|
@ -4,24 +4,29 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
)
|
||||
|
||||
type GitFlowController struct {
|
||||
baseController
|
||||
*ListControllerTrait[*models.Branch]
|
||||
c *ControllerCommon
|
||||
}
|
||||
|
||||
var _ types.IController = &GitFlowController{}
|
||||
|
||||
func NewGitFlowController(
|
||||
common *ControllerCommon,
|
||||
c *ControllerCommon,
|
||||
) *GitFlowController {
|
||||
return &GitFlowController{
|
||||
baseController: baseController{},
|
||||
c: common,
|
||||
ListControllerTrait: NewListControllerTrait[*models.Branch](
|
||||
c,
|
||||
c.Contexts().Branches,
|
||||
c.Contexts().Branches.GetSelected,
|
||||
),
|
||||
c: c,
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,7 +34,7 @@ func (self *GitFlowController) GetKeybindings(opts types.KeybindingsOpts) []*typ
|
||||
bindings := []*types.Binding{
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Branches.ViewGitFlowOptions),
|
||||
Handler: self.checkSelected(self.handleCreateGitFlowMenu),
|
||||
Handler: self.withItem(self.handleCreateGitFlowMenu),
|
||||
Description: self.c.Tr.GitFlowOptions,
|
||||
OpensMenu: true,
|
||||
},
|
||||
@ -68,6 +73,7 @@ func (self *GitFlowController) handleCreateGitFlowMenu(branch *models.Branch) er
|
||||
OnPress: func() error {
|
||||
return self.gitFlowFinishBranch(branch.Name)
|
||||
},
|
||||
DisabledReason: self.require(self.singleItemSelected())(),
|
||||
},
|
||||
{
|
||||
Label: "start feature",
|
||||
@ -102,22 +108,3 @@ func (self *GitFlowController) gitFlowFinishBranch(branchName string) error {
|
||||
self.c.LogAction(self.c.Tr.Actions.GitFlowFinish)
|
||||
return self.c.RunSubprocessAndRefresh(cmdObj)
|
||||
}
|
||||
|
||||
func (self *GitFlowController) checkSelected(callback func(*models.Branch) error) func() error {
|
||||
return func() error {
|
||||
node := self.context().GetSelected()
|
||||
if node == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return callback(node)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *GitFlowController) Context() types.Context {
|
||||
return self.context()
|
||||
}
|
||||
|
||||
func (self *GitFlowController) context() *context.BranchesContext {
|
||||
return self.c.Contexts().Branches
|
||||
}
|
||||
|
@ -11,11 +11,11 @@ type GlobalController struct {
|
||||
}
|
||||
|
||||
func NewGlobalController(
|
||||
common *ControllerCommon,
|
||||
c *ControllerCommon,
|
||||
) *GlobalController {
|
||||
return &GlobalController{
|
||||
baseController: baseController{},
|
||||
c: common,
|
||||
c: c,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,11 +14,11 @@ type JumpToSideWindowController struct {
|
||||
}
|
||||
|
||||
func NewJumpToSideWindowController(
|
||||
common *ControllerCommon,
|
||||
c *ControllerCommon,
|
||||
) *JumpToSideWindowController {
|
||||
return &JumpToSideWindowController{
|
||||
baseController: baseController{},
|
||||
c: common,
|
||||
c: c,
|
||||
}
|
||||
}
|
||||
|
||||
|
95
pkg/gui/controllers/list_controller_trait.go
Normal file
95
pkg/gui/controllers/list_controller_trait.go
Normal file
@ -0,0 +1,95 @@
|
||||
package controllers
|
||||
|
||||
import "github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
|
||||
// Embed this into your list controller to get some convenience methods for
|
||||
// ensuring a single item is selected, etc.
|
||||
|
||||
type ListControllerTrait[T comparable] struct {
|
||||
c *ControllerCommon
|
||||
context types.IListContext
|
||||
getSelected func() T
|
||||
}
|
||||
|
||||
func NewListControllerTrait[T comparable](
|
||||
c *ControllerCommon,
|
||||
context types.IListContext,
|
||||
getSelected func() T,
|
||||
) *ListControllerTrait[T] {
|
||||
return &ListControllerTrait[T]{
|
||||
c: c,
|
||||
context: context,
|
||||
getSelected: getSelected,
|
||||
}
|
||||
}
|
||||
|
||||
// Convenience function for combining multiple disabledReason callbacks.
|
||||
// The first callback to return a disabled reason will be the one returned.
|
||||
func (self *ListControllerTrait[T]) require(callbacks ...func() *types.DisabledReason) func() *types.DisabledReason {
|
||||
return func() *types.DisabledReason {
|
||||
for _, callback := range callbacks {
|
||||
if disabledReason := callback(); disabledReason != nil {
|
||||
return disabledReason
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Convenience function for enforcing that a single item is selected.
|
||||
// Also takes callbacks for additional disabled reasons, and passes the selected
|
||||
// item into each one.
|
||||
func (self *ListControllerTrait[T]) singleItemSelected(callbacks ...func(T) *types.DisabledReason) func() *types.DisabledReason {
|
||||
return func() *types.DisabledReason {
|
||||
if self.context.GetList().AreMultipleItemsSelected() {
|
||||
return &types.DisabledReason{Text: self.c.Tr.RangeSelectNotSupported}
|
||||
}
|
||||
|
||||
var zeroValue T
|
||||
item := self.getSelected()
|
||||
if item == zeroValue {
|
||||
return &types.DisabledReason{Text: self.c.Tr.NoItemSelected}
|
||||
}
|
||||
|
||||
for _, callback := range callbacks {
|
||||
if reason := callback(item); reason != nil {
|
||||
return reason
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Passes the selected item to the callback. Used for handler functions.
|
||||
func (self *ListControllerTrait[T]) withItem(callback func(T) error) func() error {
|
||||
return func() error {
|
||||
var zeroValue T
|
||||
commit := self.getSelected()
|
||||
if commit == zeroValue {
|
||||
return self.c.ErrorMsg(self.c.Tr.NoItemSelected)
|
||||
}
|
||||
|
||||
return callback(commit)
|
||||
}
|
||||
}
|
||||
|
||||
// Like withItem, but doesn't show an error message if no item is selected.
|
||||
// Use this for click actions (it's a no-op to click empty space)
|
||||
func (self *ListControllerTrait[T]) withItemGraceful(callback func(T) error) func() error {
|
||||
return func() error {
|
||||
var zeroValue T
|
||||
commit := self.getSelected()
|
||||
if commit == zeroValue {
|
||||
return nil
|
||||
}
|
||||
|
||||
return callback(commit)
|
||||
}
|
||||
}
|
||||
|
||||
// All controllers must implement this method so we're defining it here for convenience
|
||||
func (self *ListControllerTrait[T]) Context() types.Context {
|
||||
return self.context
|
||||
}
|
@ -25,6 +25,7 @@ type (
|
||||
|
||||
type LocalCommitsController struct {
|
||||
baseController
|
||||
*ListControllerTrait[*models.Commit]
|
||||
c *ControllerCommon
|
||||
|
||||
pullFiles PullFilesFn
|
||||
@ -33,13 +34,18 @@ type LocalCommitsController struct {
|
||||
var _ types.IController = &LocalCommitsController{}
|
||||
|
||||
func NewLocalCommitsController(
|
||||
common *ControllerCommon,
|
||||
c *ControllerCommon,
|
||||
pullFiles PullFilesFn,
|
||||
) *LocalCommitsController {
|
||||
return &LocalCommitsController{
|
||||
baseController: baseController{},
|
||||
c: common,
|
||||
c: c,
|
||||
pullFiles: pullFiles,
|
||||
ListControllerTrait: NewListControllerTrait[*models.Commit](
|
||||
c,
|
||||
c.Contexts().LocalCommits,
|
||||
c.Contexts().LocalCommits.GetSelected,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,47 +54,59 @@ func (self *LocalCommitsController) GetKeybindings(opts types.KeybindingsOpts) [
|
||||
|
||||
outsideFilterModeBindings := []*types.Binding{
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Commits.SquashDown),
|
||||
Handler: self.checkSelected(self.squashDown),
|
||||
GetDisabledReason: self.callGetDisabledReasonFuncWithSelectedCommit(self.getDisabledReasonForSquashDown),
|
||||
Description: self.c.Tr.SquashDown,
|
||||
Key: opts.GetKey(opts.Config.Commits.SquashDown),
|
||||
Handler: self.withItem(self.squashDown),
|
||||
GetDisabledReason: self.require(
|
||||
self.singleItemSelected(self.getDisabledReasonForSquashDown),
|
||||
),
|
||||
Description: self.c.Tr.SquashDown,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Commits.MarkCommitAsFixup),
|
||||
Handler: self.checkSelected(self.fixup),
|
||||
GetDisabledReason: self.callGetDisabledReasonFuncWithSelectedCommit(self.getDisabledReasonForFixup),
|
||||
Description: self.c.Tr.FixupCommit,
|
||||
Key: opts.GetKey(opts.Config.Commits.MarkCommitAsFixup),
|
||||
Handler: self.withItem(self.fixup),
|
||||
GetDisabledReason: self.require(
|
||||
self.singleItemSelected(self.getDisabledReasonForFixup),
|
||||
),
|
||||
Description: self.c.Tr.FixupCommit,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Commits.RenameCommit),
|
||||
Handler: self.checkSelected(self.reword),
|
||||
GetDisabledReason: self.getDisabledReasonForRebaseCommandWithSelectedCommit(todo.Reword),
|
||||
Description: self.c.Tr.RewordCommit,
|
||||
Key: opts.GetKey(opts.Config.Commits.RenameCommit),
|
||||
Handler: self.withItem(self.reword),
|
||||
GetDisabledReason: self.require(
|
||||
self.singleItemSelected(self.rebaseCommandEnabled(todo.Reword)),
|
||||
),
|
||||
Description: self.c.Tr.RewordCommit,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Commits.RenameCommitWithEditor),
|
||||
Handler: self.checkSelected(self.rewordEditor),
|
||||
GetDisabledReason: self.getDisabledReasonForRebaseCommandWithSelectedCommit(todo.Reword),
|
||||
Description: self.c.Tr.RenameCommitEditor,
|
||||
Key: opts.GetKey(opts.Config.Commits.RenameCommitWithEditor),
|
||||
Handler: self.withItem(self.rewordEditor),
|
||||
GetDisabledReason: self.require(
|
||||
self.singleItemSelected(self.rebaseCommandEnabled(todo.Reword)),
|
||||
),
|
||||
Description: self.c.Tr.RenameCommitEditor,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.Remove),
|
||||
Handler: self.checkSelected(self.drop),
|
||||
GetDisabledReason: self.getDisabledReasonForRebaseCommandWithSelectedCommit(todo.Drop),
|
||||
Description: self.c.Tr.DeleteCommit,
|
||||
Key: opts.GetKey(opts.Config.Universal.Remove),
|
||||
Handler: self.withItem(self.drop),
|
||||
GetDisabledReason: self.require(
|
||||
self.singleItemSelected(self.rebaseCommandEnabled(todo.Drop)),
|
||||
),
|
||||
Description: self.c.Tr.DeleteCommit,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(editCommitKey),
|
||||
Handler: self.checkSelected(self.edit),
|
||||
GetDisabledReason: self.getDisabledReasonForRebaseCommandWithSelectedCommit(todo.Edit),
|
||||
Description: self.c.Tr.EditCommit,
|
||||
Key: opts.GetKey(editCommitKey),
|
||||
Handler: self.withItem(self.edit),
|
||||
GetDisabledReason: self.require(
|
||||
self.singleItemSelected(self.rebaseCommandEnabled(todo.Edit)),
|
||||
),
|
||||
Description: self.c.Tr.EditCommit,
|
||||
},
|
||||
{
|
||||
// The user-facing description here is 'Start interactive rebase' but internally
|
||||
// we're calling it 'quick-start interactive rebase' to differentiate it from
|
||||
// when you manually select the base commit.
|
||||
Key: opts.GetKey(opts.Config.Commits.StartInteractiveRebase),
|
||||
Handler: self.checkSelected(self.quickStartInteractiveRebase),
|
||||
Handler: self.withItem(self.quickStartInteractiveRebase),
|
||||
GetDisabledReason: self.require(self.notMidRebase, self.canFindCommitForQuickStart),
|
||||
Description: self.c.Tr.QuickStartInteractiveRebase,
|
||||
Tooltip: utils.ResolvePlaceholderString(self.c.Tr.QuickStartInteractiveRebaseTooltip, map[string]string{
|
||||
@ -96,45 +114,50 @@ func (self *LocalCommitsController) GetKeybindings(opts types.KeybindingsOpts) [
|
||||
}),
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Commits.PickCommit),
|
||||
Handler: self.checkSelected(self.pick),
|
||||
GetDisabledReason: self.getDisabledReasonForRebaseCommandWithSelectedCommit(todo.Pick),
|
||||
Description: self.c.Tr.PickCommit,
|
||||
Key: opts.GetKey(opts.Config.Commits.PickCommit),
|
||||
Handler: self.withItem(self.pick),
|
||||
GetDisabledReason: self.require(
|
||||
self.singleItemSelected(self.rebaseCommandEnabled(todo.Pick)),
|
||||
),
|
||||
Description: self.c.Tr.PickCommit,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Commits.CreateFixupCommit),
|
||||
Handler: self.checkSelected(self.createFixupCommit),
|
||||
GetDisabledReason: self.disabledIfNoSelectedCommit(),
|
||||
Handler: self.withItem(self.createFixupCommit),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.CreateFixupCommitDescription,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Commits.SquashAboveCommits),
|
||||
Handler: self.checkSelected(self.squashAllAboveFixupCommits),
|
||||
GetDisabledReason: self.callGetDisabledReasonFuncWithSelectedCommit(self.getDisabledReasonForSquashAllAboveFixupCommits),
|
||||
Description: self.c.Tr.SquashAboveCommits,
|
||||
Key: opts.GetKey(opts.Config.Commits.SquashAboveCommits),
|
||||
Handler: self.withItem(self.squashAllAboveFixupCommits),
|
||||
GetDisabledReason: self.require(
|
||||
self.notMidRebase,
|
||||
self.singleItemSelected(),
|
||||
),
|
||||
Description: self.c.Tr.SquashAboveCommits,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Commits.MoveDownCommit),
|
||||
Handler: self.checkSelected(self.moveDown),
|
||||
GetDisabledReason: self.disabledIfNoSelectedCommit(),
|
||||
Handler: self.withItem(self.moveDown),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.MoveDownCommit,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Commits.MoveUpCommit),
|
||||
Handler: self.checkSelected(self.moveUp),
|
||||
GetDisabledReason: self.disabledIfNoSelectedCommit(),
|
||||
Handler: self.withItem(self.moveUp),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.MoveUpCommit,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Commits.PasteCommits),
|
||||
Handler: self.paste,
|
||||
GetDisabledReason: self.getDisabledReasonForPaste,
|
||||
GetDisabledReason: self.require(self.canPaste),
|
||||
Description: self.c.Tr.PasteCommits,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Commits.MarkCommitAsBaseForRebase),
|
||||
Handler: self.checkSelected(self.markAsBaseCommit),
|
||||
GetDisabledReason: self.disabledIfNoSelectedCommit(),
|
||||
Handler: self.withItem(self.markAsBaseCommit),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.MarkAsBaseCommit,
|
||||
Tooltip: self.c.Tr.MarkAsBaseCommitTooltip,
|
||||
},
|
||||
@ -161,27 +184,27 @@ func (self *LocalCommitsController) GetKeybindings(opts types.KeybindingsOpts) [
|
||||
bindings := append(outsideFilterModeBindings, []*types.Binding{
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Commits.AmendToCommit),
|
||||
Handler: self.checkSelected(self.amendTo),
|
||||
GetDisabledReason: self.callGetDisabledReasonFuncWithSelectedCommit(self.getDisabledReasonForAmendTo),
|
||||
Handler: self.withItem(self.amendTo),
|
||||
GetDisabledReason: self.require(self.singleItemSelected(self.canAmend)),
|
||||
Description: self.c.Tr.AmendToCommit,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Commits.ResetCommitAuthor),
|
||||
Handler: self.checkSelected(self.amendAttribute),
|
||||
GetDisabledReason: self.callGetDisabledReasonFuncWithSelectedCommit(self.getDisabledReasonForAmendTo),
|
||||
Handler: self.withItem(self.amendAttribute),
|
||||
GetDisabledReason: self.require(self.singleItemSelected(self.canAmend)),
|
||||
Description: self.c.Tr.SetResetCommitAuthor,
|
||||
OpensMenu: true,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Commits.RevertCommit),
|
||||
Handler: self.checkSelected(self.revert),
|
||||
GetDisabledReason: self.disabledIfNoSelectedCommit(),
|
||||
Handler: self.withItem(self.revert),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.RevertCommit,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Commits.CreateTag),
|
||||
Handler: self.checkSelected(self.createTag),
|
||||
GetDisabledReason: self.disabledIfNoSelectedCommit(),
|
||||
Handler: self.withItem(self.createTag),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.TagCommit,
|
||||
},
|
||||
{
|
||||
@ -266,7 +289,7 @@ func (self *LocalCommitsController) getDisabledReasonForSquashDown(commit *model
|
||||
return &types.DisabledReason{Text: self.c.Tr.CannotSquashOrFixupFirstCommit}
|
||||
}
|
||||
|
||||
return self.rebaseCommandEnabled(todo.Squash, commit)
|
||||
return self.rebaseCommandEnabled(todo.Squash)(commit)
|
||||
}
|
||||
|
||||
func (self *LocalCommitsController) fixup(commit *models.Commit) error {
|
||||
@ -295,7 +318,7 @@ func (self *LocalCommitsController) getDisabledReasonForFixup(commit *models.Com
|
||||
return &types.DisabledReason{Text: self.c.Tr.CannotSquashOrFixupFirstCommit}
|
||||
}
|
||||
|
||||
return self.rebaseCommandEnabled(todo.Squash, commit)
|
||||
return self.rebaseCommandEnabled(todo.Squash)(commit)
|
||||
}
|
||||
|
||||
func (self *LocalCommitsController) reword(commit *models.Commit) error {
|
||||
@ -528,36 +551,38 @@ func (self *LocalCommitsController) handleMidRebaseCommand(action todo.TodoComma
|
||||
})
|
||||
}
|
||||
|
||||
func (self *LocalCommitsController) rebaseCommandEnabled(action todo.TodoCommand, commit *models.Commit) *types.DisabledReason {
|
||||
if commit.Action == models.ActionConflict {
|
||||
return &types.DisabledReason{Text: self.c.Tr.ChangingThisActionIsNotAllowed}
|
||||
}
|
||||
func (self *LocalCommitsController) rebaseCommandEnabled(action todo.TodoCommand) func(*models.Commit) *types.DisabledReason {
|
||||
return func(commit *models.Commit) *types.DisabledReason {
|
||||
if commit.Action == models.ActionConflict {
|
||||
return &types.DisabledReason{Text: self.c.Tr.ChangingThisActionIsNotAllowed}
|
||||
}
|
||||
|
||||
if !commit.IsTODO() {
|
||||
if self.c.Model().WorkingTreeStateAtLastCommitRefresh != enums.REBASE_MODE_NONE {
|
||||
// If we are in a rebase, the only action that is allowed for
|
||||
// non-todo commits is rewording the current head commit
|
||||
if !(action == todo.Reword && self.isHeadCommit()) {
|
||||
return &types.DisabledReason{Text: self.c.Tr.AlreadyRebasing}
|
||||
if !commit.IsTODO() {
|
||||
if self.c.Model().WorkingTreeStateAtLastCommitRefresh != enums.REBASE_MODE_NONE {
|
||||
// If we are in a rebase, the only action that is allowed for
|
||||
// non-todo commits is rewording the current head commit
|
||||
if !(action == todo.Reword && self.isHeadCommit()) {
|
||||
return &types.DisabledReason{Text: self.c.Tr.AlreadyRebasing}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// for now we do not support setting 'reword' because it requires an editor
|
||||
// and that means we either unconditionally wait around for the subprocess to ask for
|
||||
// our input or we set a lazygit client as the EDITOR env variable and have it
|
||||
// request us to edit the commit message when prompted.
|
||||
if action == todo.Reword {
|
||||
return &types.DisabledReason{Text: self.c.Tr.RewordNotSupported}
|
||||
}
|
||||
|
||||
if allowed := isChangeOfRebaseTodoAllowed(action); !allowed {
|
||||
return &types.DisabledReason{Text: self.c.Tr.ChangingThisActionIsNotAllowed}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// for now we do not support setting 'reword' because it requires an editor
|
||||
// and that means we either unconditionally wait around for the subprocess to ask for
|
||||
// our input or we set a lazygit client as the EDITOR env variable and have it
|
||||
// request us to edit the commit message when prompted.
|
||||
if action == todo.Reword {
|
||||
return &types.DisabledReason{Text: self.c.Tr.RewordNotSupported}
|
||||
}
|
||||
|
||||
if allowed := isChangeOfRebaseTodoAllowed(action); !allowed {
|
||||
return &types.DisabledReason{Text: self.c.Tr.ChangingThisActionIsNotAllowed}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *LocalCommitsController) moveDown(commit *models.Commit) error {
|
||||
@ -687,7 +712,7 @@ func (self *LocalCommitsController) amendTo(commit *models.Commit) error {
|
||||
})
|
||||
}
|
||||
|
||||
func (self *LocalCommitsController) getDisabledReasonForAmendTo(commit *models.Commit) *types.DisabledReason {
|
||||
func (self *LocalCommitsController) canAmend(commit *models.Commit) *types.DisabledReason {
|
||||
if !self.isHeadCommit() && self.c.Model().WorkingTreeStateAtLastCommitRefresh != enums.REBASE_MODE_NONE {
|
||||
return &types.DisabledReason{Text: self.c.Tr.AlreadyRebasing}
|
||||
}
|
||||
@ -870,14 +895,6 @@ func (self *LocalCommitsController) squashAllAboveFixupCommits(commit *models.Co
|
||||
})
|
||||
}
|
||||
|
||||
func (self *LocalCommitsController) getDisabledReasonForSquashAllAboveFixupCommits(commit *models.Commit) *types.DisabledReason {
|
||||
if self.c.Model().WorkingTreeStateAtLastCommitRefresh != enums.REBASE_MODE_NONE {
|
||||
return &types.DisabledReason{Text: self.c.Tr.AlreadyRebasing}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// For getting disabled reason
|
||||
func (self *LocalCommitsController) notMidRebase() *types.DisabledReason {
|
||||
if self.c.Model().WorkingTreeStateAtLastCommitRefresh != enums.REBASE_MODE_NONE {
|
||||
@ -1016,39 +1033,6 @@ func (self *LocalCommitsController) handleOpenLogMenu() error {
|
||||
})
|
||||
}
|
||||
|
||||
func (self *LocalCommitsController) checkSelected(callback func(*models.Commit) error) func() error {
|
||||
return func() error {
|
||||
commit := self.context().GetSelected()
|
||||
if commit == nil {
|
||||
// The enabled callback should have checked for this
|
||||
panic("no commit selected")
|
||||
}
|
||||
|
||||
return callback(commit)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *LocalCommitsController) callGetDisabledReasonFuncWithSelectedCommit(callback func(*models.Commit) *types.DisabledReason) func() *types.DisabledReason {
|
||||
return func() *types.DisabledReason {
|
||||
commit := self.context().GetSelected()
|
||||
if commit == nil {
|
||||
return &types.DisabledReason{Text: self.c.Tr.NoCommitSelected}
|
||||
}
|
||||
|
||||
return callback(commit)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *LocalCommitsController) disabledIfNoSelectedCommit() func() *types.DisabledReason {
|
||||
return self.callGetDisabledReasonFuncWithSelectedCommit(func(*models.Commit) *types.DisabledReason { return nil })
|
||||
}
|
||||
|
||||
func (self *LocalCommitsController) getDisabledReasonForRebaseCommandWithSelectedCommit(action todo.TodoCommand) func() *types.DisabledReason {
|
||||
return self.callGetDisabledReasonFuncWithSelectedCommit(func(commit *models.Commit) *types.DisabledReason {
|
||||
return self.rebaseCommandEnabled(action, commit)
|
||||
})
|
||||
}
|
||||
|
||||
func (self *LocalCommitsController) GetOnFocus() func(types.OnFocusOpts) error {
|
||||
return func(types.OnFocusOpts) error {
|
||||
context := self.context()
|
||||
@ -1065,10 +1049,6 @@ func (self *LocalCommitsController) GetOnFocus() func(types.OnFocusOpts) error {
|
||||
}
|
||||
}
|
||||
|
||||
func (self *LocalCommitsController) Context() types.Context {
|
||||
return self.context()
|
||||
}
|
||||
|
||||
func (self *LocalCommitsController) context() *context.LocalCommitsContext {
|
||||
return self.c.Contexts().LocalCommits
|
||||
}
|
||||
@ -1077,7 +1057,7 @@ func (self *LocalCommitsController) paste() error {
|
||||
return self.c.Helpers().CherryPick.Paste()
|
||||
}
|
||||
|
||||
func (self *LocalCommitsController) getDisabledReasonForPaste() *types.DisabledReason {
|
||||
func (self *LocalCommitsController) canPaste() *types.DisabledReason {
|
||||
if !self.c.Helpers().CherryPick.CanPaste() {
|
||||
return &types.DisabledReason{Text: self.c.Tr.NoCopiedCommits}
|
||||
}
|
||||
@ -1099,19 +1079,6 @@ func (self *LocalCommitsController) isHeadCommit() bool {
|
||||
return models.IsHeadCommit(self.c.Model().Commits, self.context().GetSelectedLineIdx())
|
||||
}
|
||||
|
||||
// Convenience function for composing multiple disabled reason functions
|
||||
func (self *LocalCommitsController) require(callbacks ...func() *types.DisabledReason) func() *types.DisabledReason {
|
||||
return func() *types.DisabledReason {
|
||||
for _, callback := range callbacks {
|
||||
if disabledReason := callback(); disabledReason != nil {
|
||||
return disabledReason
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func isChangeOfRebaseTodoAllowed(action todo.TodoCommand) bool {
|
||||
allowedActions := []todo.TodoCommand{
|
||||
todo.Pick,
|
||||
|
@ -7,17 +7,23 @@ import (
|
||||
|
||||
type MenuController struct {
|
||||
baseController
|
||||
*ListControllerTrait[*types.MenuItem]
|
||||
c *ControllerCommon
|
||||
}
|
||||
|
||||
var _ types.IController = &MenuController{}
|
||||
|
||||
func NewMenuController(
|
||||
common *ControllerCommon,
|
||||
c *ControllerCommon,
|
||||
) *MenuController {
|
||||
return &MenuController{
|
||||
baseController: baseController{},
|
||||
c: common,
|
||||
ListControllerTrait: NewListControllerTrait[*types.MenuItem](
|
||||
c,
|
||||
c.Contexts().Menu,
|
||||
c.Contexts().Menu.GetSelected,
|
||||
),
|
||||
c: c,
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,14 +32,16 @@ func NewMenuController(
|
||||
func (self *MenuController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
||||
bindings := []*types.Binding{
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.Select),
|
||||
Handler: self.press,
|
||||
Key: opts.GetKey(opts.Config.Universal.Select),
|
||||
Handler: self.withItem(self.press),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.Confirm),
|
||||
Handler: self.press,
|
||||
Description: self.c.Tr.Execute,
|
||||
Display: true,
|
||||
Key: opts.GetKey(opts.Config.Universal.Confirm),
|
||||
Handler: self.withItem(self.press),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.Execute,
|
||||
Display: true,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.Return),
|
||||
@ -47,7 +55,7 @@ func (self *MenuController) GetKeybindings(opts types.KeybindingsOpts) []*types.
|
||||
}
|
||||
|
||||
func (self *MenuController) GetOnClick() func() error {
|
||||
return self.press
|
||||
return self.withItemGraceful(self.press)
|
||||
}
|
||||
|
||||
func (self *MenuController) GetOnFocus() func(types.OnFocusOpts) error {
|
||||
@ -60,8 +68,8 @@ func (self *MenuController) GetOnFocus() func(types.OnFocusOpts) error {
|
||||
}
|
||||
}
|
||||
|
||||
func (self *MenuController) press() error {
|
||||
return self.context().OnMenuPress(self.context().GetSelected())
|
||||
func (self *MenuController) press(selectedItem *types.MenuItem) error {
|
||||
return self.context().OnMenuPress(selectedItem)
|
||||
}
|
||||
|
||||
func (self *MenuController) close() error {
|
||||
@ -73,10 +81,6 @@ func (self *MenuController) close() error {
|
||||
return self.c.PopContext()
|
||||
}
|
||||
|
||||
func (self *MenuController) Context() types.Context {
|
||||
return self.context()
|
||||
}
|
||||
|
||||
func (self *MenuController) context() *context.MenuContext {
|
||||
return self.c.Contexts().Menu
|
||||
}
|
||||
|
@ -17,11 +17,11 @@ type MergeConflictsController struct {
|
||||
var _ types.IController = &MergeConflictsController{}
|
||||
|
||||
func NewMergeConflictsController(
|
||||
common *ControllerCommon,
|
||||
c *ControllerCommon,
|
||||
) *MergeConflictsController {
|
||||
return &MergeConflictsController{
|
||||
baseController: baseController{},
|
||||
c: common,
|
||||
c: c,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,11 +14,11 @@ type PatchBuildingController struct {
|
||||
var _ types.IController = &PatchBuildingController{}
|
||||
|
||||
func NewPatchBuildingController(
|
||||
common *ControllerCommon,
|
||||
c *ControllerCommon,
|
||||
) *PatchBuildingController {
|
||||
return &PatchBuildingController{
|
||||
baseController: baseController{},
|
||||
c: common,
|
||||
c: c,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,23 +1,30 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
)
|
||||
|
||||
type ReflogCommitsController struct {
|
||||
baseController
|
||||
*ListControllerTrait[*models.Commit]
|
||||
c *ControllerCommon
|
||||
}
|
||||
|
||||
var _ types.IController = &ReflogCommitsController{}
|
||||
|
||||
func NewReflogCommitsController(
|
||||
common *ControllerCommon,
|
||||
c *ControllerCommon,
|
||||
) *ReflogCommitsController {
|
||||
return &ReflogCommitsController{
|
||||
baseController: baseController{},
|
||||
c: common,
|
||||
ListControllerTrait: NewListControllerTrait[*models.Commit](
|
||||
c,
|
||||
c.Contexts().ReflogCommits,
|
||||
c.Contexts().ReflogCommits.GetSelected,
|
||||
),
|
||||
c: c,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,17 +11,23 @@ import (
|
||||
|
||||
type RemoteBranchesController struct {
|
||||
baseController
|
||||
*ListControllerTrait[*models.RemoteBranch]
|
||||
c *ControllerCommon
|
||||
}
|
||||
|
||||
var _ types.IController = &RemoteBranchesController{}
|
||||
|
||||
func NewRemoteBranchesController(
|
||||
common *ControllerCommon,
|
||||
c *ControllerCommon,
|
||||
) *RemoteBranchesController {
|
||||
return &RemoteBranchesController{
|
||||
baseController: baseController{},
|
||||
c: common,
|
||||
ListControllerTrait: NewListControllerTrait[*models.RemoteBranch](
|
||||
c,
|
||||
c.Contexts().RemoteBranches,
|
||||
c.Contexts().RemoteBranches.GetSelected,
|
||||
),
|
||||
c: c,
|
||||
}
|
||||
}
|
||||
|
||||
@ -30,33 +36,39 @@ func (self *RemoteBranchesController) GetKeybindings(opts types.KeybindingsOpts)
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.Select),
|
||||
// gonna use the exact same handler as the 'n' keybinding because everybody wants this to happen when they checkout a remote branch
|
||||
Handler: self.checkSelected(self.newLocalBranch),
|
||||
Description: self.c.Tr.Checkout,
|
||||
Handler: self.withItem(self.newLocalBranch),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.Checkout,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.New),
|
||||
Handler: self.checkSelected(self.newLocalBranch),
|
||||
Description: self.c.Tr.NewBranch,
|
||||
Key: opts.GetKey(opts.Config.Universal.New),
|
||||
Handler: self.withItem(self.newLocalBranch),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.NewBranch,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Branches.MergeIntoCurrentBranch),
|
||||
Handler: opts.Guards.OutsideFilterMode(self.checkSelected(self.merge)),
|
||||
Description: self.c.Tr.MergeIntoCurrentBranch,
|
||||
Key: opts.GetKey(opts.Config.Branches.MergeIntoCurrentBranch),
|
||||
Handler: opts.Guards.OutsideFilterMode(self.withItem(self.merge)),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.MergeIntoCurrentBranch,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Branches.RebaseBranch),
|
||||
Handler: opts.Guards.OutsideFilterMode(self.checkSelected(self.rebase)),
|
||||
Description: self.c.Tr.RebaseBranch,
|
||||
Key: opts.GetKey(opts.Config.Branches.RebaseBranch),
|
||||
Handler: opts.Guards.OutsideFilterMode(self.withItem(self.rebase)),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.RebaseBranch,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.Remove),
|
||||
Handler: self.checkSelected(self.delete),
|
||||
Description: self.c.Tr.DeleteRemoteTag,
|
||||
Key: opts.GetKey(opts.Config.Universal.Remove),
|
||||
Handler: self.withItem(self.delete),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.DeleteRemoteTag,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Branches.SetUpstream),
|
||||
Handler: self.checkSelected(self.setAsUpstream),
|
||||
Description: self.c.Tr.SetAsUpstream,
|
||||
Key: opts.GetKey(opts.Config.Branches.SetUpstream),
|
||||
Handler: self.withItem(self.setAsUpstream),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.SetAsUpstream,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Branches.SortOrder),
|
||||
@ -65,10 +77,11 @@ func (self *RemoteBranchesController) GetKeybindings(opts types.KeybindingsOpts)
|
||||
OpensMenu: true,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Commits.ViewResetOptions),
|
||||
Handler: self.checkSelected(self.createResetMenu),
|
||||
Description: self.c.Tr.ViewResetOptions,
|
||||
OpensMenu: true,
|
||||
Key: opts.GetKey(opts.Config.Commits.ViewResetOptions),
|
||||
Handler: self.withItem(self.createResetMenu),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.ViewResetOptions,
|
||||
OpensMenu: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -96,25 +109,10 @@ func (self *RemoteBranchesController) GetOnRenderToMain() func() error {
|
||||
}
|
||||
}
|
||||
|
||||
func (self *RemoteBranchesController) Context() types.Context {
|
||||
return self.context()
|
||||
}
|
||||
|
||||
func (self *RemoteBranchesController) context() *context.RemoteBranchesContext {
|
||||
return self.c.Contexts().RemoteBranches
|
||||
}
|
||||
|
||||
func (self *RemoteBranchesController) checkSelected(callback func(*models.RemoteBranch) error) func() error {
|
||||
return func() error {
|
||||
selectedItem := self.context().GetSelected()
|
||||
if selectedItem == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return callback(selectedItem)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *RemoteBranchesController) delete(selectedBranch *models.RemoteBranch) error {
|
||||
return self.c.Helpers().BranchesHelper.ConfirmDeleteRemote(selectedBranch.RemoteName, selectedBranch.Name)
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import (
|
||||
|
||||
type RemotesController struct {
|
||||
baseController
|
||||
*ListControllerTrait[*models.Remote]
|
||||
c *ControllerCommon
|
||||
|
||||
setRemoteBranches func([]*models.RemoteBranch)
|
||||
@ -22,12 +23,17 @@ type RemotesController struct {
|
||||
var _ types.IController = &RemotesController{}
|
||||
|
||||
func NewRemotesController(
|
||||
common *ControllerCommon,
|
||||
c *ControllerCommon,
|
||||
setRemoteBranches func([]*models.RemoteBranch),
|
||||
) *RemotesController {
|
||||
return &RemotesController{
|
||||
baseController: baseController{},
|
||||
c: common,
|
||||
baseController: baseController{},
|
||||
ListControllerTrait: NewListControllerTrait[*models.Remote](
|
||||
c,
|
||||
c.Contexts().Remotes,
|
||||
c.Contexts().Remotes.GetSelected,
|
||||
),
|
||||
c: c,
|
||||
setRemoteBranches: setRemoteBranches,
|
||||
}
|
||||
}
|
||||
@ -35,13 +41,15 @@ func NewRemotesController(
|
||||
func (self *RemotesController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
||||
bindings := []*types.Binding{
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.GoInto),
|
||||
Handler: self.checkSelected(self.enter),
|
||||
Key: opts.GetKey(opts.Config.Universal.GoInto),
|
||||
Handler: self.withItem(self.enter),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Branches.FetchRemote),
|
||||
Handler: self.checkSelected(self.fetch),
|
||||
Description: self.c.Tr.FetchRemote,
|
||||
Key: opts.GetKey(opts.Config.Branches.FetchRemote),
|
||||
Handler: self.withItem(self.fetch),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.FetchRemote,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.New),
|
||||
@ -49,24 +57,22 @@ func (self *RemotesController) GetKeybindings(opts types.KeybindingsOpts) []*typ
|
||||
Description: self.c.Tr.AddNewRemote,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.Remove),
|
||||
Handler: self.checkSelected(self.remove),
|
||||
Description: self.c.Tr.RemoveRemote,
|
||||
Key: opts.GetKey(opts.Config.Universal.Remove),
|
||||
Handler: self.withItem(self.remove),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.RemoveRemote,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.Edit),
|
||||
Handler: self.checkSelected(self.edit),
|
||||
Description: self.c.Tr.EditRemote,
|
||||
Key: opts.GetKey(opts.Config.Universal.Edit),
|
||||
Handler: self.withItem(self.edit),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.EditRemote,
|
||||
},
|
||||
}
|
||||
|
||||
return bindings
|
||||
}
|
||||
|
||||
func (self *RemotesController) Context() types.Context {
|
||||
return self.context()
|
||||
}
|
||||
|
||||
func (self *RemotesController) context() *context.RemotesContext {
|
||||
return self.c.Contexts().Remotes
|
||||
}
|
||||
@ -94,7 +100,7 @@ func (self *RemotesController) GetOnRenderToMain() func() error {
|
||||
}
|
||||
|
||||
func (self *RemotesController) GetOnClick() func() error {
|
||||
return self.checkSelected(self.enter)
|
||||
return self.withItemGraceful(self.enter)
|
||||
}
|
||||
|
||||
func (self *RemotesController) enter(remote *models.Remote) error {
|
||||
@ -208,14 +214,3 @@ func (self *RemotesController) fetch(remote *models.Remote) error {
|
||||
return self.c.Refresh(types.RefreshOptions{Scope: []types.RefreshableView{types.BRANCHES, types.REMOTES}})
|
||||
})
|
||||
}
|
||||
|
||||
func (self *RemotesController) checkSelected(callback func(*models.Remote) error) func() error {
|
||||
return func() error {
|
||||
file := self.context().GetSelected()
|
||||
if file == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return callback(file)
|
||||
}
|
||||
}
|
||||
|
@ -13,11 +13,11 @@ type SearchPromptController struct {
|
||||
var _ types.IController = &SearchPromptController{}
|
||||
|
||||
func NewSearchPromptController(
|
||||
common *ControllerCommon,
|
||||
c *ControllerCommon,
|
||||
) *SearchPromptController {
|
||||
return &SearchPromptController{
|
||||
baseController: baseController{},
|
||||
c: common,
|
||||
c: c,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,8 +9,8 @@ type SideWindowControllerFactory struct {
|
||||
c *ControllerCommon
|
||||
}
|
||||
|
||||
func NewSideWindowControllerFactory(common *ControllerCommon) *SideWindowControllerFactory {
|
||||
return &SideWindowControllerFactory{c: common}
|
||||
func NewSideWindowControllerFactory(c *ControllerCommon) *SideWindowControllerFactory {
|
||||
return &SideWindowControllerFactory{c: c}
|
||||
}
|
||||
|
||||
func (self *SideWindowControllerFactory) Create(context types.Context) types.IController {
|
||||
@ -24,12 +24,12 @@ type SideWindowController struct {
|
||||
}
|
||||
|
||||
func NewSideWindowController(
|
||||
common *ControllerCommon,
|
||||
c *ControllerCommon,
|
||||
context types.Context,
|
||||
) *SideWindowController {
|
||||
return &SideWindowController{
|
||||
baseController: baseController{},
|
||||
c: common,
|
||||
c: c,
|
||||
context: context,
|
||||
}
|
||||
}
|
||||
|
@ -13,11 +13,11 @@ type SnakeController struct {
|
||||
var _ types.IController = &SnakeController{}
|
||||
|
||||
func NewSnakeController(
|
||||
common *ControllerCommon,
|
||||
c *ControllerCommon,
|
||||
) *SnakeController {
|
||||
return &SnakeController{
|
||||
baseController: baseController{},
|
||||
c: common,
|
||||
c: c,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -23,14 +23,14 @@ type StagingController struct {
|
||||
var _ types.IController = &StagingController{}
|
||||
|
||||
func NewStagingController(
|
||||
common *ControllerCommon,
|
||||
c *ControllerCommon,
|
||||
context types.IPatchExplorerContext,
|
||||
otherContext types.IPatchExplorerContext,
|
||||
staged bool,
|
||||
) *StagingController {
|
||||
return &StagingController{
|
||||
baseController: baseController{},
|
||||
c: common,
|
||||
c: c,
|
||||
context: context,
|
||||
otherContext: otherContext,
|
||||
staged: staged,
|
||||
|
@ -9,46 +9,57 @@ import (
|
||||
|
||||
type StashController struct {
|
||||
baseController
|
||||
*ListControllerTrait[*models.StashEntry]
|
||||
c *ControllerCommon
|
||||
}
|
||||
|
||||
var _ types.IController = &StashController{}
|
||||
|
||||
func NewStashController(
|
||||
common *ControllerCommon,
|
||||
c *ControllerCommon,
|
||||
) *StashController {
|
||||
return &StashController{
|
||||
baseController: baseController{},
|
||||
c: common,
|
||||
ListControllerTrait: NewListControllerTrait[*models.StashEntry](
|
||||
c,
|
||||
c.Contexts().Stash,
|
||||
c.Contexts().Stash.GetSelected,
|
||||
),
|
||||
c: c,
|
||||
}
|
||||
}
|
||||
|
||||
func (self *StashController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
||||
bindings := []*types.Binding{
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.Select),
|
||||
Handler: self.checkSelected(self.handleStashApply),
|
||||
Description: self.c.Tr.Apply,
|
||||
Key: opts.GetKey(opts.Config.Universal.Select),
|
||||
Handler: self.withItem(self.handleStashApply),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.Apply,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Stash.PopStash),
|
||||
Handler: self.checkSelected(self.handleStashPop),
|
||||
Description: self.c.Tr.Pop,
|
||||
Key: opts.GetKey(opts.Config.Stash.PopStash),
|
||||
Handler: self.withItem(self.handleStashPop),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.Pop,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.Remove),
|
||||
Handler: self.checkSelected(self.handleStashDrop),
|
||||
Description: self.c.Tr.Drop,
|
||||
Key: opts.GetKey(opts.Config.Universal.Remove),
|
||||
Handler: self.withItem(self.handleStashDrop),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.Drop,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.New),
|
||||
Handler: self.checkSelected(self.handleNewBranchOffStashEntry),
|
||||
Description: self.c.Tr.NewBranch,
|
||||
Key: opts.GetKey(opts.Config.Universal.New),
|
||||
Handler: self.withItem(self.handleNewBranchOffStashEntry),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.NewBranch,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Stash.RenameStash),
|
||||
Handler: self.checkSelected(self.handleRenameStashEntry),
|
||||
Description: self.c.Tr.RenameStash,
|
||||
Key: opts.GetKey(opts.Config.Stash.RenameStash),
|
||||
Handler: self.withItem(self.handleRenameStashEntry),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.RenameStash,
|
||||
},
|
||||
}
|
||||
|
||||
@ -80,21 +91,6 @@ func (self *StashController) GetOnRenderToMain() func() error {
|
||||
}
|
||||
}
|
||||
|
||||
func (self *StashController) checkSelected(callback func(*models.StashEntry) error) func() error {
|
||||
return func() error {
|
||||
item := self.context().GetSelected()
|
||||
if item == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return callback(item)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *StashController) Context() types.Context {
|
||||
return self.context()
|
||||
}
|
||||
|
||||
func (self *StashController) context() *context.StashContext {
|
||||
return self.c.Contexts().Stash
|
||||
}
|
||||
|
@ -22,11 +22,11 @@ type StatusController struct {
|
||||
var _ types.IController = &StatusController{}
|
||||
|
||||
func NewStatusController(
|
||||
common *ControllerCommon,
|
||||
c *ControllerCommon,
|
||||
) *StatusController {
|
||||
return &StatusController{
|
||||
baseController: baseController{},
|
||||
c: common,
|
||||
c: c,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,23 +2,30 @@ package controllers
|
||||
|
||||
import (
|
||||
"github.com/jesseduffield/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/commands/models"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/context"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
)
|
||||
|
||||
type SubCommitsController struct {
|
||||
baseController
|
||||
*ListControllerTrait[*models.Commit]
|
||||
c *ControllerCommon
|
||||
}
|
||||
|
||||
var _ types.IController = &SubCommitsController{}
|
||||
|
||||
func NewSubCommitsController(
|
||||
common *ControllerCommon,
|
||||
c *ControllerCommon,
|
||||
) *SubCommitsController {
|
||||
return &SubCommitsController{
|
||||
baseController: baseController{},
|
||||
c: common,
|
||||
ListControllerTrait: NewListControllerTrait[*models.Commit](
|
||||
c,
|
||||
c.Contexts().SubCommits,
|
||||
c.Contexts().SubCommits.GetSelected,
|
||||
),
|
||||
c: c,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,41 +14,51 @@ import (
|
||||
|
||||
type SubmodulesController struct {
|
||||
baseController
|
||||
*ListControllerTrait[*models.SubmoduleConfig]
|
||||
c *ControllerCommon
|
||||
}
|
||||
|
||||
var _ types.IController = &SubmodulesController{}
|
||||
|
||||
func NewSubmodulesController(
|
||||
controllerCommon *ControllerCommon,
|
||||
c *ControllerCommon,
|
||||
) *SubmodulesController {
|
||||
return &SubmodulesController{
|
||||
baseController: baseController{},
|
||||
c: controllerCommon,
|
||||
ListControllerTrait: NewListControllerTrait[*models.SubmoduleConfig](
|
||||
c,
|
||||
c.Contexts().Submodules,
|
||||
c.Contexts().Submodules.GetSelected,
|
||||
),
|
||||
c: c,
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SubmodulesController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
||||
return []*types.Binding{
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.GoInto),
|
||||
Handler: self.checkSelected(self.enter),
|
||||
Description: self.c.Tr.EnterSubmodule,
|
||||
Key: opts.GetKey(opts.Config.Universal.GoInto),
|
||||
Handler: self.withItem(self.enter),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.EnterSubmodule,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.Select),
|
||||
Handler: self.checkSelected(self.enter),
|
||||
Description: self.c.Tr.EnterSubmodule,
|
||||
Key: opts.GetKey(opts.Config.Universal.Select),
|
||||
Handler: self.withItem(self.enter),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.EnterSubmodule,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.Remove),
|
||||
Handler: self.checkSelected(self.remove),
|
||||
Description: self.c.Tr.RemoveSubmodule,
|
||||
Key: opts.GetKey(opts.Config.Universal.Remove),
|
||||
Handler: self.withItem(self.remove),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.RemoveSubmodule,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Submodules.Update),
|
||||
Handler: self.checkSelected(self.update),
|
||||
Description: self.c.Tr.SubmoduleUpdate,
|
||||
Key: opts.GetKey(opts.Config.Submodules.Update),
|
||||
Handler: self.withItem(self.update),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.SubmoduleUpdate,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.New),
|
||||
@ -56,14 +66,16 @@ func (self *SubmodulesController) GetKeybindings(opts types.KeybindingsOpts) []*
|
||||
Description: self.c.Tr.AddSubmodule,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.Edit),
|
||||
Handler: self.checkSelected(self.editURL),
|
||||
Description: self.c.Tr.EditSubmoduleUrl,
|
||||
Key: opts.GetKey(opts.Config.Universal.Edit),
|
||||
Handler: self.withItem(self.editURL),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.EditSubmoduleUrl,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Submodules.Init),
|
||||
Handler: self.checkSelected(self.init),
|
||||
Description: self.c.Tr.InitSubmodule,
|
||||
Key: opts.GetKey(opts.Config.Submodules.Init),
|
||||
Handler: self.withItem(self.init),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.InitSubmodule,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Submodules.BulkMenu),
|
||||
@ -80,7 +92,7 @@ func (self *SubmodulesController) GetKeybindings(opts types.KeybindingsOpts) []*
|
||||
}
|
||||
|
||||
func (self *SubmodulesController) GetOnClick() func() error {
|
||||
return self.checkSelected(self.enter)
|
||||
return self.withItemGraceful(self.enter)
|
||||
}
|
||||
|
||||
func (self *SubmodulesController) GetOnRenderToMain() func() error {
|
||||
@ -265,21 +277,6 @@ func (self *SubmodulesController) easterEgg() error {
|
||||
return self.c.PushContext(self.c.Contexts().Snake)
|
||||
}
|
||||
|
||||
func (self *SubmodulesController) checkSelected(callback func(*models.SubmoduleConfig) error) func() error {
|
||||
return func() error {
|
||||
submodule := self.context().GetSelected()
|
||||
if submodule == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return callback(submodule)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SubmodulesController) Context() types.Context {
|
||||
return self.context()
|
||||
}
|
||||
|
||||
func (self *SubmodulesController) context() *context.SubmodulesContext {
|
||||
return self.c.Contexts().Submodules
|
||||
}
|
||||
|
@ -7,25 +7,32 @@ import (
|
||||
|
||||
type SuggestionsController struct {
|
||||
baseController
|
||||
*ListControllerTrait[*types.Suggestion]
|
||||
c *ControllerCommon
|
||||
}
|
||||
|
||||
var _ types.IController = &SuggestionsController{}
|
||||
|
||||
func NewSuggestionsController(
|
||||
common *ControllerCommon,
|
||||
c *ControllerCommon,
|
||||
) *SuggestionsController {
|
||||
return &SuggestionsController{
|
||||
baseController: baseController{},
|
||||
c: common,
|
||||
ListControllerTrait: NewListControllerTrait[*types.Suggestion](
|
||||
c,
|
||||
c.Contexts().Suggestions,
|
||||
c.Contexts().Suggestions.GetSelected,
|
||||
),
|
||||
c: c,
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SuggestionsController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
||||
bindings := []*types.Binding{
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.Confirm),
|
||||
Handler: func() error { return self.context().State.OnConfirm() },
|
||||
Key: opts.GetKey(opts.Config.Universal.Confirm),
|
||||
Handler: func() error { return self.context().State.OnConfirm() },
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.Return),
|
||||
@ -47,10 +54,6 @@ func (self *SuggestionsController) GetOnFocusLost() func(types.OnFocusLostOpts)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SuggestionsController) Context() types.Context {
|
||||
return self.context()
|
||||
}
|
||||
|
||||
func (self *SuggestionsController) context() *context.SuggestionsContext {
|
||||
return self.c.Contexts().Suggestions
|
||||
}
|
||||
|
@ -10,13 +10,16 @@ import (
|
||||
var _ types.IController = &SwitchToDiffFilesController{}
|
||||
|
||||
type CanSwitchToDiffFiles interface {
|
||||
types.Context
|
||||
types.IListContext
|
||||
CanRebase() bool
|
||||
GetSelectedRef() types.Ref
|
||||
}
|
||||
|
||||
// Not using our ListControllerTrait because our 'selected' item is not a list item
|
||||
// but an attribute on it i.e. the ref of an item.
|
||||
type SwitchToDiffFilesController struct {
|
||||
baseController
|
||||
*ListControllerTrait[types.Ref]
|
||||
c *ControllerCommon
|
||||
context CanSwitchToDiffFiles
|
||||
diffFilesContext *context.CommitFilesContext
|
||||
@ -28,7 +31,12 @@ func NewSwitchToDiffFilesController(
|
||||
diffFilesContext *context.CommitFilesContext,
|
||||
) *SwitchToDiffFilesController {
|
||||
return &SwitchToDiffFilesController{
|
||||
baseController: baseController{},
|
||||
baseController: baseController{},
|
||||
ListControllerTrait: NewListControllerTrait[types.Ref](
|
||||
c,
|
||||
context,
|
||||
context.GetSelectedRef,
|
||||
),
|
||||
c: c,
|
||||
context: context,
|
||||
diffFilesContext: diffFilesContext,
|
||||
@ -38,9 +46,10 @@ func NewSwitchToDiffFilesController(
|
||||
func (self *SwitchToDiffFilesController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
||||
bindings := []*types.Binding{
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.GoInto),
|
||||
Handler: self.checkSelected(self.enter),
|
||||
Description: self.c.Tr.ViewItemFiles,
|
||||
Key: opts.GetKey(opts.Config.Universal.GoInto),
|
||||
Handler: self.withItem(self.enter),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.ViewItemFiles,
|
||||
},
|
||||
}
|
||||
|
||||
@ -48,18 +57,7 @@ func (self *SwitchToDiffFilesController) GetKeybindings(opts types.KeybindingsOp
|
||||
}
|
||||
|
||||
func (self *SwitchToDiffFilesController) GetOnClick() func() error {
|
||||
return self.checkSelected(self.enter)
|
||||
}
|
||||
|
||||
func (self *SwitchToDiffFilesController) checkSelected(callback func(types.Ref) error) func() error {
|
||||
return func() error {
|
||||
ref := self.context.GetSelectedRef()
|
||||
if ref == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return callback(ref)
|
||||
}
|
||||
return self.withItemGraceful(self.enter)
|
||||
}
|
||||
|
||||
func (self *SwitchToDiffFilesController) enter(ref types.Ref) error {
|
||||
@ -70,10 +68,6 @@ func (self *SwitchToDiffFilesController) enter(ref types.Ref) error {
|
||||
})
|
||||
}
|
||||
|
||||
func (self *SwitchToDiffFilesController) Context() types.Context {
|
||||
return self.context
|
||||
}
|
||||
|
||||
func (self *SwitchToDiffFilesController) viewFiles(opts SwitchToCommitFilesContextOpts) error {
|
||||
diffFilesContext := self.diffFilesContext
|
||||
|
||||
|
@ -8,34 +8,43 @@ import (
|
||||
var _ types.IController = &SwitchToSubCommitsController{}
|
||||
|
||||
type CanSwitchToSubCommits interface {
|
||||
types.Context
|
||||
types.IListContext
|
||||
GetSelectedRef() types.Ref
|
||||
ShowBranchHeadsInSubCommits() bool
|
||||
}
|
||||
|
||||
// Not using our ListControllerTrait because our 'selected' item is not a list item
|
||||
// but an attribute on it i.e. the ref of an item.
|
||||
type SwitchToSubCommitsController struct {
|
||||
baseController
|
||||
*ListControllerTrait[types.Ref]
|
||||
c *ControllerCommon
|
||||
context CanSwitchToSubCommits
|
||||
}
|
||||
|
||||
func NewSwitchToSubCommitsController(
|
||||
controllerCommon *ControllerCommon,
|
||||
c *ControllerCommon,
|
||||
context CanSwitchToSubCommits,
|
||||
) *SwitchToSubCommitsController {
|
||||
return &SwitchToSubCommitsController{
|
||||
baseController: baseController{},
|
||||
c: controllerCommon,
|
||||
context: context,
|
||||
ListControllerTrait: NewListControllerTrait[types.Ref](
|
||||
c,
|
||||
context,
|
||||
context.GetSelectedRef,
|
||||
),
|
||||
c: c,
|
||||
context: context,
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SwitchToSubCommitsController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
||||
bindings := []*types.Binding{
|
||||
{
|
||||
Handler: self.viewCommits,
|
||||
Key: opts.GetKey(opts.Config.Universal.GoInto),
|
||||
Description: self.c.Tr.ViewCommits,
|
||||
Handler: self.viewCommits,
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Key: opts.GetKey(opts.Config.Universal.GoInto),
|
||||
Description: self.c.Tr.ViewCommits,
|
||||
},
|
||||
}
|
||||
|
||||
@ -59,7 +68,3 @@ func (self *SwitchToSubCommitsController) viewCommits() error {
|
||||
ShowBranchHeads: self.context.ShowBranchHeadsInSubCommits(),
|
||||
})
|
||||
}
|
||||
|
||||
func (self *SwitchToSubCommitsController) Context() types.Context {
|
||||
return self.context
|
||||
}
|
||||
|
@ -10,37 +10,46 @@ import (
|
||||
|
||||
type TagsController struct {
|
||||
baseController
|
||||
*ListControllerTrait[*models.Tag]
|
||||
c *ControllerCommon
|
||||
}
|
||||
|
||||
var _ types.IController = &TagsController{}
|
||||
|
||||
func NewTagsController(
|
||||
common *ControllerCommon,
|
||||
c *ControllerCommon,
|
||||
) *TagsController {
|
||||
return &TagsController{
|
||||
baseController: baseController{},
|
||||
c: common,
|
||||
ListControllerTrait: NewListControllerTrait[*models.Tag](
|
||||
c,
|
||||
c.Contexts().Tags,
|
||||
c.Contexts().Tags.GetSelected,
|
||||
),
|
||||
c: c,
|
||||
}
|
||||
}
|
||||
|
||||
func (self *TagsController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
|
||||
bindings := []*types.Binding{
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.Select),
|
||||
Handler: self.withSelectedTag(self.checkout),
|
||||
Description: self.c.Tr.Checkout,
|
||||
Key: opts.GetKey(opts.Config.Universal.Select),
|
||||
Handler: self.withItem(self.checkout),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.Checkout,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.Remove),
|
||||
Handler: self.withSelectedTag(self.delete),
|
||||
Description: self.c.Tr.ViewDeleteOptions,
|
||||
OpensMenu: true,
|
||||
Key: opts.GetKey(opts.Config.Universal.Remove),
|
||||
Handler: self.withItem(self.delete),
|
||||
Description: self.c.Tr.ViewDeleteOptions,
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
OpensMenu: true,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Branches.PushTag),
|
||||
Handler: self.withSelectedTag(self.push),
|
||||
Description: self.c.Tr.PushTag,
|
||||
Key: opts.GetKey(opts.Config.Branches.PushTag),
|
||||
Handler: self.withItem(self.push),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.PushTag,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.New),
|
||||
@ -48,10 +57,11 @@ func (self *TagsController) GetKeybindings(opts types.KeybindingsOpts) []*types.
|
||||
Description: self.c.Tr.CreateTag,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Commits.ViewResetOptions),
|
||||
Handler: self.withSelectedTag(self.createResetMenu),
|
||||
Description: self.c.Tr.ViewResetOptions,
|
||||
OpensMenu: true,
|
||||
Key: opts.GetKey(opts.Config.Commits.ViewResetOptions),
|
||||
Handler: self.withItem(self.createResetMenu),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.ViewResetOptions,
|
||||
OpensMenu: true,
|
||||
},
|
||||
}
|
||||
|
||||
@ -215,21 +225,6 @@ func (self *TagsController) create() error {
|
||||
})
|
||||
}
|
||||
|
||||
func (self *TagsController) withSelectedTag(f func(tag *models.Tag) error) func() error {
|
||||
return func() error {
|
||||
tag := self.context().GetSelected()
|
||||
if tag == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return f(tag)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *TagsController) Context() types.Context {
|
||||
return self.context()
|
||||
}
|
||||
|
||||
func (self *TagsController) context() *context.TagsContext {
|
||||
return self.c.Contexts().Tags
|
||||
}
|
||||
|
@ -27,11 +27,11 @@ type UndoController struct {
|
||||
var _ types.IController = &UndoController{}
|
||||
|
||||
func NewUndoController(
|
||||
common *ControllerCommon,
|
||||
c *ControllerCommon,
|
||||
) *UndoController {
|
||||
return &UndoController{
|
||||
baseController: baseController{},
|
||||
c: common,
|
||||
c: c,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,15 +14,21 @@ type CanViewWorktreeOptions interface {
|
||||
|
||||
type WorktreeOptionsController struct {
|
||||
baseController
|
||||
*ListControllerTrait[string]
|
||||
c *ControllerCommon
|
||||
context CanViewWorktreeOptions
|
||||
}
|
||||
|
||||
func NewWorktreeOptionsController(controllerCommon *ControllerCommon, context CanViewWorktreeOptions) *WorktreeOptionsController {
|
||||
func NewWorktreeOptionsController(c *ControllerCommon, context CanViewWorktreeOptions) *WorktreeOptionsController {
|
||||
return &WorktreeOptionsController{
|
||||
baseController: baseController{},
|
||||
c: controllerCommon,
|
||||
context: context,
|
||||
ListControllerTrait: NewListControllerTrait[string](
|
||||
c,
|
||||
context,
|
||||
context.GetSelectedItemId,
|
||||
),
|
||||
c: c,
|
||||
context: context,
|
||||
}
|
||||
}
|
||||
|
||||
@ -30,7 +36,7 @@ func (self *WorktreeOptionsController) GetKeybindings(opts types.KeybindingsOpts
|
||||
bindings := []*types.Binding{
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Worktrees.ViewWorktreeOptions),
|
||||
Handler: self.checkSelected(self.viewWorktreeOptions),
|
||||
Handler: self.withItem(self.viewWorktreeOptions),
|
||||
Description: self.c.Tr.ViewWorktreeOptions,
|
||||
OpensMenu: true,
|
||||
},
|
||||
@ -39,21 +45,6 @@ func (self *WorktreeOptionsController) GetKeybindings(opts types.KeybindingsOpts
|
||||
return bindings
|
||||
}
|
||||
|
||||
func (self *WorktreeOptionsController) checkSelected(callback func(string) error) func() error {
|
||||
return func() error {
|
||||
ref := self.context.GetSelectedItemId()
|
||||
if ref == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
return callback(ref)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *WorktreeOptionsController) Context() types.Context {
|
||||
return self.context
|
||||
}
|
||||
|
||||
func (self *WorktreeOptionsController) viewWorktreeOptions(ref string) error {
|
||||
return self.c.Helpers().Worktree.ViewWorktreeOptions(self.context, ref)
|
||||
}
|
||||
|
@ -13,17 +13,23 @@ import (
|
||||
|
||||
type WorktreesController struct {
|
||||
baseController
|
||||
*ListControllerTrait[*models.Worktree]
|
||||
c *ControllerCommon
|
||||
}
|
||||
|
||||
var _ types.IController = &WorktreesController{}
|
||||
|
||||
func NewWorktreesController(
|
||||
common *ControllerCommon,
|
||||
c *ControllerCommon,
|
||||
) *WorktreesController {
|
||||
return &WorktreesController{
|
||||
baseController: baseController{},
|
||||
c: common,
|
||||
ListControllerTrait: NewListControllerTrait[*models.Worktree](
|
||||
c,
|
||||
c.Contexts().Worktrees,
|
||||
c.Contexts().Worktrees.GetSelected,
|
||||
),
|
||||
c: c,
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,24 +41,28 @@ func (self *WorktreesController) GetKeybindings(opts types.KeybindingsOpts) []*t
|
||||
Description: self.c.Tr.CreateWorktree,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.Select),
|
||||
Handler: self.checkSelected(self.enter),
|
||||
Description: self.c.Tr.SwitchToWorktree,
|
||||
Key: opts.GetKey(opts.Config.Universal.Select),
|
||||
Handler: self.withItem(self.enter),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.SwitchToWorktree,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.Confirm),
|
||||
Handler: self.checkSelected(self.enter),
|
||||
Description: self.c.Tr.SwitchToWorktree,
|
||||
Key: opts.GetKey(opts.Config.Universal.Confirm),
|
||||
Handler: self.withItem(self.enter),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.SwitchToWorktree,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.OpenFile),
|
||||
Handler: self.checkSelected(self.open),
|
||||
Description: self.c.Tr.OpenInEditor,
|
||||
Key: opts.GetKey(opts.Config.Universal.OpenFile),
|
||||
Handler: self.withItem(self.open),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.OpenInEditor,
|
||||
},
|
||||
{
|
||||
Key: opts.GetKey(opts.Config.Universal.Remove),
|
||||
Handler: self.checkSelected(self.remove),
|
||||
Description: self.c.Tr.RemoveWorktree,
|
||||
Key: opts.GetKey(opts.Config.Universal.Remove),
|
||||
Handler: self.withItem(self.remove),
|
||||
GetDisabledReason: self.require(self.singleItemSelected()),
|
||||
Description: self.c.Tr.RemoveWorktree,
|
||||
},
|
||||
}
|
||||
|
||||
@ -113,7 +123,7 @@ func (self *WorktreesController) remove(worktree *models.Worktree) error {
|
||||
}
|
||||
|
||||
func (self *WorktreesController) GetOnClick() func() error {
|
||||
return self.checkSelected(self.enter)
|
||||
return self.withItemGraceful(self.enter)
|
||||
}
|
||||
|
||||
func (self *WorktreesController) enter(worktree *models.Worktree) error {
|
||||
@ -124,21 +134,6 @@ func (self *WorktreesController) open(worktree *models.Worktree) error {
|
||||
return self.c.Helpers().Files.OpenDirInEditor(worktree.Path)
|
||||
}
|
||||
|
||||
func (self *WorktreesController) checkSelected(callback func(worktree *models.Worktree) error) func() error {
|
||||
return func() error {
|
||||
worktree := self.context().GetSelected()
|
||||
if worktree == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return callback(worktree)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *WorktreesController) Context() types.Context {
|
||||
return self.context()
|
||||
}
|
||||
|
||||
func (self *WorktreesController) context() *context.WorktreesContext {
|
||||
return self.c.Contexts().Worktrees
|
||||
}
|
||||
|
Reference in New Issue
Block a user