diff options
19 files changed, 384 insertions, 299 deletions
@@ -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-20220318214805-3397e5e19e9f + github.com/jesseduffield/generics v0.0.0-20220319042131-63614a800d5f 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 @@ -32,7 +32,6 @@ require ( github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad github.com/stretchr/testify v1.7.0 github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 - golang.org/x/exp v0.0.0-20220318154914-8dddf5d87bd8 gopkg.in/ozeidan/fuzzy-patricia.v3 v3.0.0 ) @@ -61,6 +60,7 @@ require ( github.com/sergi/go-diff v1.1.0 // indirect github.com/xanzy/ssh-agent v0.2.1 // indirect golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 // indirect + golang.org/x/exp v0.0.0-20220318154914-8dddf5d87bd8 // indirect golang.org/x/net v0.0.0-20201002202402-0a1ea396d57c // indirect golang.org/x/sys v0.0.0-20220224120231-95c6836cb0e7 // indirect golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect @@ -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-20220318214805-3397e5e19e9f h1:9USuZttmg5ioHsjFyXboiGSbncpAqcKkq9qb4ga5PD0= -github.com/jesseduffield/generics v0.0.0-20220318214805-3397e5e19e9f/go.mod h1:+LLj9/WUPAP8LqCchs7P+7X0R98HiFujVFANdNaxhGk= +github.com/jesseduffield/generics v0.0.0-20220319042131-63614a800d5f h1:VZkNxrfkR344djm4Ju7QuKLXxZlaaOaNCrAWVRc1gvU= +github.com/jesseduffield/generics v0.0.0-20220319042131-63614a800d5f/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/cheatsheet/generate.go b/pkg/cheatsheet/generate.go index c7c2b0d37..d88f3d733 100644 --- a/pkg/cheatsheet/generate.go +++ b/pkg/cheatsheet/generate.go @@ -12,8 +12,8 @@ import ( "fmt" "log" "os" - "sort" + "github.com/jesseduffield/generics/slices" "github.com/jesseduffield/lazygit/pkg/app" "github.com/jesseduffield/lazygit/pkg/config" "github.com/jesseduffield/lazygit/pkg/gui" @@ -180,9 +180,9 @@ outer: groupedBindings = append(groupedBindings, groupedBindingsType{contextAndView: contextAndView, bindings: contextBindings}) } - sort.Slice(groupedBindings, func(i, j int) bool { - first := groupedBindings[i].contextAndView - second := groupedBindings[j].contextAndView + slices.SortFunc(groupedBindings, func(a, b groupedBindingsType) bool { + first := a.contextAndView + second := b.contextAndView if first.title == "" { return true } diff --git a/pkg/commands/hosting_service/hosting_service.go b/pkg/commands/hosting_service/hosting_service.go index b448e3925..15fc244ba 100644 --- a/pkg/commands/hosting_service/hosting_service.go +++ b/pkg/commands/hosting_service/hosting_service.go @@ -10,7 +10,7 @@ import ( "github.com/jesseduffield/lazygit/pkg/utils" "github.com/sirupsen/logrus" - "golang.org/x/exp/slices" + "github.com/jesseduffield/generics/slices" ) // This package is for handling logic specific to a git hosting service like github, gitlab, bitbucket, etc. diff --git a/pkg/commands/loaders/branches.go b/pkg/commands/loaders/branches.go index 9fa1e80f4..90480ca9a 100644 --- a/pkg/commands/loaders/branches.go +++ b/pkg/commands/loaders/branches.go @@ -5,6 +5,7 @@ import ( "strings" "github.com/jesseduffield/generics/set" + "github.com/jesseduffield/generics/slices" "github.com/jesseduffield/go-git/v5/config" "github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/common" @@ -78,8 +79,7 @@ outer: if branch.Head { foundHead = true branch.Recency = " *" - branches = append(branches[0:i], branches[i+1:]...) - branches = append([]*models.Branch{branch}, branches...) + branches = slices.Move(branches, i, 0) break } } @@ -88,7 +88,7 @@ outer: if err != nil { return nil, err } - branches = append([]*models.Branch{{Name: currentBranchName, DisplayName: currentBranchDisplayName, Head: true, Recency: " *"}}, branches...) + branches = slices.Prepend(branches, &models.Branch{Name: currentBranchName, DisplayName: currentBranchDisplayName, Head: true, Recency: " *"}) } configBranches, err := self.config.Branches() @@ -158,10 +158,10 @@ func (self *BranchLoader) obtainBranches() []*models.Branch { trimmedOutput := strings.TrimSpace(output) outputLines := strings.Split(trimmedOutput, "\n") - branches := make([]*models.Branch, 0, len(outputLines)) - for _, line := range outputLines { + + branches := slices.FilterMap(outputLines, func(line string) (*models.Branch, bool) { if line == "" { - continue + return nil, false } split := strings.Split(line, SEPARATION_CHAR) @@ -169,12 +169,11 @@ func (self *BranchLoader) obtainBranches() []*models.Branch { // Ignore line if it isn't separated into 4 parts // This is probably a warning message, for more info see: // https://github.com/jesseduffield/lazygit/issues/1385#issuecomment-885580439 - continue + return nil, false } - branch := obtainBranch(split) - branches = append(branches, branch) - } + return obtainBranch(split), true + }) return branches } diff --git a/pkg/commands/loaders/remotes.go b/pkg/commands/loaders/remotes.go index bd1fe0b6a..3cd57d9a2 100644 --- a/pkg/commands/loaders/remotes.go +++ b/pkg/commands/loaders/remotes.go @@ -3,13 +3,14 @@ package loaders import ( "fmt" "regexp" - "sort" "strings" + "github.com/jesseduffield/generics/slices" gogit "github.com/jesseduffield/go-git/v5" "github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/commands/oscommands" "github.com/jesseduffield/lazygit/pkg/common" + "github.com/samber/lo" ) type RemoteLoader struct { @@ -42,37 +43,35 @@ func (self *RemoteLoader) GetRemotes() ([]*models.Remote, error) { } // first step is to get our remotes from go-git - remotes := make([]*models.Remote, len(goGitRemotes)) - for i, goGitRemote := range goGitRemotes { + remotes := lo.Map(goGitRemotes, func(goGitRemote *gogit.Remote, _ int) *models.Remote { remoteName := goGitRemote.Config().Name re := regexp.MustCompile(fmt.Sprintf(`(?m)^\s*%s\/([\S]+)`, remoteName)) matches := re.FindAllStringSubmatch(remoteBranchesStr, -1) - branches := make([]*models.RemoteBranch, len(matches)) - for j, match := range matches { - branches[j] = &models.RemoteBranch{ + branches := lo.Map(matches, func(match []string, _ int) *models.RemoteBranch { + return &models.RemoteBranch{ Name: match[1], RemoteName: remoteName, } - } + }) - remotes[i] = &models.Remote{ + return &models.Remote{ Name: goGitRemote.Config().Name, Urls: goGitRemote.Config().URLs, Branches: branches, } - } + }) // now lets sort our remotes by name alphabetically - sort.Slice(remotes, func(i, j int) bool { + slices.SortFunc(remotes, func(a, b *models.Remote) bool { // we want origin at the top because we'll be most likely to want it - if remotes[i].Name == "origin" { + if a.Name == "origin" { return true } - if remotes[j].Name == "origin" { + if b.Name == "origin" { return false } - return strings.ToLower(remotes[i].Name) < strings.ToLower(remotes[j].Name) + return strings.ToLower(a.Name) < strings.ToLower(b.Name) }) return remotes, nil diff --git a/pkg/gui/controllers/global_controller.go b/pkg/gui/controllers/global_controller.go index c45e98d85..e59231739 100644 --- a/pkg/gui/controllers/global_controller.go +++ b/pkg/gui/controllers/global_controller.go @@ -1,7 +1,7 @@ package controllers import ( - "github.com/jesseduffield/generics/list" + "github.com/jesseduffield/generics/slices" "github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers" "github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/utils" @@ -57,7 +57,7 @@ func (self *GlobalController) customCommand() error { func (self *GlobalController) GetCustomCommandsHistorySuggestionsFunc() func(string) []*types.Suggestion { // reversing so that we display the latest command first - history := list.Reverse(self.c.GetAppState().CustomCommandsHistory) + history := slices.Reverse(self.c.GetAppState().CustomCommandsHistory) return helpers.FuzzySearchFunc(history) } diff --git a/pkg/gui/controllers/helpers/cherry_pick_helper.go b/pkg/gui/controllers/helpers/cherry_pick_helper.go index e4a9b3e81..c433655d0 100644 --- a/pkg/gui/controllers/helpers/cherry_pick_helper.go +++ b/pkg/gui/controllers/helpers/cherry_pick_helper.go @@ -2,6 +2,7 @@ package helpers import ( "github.com/jesseduffield/generics/set" + "github.com/jesseduffield/generics/slices" "github.com/jesseduffield/lazygit/pkg/commands" "github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/gui/context" @@ -118,12 +119,12 @@ func (self *CherryPickHelper) add(selectedCommit *models.Commit, commitsList []* commitSet := self.CherryPickedCommitShaSet() commitSet.Add(selectedCommit.Sha) - commitsInSet := lo.Filter(commitsList, func(commit *models.Commit, _ int) bool { - return commitSet.Includes(commit.Sha) - }) - newCommits := lo.Map(commitsInSet, func(commit *models.Commit, _ int) *models.Commit { - return &models.Commit{Name: commit.Name, Sha: commit.Sha} - }) + newCommits := slices.FilterThenMap(commitsList, + func(commit *models.Commit) bool { return commitSet.Includes(commit.Sha) }, + func(commit *models.Commit) *models.Commit { + return &models.Commit{Name: commit.Name, Sha: commit.Sha} + }, + ) self.getData().CherryPickedCommits = newCommits } diff --git a/pkg/gui/filetree/inode.go b/pkg/gui/filetree/inode.go index 7c8b9fb75..48cdc3be3 100644 --- a/pkg/gui/filetree/inode.go +++ b/pkg/gui/filetree/inode.go @@ -1,8 +1,6 @@ package filetree -import ( - "sort" -) +import "github.com/jesseduffield/generics/slices" type INode interface { IsNil() bool @@ -27,19 +25,17 @@ func sortChildren(node INode) { return } - children := node.GetChildren() - sortedChildren := make([]INode, len(children)) - copy(sortedChildren, children) + sortedChildren := slices.Clone(node.GetChildren()) - sort.Slice(sortedChildren, func(i, j int) bool { - if !sortedChildren[i].IsLeaf() && sortedChildren[j].IsLeaf() { + slices.SortFunc(sortedChildren, func(a, b INode) bool { + if !a.IsLeaf() && b.IsLeaf() { return true } - if sortedChildren[i].IsLeaf() && !sortedChildren[j].IsLeaf() { + if a.IsLeaf() && !b.IsLeaf() { return false } - return sortedChildren[i].GetPath() < sortedChildren[j].GetPath() + return a.GetPath() < b.GetPath() }) // TODO: think about making this in-place diff --git a/pkg/gui/presentation/graph/graph.go b/pkg/gui/presentation/graph/graph.go index 0e193cba8..70ab53079 100644 --- a/pkg/gui/presentation/graph/graph.go +++ b/pkg/gui/presentation/graph/graph.go @@ -2,10 +2,10 @@ package graph import ( "runtime" - "sort" "strings" "sync" + "github.com/jesseduffield/generics/slices" "github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/gui/style" "github.com/jesseduffield/lazygit/pkg/utils" @@ -265,11 +265,11 @@ func getNextPipes(prevPipes []*Pipe, commit *models.Commit, getStyle func(c *mod } // not efficient but doing it for now: sorting my pipes by toPos, then by kind - sort.Slice(newPipes, func(i, j int) bool { - if newPipes[i].toPos == newPipes[j].toPos { - return newPipes[i].kind < newPipes[j].kind + slices.SortFunc(newPipes, func(a, b *Pipe) bool { + if a.toPos == b.toPos { + return a.kind < b.kind } - return newPipes[i].toPos < newPipes[j].toPos + return a.toPos < b.toPos }) return newPipes diff --git a/vendor/github.com/jesseduffield/generics/list/comparable_list.go b/vendor/github.com/jesseduffield/generics/list/comparable_list.go deleted file mode 100644 index 21d56a80b..000000000 --- a/vendor/github.com/jesseduffield/generics/list/comparable_list.go +++ /dev/null @@ -1,49 +0,0 @@ -package list - -import ( - "golang.org/x/exp/slices" -) - -type ComparableList[T comparable] struct { - *List[T] -} - -func NewComparable[T comparable]() *ComparableList[T] { - return &ComparableList[T]{List: New[T]()} -} - -func NewComparableFromSlice[T comparable](slice []T) *ComparableList[T] { - return &ComparableList[T]{List: NewFromSlice(slice)} -} - -func (l *ComparableList[T]) Equal(other *ComparableList[T]) bool { - return l.EqualSlice(other.ToSlice()) -} - -func (l *ComparableList[T]) EqualSlice(other []T) bool { - return slices.Equal(l.ToSlice(), other) -} - -func (l *ComparableList[T]) Compact() { - l.slice = slices.Compact(l.slice) -} - -func (l *ComparableList[T]) Index(needle T) int { - return slices.Index(l.slice, needle) -} - -func (l *ComparableList[T]) Contains(needle T) bool { - return slices.Contains(l.slice, needle) -} - -func (l *ComparableList[T]) SortFuncInPlace(test func(a T, b T) bool) { - slices.SortFunc(l.slice, test) -} - -func (l *ComparableList[T]) SortFunc(test func(a T, b T) bool) *ComparableList[T] { - newSlice := slices.Clone(l.slice) - - slices.SortFunc(newSlice, test) - - return NewComparableFromSlice(newSlice) -} diff --git a/vendor/github.com/jesseduffield/generics/list/functions.go b/vendor/github.com/jesseduffield/generics/list/functions.go deleted file mode 100644 index 21578b82f..000000000 --- a/vendor/github.com/jesseduffield/generics/list/functions.go +++ /dev/null @@ -1,72 +0,0 @@ -package list - -func Some[T any](slice []T, test func(T) bool) bool { - for _, value := range slice { - if test(value) { - return true - } - } - - return false -} - -func Every[T any](slice []T, test func(T) bool) bool { - for _, value := range slice { - if !test(value) { - return false - } - } - - return true -} - -func Map[T any, V any](slice []T, f func(T) V) []V { - result := make([]V, len(slice)) - for i, value := range slice { - result[i] = f(value) - } - - return result -} - -func MapInPlace[T any](slice []T, f func(T) T) { - for i, value := range slice { - slice[i] = f(value) - } -} - -func Filter[T any](slice []T, test func(T) bool) []T { - result := make([]T, 0) - for _, element := range slice { - if test(element) { - result = append(result, element) - } - } - return result -} - -func FilterInPlace[T any](slice []T, test func(T) bool) []T { - newLength := 0 - for _, element := range slice { - if test(element) { - slice[newLength] = element - newLength++ - } - } - - return slice[:newLength] -} - -func Reverse[T any](slice []T) []T { - result := make([]T, len(slice)) - for i := range slice { - result[i] = slice[len(slice)-1-i] - } - return result -} - -func ReverseInPlace[T any](slice []T) { - for i, j := 0, len(slice)-1; i < j; i, j = i+1, j-1 { - slice[i], slice[j] = slice[j], slice[i] - } -} diff --git a/vendor/github.com/jesseduffield/generics/list/list.go b/vendor/github.com/jesseduffield/generics/list/list.go deleted file mode 100644 index 2b0f43010..000000000 --- a/vendor/github.com/jesseduffield/generics/list/list.go +++ /dev/null @@ -1,117 +0,0 @@ -package list - -import ( - "golang.org/x/exp/slices" -) - -type List[T any] struct { - slice []T -} - -func New[T any]() *List[T] { - return &List[T]{} -} - -func NewFromSlice[T any](slice []T) *List[T] { - return &List[T]{slice: slice} -} - -func (l *List[T]) ToSlice() []T { - return l.slice -} - -// Mutative methods - -func (l *List[T]) Push(v T) { - l.slice = append(l.slice, v) -} - -func (l *List[T]) Pop() { - l.slice = l.slice[0 : len(l.slice)-1] -} - -func (l *List[T]) Insert(index int, values ...T) { - l.slice = slices.Insert(l.slice, index, values...) -} - -func (l *List[T]) Append(values ...T) { - l.slice = append(l.slice, values...) -} - -func (l *List[T]) Prepend(values ...T) { - l.slice = append(values, l.slice...) -} - -func (l *List[T]) Remove(index int) { - l.Delete(index, index+1) -} - -func (l *List[T]) Delete(from int, to int) { - l.slice = slices.Delete(l.slice, from, to) -} - -func (l *List[T]) FilterInPlace(test func(value T) bool) { - l.slice = FilterInPlace(l.slice, test) -} - -func (l *List[T]) MapInPlace(f func(value T) T) { - MapInPlace(l.slice, f) -} - -func (l *List[T]) ReverseInPlace() { - ReverseInPlace(l.slice) -} - -// Non-mutative methods - -// Similar to Append but we leave the original slice untouched and return a new list -func (l *List[T]) Concat(values ...T) *List[T] { - newSlice := make([]T, 0, len(l.slice)+len(values)) - newSlice = append(newSlice, l.slice...) - newSlice = append(newSlice, values...) - return &List[T]{slice: newSlice} -} - -func (l *List[T]) Filter(test func(value T) bool) *List[T] { - return NewFromSlice(Filter(l.slice, test)) -} - -// Unfortunately this does not support mapping from one type to another -// because Go does not yet (and may never) support methods defining their own -// type parameters. For that functionality you'll need to use the standalone -// Map function instead -func (l *List[T]) Map(f func(value T) T) *List[T] { - return NewFromSlice(Map(l.slice, f)) -} - -func (l *List[T]) Clone() *List[T] { - return NewFromSlice(slices.Clone(l.slice)) -} - -func (l *List[T]) Some(test func(value T) bool) bool { - return Some(l.slice, test) -} - -func (l *List[T]) Every(test func(value T) bool) bool { - return Every(l.slice, test) -} - -func (l *List[T]) IndexFunc(f func(T) bool) int { - return slices.IndexFunc(l.slice, f) -} - -func (l *List[T]) ContainsFunc(f func(T) bool) bool { - return l.IndexFunc(f) != -1 -} - -func (l *List[T]) Reverse() *List[T] { - return NewFromSlice(Reverse(l.slice)) -} - -func (l *List[T]) IsEmpty() bool { - return len(l.slice) == 0 -} - -func (l *List[T]) Len() int { - return len(l.slice) -} diff --git a/vendor/github.com/jesseduffield/generics/hashmap/functions.go b/vendor/github.com/jesseduffield/generics/maps/maps.go index 526222b1f..eaf890022 100644 --- a/vendor/github.com/jesseduffield/generics/hashmap/functions.go +++ b/vendor/github.com/jesseduffield/generics/maps/maps.go @@ -1,4 +1,4 @@ -package hashmap +package maps func Keys[Key comparable, Value any](m map[Key]Value) []Key { keys := make([]Key, 0, len(m)) diff --git a/vendor/github.com/jesseduffield/generics/set/set.go b/vendor/github.com/jesseduffield/generics/set/set.go index 3e9b9d9bf..317a4fa6b 100644 --- a/vendor/github.com/jesseduffield/generics/set/set.go +++ b/vendor/github.com/jesseduffield/generics/set/set.go @@ -1,6 +1,6 @@ package set -import "github.com/jesseduffield/generics/hashmap" +import "github.com/jesseduffield/generics/maps" type Set[T comparable] struct { hashMap map[T]bool @@ -45,5 +45,5 @@ func (s *Set[T]) Includes(value T) bool { // output slice is not necessarily in the same order that items were added func (s *Set[T]) ToSlice() []T { - return hashmap.Keys(s.hashMap) + return maps.Keys(s.hashMap) } diff --git a/vendor/github.com/jesseduffield/generics/slices/delegated_slices.go b/vendor/github.com/jesseduffield/generics/slices/delegated_slices.go new file mode 100644 index 000000000..015935331 --- /dev/null +++ b/vendor/github.com/jesseduffield/generics/slices/delegated_slices.go @@ -0,0 +1,117 @@ +package slices + +import ( + "golang.org/x/exp/constraints" + "golang.org/x/exp/slices" +) + +// This file delegates to the official slices package, so that we end up with a superset of the official API. + +// Equal reports whether two slices are equal: the same length and all +// elements equal. If the lengths are different, Equal returns false. +// Otherwise, the elements are compared in increasing index order, and the +// comparison stops at the first unequal pair. +// Floating point NaNs are not considered equal. +func Equal[E comparable](s1, s2 []E) bool { + return slices.Equal(s1, s2) +} + +// EqualFunc reports whether two slices are equal using a comparison +// function on each pair of elements. If the lengths are different, +// EqualFunc returns false. Otherwise, the elements are compared in +// increasing index order, and the comparison stops at the first index +// for which eq returns false. +func EqualFunc[E1, E2 any](s1 []E1, s2 []E2, eq func(E1, E2) bool) bool { + return slices.EqualFunc(s1, s2, eq) +} + +// Compare compares the elements of s1 and s2. +// The elements are compared sequentially, starting at index 0, +// until one element is not equal to the other. +// The result of comparing the first non-matching elements is returned. +// If both slices are equal until one of them ends, the shorter slice is +// considered less than the longer one. +// The result is 0 if s1 == s2, -1 if s1 < s2, and +1 if s1 > s2. +// Comparisons involving floating point NaNs are ignored. +func Compare[E constraints.Ordered](s1, s2 []E) int { + return slices.Compare(s1, s2) +} + +// CompareFunc is like Compare but uses a comparison function +// on each pair of elements. The elements are compared in increasing +// index order, and the comparisons stop after the first time cmp +// returns non-zero. +// The result is the first non-zero result of cmp; if cmp always +// returns 0 the result is 0 if len(s1) == len(s2), -1 if len(s1) < len(s2), +// and +1 if len(s1) > len(s2). +func CompareFunc[E1, E2 any](s1 []E1, s2 []E2, cmp func(E1, E2) int) int { + return slices.CompareFunc(s1, s2, cmp) +} + +// Index returns the index of the first occurrence of v in s, +// or -1 if not present. +func Index[E comparable](s []E, v E) int { + return slices.Index(s, v) +} + +// IndexFunc returns the first index i satisfying f(s[i]), +// or -1 if none do. +func IndexFunc[E any](s []E, f func(E) bool) int { + return slices.IndexFunc(s, f) +} + +// Contains reports whether v is present in s. +func Contains[E comparable](s []E, v E) bool { + return slices.Contains(s, v) +} + +// Insert inserts the values v... into s at index i, +// returning the modified slice. +// In the returned slice r, r[i] == v[0]. +// Insert panics if i is out of range. +// This function is O(len(s) + len(v)). +func Insert[S ~[]E, E any](s S, i int, v ...E) S { + return slices.Insert(s, i, v...) +} + +// Delete removes the elements s[i:j] from s, returning the modified slice. +// Delete panics if s[i:j] is not a valid slice of s. +// Delete modifies the contents of the slice s; it does not create a new slice. +// Delete is O(len(s)-(j-i)), so if many items must be deleted, it is better to +// make a single call deleting them all together than to delete one at a time. +func Delete[S ~[]E, E any](s S, i, j int) S { + return slices.Delete(s, i, j) +} + +// Clone returns a copy of the slice. +// The elements are copied using assignment, so this is a shallow clone. +func Clone[S ~[]E, E any](s S) S { + return slices.Clone(s) +} + +// Compact replaces consecutive runs of equal elements with a single copy. +// This is like the uniq command found on Unix. +// Compact modifies the contents of the slice s; it does not create a new slice. +// Intended usage is to assign the result back to the input slice. +func Compact[S ~[]E, E comparable](s S) S { + return slices.Compact(s) +} + +// CompactFunc is like Compact but uses a comparison function. +func CompactFunc[S ~[]E, E any](s S, eq func(E, E) bool) S { + return slices.CompactFunc(s, eq) +} + +// Grow increases the slice's capacity, if necessary, to guarantee space for +// another n elements. After Grow(n), at least n elements can be appended +// to the slice without another allocation. Grow may modify elements of the +// slice between the length and the capacity. If n is negative or too large to +// allocate the memory, Grow panics. +func Grow[S ~[]E, E any](s S, n int) S { + return slices.Grow(s, n) +} + +// Clip removes unused capacity from the slice, returning s[:len(s):len(s)]. +func Clip[S ~[]E, E any](s S) S { + return slices.Clip(s) +} diff --git a/vendor/github.com/jesseduffield/generics/slices/delegated_sort.go b/vendor/github.com/jesseduffield/generics/slices/delegated_sort.go new file mode 100644 index 000000000..0741f0c55 --- /dev/null +++ b/vendor/github.com/jesseduffield/generics/slices/delegated_sort.go @@ -0,0 +1,57 @@ +package slices + +import ( + "golang.org/x/exp/constraints" + "golang.org/x/exp/slices" +) + +// This file delegates to the official slices package, so that we end up with a superset of the official API. + +// Sort sorts a slice of any ordered type in ascending order. +func Sort[E constraints.Ordered](x []E) { + slices.Sort(x) +} + +// Sort sorts the slice x in ascending order as determined by the less function. +// This sort is not guaranteed to be stable. +func SortFunc[E any](x []E, less func(a, b E) bool) { + slices.SortFunc(x, less) +} + +// SortStable sorts the slice x while keeping the original order of equal +// elements, using less to compare elements. +func SortStableFunc[E any](x []E, less func(a, b E) bool) { + slices.SortStableFunc(x, less) +} + +// IsSorted reports whether x is sorted in ascending order. +func IsSorted[E constraints.Ordered](x []E) bool { + return slices.IsSorted(x) +} + +// IsSortedFunc reports whether x is sorted in ascending order, with less as the +// comparison function. +func IsSortedFunc[E any](x []E, less func(a, b E) bool) bool { + return slices.IsSortedFunc(x, less) +} + +// BinarySearch searches for target in a sorted slice and returns the smallest +// index at which target is found. If the target is not found, the index at +// which it could be inserted into the slice is returned; therefore, if the +// intention is to find target itself a separate che |