summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Haller <stefan@haller-berlin.de>2023-09-18 10:26:11 +0200
committerGitHub <noreply@github.com>2023-09-18 10:26:11 +0200
commite2a966443bcc4c71d6c83f1bee90288c22c57ddb (patch)
tree059376c3745f60abd7548dca2c65687946c38742
parent679148449a27486196e4d5aa7f1bf27d8853e9fe (diff)
parent0b13c3ca87313a94d5c7972db39b7e64fbea5d67 (diff)
Add a DisabledReason mechanism for menu items and keybindings (#2992)
-rw-r--r--pkg/gui/context/menu_context.go7
-rw-r--r--pkg/gui/controllers/branches_controller.go218
-rw-r--r--pkg/gui/controllers/helpers/cherry_pick_helper.go4
-rw-r--r--pkg/gui/controllers/helpers/confirmation_helper.go13
-rw-r--r--pkg/gui/controllers/helpers/merge_and_rebase_helper.go3
-rw-r--r--pkg/gui/controllers/local_commits_controller.go245
-rw-r--r--pkg/gui/controllers/menu_controller.go2
-rw-r--r--pkg/gui/controllers/options_menu_action.go13
-rw-r--r--pkg/gui/gui_common.go4
-rw-r--r--pkg/gui/keybindings.go16
-rw-r--r--pkg/gui/types/common.go5
-rw-r--r--pkg/gui/types/keybindings.go7
-rw-r--r--pkg/i18n/english.go16
-rw-r--r--pkg/integration/tests/branch/reset_to_upstream.go4
14 files changed, 346 insertions, 211 deletions
diff --git a/pkg/gui/context/menu_context.go b/pkg/gui/context/menu_context.go
index 287ed92ec..f972f2fbb 100644
--- a/pkg/gui/context/menu_context.go
+++ b/pkg/gui/context/menu_context.go
@@ -90,6 +90,9 @@ func (self *MenuViewModel) GetDisplayStrings(_ int, _ int) [][]string {
return lo.Map(menuItems, func(item *types.MenuItem, _ int) []string {
displayStrings := item.LabelColumns
+ if item.DisabledReason != "" {
+ displayStrings[0] = style.FgDefault.SetStrikethrough().Sprint(displayStrings[0])
+ }
if !showKeys {
return displayStrings
@@ -169,6 +172,10 @@ func (self *MenuContext) GetKeybindings(opts types.KeybindingsOpts) []*types.Bin
}
func (self *MenuContext) OnMenuPress(selectedItem *types.MenuItem) error {
+ if selectedItem != nil && selectedItem.DisabledReason != "" {
+ return self.c.ErrorMsg(selectedItem.DisabledReason)
+ }
+
if err := self.c.PopContext(); err != nil {
return err
}
diff --git a/pkg/gui/controllers/branches_controller.go b/pkg/gui/controllers/branches_controller.go
index 1dc1f77e8..3c18b955c 100644
--- a/pkg/gui/controllers/branches_controller.go
+++ b/pkg/gui/controllers/branches_controller.go
@@ -12,6 +12,7 @@ import (
"github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/utils"
+ "github.com/samber/lo"
)
type BranchesController struct {
@@ -75,9 +76,10 @@ func (self *BranchesController) GetKeybindings(opts types.KeybindingsOpts) []*ty
OpensMenu: true,
},
{
- Key: opts.GetKey(opts.Config.Branches.RebaseBranch),
- Handler: opts.Guards.OutsideFilterMode(self.rebase),
- Description: self.c.Tr.RebaseBranch,
+ 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.MergeIntoCurrentBranch),
@@ -140,32 +142,55 @@ func (self *BranchesController) GetOnRenderToMain() func() error {
}
func (self *BranchesController) setUpstream(selectedBranch *models.Branch) error {
- options := []*types.MenuItem{
- {
- LabelColumns: []string{self.c.Tr.ViewDivergenceFromUpstream},
- OnPress: func() error {
- branch := self.context().GetSelected()
- if branch == nil {
- return nil
- }
+ viewDivergenceItem := &types.MenuItem{
+ LabelColumns: []string{self.c.Tr.ViewDivergenceFromUpstream},
+ OnPress: func() error {
+ branch := self.context().GetSelected()
+ if branch == nil {
+ return nil
+ }
- if !branch.RemoteBranchStoredLocally() {
- return self.c.ErrorMsg(self.c.Tr.DivergenceNoUpstream)
- }
- return self.c.Helpers().SubCommits.ViewSubCommits(helpers.ViewSubCommitsOpts{
- Ref: branch,
- TitleRef: fmt.Sprintf("%s <-> %s", branch.RefName(), branch.ShortUpstreamRefName()),
- RefToShowDivergenceFrom: branch.FullUpstreamRefName(),
- Context: self.context(),
- ShowBranchHeads: false,
- })
- },
- Key: 'v',
+ return self.c.Helpers().SubCommits.ViewSubCommits(helpers.ViewSubCommitsOpts{
+ Ref: branch,
+ TitleRef: fmt.Sprintf("%s <-> %s", branch.RefName(), branch.ShortUpstreamRefName()),
+ RefToShowDivergenceFrom: branch.FullUpstreamRefName(),
+ Context: self.context(),
+ ShowBranchHeads: false,
+ })
},
- {
- LabelColumns: []string{self.c.Tr.UnsetUpstream},
- OnPress: func() error {
- if err := self.c.Git().Branch.UnsetUpstream(selectedBranch.Name); err != nil {
+ Key: 'v',
+ }
+
+ unsetUpstreamItem := &types.MenuItem{
+ LabelColumns: []string{self.c.Tr.UnsetUpstream},
+ OnPress: func() error {
+ if err := self.c.Git().Branch.UnsetUpstream(selectedBranch.Name); err != nil {
+ return self.c.Error(err)
+ }
+ if err := self.c.Refresh(types.RefreshOptions{
+ Mode: types.SYNC,
+ Scope: []types.RefreshableView{
+ types.BRANCHES,
+ types.COMMITS,
+ },
+ }); err != nil {
+ return self.c.Error(err)
+ }
+ return nil
+ },
+ Key: 'u',
+ }
+
+ setUpstreamItem := &types.MenuItem{
+ LabelColumns: []string{self.c.Tr.SetUpstream},
+ OnPress: func() error {
+ return self.c.Helpers().Upstream.PromptForUpstreamWithoutInitialContent(selectedBranch, func(upstream string) error {
+ upstreamRemote, upstreamBranch, err := self.c.Helpers().Upstream.ParseUpstream(upstream)
+ if err != nil {
+ return self.c.Error(err)
+ }
+
+ if err := self.c.Git().Branch.SetUpstream(upstreamRemote, upstreamBranch, selectedBranch.Name); err != nil {
return self.c.Error(err)
}
if err := self.c.Refresh(types.RefreshOptions{
@@ -178,75 +203,48 @@ func (self *BranchesController) setUpstream(selectedBranch *models.Branch) error
return self.c.Error(err)
}
return nil
- },
- Key: 'u',
+ })
},
- {
- LabelColumns: []string{self.c.Tr.SetUpstream},
- OnPress: func() error {
- return self.c.Helpers().Upstream.PromptForUpstreamWithoutInitialContent(selectedBranch, func(upstream string) error {
- upstreamRemote, upstreamBranch, err := self.c.Helpers().Upstream.ParseUpstream(upstream)
- if err != nil {
- return self.c.Error(err)
- }
+ Key: 's',
+ }
- if err := self.c.Git().Branch.SetUpstream(upstreamRemote, upstreamBranch, selectedBranch.Name); err != nil {
- return self.c.Error(err)
- }
- if err := self.c.Refresh(types.RefreshOptions{
- Mode: types.SYNC,
- Scope: []types.RefreshableView{
- types.BRANCHES,
- types.COMMITS,
- },
- }); err != nil {
- return self.c.Error(err)
- }
- return nil
- })
- },
- Key: 's',
+ upstream := lo.Ternary(selectedBranch.RemoteBranchStoredLocally(),
+ fmt.Sprintf("%s/%s", selectedBranch.UpstreamRemote, selectedBranch.Name),
+ self.c.Tr.UpstreamGenericName)
+ upstreamResetOptions := utils.ResolvePlaceholderString(
+ self.c.Tr.ViewUpstreamResetOptions,
+ map[string]string{"upstream": upstream},
+ )
+ upstreamResetTooltip := utils.ResolvePlaceholderString(
+ self.c.Tr.ViewUpstreamResetOptionsTooltip,
+ map[string]string{"upstream": upstream},
+ )
+
+ upstreamResetItem := &types.MenuItem{
+ LabelColumns: []string{upstreamResetOptions},
+ OpensMenu: true,
+ OnPress: func() error {
+ err := self.c.Helpers().Refs.CreateGitResetMenu(upstream)
+ if err != nil {
+ return self.c.Error(err)
+ }
+ return nil
},
+ Tooltip: upstreamResetTooltip,
+ Key: 'g',
}
- if selectedBranch.IsTrackingRemote() {
- upstream := fmt.Sprintf("%s/%s", selectedBranch.UpstreamRemote, selectedBranch.Name)
- upstreamResetOptions := utils.ResolvePlaceholderString(
- self.c.Tr.ViewUpstreamResetOptions,
- map[string]string{"upstream": upstream},
- )
- upstreamResetTooltip := utils.ResolvePlaceholderString(
- self.c.Tr.ViewUpstreamResetOptionsTooltip,
- map[string]string{"upstream": upstream},
- )
-
- options = append(options, &types.MenuItem{
- LabelColumns: []string{upstreamResetOptions},
- OpensMenu: true,
- OnPress: func() error {
- if selectedBranch.RemoteBranchNotStoredLocally() {
- return self.c.ErrorMsg(self.c.Tr.UpstreamNotStoredLocallyError)
- }
+ if !selectedBranch.RemoteBranchStoredLocally() {
+ viewDivergenceItem.DisabledReason = self.c.Tr.UpstreamNotSetError
+ unsetUpstreamItem.DisabledReason = self.c.Tr.UpstreamNotSetError
+ upstreamResetItem.DisabledReason = self.c.Tr.UpstreamNotSetError
+ }
- err := self.c.Helpers().Refs.CreateGitResetMenu(upstream)
- if err != nil {
- return self.c.Error(err)
- }
- return nil
- },
- Tooltip: upstreamResetTooltip,
- Key: 'g',
- })
- } else {
- options = append(options, &types.MenuItem{
- LabelColumns: []string{self.c.Tr.ViewUpstreamDisabledResetOptions},
- OpensMenu: true,
- OnPress: func() error {
- return self.c.ErrorMsg(self.c.Tr.UpstreamNotSetError)
- },
- Tooltip: self.c.Tr.UpstreamNotSetError,
- Key: 'g',
- })
+ options := []*types.MenuItem{
+ viewDivergenceItem,
+ unsetUpstreamItem,
+ setUpstreamItem,
+ upstreamResetItem,
}
return self.c.Menu(types.CreateMenuOptions{
@@ -468,7 +466,6 @@ func (self *BranchesController) forceDelete(branch *models.Branch) error {
}
func (self *BranchesController) delete(branch *models.Branch) error {
- menuItems := []*types.MenuItem{}
checkedOutBranch := self.c.Helpers().Refs.GetCheckedOutRef()
localDeleteItem := &types.MenuItem{
@@ -479,25 +476,18 @@ func (self *BranchesController) delete(branch *models.Branch) error {
},
}
if checkedOutBranch.Name == branch.Name {
- localDeleteItem = &types.MenuItem{
- Label: self.c.Tr.DeleteLocalBranch,
- Key: 'c',
- Tooltip: self.c.Tr.CantDeleteCheckOutBranch,
- OnPress: func() error {
- return self.c.ErrorMsg(self.c.Tr.CantDeleteCheckOutBranch)
- },
- }
+ localDeleteItem.DisabledReason = self.c.Tr.CantDeleteCheckOutBranch
}
- menuItems = append(menuItems, localDeleteItem)
- if branch.IsTrackingRemote() && !branch.UpstreamGone {
- menuItems = append(menuItems, &types.MenuItem{
- Label: self.c.Tr.DeleteRemoteBranch,
- Key: 'r',
- OnPress: func() error {
- return self.remoteDelete(branch)
- },
- })
+ remoteDeleteItem := &types.MenuItem{
+ Label: self.c.Tr.DeleteRemoteBranch,
+ Key: 'r',
+ OnPress: func() error {
+ return self.remoteDelete(branch)
+ },
+ }
+ if !branch.IsTrackingRemote() || branch.UpstreamGone {
+ remoteDeleteItem.DisabledReason = self.c.Tr.UpstreamNotSetError
}
menuTitle := utils.ResolvePlaceholderString(
@@ -509,7 +499,7 @@ func (self *BranchesController) delete(branch *models.Branch) error {
return self.c.Menu(types.CreateMenuOptions{
Title: menuTitle,
- Items: menuItems,
+ Items: []*types.MenuItem{localDeleteItem, remoteDeleteItem},
})
}
@@ -523,6 +513,16 @@ func (self *BranchesController) rebase() error {
return self.c.Helpers().MergeAndRebase.RebaseOntoRef(selectedBranchName)
}
+func (self *BranchesController) getDisabledReasonForRebase() string {
+ selectedBranchName := self.context().GetSelected().Name
+ checkedOutBranch := self.c.Helpers().Refs.GetCheckedOutRef().Name
+ if selectedBranchName == checkedOutBranch {
+ return self.c.Tr.CantRebaseOntoSelf
+ }
+
+ return ""
+}
+
func (self *BranchesController) fastForward(branch *models.Branch) error {
if !branch.IsTrackingRemote() {
return self.c.ErrorMsg(self.c.Tr.FwdNoUpstream)
diff --git a/pkg/gui/controllers/helpers/cherry_pick_helper.go b/pkg/gui/controllers/helpers/cherry_pick_helper.go
index 2e8a11f7d..e27e469b6 100644
--- a/pkg/gui/controllers/helpers/cherry_pick_helper.go
+++ b/pkg/gui/controllers/helpers/cherry_pick_helper.go
@@ -85,6 +85,10 @@ func (self *CherryPickHelper) Paste() error {
})
}
+func (self *CherryPickHelper) CanPaste() bool {
+ return self.getData().Active()
+}
+
func (self *CherryPickHelper) Reset() error {
self.getData().ContextKey = ""
self.getData().CherryPickedCommits = nil
diff --git a/pkg/gui/controllers/helpers/confirmation_helper.go b/pkg/gui/controllers/helpers/confirmation_helper.go
index c920df39f..7d4ca1464 100644
--- a/pkg/gui/controllers/helpers/confirmation_helper.go
+++ b/pkg/gui/controllers/helpers/confirmation_helper.go
@@ -333,7 +333,7 @@ func (self *ConfirmationHelper) resizeMenu() {
tooltip := ""
selectedItem := self.c.Contexts().Menu.GetSelected()
if selectedItem != nil {
- tooltip = selectedItem.Tooltip
+ tooltip = self.TooltipForMenuItem(selectedItem)
}
tooltipHeight := getMessageHeight(true, tooltip, panelWidth) + 2 // plus 2 for the frame
_, _ = self.c.GocuiGui().SetView(self.c.Views().Tooltip.Name(), x0, tooltipTop, x1, tooltipTop+tooltipHeight-1, 0)
@@ -382,3 +382,14 @@ func (self *ConfirmationHelper) IsPopupPanel(viewName string) bool {
func (self *ConfirmationHelper) IsPopupPanelFocused() bool {
return self.IsPopupPanel(self.c.CurrentContext().GetViewName())
}
+
+func (self *ConfirmationHelper) TooltipForMenuItem(menuItem *types.MenuItem) string {
+ tooltip := menuItem.Tooltip
+ if menuItem.DisabledReason != "" {
+ if tooltip != "" {
+ tooltip += "\n\n"
+ }
+ tooltip += style.FgRed.Sprintf(self.c.Tr.DisabledMenuItemPrefix) + menuItem.DisabledReason
+ }
+ return tooltip
+}
diff --git a/pkg/gui/controllers/helpers/merge_and_rebase_helper.go b/pkg/gui/controllers/helpers/merge_and_rebase_helper.go
index a88615271..de34f2193 100644
--- a/pkg/gui/controllers/helpers/merge_and_rebase_helper.go
+++ b/pkg/gui/controllers/helpers/merge_and_rebase_helper.go
@@ -220,9 +220,6 @@ func (self *MergeAndRebaseHelper) PromptToContinueRebase() error {
func (self *MergeAndRebaseHelper) RebaseOntoRef(ref string) error {
checkedOutBranch := self.refsHelper.GetCheckedOutRef().Name
- if ref == checkedOutBranch {
- return self.c.ErrorMsg(self.c.Tr.CantRebaseOntoSelf)
- }
menuItems := []*types.MenuItem{
{
Label: self.c.Tr.SimpleRebase,
diff --git a/pkg/gui/controllers/local_commits_controller.go b/pkg/gui/controllers/local_commits_controller.go
index 1bd079f53..2c4794195 100644
--- a/pkg/gui/controllers/local_commits_controller.go
+++ b/pkg/gui/controllers/local_commits_controller.go
@@ -44,70 +44,83 @@ func NewLocalCommitsController(
func (self *LocalCommitsController) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
outsideFilterModeBindings := []*types.Binding{
{
- Key: opts.GetKey(opts.Config.Commits.SquashDown),
- Handler: self.checkSelected(self.squashDown),
- Description: self.c.Tr.SquashDown,
+ 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.MarkCommitAsFixup),
- Handler: self.checkSelected(self.fixup),
- Description: self.c.Tr.FixupCommit,
+ 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.RenameCommit),
- Handler: self.checkSelected(self.reword),
- Description: self.c.Tr.RewordCommit,
+ 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.RenameCommitWithEditor),
- Handler: self.checkSelected(self.rewordEditor),
- Description: self.c.Tr.RenameCommitEditor,
+ 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.Universal.Remove),
- Handler: self.checkSelected(self.drop),
- Description: self.c.Tr.DeleteCommit,
+ 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.Edit),
- Handler: self.checkSelected(self.edit),
- Description: self.c.Tr.EditCommit,
+ Key: opts.GetKey(opts.Config.Universal.Edit),
+ Handler: self.checkSelected(self.edit),
+ GetDisabledReason: self.getDisabledReasonForRebaseCommandWithSelectedCommit(todo.Edit),
+ Description: self.c.Tr.EditCommit,
},
{
- Key: opts.GetKey(opts.Config.Commits.PickCommit),
- Handler: self.checkSelected(self.pick),
- Description: self.c.Tr.PickCommit,
+ 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.CreateFixupCommit),
- Handler: self.checkSelected(self.createFixupCommit),
- Description: self.c.Tr.CreateFixupCommitDescription,
+ Key: opts.GetKey(opts.Config.Commits.CreateFixupCommit),
+ Handler: self.checkSelected(self.createFixupCommit),
+ GetDisabledReason: self.disabledIfNoSelectedCommit(),
+ Description: self.c.Tr.CreateFixupCommitDescription,
},
{
- Key: opts.GetKey(opts.Config.Commits.SquashAboveCommits),
- Handler: self.checkSelected(self.squashAllAboveFixupCommits),
- Description: self.c.Tr.SquashAboveCommits,
+ 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.MoveDownCommit),
- Handler: self.checkSelected(self.moveDown),
- Description: self.c.Tr.MoveDownCommit,
+ Key: opts.GetKey(opts.Config.Commits.MoveDownCommit),
+ Handler: self.checkSelected(self.moveDown),
+ GetDisabledReason: self.disabledIfNoSelectedCommit(),
+ Description: self.c.Tr.MoveDownCommit,
},
{
- Key: opts.GetKey(opts.Config.Commits.MoveUpCommit),
- Handler: self.checkSelected(self.moveUp),
- Description: self.c.Tr.MoveUpCommit,
+ Key: opts.GetKey(opts.Config.Commits.MoveUpCommit),
+ Handler: self.checkSelected(self.moveUp),
+ GetDisabledReason: self.disabledIfNoSelectedCommit(),
+ Description: self.c.Tr.MoveUpCommit,
},
{
- Key: opts.GetKey(opts.Config.Commits.PasteCommits),
- Handler: self.paste,
- Description: self.c.Tr.PasteCommits,
+ Key: opts.GetKey(opts.Config.Commits.PasteCommits),
+ Handler: self.paste,
+ GetDisabledReason: self.getDisabledReasonForPaste,
+ Description: self.c.Tr.PasteCommits,
},
{
- Key: opts.GetKey(opts.Config.Commits.MarkCommitAsBaseForRebase),
- Handler: self.checkSelected(self.markAsBaseCommit),
- Description: self.c.Tr.MarkAsBaseCommit,
- Tooltip: self.c.Tr.MarkAsBaseCommitTooltip,
+ Key: opts.GetKey(opts.Config.Commits.MarkCommitAsBaseForRebase),
+ Handler: self.checkSelected(self.markAsBaseCommit),
+ GetDisabledReason: self.disabledIfNoSelectedCommit(),
+ Description: self.c.Tr.MarkAsBaseCommit,
+ Tooltip: self.c.Tr.MarkAsBaseCommitTooltip,
},
// overriding these navigation keybindings because we might need to load
// more commits on demand
@@ -131,25 +144,29 @@ func (self *LocalCommitsController) GetKeybindings(opts types.KeybindingsOpts) [
bindings := append(outsideFilterModeBindings, []*types.Binding{
{
- Key: opts.GetKey(opts.Config.Commits.AmendToCommit),
- Handler: self.checkSelected(self.amendTo),
- Description: self.c.Tr.AmendToCommit,
+ Key: opts.GetKey(opts.Config.Commits.AmendToCommit),
+ Handler: self.checkSelected(self.amendTo),
+ GetDisabledReason: self.callGetDisabledReasonFuncWithSelectedCommit(self.getDisabledReasonForAmendTo),
+ Description: self.c.Tr.AmendToCommit,
},
{
- Key: opts.GetKey(opts.Config.Commits.ResetCommitAuthor),
- Handler: self.checkSelected(self.amendAttribute),
- Description: self.c.Tr.SetResetCommitAuthor,
- OpensMenu: true,
+ Key: opts.GetKey(opts.Config.Commits.ResetCommitAuthor),
+ Handler: self.checkSelected(self.amendAttribute),
+ GetDisabledReason: self.callGetDisabledReasonFuncWithSelectedCommit(self.getDisabledReasonForAmendTo),
+ Description: self.c.Tr.SetResetCommitAuthor,
+ OpensMenu: true,
},
{
- Key: opts.GetKey(opts.Config.Commits.RevertCommit),
- Handler: self.checkSelected(self.revert),
- Description: self.c.Tr.RevertCommit,
+ Key: opts.GetKey(opts.Config.Commits.RevertCommit),
+ Handler: self.checkSelected(self.revert),
+ GetDisabledReason: self.disabledIfNoSelectedCommit(),
+ Description: self.c.Tr.RevertCommit,
},
{
- Key: opts.GetKey(opts.Config.Commits.CreateTag),
- Handler: self.checkSelected(self.createTag),
- Description: self.c.Tr.TagCommit,
+ Key: opts.GetKey(opts.Config.Commits.CreateTag),
+ Handler: self.checkSelected(self.createTag),
+ GetDisabledReason: self.disabledIfNoSelectedCommit(),
+ Description: self.c.Tr.TagCommit,
},
{
Key: opts.GetKey(opts.Config.Commits.OpenLogMenu),
@@ -208,10 +225,6 @@ func secondaryPatchPanelUpdateOpts(c *ControllerCommon) *types.ViewUpdateOpts {
}
func (self *LocalCommitsController) squashDown(commit *models.Commit) error {
- if self.context().GetSelectedLineIdx() >= len(self.c.Model().Commits)-1 {
- return self.c.ErrorMsg(self.c.Tr.CannotSquashOrFixupFirstCommit)
- }
-
applied, err := self.handleMidRebaseCommand(todo.Squash, commit)
if err != nil {
return err
@@ -232,11 +245,15 @@ func (self *LocalCommitsController) squashDown(commit *models.Commit) error {
})
}
-func (self *LocalCommitsController) fixup(commit *models.Commit) error {
+func (self *LocalCommitsController) getDisabledReasonForSquashDown(commit *models.Commit) string {
if self.context().GetSelectedLineIdx() >= len(self.c.Model().Commits)-1 {
- return self.c.ErrorMsg(self.c.Tr.CannotSquashOrFixupFirstCommit)
+ return self.c.Tr.CannotSquashOrFixupFirstCommit
}
+ return self.rebaseCommandEnabled(todo.Squash, commit)
+}
+
+func (self *LocalCommitsController) fixup(commit *models.Commit) error {
applied, err := self.handleMidRebaseCommand(todo.Fixup, commit)
if err != nil {
return err
@@ -257,6 +274,14 @@ func (self *LocalCommitsController) fixup(commit *models.Commit) error {
})
}
+func (self *LocalCommitsController) getDisabledReasonForFixup(commit *models.Commit) string {
+ if self.context().GetSelectedLineIdx() >= len(self.c.Model().Commits)-1 {
+ return self.c.Tr.CannotSquashOrFixupFirstCommit
+ }
+
+ return self.rebaseCommandEnabled(todo.Squash, commit)
+}
+
func (self *LocalCommitsController) reword(commit *models.Commit) error {
applied, err := self.handleMidRebaseCommand(todo.Reword, commit)
if err != nil {
@@ -428,8 +453,33 @@ func (self *LocalCommitsController) interactiveRebase(action todo.TodoCommand) e
// commit meaning you are trying to edit the todo file rather than actually
// begin a rebase. It then updates the todo file with that action
func (self *LocalCommitsController) handleMidRebaseCommand(action todo.TodoCommand, commit *models.Commit) (bool, error) {
+ if !commit.IsTODO() {
+ return false, nil
+ }
+
+ self.c.LogAction("Update rebase TODO")
+
+ msg := utils.ResolvePlaceholderString(
+ self.c.Tr.Log.HandleMidRebaseCommand,
+ map[string]string{
+ "shortSha": commit.ShortSha(),
+ "action": action.String(),
+ },
+ )
+ self.c.LogCommand(msg, false)
+
+ if err := self.c.Git().Rebase.EditRebaseTodo(commit, action); err != nil {
+ return false, self.c.Error(err)
+ }
+
+ return true, self.c.Refresh(types.RefreshOptions{
+ Mode: types.SYNC, Scope: []types.RefreshableView{types.REBASE_COMMITS},
+ })
+}
+
+func (self *LocalCommitsController) rebaseCommandEnabled(action todo.TodoCommand, commit *models.Commit) string {
if commit.Action == models.ActionConflict {
- return true, self.c.ErrorMsg(self.c.Tr.ChangingThisActionIsNotAllowed)
+ return self.c.Tr.ChangingThisActionIsNotAllowed
}
if !commit.IsTODO() {
@@ -437,11 +487,11 @@ func (self *LocalCommitsController) handleMidRebaseCommand(action todo.TodoComma
// 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 true, self.c.ErrorMsg(self.c.Tr.AlreadyRebasing)
+ return self.c.Tr.AlreadyRebasing
}
}
- return false, nil
+ return ""
}
// for now we do not support setting 'reword' because it requires an editor
@@ -449,31 +499,14 @@ func (self *LocalCommitsController) handleMidRebaseCommand(action todo.TodoComma
// 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 true, self.c.ErrorMsg(self.c.Tr.RewordNotSupported)
+ return self.c.Tr.RewordNotSupported
}
if allowed := isChangeOfRebaseTodoAllowed(action); !allowed {
- return true, self.c.ErrorMsg(self.c.Tr.ChangingThisActionIsNotAllowed)
+ return self.c.Tr.ChangingThisActionIsNotAllowed
}
- self.c.LogAction("Update rebase TODO")
-
- msg := utils.ResolvePlaceholderString(
- self.c.Tr.Log.HandleMidRebaseCommand,
- map[string]string{
- "shortSha": commit.ShortSha(),
- "action": action.String(),
- },
- )
- self.c.LogCommand(msg, false)
-
- if err := self.c.Git().Rebase.EditRebaseTodo(commit, action); err != nil {
- return false, self.c.Error(err)
- }
-
- return true, self.c.Refresh(types.RefreshOptions{
- Mode: types.SYNC, Scope: []types.RefreshableView{types.REBASE_COMMITS},
- })
+ return ""
}
func (self *LocalCommitsController) moveDown(commit *models.Commit) error {
@@ -601,6 +634,14 @@ func (self *LocalCommitsController) amendTo(commit *models.Commit) error {
})
}
+func (self *LocalCommitsController) getDisabledReasonForAmendTo(commit *models.Commit) string {
+ if !self.isHeadCommit() && self.c.Git().Status.WorkingTreeState() != enums.REBASE_MODE_NONE {
+ return self.c.Tr.AlreadyRebasing
+ }
+
+ return ""
+}
+
func (self *LocalCommitsController) amendAttribute(commit *models.Commit) error {
if self.c.Git().Status.WorkingTreeState() != enums.REBASE_MODE_NONE && !self.isHeadCommit() {
return self.c.ErrorMsg(self.c.Tr.AlreadyRebasing)
@@ -772,6 +813,14 @@ func (self *LocalCommitsController) squashAllAboveFixupCommits(commit *models.Co
})
}
+func (self *LocalCommitsController) getDisabledReasonForSquashAllAboveFixupCommits(commit *models.Commit) string {
+ if self.c.Git().Status.WorkingTreeState() != enums.REBASE_MODE_NONE {
+ return self.c.Tr.AlreadyRebasing
+ }
+
+ return ""
+}
+
func (self *LocalCommitsController) createTag(commit *models.Commit) error {
return self.c.Helpers().Tags.OpenCreateTagPrompt(commit.Sha, func() {})
}
@@ -896,13 +945,35 @@ func (self *LocalCommitsController) checkSelected(callback func(*models.Commit)
return func() error {
commit := self.context().GetSelected()
if commit == nil {
- return nil
+ // The enabled callback should have checked for this
+ panic("no commit selected")
+ }
+
+ return callback(commit)
+ }
+}
+
+func (self *LocalCommitsController) callGetDisabledReasonFuncWithSelectedCommit(callback func(*models.Commit) string) func() string {
+ return func() string {
+ commit := self.context().GetSelected()
+ if commit == nil {
+ return self.c.Tr.NoCommitSelected
}
return callback(commit)
}
}
+func (self *LocalCommitsController) disabledIfNoSelectedCommit() func() string {
+ return self.callGetDisabledReasonFuncWithSelectedCommit(func(*models.Commit) string { return "" })
+}
+
+func (self *LocalCommitsController) getDisabledReasonForRebaseCommandWithSelectedCommit(action todo.TodoCommand) func() string {
+ return self.callGetDisabledReasonFuncWithSelectedCommit(func(commit *models.Commit) string {
+ return self.rebaseCommandEnabled(action, commit)
+ })
+}
+
func (self *LocalCommitsController) GetOnFocus() func(types.OnFocusOpts) error {
return func(types.OnFocusOpts) error {
context := self.context()
@@ -931,6 +1002,14 @@ func (self *LocalCommitsController) paste() error {
return self.c.Helpers().CherryPick.Paste()
}
+func (self *LocalCommitsController) getDisabledReasonForPaste() string {
+ if !self.c.Helpers().CherryPick.CanPaste() {
+ return self.c.Tr.NoCopiedCommits
+ }
+
+ return ""
+}
+
func (self *LocalCommitsController) markAsBaseCommit(commit *models.Commit) error {
if commit.Sha == self.c.Modes().MarkedBaseCommit.GetSha() {
// Reset when invoking it again on the marked commit
diff --git a/pkg/gui/controllers/menu_controller.go b/pkg/gui/controllers/menu_controller.go
index 108bd9cf7..0af32ef71 100644
--- a/pkg/gui/controllers/menu_controller.go
+++ b/pkg/gui/controllers/menu_controller.go
@@ -54,7 +54,7 @@ func (self *MenuController) GetOnFocus() func(types.OnFocusOpts) error {
return func(types.OnFocusOpts) error {
selectedMenuItem := self.context().GetSelected()
if selectedMenuItem != nil {
- self.c.Views().Tooltip.SetContent(selectedMenuItem.Tooltip)
+ self.c.Views().Tooltip.SetContent(self.c.Helpers().Confirmation.TooltipForMenuItem(selectedMenuItem))
}
return nil
}
diff --git a/pkg/gui/controllers/options_menu_action.go b/pkg/gui/controllers/options_menu_action.go
index 341fe8fb3..27a2915b8 100644
--- a/pkg/gui/controllers/options_menu_action.go
+++ b/pkg/gui/controllers/options_menu_action.go
@@ -25,6 +25,10 @@ func (self *OptionsMenuAction) Call() error {
appendBindings := func(bindings []*types.Binding, section *types.MenuSection) {