diff options
author | Jesse Duffield <jessedduffield@gmail.com> | 2024-01-16 17:28:14 +1100 |
---|---|---|
committer | Jesse Duffield <jessedduffield@gmail.com> | 2024-01-23 13:03:37 +1100 |
commit | a5f3515ad87f978c24d9454d45a454d824eb0897 (patch) | |
tree | 59022c18ae15cc5c89e235215a65d6775dab10a2 /pkg/gui/controllers/list_controller_trait.go | |
parent | a67ad447813ceaf389254b723b0783cf1021f40d (diff) |
Set groundwork for better disabled reasons with range select
Something dumb that we're currently doing is expecting list items
to define an ID method which returns a string. We use that when copying
items to clipboard with ctrl+o and when getting a ref name for diffing.
This commit gets us a little deeper into that hole by explicitly requiring
list items to implement that method so that we can easily use the new
helper functions in list_controller_trait.go.
In future we need to just remove the whole ID thing entirely but I'm too
lazy to do that right now.
Diffstat (limited to 'pkg/gui/controllers/list_controller_trait.go')
-rw-r--r-- | pkg/gui/controllers/list_controller_trait.go | 79 |
1 files changed, 70 insertions, 9 deletions
diff --git a/pkg/gui/controllers/list_controller_trait.go b/pkg/gui/controllers/list_controller_trait.go index fa60223b9..0edaa0114 100644 --- a/pkg/gui/controllers/list_controller_trait.go +++ b/pkg/gui/controllers/list_controller_trait.go @@ -6,20 +6,23 @@ import "github.com/jesseduffield/lazygit/pkg/gui/types" // ensuring a single item is selected, etc. type ListControllerTrait[T comparable] struct { - c *ControllerCommon - context types.IListContext - getSelected func() T + c *ControllerCommon + context types.IListContext + getSelectedItem func() T + getSelectedItems func() ([]T, int, int) } func NewListControllerTrait[T comparable]( c *ControllerCommon, context types.IListContext, getSelected func() T, + getSelectedItems func() ([]T, int, int), ) *ListControllerTrait[T] { return &ListControllerTrait[T]{ - c: c, - context: context, - getSelected: getSelected, + c: c, + context: context, + getSelectedItem: getSelected, + getSelectedItems: getSelectedItems, } } @@ -47,7 +50,7 @@ func (self *ListControllerTrait[T]) singleItemSelected(callbacks ...func(T) *typ } var zeroValue T - item := self.getSelected() + item := self.getSelectedItem() if item == zeroValue { return &types.DisabledReason{Text: self.c.Tr.NoItemSelected} } @@ -62,11 +65,46 @@ func (self *ListControllerTrait[T]) singleItemSelected(callbacks ...func(T) *typ } } +// Ensures that at least one item is selected. +func (self *ListControllerTrait[T]) itemRangeSelected(callbacks ...func([]T, int, int) *types.DisabledReason) func() *types.DisabledReason { + return func() *types.DisabledReason { + items, startIdx, endIdx := self.getSelectedItems() + if len(items) == 0 { + return &types.DisabledReason{Text: self.c.Tr.NoItemSelected} + } + + for _, callback := range callbacks { + if reason := callback(items, startIdx, endIdx); reason != nil { + return reason + } + } + + return nil + } +} + +func (self *ListControllerTrait[T]) itemsSelected(callbacks ...func([]T) *types.DisabledReason) func() *types.DisabledReason { //nolint:unused + return func() *types.DisabledReason { + items, _, _ := self.getSelectedItems() + if len(items) == 0 { + return &types.DisabledReason{Text: self.c.Tr.NoItemSelected} + } + + for _, callback := range callbacks { + if reason := callback(items); 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() + commit := self.getSelectedItem() if commit == zeroValue { return self.c.ErrorMsg(self.c.Tr.NoItemSelected) } @@ -75,12 +113,35 @@ func (self *ListControllerTrait[T]) withItem(callback func(T) error) func() erro } } +func (self *ListControllerTrait[T]) withItems(callback func([]T) error) func() error { + return func() error { + items, _, _ := self.getSelectedItems() + if len(items) == 0 { + return self.c.ErrorMsg(self.c.Tr.NoItemSelected) + } + + return callback(items) + } +} + +// like withItems but also passes the start and end index of the selection +func (self *ListControllerTrait[T]) withItemsRange(callback func([]T, int, int) error) func() error { + return func() error { + items, startIdx, endIdx := self.getSelectedItems() + if len(items) == 0 { + return self.c.ErrorMsg(self.c.Tr.NoItemSelected) + } + + return callback(items, startIdx, endIdx) + } +} + // 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() + commit := self.getSelectedItem() if commit == zeroValue { return nil } |