1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2025-04-17 12:06:38 +02:00

Make DisabledReason a struct

This is a pure refactoring, no change in behavior yet. We'll add another field
to the struct in the next commit.
This commit is contained in:
Stefan Haller 2024-01-13 20:02:10 +01:00
parent 09a24ee97d
commit 84e1d15079
10 changed files with 73 additions and 69 deletions

View File

@ -90,7 +90,7 @@ func (self *MenuViewModel) GetDisplayStrings(_ int, _ int) [][]string {
return lo.Map(menuItems, func(item *types.MenuItem, _ int) []string { return lo.Map(menuItems, func(item *types.MenuItem, _ int) []string {
displayStrings := item.LabelColumns displayStrings := item.LabelColumns
if item.DisabledReason != "" { if item.DisabledReason != nil {
displayStrings[0] = style.FgDefault.SetStrikethrough().Sprint(displayStrings[0]) displayStrings[0] = style.FgDefault.SetStrikethrough().Sprint(displayStrings[0])
} }
@ -172,8 +172,8 @@ func (self *MenuContext) GetKeybindings(opts types.KeybindingsOpts) []*types.Bin
} }
func (self *MenuContext) OnMenuPress(selectedItem *types.MenuItem) error { func (self *MenuContext) OnMenuPress(selectedItem *types.MenuItem) error {
if selectedItem != nil && selectedItem.DisabledReason != "" { if selectedItem != nil && selectedItem.DisabledReason != nil {
self.c.ErrorToast(self.c.Tr.DisabledMenuItemPrefix + selectedItem.DisabledReason) self.c.ErrorToast(self.c.Tr.DisabledMenuItemPrefix + selectedItem.DisabledReason.Text)
return nil return nil
} }

View File

@ -264,13 +264,13 @@ func (self *BranchesController) viewUpstreamOptions(selectedBranch *models.Branc
} }
if !selectedBranch.IsTrackingRemote() { if !selectedBranch.IsTrackingRemote() {
unsetUpstreamItem.DisabledReason = self.c.Tr.UpstreamNotSetError unsetUpstreamItem.DisabledReason = &types.DisabledReason{Text: self.c.Tr.UpstreamNotSetError}
} }
if !selectedBranch.RemoteBranchStoredLocally() { if !selectedBranch.RemoteBranchStoredLocally() {
viewDivergenceItem.DisabledReason = self.c.Tr.UpstreamNotSetError viewDivergenceItem.DisabledReason = &types.DisabledReason{Text: self.c.Tr.UpstreamNotSetError}
upstreamResetItem.DisabledReason = self.c.Tr.UpstreamNotSetError upstreamResetItem.DisabledReason = &types.DisabledReason{Text: self.c.Tr.UpstreamNotSetError}
upstreamRebaseItem.DisabledReason = self.c.Tr.UpstreamNotSetError upstreamRebaseItem.DisabledReason = &types.DisabledReason{Text: self.c.Tr.UpstreamNotSetError}
} }
options := []*types.MenuItem{ options := []*types.MenuItem{
@ -309,16 +309,16 @@ func (self *BranchesController) press(selectedBranch *models.Branch) error {
return self.c.Helpers().Refs.CheckoutRef(selectedBranch.Name, types.CheckoutRefOptions{}) return self.c.Helpers().Refs.CheckoutRef(selectedBranch.Name, types.CheckoutRefOptions{})
} }
func (self *BranchesController) getDisabledReasonForPress() string { func (self *BranchesController) getDisabledReasonForPress() *types.DisabledReason {
currentBranch := self.c.Helpers().Refs.GetCheckedOutRef() currentBranch := self.c.Helpers().Refs.GetCheckedOutRef()
if currentBranch != nil { if currentBranch != nil {
op := self.c.State().GetItemOperation(currentBranch) op := self.c.State().GetItemOperation(currentBranch)
if op == types.ItemOperationFastForwarding || op == types.ItemOperationPulling { if op == types.ItemOperationFastForwarding || op == types.ItemOperationPulling {
return self.c.Tr.CantCheckoutBranchWhilePulling return &types.DisabledReason{Text: self.c.Tr.CantCheckoutBranchWhilePulling}
} }
} }
return "" return nil
} }
func (self *BranchesController) worktreeForBranch(branch *models.Branch) (*models.Worktree, bool) { func (self *BranchesController) worktreeForBranch(branch *models.Branch) (*models.Worktree, bool) {
@ -525,7 +525,7 @@ func (self *BranchesController) delete(branch *models.Branch) error {
}, },
} }
if checkedOutBranch.Name == branch.Name { if checkedOutBranch.Name == branch.Name {
localDeleteItem.DisabledReason = self.c.Tr.CantDeleteCheckOutBranch localDeleteItem.DisabledReason = &types.DisabledReason{Text: self.c.Tr.CantDeleteCheckOutBranch}
} }
remoteDeleteItem := &types.MenuItem{ remoteDeleteItem := &types.MenuItem{
@ -536,7 +536,7 @@ func (self *BranchesController) delete(branch *models.Branch) error {
}, },
} }
if !branch.IsTrackingRemote() || branch.UpstreamGone { if !branch.IsTrackingRemote() || branch.UpstreamGone {
remoteDeleteItem.DisabledReason = self.c.Tr.UpstreamNotSetError remoteDeleteItem.DisabledReason = &types.DisabledReason{Text: self.c.Tr.UpstreamNotSetError}
} }
menuTitle := utils.ResolvePlaceholderString( menuTitle := utils.ResolvePlaceholderString(
@ -562,14 +562,14 @@ func (self *BranchesController) rebase() error {
return self.c.Helpers().MergeAndRebase.RebaseOntoRef(selectedBranchName) return self.c.Helpers().MergeAndRebase.RebaseOntoRef(selectedBranchName)
} }
func (self *BranchesController) getDisabledReasonForRebase() string { func (self *BranchesController) getDisabledReasonForRebase() *types.DisabledReason {
selectedBranchName := self.context().GetSelected().Name selectedBranchName := self.context().GetSelected().Name
checkedOutBranch := self.c.Helpers().Refs.GetCheckedOutRef().Name checkedOutBranch := self.c.Helpers().Refs.GetCheckedOutRef().Name
if selectedBranchName == checkedOutBranch { if selectedBranchName == checkedOutBranch {
return self.c.Tr.CantRebaseOntoSelf return &types.DisabledReason{Text: self.c.Tr.CantRebaseOntoSelf}
} }
return "" return nil
} }
func (self *BranchesController) fastForward(branch *models.Branch) error { func (self *BranchesController) fastForward(branch *models.Branch) error {

View File

@ -848,15 +848,15 @@ func (self *FilesController) openCopyMenu() error {
} }
if node == nil { if node == nil {
copyNameItem.DisabledReason = self.c.Tr.NoContentToCopyError copyNameItem.DisabledReason = &types.DisabledReason{Text: self.c.Tr.NoContentToCopyError}
copyPathItem.DisabledReason = self.c.Tr.NoContentToCopyError copyPathItem.DisabledReason = &types.DisabledReason{Text: self.c.Tr.NoContentToCopyError}
copyFileDiffItem.DisabledReason = self.c.Tr.NoContentToCopyError copyFileDiffItem.DisabledReason = &types.DisabledReason{Text: self.c.Tr.NoContentToCopyError}
} }
if node != nil && !node.GetHasStagedOrTrackedChanges() { if node != nil && !node.GetHasStagedOrTrackedChanges() {
copyFileDiffItem.DisabledReason = self.c.Tr.NoContentToCopyError copyFileDiffItem.DisabledReason = &types.DisabledReason{Text: self.c.Tr.NoContentToCopyError}
} }
if !self.anyStagedOrTrackedFile() { if !self.anyStagedOrTrackedFile() {
copyAllDiff.DisabledReason = self.c.Tr.NoContentToCopyError copyAllDiff.DisabledReason = &types.DisabledReason{Text: self.c.Tr.NoContentToCopyError}
} }
return self.c.Menu(types.CreateMenuOptions{ return self.c.Menu(types.CreateMenuOptions{

View File

@ -378,11 +378,11 @@ func (self *ConfirmationHelper) IsPopupPanelFocused() bool {
func (self *ConfirmationHelper) TooltipForMenuItem(menuItem *types.MenuItem) string { func (self *ConfirmationHelper) TooltipForMenuItem(menuItem *types.MenuItem) string {
tooltip := menuItem.Tooltip tooltip := menuItem.Tooltip
if menuItem.DisabledReason != "" { if menuItem.DisabledReason != nil {
if tooltip != "" { if tooltip != "" {
tooltip += "\n\n" tooltip += "\n\n"
} }
tooltip += style.FgRed.Sprintf(self.c.Tr.DisabledMenuItemPrefix) + menuItem.DisabledReason tooltip += style.FgRed.Sprintf(self.c.Tr.DisabledMenuItemPrefix) + menuItem.DisabledReason.Text
} }
return tooltip return tooltip
} }

View File

@ -261,9 +261,9 @@ func (self *LocalCommitsController) squashDown(commit *models.Commit) error {
}) })
} }
func (self *LocalCommitsController) getDisabledReasonForSquashDown(commit *models.Commit) string { func (self *LocalCommitsController) getDisabledReasonForSquashDown(commit *models.Commit) *types.DisabledReason {
if self.context().GetSelectedLineIdx() >= len(self.c.Model().Commits)-1 { if self.context().GetSelectedLineIdx() >= len(self.c.Model().Commits)-1 {
return self.c.Tr.CannotSquashOrFixupFirstCommit return &types.DisabledReason{Text: self.c.Tr.CannotSquashOrFixupFirstCommit}
} }
return self.rebaseCommandEnabled(todo.Squash, commit) return self.rebaseCommandEnabled(todo.Squash, commit)
@ -290,9 +290,9 @@ func (self *LocalCommitsController) fixup(commit *models.Commit) error {
}) })
} }
func (self *LocalCommitsController) getDisabledReasonForFixup(commit *models.Commit) string { func (self *LocalCommitsController) getDisabledReasonForFixup(commit *models.Commit) *types.DisabledReason {
if self.context().GetSelectedLineIdx() >= len(self.c.Model().Commits)-1 { if self.context().GetSelectedLineIdx() >= len(self.c.Model().Commits)-1 {
return self.c.Tr.CannotSquashOrFixupFirstCommit return &types.DisabledReason{Text: self.c.Tr.CannotSquashOrFixupFirstCommit}
} }
return self.rebaseCommandEnabled(todo.Squash, commit) return self.rebaseCommandEnabled(todo.Squash, commit)
@ -528,9 +528,9 @@ func (self *LocalCommitsController) handleMidRebaseCommand(action todo.TodoComma
}) })
} }
func (self *LocalCommitsController) rebaseCommandEnabled(action todo.TodoCommand, commit *models.Commit) string { func (self *LocalCommitsController) rebaseCommandEnabled(action todo.TodoCommand, commit *models.Commit) *types.DisabledReason {
if commit.Action == models.ActionConflict { if commit.Action == models.ActionConflict {
return self.c.Tr.ChangingThisActionIsNotAllowed return &types.DisabledReason{Text: self.c.Tr.ChangingThisActionIsNotAllowed}
} }
if !commit.IsTODO() { if !commit.IsTODO() {
@ -538,11 +538,11 @@ func (self *LocalCommitsController) rebaseCommandEnabled(action todo.TodoCommand
// If we are in a rebase, the only action that is allowed for // If we are in a rebase, the only action that is allowed for
// non-todo commits is rewording the current head commit // non-todo commits is rewording the current head commit
if !(action == todo.Reword && self.isHeadCommit()) { if !(action == todo.Reword && self.isHeadCommit()) {
return self.c.Tr.AlreadyRebasing return &types.DisabledReason{Text: self.c.Tr.AlreadyRebasing}
} }
} }
return "" return nil
} }
// for now we do not support setting 'reword' because it requires an editor // for now we do not support setting 'reword' because it requires an editor
@ -550,14 +550,14 @@ func (self *LocalCommitsController) rebaseCommandEnabled(action todo.TodoCommand
// our input or we set a lazygit client as the EDITOR env variable and have it // 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. // request us to edit the commit message when prompted.
if action == todo.Reword { if action == todo.Reword {
return self.c.Tr.RewordNotSupported return &types.DisabledReason{Text: self.c.Tr.RewordNotSupported}
} }
if allowed := isChangeOfRebaseTodoAllowed(action); !allowed { if allowed := isChangeOfRebaseTodoAllowed(action); !allowed {
return self.c.Tr.ChangingThisActionIsNotAllowed return &types.DisabledReason{Text: self.c.Tr.ChangingThisActionIsNotAllowed}
} }
return "" return nil
} }
func (self *LocalCommitsController) moveDown(commit *models.Commit) error { func (self *LocalCommitsController) moveDown(commit *models.Commit) error {
@ -687,12 +687,12 @@ func (self *LocalCommitsController) amendTo(commit *models.Commit) error {
}) })
} }
func (self *LocalCommitsController) getDisabledReasonForAmendTo(commit *models.Commit) string { func (self *LocalCommitsController) getDisabledReasonForAmendTo(commit *models.Commit) *types.DisabledReason {
if !self.isHeadCommit() && self.c.Model().WorkingTreeStateAtLastCommitRefresh != enums.REBASE_MODE_NONE { if !self.isHeadCommit() && self.c.Model().WorkingTreeStateAtLastCommitRefresh != enums.REBASE_MODE_NONE {
return self.c.Tr.AlreadyRebasing return &types.DisabledReason{Text: self.c.Tr.AlreadyRebasing}
} }
return "" return nil
} }
func (self *LocalCommitsController) amendAttribute(commit *models.Commit) error { func (self *LocalCommitsController) amendAttribute(commit *models.Commit) error {
@ -870,30 +870,30 @@ func (self *LocalCommitsController) squashAllAboveFixupCommits(commit *models.Co
}) })
} }
func (self *LocalCommitsController) getDisabledReasonForSquashAllAboveFixupCommits(commit *models.Commit) string { func (self *LocalCommitsController) getDisabledReasonForSquashAllAboveFixupCommits(commit *models.Commit) *types.DisabledReason {
if self.c.Model().WorkingTreeStateAtLastCommitRefresh != enums.REBASE_MODE_NONE { if self.c.Model().WorkingTreeStateAtLastCommitRefresh != enums.REBASE_MODE_NONE {
return self.c.Tr.AlreadyRebasing return &types.DisabledReason{Text: self.c.Tr.AlreadyRebasing}
} }
return "" return nil
} }
// For getting disabled reason // For getting disabled reason
func (self *LocalCommitsController) notMidRebase() string { func (self *LocalCommitsController) notMidRebase() *types.DisabledReason {
if self.c.Model().WorkingTreeStateAtLastCommitRefresh != enums.REBASE_MODE_NONE { if self.c.Model().WorkingTreeStateAtLastCommitRefresh != enums.REBASE_MODE_NONE {
return self.c.Tr.AlreadyRebasing return &types.DisabledReason{Text: self.c.Tr.AlreadyRebasing}
} }
return "" return nil
} }
// For getting disabled reason // For getting disabled reason
func (self *LocalCommitsController) canFindCommitForQuickStart() string { func (self *LocalCommitsController) canFindCommitForQuickStart() *types.DisabledReason {
if _, err := self.findCommitForQuickStartInteractiveRebase(); err != nil { if _, err := self.findCommitForQuickStartInteractiveRebase(); err != nil {
return err.Error() return &types.DisabledReason{Text: err.Error()}
} }
return "" return nil
} }
func (self *LocalCommitsController) createTag(commit *models.Commit) error { func (self *LocalCommitsController) createTag(commit *models.Commit) error {
@ -1028,23 +1028,23 @@ func (self *LocalCommitsController) checkSelected(callback func(*models.Commit)
} }
} }
func (self *LocalCommitsController) callGetDisabledReasonFuncWithSelectedCommit(callback func(*models.Commit) string) func() string { func (self *LocalCommitsController) callGetDisabledReasonFuncWithSelectedCommit(callback func(*models.Commit) *types.DisabledReason) func() *types.DisabledReason {
return func() string { return func() *types.DisabledReason {
commit := self.context().GetSelected() commit := self.context().GetSelected()
if commit == nil { if commit == nil {
return self.c.Tr.NoCommitSelected return &types.DisabledReason{Text: self.c.Tr.NoCommitSelected}
} }
return callback(commit) return callback(commit)
} }
} }
func (self *LocalCommitsController) disabledIfNoSelectedCommit() func() string { func (self *LocalCommitsController) disabledIfNoSelectedCommit() func() *types.DisabledReason {
return self.callGetDisabledReasonFuncWithSelectedCommit(func(*models.Commit) string { return "" }) return self.callGetDisabledReasonFuncWithSelectedCommit(func(*models.Commit) *types.DisabledReason { return nil })
} }
func (self *LocalCommitsController) getDisabledReasonForRebaseCommandWithSelectedCommit(action todo.TodoCommand) func() string { func (self *LocalCommitsController) getDisabledReasonForRebaseCommandWithSelectedCommit(action todo.TodoCommand) func() *types.DisabledReason {
return self.callGetDisabledReasonFuncWithSelectedCommit(func(commit *models.Commit) string { return self.callGetDisabledReasonFuncWithSelectedCommit(func(commit *models.Commit) *types.DisabledReason {
return self.rebaseCommandEnabled(action, commit) return self.rebaseCommandEnabled(action, commit)
}) })
} }
@ -1077,12 +1077,12 @@ func (self *LocalCommitsController) paste() error {
return self.c.Helpers().CherryPick.Paste() return self.c.Helpers().CherryPick.Paste()
} }
func (self *LocalCommitsController) getDisabledReasonForPaste() string { func (self *LocalCommitsController) getDisabledReasonForPaste() *types.DisabledReason {
if !self.c.Helpers().CherryPick.CanPaste() { if !self.c.Helpers().CherryPick.CanPaste() {
return self.c.Tr.NoCopiedCommits return &types.DisabledReason{Text: self.c.Tr.NoCopiedCommits}
} }
return "" return nil
} }
func (self *LocalCommitsController) markAsBaseCommit(commit *models.Commit) error { func (self *LocalCommitsController) markAsBaseCommit(commit *models.Commit) error {
@ -1100,15 +1100,15 @@ func (self *LocalCommitsController) isHeadCommit() bool {
} }
// Convenience function for composing multiple disabled reason functions // Convenience function for composing multiple disabled reason functions
func (self *LocalCommitsController) require(callbacks ...func() string) func() string { func (self *LocalCommitsController) require(callbacks ...func() *types.DisabledReason) func() *types.DisabledReason {
return func() string { return func() *types.DisabledReason {
for _, callback := range callbacks { for _, callback := range callbacks {
if disabledReason := callback(); disabledReason != "" { if disabledReason := callback(); disabledReason != nil {
return disabledReason return disabledReason
} }
} }
return "" return nil
} }
} }

View File

@ -25,7 +25,7 @@ func (self *OptionsMenuAction) Call() error {
appendBindings := func(bindings []*types.Binding, section *types.MenuSection) { appendBindings := func(bindings []*types.Binding, section *types.MenuSection) {
menuItems = append(menuItems, menuItems = append(menuItems,
lo.Map(bindings, func(binding *types.Binding, _ int) *types.MenuItem { lo.Map(bindings, func(binding *types.Binding, _ int) *types.MenuItem {
disabledReason := "" var disabledReason *types.DisabledReason
if binding.GetDisabledReason != nil { if binding.GetDisabledReason != nil {
disabledReason = binding.GetDisabledReason() disabledReason = binding.GetDisabledReason()
} }

View File

@ -59,16 +59,16 @@ func (self *SyncController) HandlePull() error {
return self.branchCheckedOut(self.pull)() return self.branchCheckedOut(self.pull)()
} }
func (self *SyncController) getDisabledReasonForPushOrPull() string { func (self *SyncController) getDisabledReasonForPushOrPull() *types.DisabledReason {
currentBranch := self.c.Helpers().Refs.GetCheckedOutRef() currentBranch := self.c.Helpers().Refs.GetCheckedOutRef()
if currentBranch != nil { if currentBranch != nil {
op := self.c.State().GetItemOperation(currentBranch) op := self.c.State().GetItemOperation(currentBranch)
if op != types.ItemOperationNone { if op != types.ItemOperationNone {
return self.c.Tr.CantPullOrPushSameBranchTwice return &types.DisabledReason{Text: self.c.Tr.CantPullOrPushSameBranchTwice}
} }
} }
return "" return nil
} }
func (self *SyncController) branchCheckedOut(f func(*models.Branch) error) func() error { func (self *SyncController) branchCheckedOut(f func(*models.Branch) error) func() error {

View File

@ -411,12 +411,12 @@ func (gui *Gui) SetMouseKeybinding(binding *gocui.ViewMouseBinding) error {
} }
func (gui *Gui) callKeybindingHandler(binding *types.Binding) error { func (gui *Gui) callKeybindingHandler(binding *types.Binding) error {
disabledReason := "" var disabledReason *types.DisabledReason
if binding.GetDisabledReason != nil { if binding.GetDisabledReason != nil {
disabledReason = binding.GetDisabledReason() disabledReason = binding.GetDisabledReason()
} }
if disabledReason != "" { if disabledReason != nil {
gui.c.ErrorToast(gui.Tr.DisabledMenuItemPrefix + disabledReason) gui.c.ErrorToast(gui.Tr.DisabledMenuItemPrefix + disabledReason.Text)
return nil return nil
} }
return binding.Handler() return binding.Handler()

View File

@ -201,6 +201,10 @@ type MenuSection struct {
Column int // The column that this section title should be aligned with Column int // The column that this section title should be aligned with
} }
type DisabledReason struct {
Text string
}
type MenuItem struct { type MenuItem struct {
Label string Label string
@ -219,9 +223,9 @@ type MenuItem struct {
// The tooltip will be displayed upon highlighting the menu item // The tooltip will be displayed upon highlighting the menu item
Tooltip string Tooltip string
// If non-empty, show this in a tooltip, style the menu item as disabled, // If non-nil, show this in a tooltip, style the menu item as disabled,
// and refuse to invoke the command // and refuse to invoke the command
DisabledReason string DisabledReason *DisabledReason
// Can be used to group menu items into sections with headers. MenuItems // Can be used to group menu items into sections with headers. MenuItems
// with the same Section should be contiguous, and will automatically get a // with the same Section should be contiguous, and will automatically get a

View File

@ -31,7 +31,7 @@ type Binding struct {
// disabled and we show the given text in an error message when trying to // disabled and we show the given text in an error message when trying to
// invoke it. When left nil, the command is always enabled. Note that this // invoke it. When left nil, the command is always enabled. Note that this
// function must not do expensive calls. // function must not do expensive calls.
GetDisabledReason func() string GetDisabledReason func() *DisabledReason
} }
// A guard is a decorator which checks something before executing a handler // A guard is a decorator which checks something before executing a handler