From 84e1d15079ab688d3a7379868c8b6b71a3a6edb1 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Sat, 13 Jan 2024 20:02:10 +0100 Subject: [PATCH] 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. --- pkg/gui/context/menu_context.go | 6 +- pkg/gui/controllers/branches_controller.go | 24 +++--- pkg/gui/controllers/files_controller.go | 10 +-- .../helpers/confirmation_helper.go | 4 +- .../controllers/local_commits_controller.go | 74 +++++++++---------- pkg/gui/controllers/options_menu_action.go | 2 +- pkg/gui/controllers/sync_controller.go | 6 +- pkg/gui/keybindings.go | 6 +- pkg/gui/types/common.go | 8 +- pkg/gui/types/keybindings.go | 2 +- 10 files changed, 73 insertions(+), 69 deletions(-) diff --git a/pkg/gui/context/menu_context.go b/pkg/gui/context/menu_context.go index 1ea0e64c1..d7c982651 100644 --- a/pkg/gui/context/menu_context.go +++ b/pkg/gui/context/menu_context.go @@ -90,7 +90,7 @@ func (self *MenuViewModel) GetDisplayStrings(_ int, _ int) [][]string { return lo.Map(menuItems, func(item *types.MenuItem, _ int) []string { displayStrings := item.LabelColumns - if item.DisabledReason != "" { + if item.DisabledReason != nil { 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 { - if selectedItem != nil && selectedItem.DisabledReason != "" { - self.c.ErrorToast(self.c.Tr.DisabledMenuItemPrefix + selectedItem.DisabledReason) + if selectedItem != nil && selectedItem.DisabledReason != nil { + self.c.ErrorToast(self.c.Tr.DisabledMenuItemPrefix + selectedItem.DisabledReason.Text) return nil } diff --git a/pkg/gui/controllers/branches_controller.go b/pkg/gui/controllers/branches_controller.go index 22390fc8e..e0a38d463 100644 --- a/pkg/gui/controllers/branches_controller.go +++ b/pkg/gui/controllers/branches_controller.go @@ -264,13 +264,13 @@ func (self *BranchesController) viewUpstreamOptions(selectedBranch *models.Branc } if !selectedBranch.IsTrackingRemote() { - unsetUpstreamItem.DisabledReason = self.c.Tr.UpstreamNotSetError + unsetUpstreamItem.DisabledReason = &types.DisabledReason{Text: self.c.Tr.UpstreamNotSetError} } if !selectedBranch.RemoteBranchStoredLocally() { - viewDivergenceItem.DisabledReason = self.c.Tr.UpstreamNotSetError - upstreamResetItem.DisabledReason = self.c.Tr.UpstreamNotSetError - upstreamRebaseItem.DisabledReason = self.c.Tr.UpstreamNotSetError + viewDivergenceItem.DisabledReason = &types.DisabledReason{Text: self.c.Tr.UpstreamNotSetError} + upstreamResetItem.DisabledReason = &types.DisabledReason{Text: self.c.Tr.UpstreamNotSetError} + upstreamRebaseItem.DisabledReason = &types.DisabledReason{Text: self.c.Tr.UpstreamNotSetError} } 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{}) } -func (self *BranchesController) getDisabledReasonForPress() string { +func (self *BranchesController) getDisabledReasonForPress() *types.DisabledReason { currentBranch := self.c.Helpers().Refs.GetCheckedOutRef() if currentBranch != nil { op := self.c.State().GetItemOperation(currentBranch) 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) { @@ -525,7 +525,7 @@ func (self *BranchesController) delete(branch *models.Branch) error { }, } if checkedOutBranch.Name == branch.Name { - localDeleteItem.DisabledReason = self.c.Tr.CantDeleteCheckOutBranch + localDeleteItem.DisabledReason = &types.DisabledReason{Text: self.c.Tr.CantDeleteCheckOutBranch} } remoteDeleteItem := &types.MenuItem{ @@ -536,7 +536,7 @@ func (self *BranchesController) delete(branch *models.Branch) error { }, } if !branch.IsTrackingRemote() || branch.UpstreamGone { - remoteDeleteItem.DisabledReason = self.c.Tr.UpstreamNotSetError + remoteDeleteItem.DisabledReason = &types.DisabledReason{Text: self.c.Tr.UpstreamNotSetError} } menuTitle := utils.ResolvePlaceholderString( @@ -562,14 +562,14 @@ func (self *BranchesController) rebase() error { return self.c.Helpers().MergeAndRebase.RebaseOntoRef(selectedBranchName) } -func (self *BranchesController) getDisabledReasonForRebase() string { +func (self *BranchesController) getDisabledReasonForRebase() *types.DisabledReason { selectedBranchName := self.context().GetSelected().Name checkedOutBranch := self.c.Helpers().Refs.GetCheckedOutRef().Name 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 { diff --git a/pkg/gui/controllers/files_controller.go b/pkg/gui/controllers/files_controller.go index d60773ec1..7776da5b3 100644 --- a/pkg/gui/controllers/files_controller.go +++ b/pkg/gui/controllers/files_controller.go @@ -848,15 +848,15 @@ func (self *FilesController) openCopyMenu() error { } if node == nil { - copyNameItem.DisabledReason = self.c.Tr.NoContentToCopyError - copyPathItem.DisabledReason = self.c.Tr.NoContentToCopyError - copyFileDiffItem.DisabledReason = self.c.Tr.NoContentToCopyError + 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 = self.c.Tr.NoContentToCopyError + copyFileDiffItem.DisabledReason = &types.DisabledReason{Text: self.c.Tr.NoContentToCopyError} } if !self.anyStagedOrTrackedFile() { - copyAllDiff.DisabledReason = self.c.Tr.NoContentToCopyError + copyAllDiff.DisabledReason = &types.DisabledReason{Text: self.c.Tr.NoContentToCopyError} } return self.c.Menu(types.CreateMenuOptions{ diff --git a/pkg/gui/controllers/helpers/confirmation_helper.go b/pkg/gui/controllers/helpers/confirmation_helper.go index 62beaacda..8a61a86e1 100644 --- a/pkg/gui/controllers/helpers/confirmation_helper.go +++ b/pkg/gui/controllers/helpers/confirmation_helper.go @@ -378,11 +378,11 @@ func (self *ConfirmationHelper) IsPopupPanelFocused() bool { func (self *ConfirmationHelper) TooltipForMenuItem(menuItem *types.MenuItem) string { tooltip := menuItem.Tooltip - if menuItem.DisabledReason != "" { + if menuItem.DisabledReason != nil { if tooltip != "" { 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 } diff --git a/pkg/gui/controllers/local_commits_controller.go b/pkg/gui/controllers/local_commits_controller.go index d3b92bc93..ea2038f71 100644 --- a/pkg/gui/controllers/local_commits_controller.go +++ b/pkg/gui/controllers/local_commits_controller.go @@ -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 { - return self.c.Tr.CannotSquashOrFixupFirstCommit + return &types.DisabledReason{Text: self.c.Tr.CannotSquashOrFixupFirstCommit} } 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 { - return self.c.Tr.CannotSquashOrFixupFirstCommit + return &types.DisabledReason{Text: self.c.Tr.CannotSquashOrFixupFirstCommit} } 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 { - return self.c.Tr.ChangingThisActionIsNotAllowed + return &types.DisabledReason{Text: self.c.Tr.ChangingThisActionIsNotAllowed} } 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 // non-todo commits is rewording the current head commit 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 @@ -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 // request us to edit the commit message when prompted. if action == todo.Reword { - return self.c.Tr.RewordNotSupported + return &types.DisabledReason{Text: self.c.Tr.RewordNotSupported} } 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 { @@ -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 { - return self.c.Tr.AlreadyRebasing + return &types.DisabledReason{Text: self.c.Tr.AlreadyRebasing} } - return "" + return nil } 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 { - return self.c.Tr.AlreadyRebasing + return &types.DisabledReason{Text: self.c.Tr.AlreadyRebasing} } - return "" + return nil } // For getting disabled reason -func (self *LocalCommitsController) notMidRebase() string { +func (self *LocalCommitsController) notMidRebase() *types.DisabledReason { 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 -func (self *LocalCommitsController) canFindCommitForQuickStart() string { +func (self *LocalCommitsController) canFindCommitForQuickStart() *types.DisabledReason { 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 { @@ -1028,23 +1028,23 @@ func (self *LocalCommitsController) checkSelected(callback func(*models.Commit) } } -func (self *LocalCommitsController) callGetDisabledReasonFuncWithSelectedCommit(callback func(*models.Commit) string) func() string { - return func() string { +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 self.c.Tr.NoCommitSelected + return &types.DisabledReason{Text: self.c.Tr.NoCommitSelected} } return callback(commit) } } -func (self *LocalCommitsController) disabledIfNoSelectedCommit() func() string { - return self.callGetDisabledReasonFuncWithSelectedCommit(func(*models.Commit) string { return "" }) +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() string { - return self.callGetDisabledReasonFuncWithSelectedCommit(func(commit *models.Commit) string { +func (self *LocalCommitsController) getDisabledReasonForRebaseCommandWithSelectedCommit(action todo.TodoCommand) func() *types.DisabledReason { + return self.callGetDisabledReasonFuncWithSelectedCommit(func(commit *models.Commit) *types.DisabledReason { return self.rebaseCommandEnabled(action, commit) }) } @@ -1077,12 +1077,12 @@ func (self *LocalCommitsController) paste() error { return self.c.Helpers().CherryPick.Paste() } -func (self *LocalCommitsController) getDisabledReasonForPaste() string { +func (self *LocalCommitsController) getDisabledReasonForPaste() *types.DisabledReason { 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 { @@ -1100,15 +1100,15 @@ func (self *LocalCommitsController) isHeadCommit() bool { } // Convenience function for composing multiple disabled reason functions -func (self *LocalCommitsController) require(callbacks ...func() string) func() string { - return func() string { +func (self *LocalCommitsController) require(callbacks ...func() *types.DisabledReason) func() *types.DisabledReason { + return func() *types.DisabledReason { for _, callback := range callbacks { - if disabledReason := callback(); disabledReason != "" { + if disabledReason := callback(); disabledReason != nil { return disabledReason } } - return "" + return nil } } diff --git a/pkg/gui/controllers/options_menu_action.go b/pkg/gui/controllers/options_menu_action.go index 27a2915b8..1100cf876 100644 --- a/pkg/gui/controllers/options_menu_action.go +++ b/pkg/gui/controllers/options_menu_action.go @@ -25,7 +25,7 @@ func (self *OptionsMenuAction) Call() error { appendBindings := func(bindings []*types.Binding, section *types.MenuSection) { menuItems = append(menuItems, lo.Map(bindings, func(binding *types.Binding, _ int) *types.MenuItem { - disabledReason := "" + var disabledReason *types.DisabledReason if binding.GetDisabledReason != nil { disabledReason = binding.GetDisabledReason() } diff --git a/pkg/gui/controllers/sync_controller.go b/pkg/gui/controllers/sync_controller.go index 4e3369e0a..ada4997d2 100644 --- a/pkg/gui/controllers/sync_controller.go +++ b/pkg/gui/controllers/sync_controller.go @@ -59,16 +59,16 @@ func (self *SyncController) HandlePull() error { return self.branchCheckedOut(self.pull)() } -func (self *SyncController) getDisabledReasonForPushOrPull() string { +func (self *SyncController) getDisabledReasonForPushOrPull() *types.DisabledReason { currentBranch := self.c.Helpers().Refs.GetCheckedOutRef() if currentBranch != nil { op := self.c.State().GetItemOperation(currentBranch) 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 { diff --git a/pkg/gui/keybindings.go b/pkg/gui/keybindings.go index a2e9fafbd..4a64dbde5 100644 --- a/pkg/gui/keybindings.go +++ b/pkg/gui/keybindings.go @@ -411,12 +411,12 @@ func (gui *Gui) SetMouseKeybinding(binding *gocui.ViewMouseBinding) error { } func (gui *Gui) callKeybindingHandler(binding *types.Binding) error { - disabledReason := "" + var disabledReason *types.DisabledReason if binding.GetDisabledReason != nil { disabledReason = binding.GetDisabledReason() } - if disabledReason != "" { - gui.c.ErrorToast(gui.Tr.DisabledMenuItemPrefix + disabledReason) + if disabledReason != nil { + gui.c.ErrorToast(gui.Tr.DisabledMenuItemPrefix + disabledReason.Text) return nil } return binding.Handler() diff --git a/pkg/gui/types/common.go b/pkg/gui/types/common.go index afa4156c8..79b4e153c 100644 --- a/pkg/gui/types/common.go +++ b/pkg/gui/types/common.go @@ -201,6 +201,10 @@ type MenuSection struct { Column int // The column that this section title should be aligned with } +type DisabledReason struct { + Text string +} + type MenuItem struct { Label string @@ -219,9 +223,9 @@ type MenuItem struct { // The tooltip will be displayed upon highlighting the menu item 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 - DisabledReason string + DisabledReason *DisabledReason // Can be used to group menu items into sections with headers. MenuItems // with the same Section should be contiguous, and will automatically get a diff --git a/pkg/gui/types/keybindings.go b/pkg/gui/types/keybindings.go index 4c3d02c6f..bb125d4e5 100644 --- a/pkg/gui/types/keybindings.go +++ b/pkg/gui/types/keybindings.go @@ -31,7 +31,7 @@ type Binding struct { // 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 // function must not do expensive calls. - GetDisabledReason func() string + GetDisabledReason func() *DisabledReason } // A guard is a decorator which checks something before executing a handler