diff --git a/go.mod b/go.mod index 958440ca6..fd00f19d8 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/gookit/color v1.4.2 github.com/imdario/mergo v0.3.11 github.com/integrii/flaggy v1.4.0 - github.com/jesseduffield/generics v0.0.0-20220319083513-5f145a9c0677 + github.com/jesseduffield/generics v0.0.0-20220319230408-6eaa96457df2 github.com/jesseduffield/go-git/v5 v5.1.2-0.20201006095850-341962be15a4 github.com/jesseduffield/gocui v0.3.1-0.20220227022729-69f0c798eec8 github.com/jesseduffield/minimal/gitignore v0.3.3-0.20211018110810-9cde264e6b1e diff --git a/go.sum b/go.sum index e99d02da5..2f8f8e890 100644 --- a/go.sum +++ b/go.sum @@ -66,8 +66,8 @@ github.com/integrii/flaggy v1.4.0 h1:A1x7SYx4jqu5NSrY14z8Z+0UyX2S5ygfJJrfolWR3zM github.com/integrii/flaggy v1.4.0/go.mod h1:tnTxHeTJbah0gQ6/K0RW0J7fMUBk9MCF5blhm43LNpI= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jesseduffield/generics v0.0.0-20220319083513-5f145a9c0677 h1:GoP06WWOE4AvTkAavXkF40nhYsg2hI09uVLDIuxzZYI= -github.com/jesseduffield/generics v0.0.0-20220319083513-5f145a9c0677/go.mod h1:+LLj9/WUPAP8LqCchs7P+7X0R98HiFujVFANdNaxhGk= +github.com/jesseduffield/generics v0.0.0-20220319230408-6eaa96457df2 h1:nGS5ysWioxYaPzwuEK3b4NKzBnNhQjiD1fK3bkn43cQ= +github.com/jesseduffield/generics v0.0.0-20220319230408-6eaa96457df2/go.mod h1:+LLj9/WUPAP8LqCchs7P+7X0R98HiFujVFANdNaxhGk= github.com/jesseduffield/go-git/v5 v5.1.2-0.20201006095850-341962be15a4 h1:GOQrmaE8i+KEdB8NzAegKYd4tPn/inM0I1uo0NXFerg= github.com/jesseduffield/go-git/v5 v5.1.2-0.20201006095850-341962be15a4/go.mod h1:nGNEErzf+NRznT+N2SWqmHnDnF9aLgANB1CUNEan09o= github.com/jesseduffield/gocui v0.3.1-0.20220227022729-69f0c798eec8 h1:9N08i5kjvOfkzMj6THmIM110wPTQLdVYEOHMHT2DFiI= diff --git a/pkg/app/app.go b/pkg/app/app.go index 2d279936f..eeb1b849f 100644 --- a/pkg/app/app.go +++ b/pkg/app/app.go @@ -14,6 +14,7 @@ import ( "strings" "github.com/aybabtme/humanlog" + "github.com/jesseduffield/generics/slices" "github.com/jesseduffield/lazygit/pkg/commands" "github.com/jesseduffield/lazygit/pkg/commands/git_config" "github.com/jesseduffield/lazygit/pkg/commands/oscommands" @@ -284,13 +285,9 @@ func (app *App) Rebase() error { // Close closes any resources func (app *App) Close() error { - for _, closer := range app.closers { - err := closer.Close() - if err != nil { - return err - } - } - return nil + return slices.TryForEach(app.closers, func(closer io.Closer) error { + return closer.Close() + }) } // KnownError takes an error and tells us whether it's an error that we know about where we can print a nicely formatted version of it rather than panicking with a stack trace @@ -299,10 +296,10 @@ func (app *App) KnownError(err error) (string, bool) { knownErrorMessages := []string{app.Tr.MinGitVersionError} - for _, message := range knownErrorMessages { - if errorMessage == message { - return message, true - } + if message, ok := slices.Find(knownErrorMessages, func(knownErrorMessage string) bool { + return knownErrorMessage == errorMessage + }); ok { + return message, true } mappings := []errorMapping{ @@ -312,11 +309,12 @@ func (app *App) KnownError(err error) (string, bool) { }, } - for _, mapping := range mappings { - if strings.Contains(errorMessage, mapping.originalError) { - return mapping.newError, true - } + if mapping, ok := slices.Find(mappings, func(mapping errorMapping) bool { + return strings.Contains(errorMessage, mapping.originalError) + }); ok { + return mapping.newError, true } + return "", false } diff --git a/pkg/cheatsheet/generate.go b/pkg/cheatsheet/generate.go index ecb75f935..04d8d3fd5 100644 --- a/pkg/cheatsheet/generate.go +++ b/pkg/cheatsheet/generate.go @@ -141,12 +141,11 @@ outer: if existing == nil { contextAndViewBindingMap[key] = []*types.Binding{binding} } else { - for _, navBinding := range contextAndViewBindingMap[key] { - if navBinding.Description == binding.Description { - continue outer - } + if !slices.Some(contextAndViewBindingMap[key], func(navBinding *types.Binding) bool { + return navBinding.Description == binding.Description + }) { + contextAndViewBindingMap[key] = append(contextAndViewBindingMap[key], binding) } - contextAndViewBindingMap[key] = append(contextAndViewBindingMap[key], binding) } continue outer diff --git a/pkg/gui/information_panel.go b/pkg/gui/information_panel.go index 3e317a349..4527da43b 100644 --- a/pkg/gui/information_panel.go +++ b/pkg/gui/information_panel.go @@ -3,15 +3,14 @@ package gui import ( "fmt" + "github.com/jesseduffield/generics/slices" "github.com/jesseduffield/lazygit/pkg/constants" "github.com/jesseduffield/lazygit/pkg/gui/style" ) func (gui *Gui) informationStr() string { - for _, mode := range gui.modeStatuses() { - if mode.isActive() { - return mode.description() - } + if activeMode, ok := gui.getActiveMode(); ok { + return activeMode.description() } if gui.g.Mouse { @@ -23,6 +22,12 @@ func (gui *Gui) informationStr() string { } } +func (gui *Gui) getActiveMode() (modeStatus, bool) { + return slices.Find(gui.modeStatuses(), func(mode modeStatus) bool { + return mode.isActive() + }) +} + func (gui *Gui) handleInfoClick() error { if !gui.g.Mouse { return nil @@ -33,13 +38,11 @@ func (gui *Gui) handleInfoClick() error { cx, _ := view.Cursor() width, _ := view.Size() - for _, mode := range gui.modeStatuses() { - if mode.isActive() { - if width-cx > len(gui.c.Tr.ResetInParentheses) { - return nil - } - return mode.reset() + if activeMode, ok := gui.getActiveMode(); ok { + if width-cx > len(gui.c.Tr.ResetInParentheses) { + return nil } + return activeMode.reset() } // if we're not in an active mode we show the donate button diff --git a/vendor/github.com/jesseduffield/generics/slices/slices.go b/vendor/github.com/jesseduffield/generics/slices/slices.go index 1d224255a..18ad4694f 100644 --- a/vendor/github.com/jesseduffield/generics/slices/slices.go +++ b/vendor/github.com/jesseduffield/generics/slices/slices.go @@ -47,6 +47,32 @@ func MapWithIndex[T any, V any](slice []T, f func(T, int) V) []V { return result } +func TryMap[T any, V any](slice []T, f func(T) (V, error)) ([]V, error) { + result := make([]V, 0, len(slice)) + for _, value := range slice { + output, err := f(value) + if err != nil { + return nil, err + } + result = append(result, output) + } + + return result, nil +} + +func TryMapWithIndex[T any, V any](slice []T, f func(T, int) (V, error)) ([]V, error) { + result := make([]V, 0, len(slice)) + for i, value := range slice { + output, err := f(value, i) + if err != nil { + return nil, err + } + result = append(result, output) + } + + return result, nil +} + // Produces a new slice, leaves the input slice untouched. func FlatMap[T any, V any](slice []T, f func(T) []V) []V { // impossible to know how long this slice will be in the end but the length @@ -59,6 +85,17 @@ func FlatMap[T any, V any](slice []T, f func(T) []V) []V { return result } +func FlatMapWithIndex[T any, V any](slice []T, f func(T, int) []V) []V { + // impossible to know how long this slice will be in the end but the length + // of the original slice is the lower bound + result := make([]V, 0, len(slice)) + for i, value := range slice { + result = append(result, f(value, i)...) + } + + return result +} + func Flatten[T any](slice [][]T) []T { result := make([]T, 0, len(slice)) for _, subSlice := range slice { @@ -96,6 +133,34 @@ func FilterWithIndex[T any](slice []T, f func(T, int) bool) []T { return result } +func TryFilter[T any](slice []T, test func(T) (bool, error)) ([]T, error) { + result := make([]T, 0) + for _, element := range slice { + ok, err := test(element) + if err != nil { + return nil, err + } + if ok { + result = append(result, element) + } + } + return result, nil +} + +func TryFilterWithIndex[T any](slice []T, test func(T, int) (bool, error)) ([]T, error) { + result := make([]T, 0) + for i, element := range slice { + ok, err := test(element, i) + if err != nil { + return nil, err + } + if ok { + result = append(result, element) + } + } + return result, nil +} + // Mutates original slice. Intended usage is to reassign the slice result to the input slice. func FilterInPlace[T any](slice []T, test func(T) bool) []T { newLength := 0 @@ -125,10 +190,10 @@ func ReverseInPlace[T any](slice []T) { } // Produces a new slice, leaves the input slice untouched. -func FilterMap[T any, E any](slice []T, test func(T) (bool, E)) []E { +func FilterMap[T any, E any](slice []T, test func(T) (E, bool)) []E { result := make([]E, 0, len(slice)) for _, element := range slice { - ok, mapped := test(element) + mapped, ok := test(element) if ok { result = append(result, mapped) } @@ -137,17 +202,48 @@ func FilterMap[T any, E any](slice []T, test func(T) (bool, E)) []E { return result } -// Produces a new slice, leaves the input slice untouched. -func FilterThenMap[T any, E any](slice []T, test func(T) bool, mapFn func(T) E) []E { +func FilterMapWithIndex[T any, E any](slice []T, test func(T, int) (E, bool)) []E { result := make([]E, 0, len(slice)) - for _, element := range slice { - if test(element) { - result = append(result, mapFn(element)) + for i, element := range slice { + mapped, ok := test(element, i) + if ok { + result = append(result, mapped) } } + return result } +func TryFilterMap[T any, E any](slice []T, test func(T) (E, bool, error)) ([]E, error) { + result := make([]E, 0, len(slice)) + for _, element := range slice { + mapped, ok, err := test(element) + if err != nil { + return nil, err + } + if ok { + result = append(result, mapped) + } + } + + return result, nil +} + +func TryFilterMapWithIndex[T any, E any](slice []T, test func(T, int) (E, bool, error)) ([]E, error) { + result := make([]E, 0, len(slice)) + for i, element := range slice { + mapped, ok, err := test(element, i) + if err != nil { + return nil, err + } + if ok { + result = append(result, mapped) + } + } + + return result, nil +} + // Prepends items to the beginning of a slice. // E.g. Prepend([]int{1,2}, 3, 4) = []int{3,4,1,2} // Mutates original slice. Intended usage is to reassign the slice result to the input slice. @@ -241,6 +337,45 @@ func MinBy[T any, V constraints.Ordered](slice []T, f func(T) V) V { return min } +func Find[T any](slice []T, f func(T) bool) (T, bool) { + for _, element := range slice { + if f(element) { + return element, true + } + } + return zero[T](), false +} + +func ForEach[T any](slice []T, f func(T)) { + for _, element := range slice { + f(element) + } +} + +func ForEachWithIndex[T any](slice []T, f func(T, int)) { + for i, element := range slice { + f(element, i) + } +} + +func TryForEach[T any](slice []T, f func(T) error) error { + for _, element := range slice { + if err := f(element); err != nil { + return err + } + } + return nil +} + +func TryForEachWithIndex[T any](slice []T, f func(T, int) error) error { + for i, element := range slice { + if err := f(element, i); err != nil { + return err + } + } + return nil +} + func zero[T any]() T { var value T return value diff --git a/vendor/modules.txt b/vendor/modules.txt index a7b196cea..e6dc129fc 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -120,7 +120,7 @@ github.com/integrii/flaggy # github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 ## explicit github.com/jbenet/go-context/io -# github.com/jesseduffield/generics v0.0.0-20220319083513-5f145a9c0677 +# github.com/jesseduffield/generics v0.0.0-20220319230408-6eaa96457df2 ## explicit; go 1.18 github.com/jesseduffield/generics/maps github.com/jesseduffield/generics/set