summaryrefslogtreecommitdiffstats
path: root/pkg/gui/controllers/list_controller_trait.go
diff options
context:
space:
mode:
authorJesse Duffield <jessedduffield@gmail.com>2024-01-16 17:28:14 +1100
committerJesse Duffield <jessedduffield@gmail.com>2024-01-23 13:03:37 +1100
commita5f3515ad87f978c24d9454d45a454d824eb0897 (patch)
tree59022c18ae15cc5c89e235215a65d6775dab10a2 /pkg/gui/controllers/list_controller_trait.go
parenta67ad447813ceaf389254b723b0783cf1021f40d (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.go79
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
}