mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-04-21 12:16:54 +02:00
There is no reason any more for application code to show error messages in a panel. Just return an error instead.
161 lines
4.4 KiB
Go
161 lines
4.4 KiB
Go
package controllers
|
|
|
|
import (
|
|
"errors"
|
|
|
|
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
|
)
|
|
|
|
// Embed this into your list controller to get some convenience methods for
|
|
// ensuring a single item is selected, etc.
|
|
|
|
type ListControllerTrait[T comparable] struct {
|
|
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,
|
|
getSelectedItem: getSelected,
|
|
getSelectedItems: getSelectedItems,
|
|
}
|
|
}
|
|
|
|
// Convenience function for combining multiple disabledReason callbacks.
|
|
// The first callback to return a disabled reason will be the one returned.
|
|
func (self *ListControllerTrait[T]) require(callbacks ...func() *types.DisabledReason) func() *types.DisabledReason {
|
|
return func() *types.DisabledReason {
|
|
for _, callback := range callbacks {
|
|
if disabledReason := callback(); disabledReason != nil {
|
|
return disabledReason
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// Convenience function for enforcing that a single item is selected.
|
|
// Also takes callbacks for additional disabled reasons, and passes the selected
|
|
// item into each one.
|
|
func (self *ListControllerTrait[T]) singleItemSelected(callbacks ...func(T) *types.DisabledReason) func() *types.DisabledReason {
|
|
return func() *types.DisabledReason {
|
|
if self.context.GetList().AreMultipleItemsSelected() {
|
|
return &types.DisabledReason{Text: self.c.Tr.RangeSelectNotSupported}
|
|
}
|
|
|
|
var zeroValue T
|
|
item := self.getSelectedItem()
|
|
if item == zeroValue {
|
|
return &types.DisabledReason{Text: self.c.Tr.NoItemSelected}
|
|
}
|
|
|
|
for _, callback := range callbacks {
|
|
if reason := callback(item); reason != nil {
|
|
return reason
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// 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.getSelectedItem()
|
|
if commit == zeroValue {
|
|
return errors.New(self.c.Tr.NoItemSelected)
|
|
}
|
|
|
|
return callback(commit)
|
|
}
|
|
}
|
|
|
|
func (self *ListControllerTrait[T]) withItems(callback func([]T) error) func() error {
|
|
return func() error {
|
|
items, _, _ := self.getSelectedItems()
|
|
if len(items) == 0 {
|
|
return errors.New(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 errors.New(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.getSelectedItem()
|
|
if commit == zeroValue {
|
|
return nil
|
|
}
|
|
|
|
return callback(commit)
|
|
}
|
|
}
|
|
|
|
// All controllers must implement this method so we're defining it here for convenience
|
|
func (self *ListControllerTrait[T]) Context() types.Context {
|
|
return self.context
|
|
}
|