1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2025-04-13 11:50:28 +02:00

Standardise on using lo for slice functions

We've been sometimes using lo and sometimes using my slices package, and we need to pick one
for consistency. Lo is more extensive and better maintained so we're going with that.

My slices package was a superset of go's own slices package so in some places I've just used
the official one (the methods were just wrappers anyway).

I've also moved the remaining methods into the utils package.
This commit is contained in:
Jesse Duffield 2023-07-24 13:06:42 +10:00
parent ea54cb6e9c
commit e33fe37a99
58 changed files with 212 additions and 732 deletions

View File

@ -13,7 +13,6 @@ import (
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/spf13/afero" "github.com/spf13/afero"
"github.com/jesseduffield/generics/slices"
appTypes "github.com/jesseduffield/lazygit/pkg/app/types" appTypes "github.com/jesseduffield/lazygit/pkg/app/types"
"github.com/jesseduffield/lazygit/pkg/commands" "github.com/jesseduffield/lazygit/pkg/commands"
"github.com/jesseduffield/lazygit/pkg/commands/git_commands" "github.com/jesseduffield/lazygit/pkg/commands/git_commands"
@ -267,7 +266,11 @@ func (app *App) Run(startArgs appTypes.StartArgs) error {
// Close closes any resources // Close closes any resources
func (app *App) Close() error { func (app *App) Close() error {
return slices.TryForEach(app.closers, func(closer io.Closer) error { for _, closer := range app.closers {
return closer.Close() if err := closer.Close(); err != nil {
}) return err
}
}
return nil
} }

View File

@ -6,10 +6,10 @@ import (
"strings" "strings"
"github.com/fsmiamoto/git-todo-parser/todo" "github.com/fsmiamoto/git-todo-parser/todo"
"github.com/jesseduffield/generics/slices"
"github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/common" "github.com/jesseduffield/lazygit/pkg/common"
"github.com/jesseduffield/lazygit/pkg/env" "github.com/jesseduffield/lazygit/pkg/env"
"github.com/samber/lo"
) )
type TodoLine struct { type TodoLine struct {
@ -26,11 +26,11 @@ func (self *TodoLine) ToString() string {
} }
func TodoLinesToString(todoLines []TodoLine) string { func TodoLinesToString(todoLines []TodoLine) string {
lines := slices.Map(todoLines, func(todoLine TodoLine) string { lines := lo.Map(todoLines, func(todoLine TodoLine, _ int) string {
return todoLine.ToString() return todoLine.ToString()
}) })
return strings.Join(slices.Reverse(lines), "") return strings.Join(lo.Reverse(lines), "")
} }
type ChangeTodoAction struct { type ChangeTodoAction struct {

View File

@ -3,8 +3,8 @@ package app
import ( import (
"strings" "strings"
"github.com/jesseduffield/generics/slices"
"github.com/jesseduffield/lazygit/pkg/i18n" "github.com/jesseduffield/lazygit/pkg/i18n"
"github.com/samber/lo"
) )
type errorMapping struct { type errorMapping struct {
@ -18,7 +18,7 @@ func knownError(tr *i18n.TranslationSet, err error) (string, bool) {
knownErrorMessages := []string{tr.MinGitVersionError} knownErrorMessages := []string{tr.MinGitVersionError}
if slices.Contains(knownErrorMessages, errorMessage) { if lo.Contains(knownErrorMessages, errorMessage) {
return errorMessage, true return errorMessage, true
} }
@ -29,7 +29,7 @@ func knownError(tr *i18n.TranslationSet, err error) (string, bool) {
}, },
} }
if mapping, ok := slices.Find(mappings, func(mapping errorMapping) bool { if mapping, ok := lo.Find(mappings, func(mapping errorMapping) bool {
return strings.Contains(errorMessage, mapping.originalError) return strings.Contains(errorMessage, mapping.originalError)
}); ok { }); ok {
return mapping.newError, true return mapping.newError, true

View File

@ -15,7 +15,6 @@ import (
"strings" "strings"
"github.com/jesseduffield/generics/maps" "github.com/jesseduffield/generics/maps"
"github.com/jesseduffield/generics/slices"
"github.com/jesseduffield/lazycore/pkg/utils" "github.com/jesseduffield/lazycore/pkg/utils"
"github.com/jesseduffield/lazygit/pkg/app" "github.com/jesseduffield/lazygit/pkg/app"
"github.com/jesseduffield/lazygit/pkg/config" "github.com/jesseduffield/lazygit/pkg/config"
@ -23,6 +22,7 @@ import (
"github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/i18n" "github.com/jesseduffield/lazygit/pkg/i18n"
"github.com/samber/lo" "github.com/samber/lo"
"golang.org/x/exp/slices"
) )
type bindingSection struct { type bindingSection struct {
@ -129,7 +129,7 @@ func localisedTitle(tr *i18n.TranslationSet, str string) string {
func getBindingSections(bindings []*types.Binding, tr *i18n.TranslationSet) []*bindingSection { func getBindingSections(bindings []*types.Binding, tr *i18n.TranslationSet) []*bindingSection {
excludedViews := []string{"stagingSecondary", "patchBuildingSecondary"} excludedViews := []string{"stagingSecondary", "patchBuildingSecondary"}
bindingsToDisplay := slices.Filter(bindings, func(binding *types.Binding) bool { bindingsToDisplay := lo.Filter(bindings, func(binding *types.Binding, _ int) bool {
if lo.Contains(excludedViews, binding.ViewName) { if lo.Contains(excludedViews, binding.ViewName) {
return false return false
} }
@ -162,7 +162,7 @@ func getBindingSections(bindings []*types.Binding, tr *i18n.TranslationSet) []*b
return a.header.title < b.header.title return a.header.title < b.header.title
}) })
return slices.Map(bindingGroups, func(hb headerWithBindings) *bindingSection { return lo.Map(bindingGroups, func(hb headerWithBindings, _ int) *bindingSection {
return &bindingSection{ return &bindingSection{
title: hb.header.title, title: hb.header.title,
bindings: hb.bindings, bindings: hb.bindings,

View File

@ -2,7 +2,7 @@ package git_commands
import ( import (
"github.com/jesseduffield/generics/maps" "github.com/jesseduffield/generics/maps"
"github.com/jesseduffield/generics/slices" "github.com/samber/lo"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
@ -97,5 +97,5 @@ func (self *BisectInfo) Bisecting() bool {
return false return false
} }
return slices.Contains(maps.Values(self.statusMap), BisectStatusOld) return lo.Contains(maps.Values(self.statusMap), BisectStatusOld)
} }

View File

@ -6,13 +6,13 @@ import (
"strings" "strings"
"github.com/jesseduffield/generics/set" "github.com/jesseduffield/generics/set"
"github.com/jesseduffield/generics/slices"
"github.com/jesseduffield/go-git/v5/config" "github.com/jesseduffield/go-git/v5/config"
"github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/commands/oscommands" "github.com/jesseduffield/lazygit/pkg/commands/oscommands"
"github.com/jesseduffield/lazygit/pkg/common" "github.com/jesseduffield/lazygit/pkg/common"
"github.com/jesseduffield/lazygit/pkg/utils" "github.com/jesseduffield/lazygit/pkg/utils"
"github.com/samber/lo" "github.com/samber/lo"
"golang.org/x/exp/slices"
) )
// context: // context:
@ -75,7 +75,7 @@ outer:
if strings.EqualFold(reflogBranch.Name, branch.Name) { if strings.EqualFold(reflogBranch.Name, branch.Name) {
branch.Recency = reflogBranch.Recency branch.Recency = reflogBranch.Recency
branchesWithRecency = append(branchesWithRecency, branch) branchesWithRecency = append(branchesWithRecency, branch)
branches = slices.Remove(branches, j) branches = utils.Remove(branches, j)
continue outer continue outer
} }
} }
@ -87,14 +87,14 @@ outer:
return a.Name < b.Name return a.Name < b.Name
}) })
branches = slices.Prepend(branches, branchesWithRecency...) branches = utils.Prepend(branches, branchesWithRecency...)
foundHead := false foundHead := false
for i, branch := range branches { for i, branch := range branches {
if branch.Head { if branch.Head {
foundHead = true foundHead = true
branch.Recency = " *" branch.Recency = " *"
branches = slices.Move(branches, i, 0) branches = utils.Move(branches, i, 0)
break break
} }
} }
@ -103,7 +103,7 @@ outer:
if err != nil { if err != nil {
return nil, err return nil, err
} }
branches = slices.Prepend(branches, &models.Branch{Name: info.RefName, DisplayName: info.DisplayName, Head: true, DetachedHead: info.DetachedHead, Recency: " *"}) branches = utils.Prepend(branches, &models.Branch{Name: info.RefName, DisplayName: info.DisplayName, Head: true, DetachedHead: info.DetachedHead, Recency: " *"})
} }
configBranches, err := self.config.Branches() configBranches, err := self.config.Branches()
@ -131,7 +131,7 @@ func (self *BranchLoader) obtainBranches() []*models.Branch {
trimmedOutput := strings.TrimSpace(output) trimmedOutput := strings.TrimSpace(output)
outputLines := strings.Split(trimmedOutput, "\n") outputLines := strings.Split(trimmedOutput, "\n")
return slices.FilterMap(outputLines, func(line string) (*models.Branch, bool) { return lo.FilterMap(outputLines, func(line string, _ int) (*models.Branch, bool) {
if line == "" { if line == "" {
return nil, false return nil, false
} }

View File

@ -3,7 +3,6 @@ package git_commands
import ( import (
"strings" "strings"
"github.com/jesseduffield/generics/slices"
"github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/commands/oscommands" "github.com/jesseduffield/lazygit/pkg/commands/oscommands"
"github.com/jesseduffield/lazygit/pkg/common" "github.com/jesseduffield/lazygit/pkg/common"
@ -52,7 +51,7 @@ func getCommitFilesFromFilenames(filenames string) []*models.CommitFile {
} }
// typical result looks like 'A my_file' meaning my_file was added // typical result looks like 'A my_file' meaning my_file was added
return slices.Map(lo.Chunk(lines, 2), func(chunk []string) *models.CommitFile { return lo.Map(lo.Chunk(lines, 2), func(chunk []string, _ int) *models.CommitFile {
return &models.CommitFile{ return &models.CommitFile{
ChangeStatus: chunk[0], ChangeStatus: chunk[0],
Name: chunk[1], Name: chunk[1],

View File

@ -11,7 +11,6 @@ import (
"sync" "sync"
"github.com/fsmiamoto/git-todo-parser/todo" "github.com/fsmiamoto/git-todo-parser/todo"
"github.com/jesseduffield/generics/slices"
"github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/commands/oscommands" "github.com/jesseduffield/lazygit/pkg/commands/oscommands"
"github.com/jesseduffield/lazygit/pkg/commands/types/enums" "github.com/jesseduffield/lazygit/pkg/commands/types/enums"
@ -233,7 +232,7 @@ func (self *CommitLoader) getHydratedRebasingCommits(rebaseMode enums.RebaseMode
return nil, nil return nil, nil
} }
commitShas := slices.FilterMap(commits, func(commit *models.Commit) (string, bool) { commitShas := lo.FilterMap(commits, func(commit *models.Commit, _ int) (string, bool) {
return commit.Sha, commit.Sha != "" return commit.Sha, commit.Sha != ""
}) })
@ -379,7 +378,7 @@ func (self *CommitLoader) getInteractiveRebasingCommits() ([]*models.Commit, err
// Command does not have a commit associated, skip // Command does not have a commit associated, skip
continue continue
} }
commits = slices.Prepend(commits, &models.Commit{ commits = utils.Prepend(commits, &models.Commit{
Sha: t.Commit, Sha: t.Commit,
Name: t.Msg, Name: t.Msg,
Status: models.StatusRebasing, Status: models.StatusRebasing,

View File

@ -7,7 +7,6 @@ import (
"github.com/fsmiamoto/git-todo-parser/todo" "github.com/fsmiamoto/git-todo-parser/todo"
"github.com/go-errors/errors" "github.com/go-errors/errors"
"github.com/jesseduffield/generics/slices"
"github.com/jesseduffield/lazygit/pkg/app/daemon" "github.com/jesseduffield/lazygit/pkg/app/daemon"
"github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/commands/oscommands" "github.com/jesseduffield/lazygit/pkg/commands/oscommands"
@ -158,7 +157,7 @@ func (self *RebaseCommands) EditRebase(branchRef string) error {
} }
func logTodoChanges(changes []daemon.ChangeTodoAction) string { func logTodoChanges(changes []daemon.ChangeTodoAction) string {
changeTodoStr := strings.Join(slices.Map(changes, func(c daemon.ChangeTodoAction) string { changeTodoStr := strings.Join(lo.Map(changes, func(c daemon.ChangeTodoAction, _ int) string {
return fmt.Sprintf("%s:%s", c.Sha, c.NewAction) return fmt.Sprintf("%s:%s", c.Sha, c.NewAction)
}), "\n") }), "\n")
return fmt.Sprintf("Changing TODO actions: %s", changeTodoStr) return fmt.Sprintf("Changing TODO actions: %s", changeTodoStr)

View File

@ -4,12 +4,13 @@ import (
"strings" "strings"
"sync" "sync"
"github.com/jesseduffield/generics/slices"
gogit "github.com/jesseduffield/go-git/v5" gogit "github.com/jesseduffield/go-git/v5"
"github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/commands/oscommands" "github.com/jesseduffield/lazygit/pkg/commands/oscommands"
"github.com/jesseduffield/lazygit/pkg/common" "github.com/jesseduffield/lazygit/pkg/common"
"github.com/jesseduffield/lazygit/pkg/utils" "github.com/jesseduffield/lazygit/pkg/utils"
"github.com/samber/lo"
"golang.org/x/exp/slices"
) )
type RemoteLoader struct { type RemoteLoader struct {
@ -53,7 +54,7 @@ func (self *RemoteLoader) GetRemotes() ([]*models.Remote, error) {
return nil, remoteBranchesErr return nil, remoteBranchesErr
} }
remotes := slices.Map(goGitRemotes, func(goGitRemote *gogit.Remote) *models.Remote { remotes := lo.Map(goGitRemotes, func(goGitRemote *gogit.Remote, _ int) *models.Remote {
remoteName := goGitRemote.Config().Name remoteName := goGitRemote.Config().Name
branches := remoteBranchesByRemoteName[remoteName] branches := remoteBranchesByRemoteName[remoteName]

View File

@ -5,11 +5,11 @@ import (
"strconv" "strconv"
"strings" "strings"
"github.com/jesseduffield/generics/slices"
"github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/commands/oscommands" "github.com/jesseduffield/lazygit/pkg/commands/oscommands"
"github.com/jesseduffield/lazygit/pkg/common" "github.com/jesseduffield/lazygit/pkg/common"
"github.com/jesseduffield/lazygit/pkg/utils" "github.com/jesseduffield/lazygit/pkg/utils"
"github.com/samber/lo"
) )
type StashLoader struct { type StashLoader struct {
@ -69,7 +69,7 @@ func (self *StashLoader) getUnfilteredStashEntries() []*models.StashEntry {
cmdArgs := NewGitCmd("stash").Arg("list", "-z", "--pretty=%gs").ToArgv() cmdArgs := NewGitCmd("stash").Arg("list", "-z", "--pretty=%gs").ToArgv()
rawString, _ := self.cmd.New(cmdArgs).DontLog().RunWithOutput() rawString, _ := self.cmd.New(cmdArgs).DontLog().RunWithOutput()
return slices.MapWithIndex(utils.SplitNul(rawString), func(line string, index int) *models.StashEntry { return lo.Map(utils.SplitNul(rawString), func(line string, index int) *models.StashEntry {
return self.stashEntryFromLine(line, index) return self.stashEntryFromLine(line, index)
}) })
} }

View File

@ -3,11 +3,11 @@ package git_commands
import ( import (
"regexp" "regexp"
"github.com/jesseduffield/generics/slices"
"github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/commands/oscommands" "github.com/jesseduffield/lazygit/pkg/commands/oscommands"
"github.com/jesseduffield/lazygit/pkg/common" "github.com/jesseduffield/lazygit/pkg/common"
"github.com/jesseduffield/lazygit/pkg/utils" "github.com/jesseduffield/lazygit/pkg/utils"
"github.com/samber/lo"
) )
type TagLoader struct { type TagLoader struct {
@ -38,7 +38,7 @@ func (self *TagLoader) GetTags() ([]*models.Tag, error) {
lineRegex := regexp.MustCompile(`^([^\s]+)(\s+)?(.*)$`) lineRegex := regexp.MustCompile(`^([^\s]+)(\s+)?(.*)$`)
tags := slices.Map(split, func(line string) *models.Tag { tags := lo.Map(split, func(line string, _ int) *models.Tag {
matches := lineRegex.FindStringSubmatch(line) matches := lineRegex.FindStringSubmatch(line)
tagName := matches[1] tagName := matches[1]
message := "" message := ""

View File

@ -8,9 +8,10 @@ import (
"github.com/go-errors/errors" "github.com/go-errors/errors"
"github.com/jesseduffield/lazygit/pkg/i18n" "github.com/jesseduffield/lazygit/pkg/i18n"
"github.com/jesseduffield/lazygit/pkg/utils" "github.com/jesseduffield/lazygit/pkg/utils"
"github.com/samber/lo"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/jesseduffield/generics/slices" "golang.org/x/exp/slices"
) )
// This package is for handling logic specific to a git hosting service like github, gitlab, bitbucket, gitea, etc. // This package is for handling logic specific to a git hosting service like github, gitlab, bitbucket, gitea, etc.
@ -111,7 +112,7 @@ func (self *HostingServiceMgr) getCandidateServiceDomains() []ServiceDomain {
serviceDefinition, ok := serviceDefinitionByProvider[provider] serviceDefinition, ok := serviceDefinitionByProvider[provider]
if !ok { if !ok {
providerNames := slices.Map(serviceDefinitions, func(serviceDefinition ServiceDefinition) string { providerNames := lo.Map(serviceDefinitions, func(serviceDefinition ServiceDefinition, _ int) string {
return serviceDefinition.provider return serviceDefinition.provider
}) })

View File

@ -13,7 +13,6 @@ import (
"github.com/samber/lo" "github.com/samber/lo"
"github.com/atotto/clipboard" "github.com/atotto/clipboard"
"github.com/jesseduffield/generics/slices"
"github.com/jesseduffield/kill" "github.com/jesseduffield/kill"
"github.com/jesseduffield/lazygit/pkg/common" "github.com/jesseduffield/lazygit/pkg/common"
"github.com/jesseduffield/lazygit/pkg/config" "github.com/jesseduffield/lazygit/pkg/config"
@ -189,7 +188,7 @@ func (c *OSCommand) FileExists(path string) (bool, error) {
// PipeCommands runs a heap of commands and pipes their inputs/outputs together like A | B | C // PipeCommands runs a heap of commands and pipes their inputs/outputs together like A | B | C
func (c *OSCommand) PipeCommands(cmdObjs ...ICmdObj) error { func (c *OSCommand) PipeCommands(cmdObjs ...ICmdObj) error {
cmds := slices.Map(cmdObjs, func(cmdObj ICmdObj) *exec.Cmd { cmds := lo.Map(cmdObjs, func(cmdObj ICmdObj, _ int) *exec.Cmd {
return cmdObj.GetCmd() return cmdObj.GetCmd()
}) })

View File

@ -5,7 +5,6 @@ import (
"strings" "strings"
"github.com/jesseduffield/generics/maps" "github.com/jesseduffield/generics/maps"
"github.com/jesseduffield/generics/slices"
"github.com/samber/lo" "github.com/samber/lo"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
@ -209,10 +208,10 @@ func (p *PatchBuilder) renderEachFilePatch(plain bool) []string {
filenames := maps.Keys(p.fileInfoMap) filenames := maps.Keys(p.fileInfoMap)
sort.Strings(filenames) sort.Strings(filenames)
patches := slices.Map(filenames, func(filename string) string { patches := lo.Map(filenames, func(filename string, _ int) string {
return p.RenderPatchForFile(filename, plain, false) return p.RenderPatchForFile(filename, plain, false)
}) })
output := slices.Filter(patches, func(patch string) bool { output := lo.Filter(patches, func(patch string, _ int) bool {
return patch != "" return patch != ""
}) })

View File

@ -4,9 +4,9 @@ import (
"errors" "errors"
"sync" "sync"
"github.com/jesseduffield/generics/slices"
"github.com/jesseduffield/lazygit/pkg/gui/context" "github.com/jesseduffield/lazygit/pkg/gui/context"
"github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/utils"
"github.com/samber/lo" "github.com/samber/lo"
) )
@ -134,7 +134,7 @@ func (self *ContextMgr) pushToContextStack(c types.Context) ([]types.Context, ty
(topContext.GetKind() == types.MAIN_CONTEXT && c.GetKind() == types.MAIN_CONTEXT) { (topContext.GetKind() == types.MAIN_CONTEXT && c.GetKind() == types.MAIN_CONTEXT) {
contextsToDeactivate = append(contextsToDeactivate, topContext) contextsToDeactivate = append(contextsToDeactivate, topContext)
_, self.ContextStack = slices.Pop(self.ContextStack) _, self.ContextStack = utils.Pop(self.ContextStack)
} }
self.ContextStack = append(self.ContextStack, c) self.ContextStack = append(self.ContextStack, c)
@ -154,7 +154,7 @@ func (self *ContextMgr) Pop() error {
} }
var currentContext types.Context var currentContext types.Context
currentContext, self.ContextStack = slices.Pop(self.ContextStack) currentContext, self.ContextStack = utils.Pop(self.ContextStack)
newContext := self.ContextStack[len(self.ContextStack)-1] newContext := self.ContextStack[len(self.ContextStack)-1]

View File

@ -1,12 +1,12 @@
package context package context
import ( import (
"github.com/jesseduffield/generics/slices"
"github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/gui/filetree" "github.com/jesseduffield/lazygit/pkg/gui/filetree"
"github.com/jesseduffield/lazygit/pkg/gui/presentation" "github.com/jesseduffield/lazygit/pkg/gui/presentation"
"github.com/jesseduffield/lazygit/pkg/gui/style" "github.com/jesseduffield/lazygit/pkg/gui/style"
"github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/samber/lo"
) )
type CommitFilesContext struct { type CommitFilesContext struct {
@ -34,7 +34,7 @@ func NewCommitFilesContext(c *ContextCommon) *CommitFilesContext {
} }
lines := presentation.RenderCommitFileTree(viewModel, c.Modes().Diffing.Ref, c.Git().Patch.PatchBuilder) lines := presentation.RenderCommitFileTree(viewModel, c.Modes().Diffing.Ref, c.Git().Patch.PatchBuilder)
return slices.Map(lines, func(line string) []string { return lo.Map(lines, func(line string, _ int) []string {
return []string{line} return []string{line}
}) })
} }

View File

@ -1,7 +1,6 @@
package context package context
import ( import (
"github.com/jesseduffield/generics/slices"
"github.com/jesseduffield/lazygit/pkg/gui/keybindings" "github.com/jesseduffield/lazygit/pkg/gui/keybindings"
"github.com/jesseduffield/lazygit/pkg/gui/style" "github.com/jesseduffield/lazygit/pkg/gui/style"
"github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/gui/types"
@ -82,11 +81,11 @@ func (self *MenuViewModel) SetMenuItems(items []*types.MenuItem, columnAlignment
// TODO: move into presentation package // TODO: move into presentation package
func (self *MenuViewModel) GetDisplayStrings(_startIdx int, _length int) [][]string { func (self *MenuViewModel) GetDisplayStrings(_startIdx int, _length int) [][]string {
menuItems := self.FilteredListViewModel.GetItems() menuItems := self.FilteredListViewModel.GetItems()
showKeys := slices.Some(menuItems, func(item *types.MenuItem) bool { showKeys := lo.SomeBy(menuItems, func(item *types.MenuItem) bool {
return item.Key != nil return item.Key != nil
}) })
return slices.Map(menuItems, func(item *types.MenuItem) []string { return lo.Map(menuItems, func(item *types.MenuItem, _ int) []string {
displayStrings := item.LabelColumns displayStrings := item.LabelColumns
if !showKeys { if !showKeys {
@ -107,18 +106,18 @@ func (self *MenuViewModel) GetDisplayStrings(_startIdx int, _length int) [][]str
keyStyle = style.FgDefault.SetStrikethrough() keyStyle = style.FgDefault.SetStrikethrough()
} }
displayStrings = slices.Prepend(displayStrings, keyStyle.Sprint(keyLabel)) displayStrings = utils.Prepend(displayStrings, keyStyle.Sprint(keyLabel))
return displayStrings return displayStrings
}) })
} }
func (self *MenuContext) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding { func (self *MenuContext) GetKeybindings(opts types.KeybindingsOpts) []*types.Binding {
basicBindings := self.ListContextTrait.GetKeybindings(opts) basicBindings := self.ListContextTrait.GetKeybindings(opts)
menuItemsWithKeys := slices.Filter(self.menuItems, func(item *types.MenuItem) bool { menuItemsWithKeys := lo.Filter(self.menuItems, func(item *types.MenuItem, _ int) bool {
return item.Key != nil return item.Key != nil
}) })
menuItemBindings := slices.Map(menuItemsWithKeys, func(item *types.MenuItem) *types.Binding { menuItemBindings := lo.Map(menuItemsWithKeys, func(item *types.MenuItem, _ int) *types.Binding {
return &types.Binding{ return &types.Binding{
Key: item.Key, Key: item.Key,
Handler: func() error { return self.OnMenuPress(item) }, Handler: func() error { return self.OnMenuPress(item) },

View File

@ -1,11 +1,11 @@
package context package context
import ( import (
"github.com/jesseduffield/generics/slices"
"github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/gui/filetree" "github.com/jesseduffield/lazygit/pkg/gui/filetree"
"github.com/jesseduffield/lazygit/pkg/gui/presentation" "github.com/jesseduffield/lazygit/pkg/gui/presentation"
"github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/samber/lo"
) )
type WorkingTreeContext struct { type WorkingTreeContext struct {
@ -25,7 +25,7 @@ func NewWorkingTreeContext(c *ContextCommon) *WorkingTreeContext {
getDisplayStrings := func(startIdx int, length int) [][]string { getDisplayStrings := func(startIdx int, length int) [][]string {
lines := presentation.RenderFileTree(viewModel, c.Modes().Diffing.Ref, c.Model().Submodules) lines := presentation.RenderFileTree(viewModel, c.Modes().Diffing.Ref, c.Model().Submodules)
return slices.Map(lines, func(line string) []string { return lo.Map(lines, func(line string, _ int) []string {
return []string{line} return []string{line}
}) })
} }

View File

@ -3,7 +3,6 @@ package controllers
import ( import (
"strings" "strings"
"github.com/jesseduffield/generics/slices"
"github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers" "github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers"
"github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/utils" "github.com/jesseduffield/lazygit/pkg/utils"
@ -41,7 +40,7 @@ func (self *CustomCommandAction) Call() error {
func (self *CustomCommandAction) GetCustomCommandsHistorySuggestionsFunc() func(string) []*types.Suggestion { func (self *CustomCommandAction) GetCustomCommandsHistorySuggestionsFunc() func(string) []*types.Suggestion {
// reversing so that we display the latest command first // reversing so that we display the latest command first
history := slices.Reverse(self.c.GetAppState().CustomCommandsHistory) history := lo.Reverse(self.c.GetAppState().CustomCommandsHistory)
return helpers.FuzzySearchFunc(history) return helpers.FuzzySearchFunc(history)
} }

View File

@ -4,11 +4,11 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/jesseduffield/generics/slices"
"github.com/jesseduffield/lazygit/pkg/commands/git_commands" "github.com/jesseduffield/lazygit/pkg/commands/git_commands"
"github.com/jesseduffield/lazygit/pkg/commands/types/enums" "github.com/jesseduffield/lazygit/pkg/commands/types/enums"
"github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/utils" "github.com/jesseduffield/lazygit/pkg/utils"
"github.com/samber/lo"
) )
type MergeAndRebaseHelper struct { type MergeAndRebaseHelper struct {
@ -51,7 +51,7 @@ func (self *MergeAndRebaseHelper) CreateRebaseOptionsMenu() error {
}) })
} }
menuItems := slices.Map(options, func(row optionAndKey) *types.MenuItem { menuItems := lo.Map(options, func(row optionAndKey, _ int) *types.MenuItem {
return &types.MenuItem{ return &types.MenuItem{
Label: row.option, Label: row.option,
OnPress: func() error { OnPress: func() error {

View File

@ -4,11 +4,11 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/jesseduffield/generics/slices"
"github.com/jesseduffield/lazygit/pkg/commands/types/enums" "github.com/jesseduffield/lazygit/pkg/commands/types/enums"
"github.com/jesseduffield/lazygit/pkg/gui/presentation" "github.com/jesseduffield/lazygit/pkg/gui/presentation"
"github.com/jesseduffield/lazygit/pkg/gui/style" "github.com/jesseduffield/lazygit/pkg/gui/style"
"github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/samber/lo"
) )
type ModeHelper struct { type ModeHelper struct {
@ -135,13 +135,13 @@ func (self *ModeHelper) withResetButton(content string, textStyle style.TextStyl
} }
func (self *ModeHelper) GetActiveMode() (ModeStatus, bool) { func (self *ModeHelper) GetActiveMode() (ModeStatus, bool) {
return slices.Find(self.Statuses(), func(mode ModeStatus) bool { return lo.Find(self.Statuses(), func(mode ModeStatus) bool {
return mode.IsActive() return mode.IsActive()
}) })
} }
func (self *ModeHelper) IsAnyModeActive() bool { func (self *ModeHelper) IsAnyModeActive() bool {
return slices.Some(self.Statuses(), func(mode ModeStatus) bool { return lo.SomeBy(self.Statuses(), func(mode ModeStatus) bool {
return mode.IsActive() return mode.IsActive()
}) })
} }

View File

@ -7,7 +7,6 @@ import (
"time" "time"
"github.com/jesseduffield/generics/set" "github.com/jesseduffield/generics/set"
"github.com/jesseduffield/generics/slices"
"github.com/jesseduffield/gocui" "github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands/git_commands" "github.com/jesseduffield/lazygit/pkg/commands/git_commands"
"github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/commands/models"
@ -18,6 +17,7 @@ import (
"github.com/jesseduffield/lazygit/pkg/gui/presentation" "github.com/jesseduffield/lazygit/pkg/gui/presentation"
"github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/utils" "github.com/jesseduffield/lazygit/pkg/utils"
"github.com/samber/lo"
) )
type RefreshHelper struct { type RefreshHelper struct {
@ -211,7 +211,7 @@ func getScopeNames(scopes []types.RefreshableView) []string {
types.MERGE_CONFLICTS: "mergeConflicts", types.MERGE_CONFLICTS: "mergeConflicts",
} }
return slices.Map(scopes, func(scope types.RefreshableView) string { return lo.Map(scopes, func(scope types.RefreshableView, _ int) string {
return scopeNameMap[scope] return scopeNameMap[scope]
}) })
} }

View File

@ -4,13 +4,13 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/jesseduffield/generics/slices"
"github.com/jesseduffield/gocui" "github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands/git_commands" "github.com/jesseduffield/lazygit/pkg/commands/git_commands"
"github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/gui/style" "github.com/jesseduffield/lazygit/pkg/gui/style"
"github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/utils" "github.com/jesseduffield/lazygit/pkg/utils"
"github.com/samber/lo"
) )
type IRefsHelper interface { type IRefsHelper interface {
@ -132,7 +132,7 @@ func (self *RefsHelper) CreateGitResetMenu(ref string) error {
{strength: "hard", label: "Hard reset", key: 'h'}, {strength: "hard", label: "Hard reset", key: 'h'},
} }
menuItems := slices.Map(strengths, func(row strengthWithKey) *types.MenuItem { menuItems := lo.Map(strengths, func(row strengthWithKey, _ int) *types.MenuItem {
return &types.MenuItem{ return &types.MenuItem{
LabelColumns: []string{ LabelColumns: []string{
row.label, row.label,

View File

@ -7,7 +7,6 @@ import (
"strings" "strings"
"sync" "sync"
"github.com/jesseduffield/generics/slices"
"github.com/jesseduffield/gocui" "github.com/jesseduffield/gocui"
appTypes "github.com/jesseduffield/lazygit/pkg/app/types" appTypes "github.com/jesseduffield/lazygit/pkg/app/types"
"github.com/jesseduffield/lazygit/pkg/commands" "github.com/jesseduffield/lazygit/pkg/commands"
@ -18,6 +17,7 @@ import (
"github.com/jesseduffield/lazygit/pkg/gui/style" "github.com/jesseduffield/lazygit/pkg/gui/style"
"github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/utils" "github.com/jesseduffield/lazygit/pkg/utils"
"github.com/samber/lo"
) )
type onNewRepoFn func(startArgs appTypes.StartArgs, contextKey types.ContextKey) error type onNewRepoFn func(startArgs appTypes.StartArgs, contextKey types.ContextKey) error
@ -115,7 +115,7 @@ func (self *ReposHelper) CreateRecentReposMenu() error {
wg.Wait() wg.Wait()
menuItems := slices.Map(recentRepoPaths, func(path string) *types.MenuItem { menuItems := lo.Map(recentRepoPaths, func(path string, _ int) *types.MenuItem {
branchName, _ := currentBranches.Load(path) branchName, _ := currentBranches.Load(path)
if icons.IsIconEnabled() { if icons.IsIconEnabled() {
branchName = icons.BRANCH_ICON + " " + fmt.Sprintf("%v", branchName) branchName = icons.BRANCH_ICON + " " + fmt.Sprintf("%v", branchName)

View File

@ -4,7 +4,6 @@ import (
"fmt" "fmt"
"os" "os"
"github.com/jesseduffield/generics/slices"
"github.com/jesseduffield/gocui" "github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/gui/presentation" "github.com/jesseduffield/lazygit/pkg/gui/presentation"
@ -12,6 +11,7 @@ import (
"github.com/jesseduffield/lazygit/pkg/utils" "github.com/jesseduffield/lazygit/pkg/utils"
"github.com/jesseduffield/minimal/gitignore" "github.com/jesseduffield/minimal/gitignore"
"github.com/samber/lo" "github.com/samber/lo"
"golang.org/x/exp/slices"
"gopkg.in/ozeidan/fuzzy-patricia.v3/patricia" "gopkg.in/ozeidan/fuzzy-patricia.v3/patricia"
) )
@ -48,13 +48,13 @@ func NewSuggestionsHelper(
} }
func (self *SuggestionsHelper) getRemoteNames() []string { func (self *SuggestionsHelper) getRemoteNames() []string {
return slices.Map(self.c.Model().Remotes, func(remote *models.Remote) string { return lo.Map(self.c.Model().Remotes, func(remote *models.Remote, _ int) string {
return remote.Name return remote.Name
}) })
} }
func matchesToSuggestions(matches []string) []*types.Suggestion { func matchesToSuggestions(matches []string) []*types.Suggestion {
return slices.Map(matches, func(match string) *types.Suggestion { return lo.Map(matches, func(match string, _ int) *types.Suggestion {
return &types.Suggestion{ return &types.Suggestion{
Value: match, Value: match,
Label: match, Label: match,
@ -69,7 +69,7 @@ func (self *SuggestionsHelper) GetRemoteSuggestionsFunc() func(string) []*types.
} }
func (self *SuggestionsHelper) getBranchNames() []string { func (self *SuggestionsHelper) getBranchNames() []string {
return slices.Map(self.c.Model().Branches, func(branch *models.Branch) string { return lo.Map(self.c.Model().Branches, func(branch *models.Branch, _ int) string {
return branch.Name return branch.Name
}) })
} }
@ -85,7 +85,7 @@ func (self *SuggestionsHelper) GetBranchNameSuggestionsFunc() func(string) []*ty
matchingBranchNames = utils.FuzzySearch(input, branchNames) matchingBranchNames = utils.FuzzySearch(input, branchNames)
} }
return slices.Map(matchingBranchNames, func(branchName string) *types.Suggestion { return lo.Map(matchingBranchNames, func(branchName string, _ int) *types.Suggestion {
return &types.Suggestion{ return &types.Suggestion{
Value: branchName, Value: branchName,
Label: presentation.GetBranchTextStyle(branchName).Sprint(branchName), Label: presentation.GetBranchTextStyle(branchName).Sprint(branchName),
@ -141,8 +141,8 @@ func (self *SuggestionsHelper) GetFilePathSuggestionsFunc() func(string) []*type
} }
func (self *SuggestionsHelper) getRemoteBranchNames(separator string) []string { func (self *SuggestionsHelper) getRemoteBranchNames(separator string) []string {
return slices.FlatMap(self.c.Model().Remotes, func(remote *models.Remote) []string { return lo.FlatMap(self.c.Model().Remotes, func(remote *models.Remote, _ int) []string {
return slices.Map(remote.Branches, func(branch *models.RemoteBranch) string { return lo.Map(remote.Branches, func(branch *models.RemoteBranch, _ int) string {
return fmt.Sprintf("%s%s%s", remote.Name, separator, branch.Name) return fmt.Sprintf("%s%s%s", remote.Name, separator, branch.Name)
}) })
}) })
@ -153,7 +153,7 @@ func (self *SuggestionsHelper) GetRemoteBranchesSuggestionsFunc(separator string
} }
func (self *SuggestionsHelper) getTagNames() []string { func (self *SuggestionsHelper) getTagNames() []string {
return slices.Map(self.c.Model().Tags, func(tag *models.Tag) string { return lo.Map(self.c.Model().Tags, func(tag *models.Tag, _ int) string {
return tag.Name return tag.Name
}) })
} }

View File

@ -3,8 +3,8 @@ package helpers
import ( import (
"testing" "testing"
"github.com/jesseduffield/generics/slices"
"github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/samber/lo"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -25,7 +25,7 @@ func TestGetSuggestedRemote(t *testing.T) {
} }
func mkRemoteList(names ...string) []*models.Remote { func mkRemoteList(names ...string) []*models.Remote {
return slices.Map(names, func(name string) *models.Remote { return lo.Map(names, func(name string, _ int) *models.Remote {
return &models.Remote{Name: name} return &models.Remote{Name: name}
}) })
} }

View File

@ -1,7 +1,6 @@
package controllers package controllers
import ( import (
"github.com/jesseduffield/generics/slices"
"github.com/jesseduffield/lazygit/pkg/gui/keybindings" "github.com/jesseduffield/lazygit/pkg/gui/keybindings"
"github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/utils" "github.com/jesseduffield/lazygit/pkg/utils"
@ -21,7 +20,7 @@ func (self *OptionsMenuAction) Call() error {
bindings := self.getBindings(ctx) bindings := self.getBindings(ctx)
menuItems := slices.Map(bindings, func(binding *types.Binding) *types.MenuItem { menuItems := lo.Map(bindings, func(binding *types.Binding, _ int) *types.MenuItem {
return &types.MenuItem{ return &types.MenuItem{
OpensMenu: binding.OpensMenu, OpensMenu: binding.OpensMenu,
Label: binding.Description, Label: binding.Description,

View File

@ -5,12 +5,12 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/jesseduffield/generics/slices"
"github.com/jesseduffield/lazygit/pkg/commands/types/enums" "github.com/jesseduffield/lazygit/pkg/commands/types/enums"
"github.com/jesseduffield/lazygit/pkg/constants" "github.com/jesseduffield/lazygit/pkg/constants"
"github.com/jesseduffield/lazygit/pkg/gui/presentation" "github.com/jesseduffield/lazygit/pkg/gui/presentation"
"github.com/jesseduffield/lazygit/pkg/gui/style" "github.com/jesseduffield/lazygit/pkg/gui/style"
"github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/samber/lo"
) )
type StatusController struct { type StatusController struct {
@ -155,7 +155,7 @@ func (self *StatusController) askForConfigFile(action func(file string) error) e
case 1: case 1:
return action(confPaths[0]) return action(confPaths[0])
default: default:
menuItems := slices.Map(confPaths, func(path string) *types.MenuItem { menuItems := lo.Map(confPaths, func(path string, _ int) *types.MenuItem {
return &types.MenuItem{ return &types.MenuItem{
Label: path, Label: path,
OnPress: func() error { OnPress: func() error {

View File

@ -1,8 +1,8 @@
package filetree package filetree
import ( import (
"github.com/jesseduffield/generics/slices"
"github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/samber/lo"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
@ -60,7 +60,7 @@ func (self *CommitFileTree) GetAllItems() []*CommitFileNode {
} }
// ignoring root // ignoring root
return slices.Map(self.tree.Flatten(self.collapsedPaths)[1:], func(node *Node[models.CommitFile]) *CommitFileNode { return lo.Map(self.tree.Flatten(self.collapsedPaths)[1:], func(node *Node[models.CommitFile], _ int) *CommitFileNode {
return NewCommitFileNode(node) return NewCommitFileNode(node)
}) })
} }

View File

@ -3,8 +3,8 @@ package filetree
import ( import (
"fmt" "fmt"
"github.com/jesseduffield/generics/slices"
"github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/samber/lo"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
@ -88,7 +88,7 @@ func (self *FileTree) getFilesForDisplay() []*models.File {
} }
func (self *FileTree) FilterFiles(test func(*models.File) bool) []*models.File { func (self *FileTree) FilterFiles(test func(*models.File) bool) []*models.File {
return slices.Filter(self.getFiles(), test) return lo.Filter(self.getFiles(), func(file *models.File, _ int) bool { return test(file) })
} }
func (self *FileTree) SetStatusFilter(filter FileTreeDisplayFilter) { func (self *FileTree) SetStatusFilter(filter FileTreeDisplayFilter) {
@ -130,7 +130,7 @@ func (self *FileTree) GetAllItems() []*FileNode {
} }
// ignoring root // ignoring root
return slices.Map(self.tree.Flatten(self.collapsedPaths)[1:], func(node *Node[models.File]) *FileNode { return lo.Map(self.tree.Flatten(self.collapsedPaths)[1:], func(node *Node[models.File], _ int) *FileNode {
return NewFileNode(node) return NewFileNode(node)
}) })
} }

View File

@ -1,9 +1,10 @@
package filetree package filetree
import ( import (
"github.com/jesseduffield/generics/slices"
"github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/samber/lo"
"golang.org/x/exp/slices"
) )
// Represents a file or directory in a file tree. // Represents a file or directory in a file tree.
@ -152,7 +153,7 @@ func (self *Node[T]) Flatten(collapsedPaths *CollapsedPaths) []*Node[T] {
result := []*Node[T]{self} result := []*Node[T]{self}
if len(self.Children) > 0 && !collapsedPaths.IsCollapsed(self.GetPath()) { if len(self.Children) > 0 && !collapsedPaths.IsCollapsed(self.GetPath()) {
result = append(result, slices.FlatMap(self.Children, func(child *Node[T]) []*Node[T] { result = append(result, lo.FlatMap(self.Children, func(child *Node[T], _ int) []*Node[T] {
return child.Flatten(collapsedPaths) return child.Flatten(collapsedPaths)
})...) })...)
} }
@ -273,11 +274,11 @@ func (self *Node[T]) GetPathsMatching(test func(*Node[T]) bool) []string {
} }
func (self *Node[T]) GetFilePathsMatching(test func(*T) bool) []string { func (self *Node[T]) GetFilePathsMatching(test func(*T) bool) []string {
matchingFileNodes := slices.Filter(self.GetLeaves(), func(node *Node[T]) bool { matchingFileNodes := lo.Filter(self.GetLeaves(), func(node *Node[T], _ int) bool {
return test(node.File) return test(node.File)
}) })
return slices.Map(matchingFileNodes, func(node *Node[T]) string { return lo.Map(matchingFileNodes, func(node *Node[T], _ int) string {
return node.GetPath() return node.GetPath()
}) })
} }
@ -287,7 +288,7 @@ func (self *Node[T]) GetLeaves() []*Node[T] {
return []*Node[T]{self} return []*Node[T]{self}
} }
return slices.FlatMap(self.Children, func(child *Node[T]) []*Node[T] { return lo.FlatMap(self.Children, func(child *Node[T], _ int) []*Node[T] {
return child.GetLeaves() return child.GetLeaves()
}) })
} }

View File

@ -1,11 +1,12 @@
package gui package gui
import ( import (
"github.com/jesseduffield/generics/slices"
"github.com/jesseduffield/gocui" "github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/context" "github.com/jesseduffield/lazygit/pkg/gui/context"
"github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/theme" "github.com/jesseduffield/lazygit/pkg/theme"
"github.com/samber/lo"
"golang.org/x/exp/slices"
) )
// layout is called for every screen re-render e.g. when the screen is resized // layout is called for every screen re-render e.g. when the screen is resized
@ -196,11 +197,11 @@ func (gui *Gui) onInitialViewsCreationForRepo() error {
} }
func (gui *Gui) popupViewNames() []string { func (gui *Gui) popupViewNames() []string {
popups := slices.Filter(gui.State.Contexts.Flatten(), func(c types.Context) bool { popups := lo.Filter(gui.State.Contexts.Flatten(), func(c types.Context, _ int) bool {
return c.GetKind() == types.PERSISTENT_POPUP || c.GetKind() == types.TEMPORARY_POPUP return c.GetKind() == types.PERSISTENT_POPUP || c.GetKind() == types.TEMPORARY_POPUP
}) })
return slices.Map(popups, func(c types.Context) string { return lo.Map(popups, func(c types.Context, _ int) string {
return c.GetViewName() return c.GetViewName()
}) })
} }
@ -223,7 +224,7 @@ func (gui *Gui) onRepoViewReset() error {
}) })
if index != -1 { if index != -1 {
view.Tabs = slices.Map(values, func(tabContext context.TabView) string { view.Tabs = lo.Map(values, func(tabContext context.TabView, _ int) string {
return tabContext.Tab return tabContext.Tab
}) })
view.TabIndex = index view.TabIndex = index
@ -287,7 +288,7 @@ func (gui *Gui) onViewFocusLost(oldView *gocui.View) error {
} }
func (gui *Gui) transientContexts() []types.Context { func (gui *Gui) transientContexts() []types.Context {
return slices.Filter(gui.State.Contexts.Flatten(), func(context types.Context) bool { return lo.Filter(gui.State.Contexts.Flatten(), func(context types.Context, _ int) bool {
return context.IsTransient() return context.IsTransient()
}) })
} }

View File

@ -2,8 +2,8 @@ package cherrypicking
import ( import (
"github.com/jesseduffield/generics/set" "github.com/jesseduffield/generics/set"
"github.com/jesseduffield/generics/slices"
"github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/samber/lo"
) )
type CherryPicking struct { type CherryPicking struct {
@ -25,7 +25,7 @@ func (self *CherryPicking) Active() bool {
} }
func (self *CherryPicking) SelectedShaSet() *set.Set[string] { func (self *CherryPicking) SelectedShaSet() *set.Set[string] {
shas := slices.Map(self.CherryPickedCommits, func(commit *models.Commit) string { shas := lo.Map(self.CherryPickedCommits, func(commit *models.Commit, _ int) string {
return commit.Sha return commit.Sha
}) })
return set.NewFromSlice(shas) return set.NewFromSlice(shas)
@ -46,11 +46,11 @@ func (self *CherryPicking) Remove(selectedCommit *models.Commit, commitsList []*
} }
func (self *CherryPicking) update(selectedShaSet *set.Set[string], commitsList []*models.Commit) { func (self *CherryPicking) update(selectedShaSet *set.Set[string], commitsList []*models.Commit) {
cherryPickedCommits := slices.Filter(commitsList, func(commit *models.Commit) bool { cherryPickedCommits := lo.Filter(commitsList, func(commit *models.Commit, _ int) bool {
return selectedShaSet.Includes(commit.Sha) return selectedShaSet.Includes(commit.Sha)
}) })
self.CherryPickedCommits = slices.Map(cherryPickedCommits, func(commit *models.Commit) *models.Commit { self.CherryPickedCommits = lo.Map(cherryPickedCommits, func(commit *models.Commit, _ int) *models.Commit {
return &models.Commit{Name: commit.Name, Sha: commit.Sha} return &models.Commit{Name: commit.Name, Sha: commit.Sha}
}) })
} }

View File

@ -4,7 +4,6 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/jesseduffield/generics/slices"
"github.com/jesseduffield/lazygit/pkg/commands/git_commands" "github.com/jesseduffield/lazygit/pkg/commands/git_commands"
"github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/config" "github.com/jesseduffield/lazygit/pkg/config"
@ -26,7 +25,7 @@ func GetBranchListDisplayStrings(
userConfig *config.UserConfig, userConfig *config.UserConfig,
worktrees []*models.Worktree, worktrees []*models.Worktree,
) [][]string { ) [][]string {
return slices.Map(branches, func(branch *models.Branch) []string { return lo.Map(branches, func(branch *models.Branch, _ int) []string {
diffed := branch.Name == diffName diffed := branch.Name == diffName
return getBranchDisplayStrings(branch, fullDescription, diffed, tr, userConfig, worktrees) return getBranchDisplayStrings(branch, fullDescription, diffed, tr, userConfig, worktrees)
}) })

View File

@ -6,11 +6,11 @@ import (
"sync" "sync"
"github.com/jesseduffield/generics/set" "github.com/jesseduffield/generics/set"
"github.com/jesseduffield/generics/slices"
"github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/gui/style" "github.com/jesseduffield/lazygit/pkg/gui/style"
"github.com/jesseduffield/lazygit/pkg/utils" "github.com/jesseduffield/lazygit/pkg/utils"
"github.com/samber/lo" "github.com/samber/lo"
"golang.org/x/exp/slices"
) )
type PipeKind uint8 type PipeKind uint8
@ -67,7 +67,7 @@ func GetPipeSets(commits []*models.Commit, getStyle func(c *models.Commit) style
pipes := []*Pipe{{fromPos: 0, toPos: 0, fromSha: "START", toSha: commits[0].Sha, kind: STARTS, style: style.FgDefault}} pipes := []*Pipe{{fromPos: 0, toPos: 0, fromSha: "START", toSha: commits[0].Sha, kind: STARTS, style: style.FgDefault}}
return slices.Map(commits, func(commit *models.Commit) []*Pipe { return lo.Map(commits, func(commit *models.Commit, _ int) []*Pipe {
pipes = getNextPipes(pipes, commit, getStyle) pipes = getNextPipes(pipes, commit, getStyle)
return pipes return pipes
}) })
@ -108,17 +108,20 @@ func RenderAux(pipeSets [][]*Pipe, commits []*models.Commit, selectedCommitSha s
wg.Wait() wg.Wait()
return slices.Flatten(chunks) return lo.Flatten(chunks)
} }
func getNextPipes(prevPipes []*Pipe, commit *models.Commit, getStyle func(c *models.Commit) style.TextStyle) []*Pipe { func getNextPipes(prevPipes []*Pipe, commit *models.Commit, getStyle func(c *models.Commit) style.TextStyle) []*Pipe {
maxPos := slices.MaxBy(prevPipes, func(pipe *Pipe) int { maxPos := 0
return pipe.toPos for _, pipe := range prevPipes {
}) if pipe.toPos > maxPos {
maxPos = pipe.toPos
}
}
// a pipe that terminated in the previous line has no bearing on the current line // a pipe that terminated in the previous line has no bearing on the current line
// so we'll filter those out // so we'll filter those out
currentPipes := slices.Filter(prevPipes, func(pipe *Pipe) bool { currentPipes := lo.Filter(prevPipes, func(pipe *Pipe, _ int) bool {
return pipe.kind != TERMINATES return pipe.kind != TERMINATES
}) })
@ -299,7 +302,7 @@ func renderPipeSet(
} }
isMerge := startCount > 1 isMerge := startCount > 1
cells := slices.Map(lo.Range(maxPos+1), func(i int) *Cell { cells := lo.Map(lo.Range(maxPos+1), func(i int, _ int) *Cell {
return &Cell{cellType: CONNECTION, style: style.FgDefault} return &Cell{cellType: CONNECTION, style: style.FgDefault}
}) })
@ -337,7 +340,7 @@ func renderPipeSet(
// so we have our commit pos again, now it's time to build the cells. // so we have our commit pos again, now it's time to build the cells.
// we'll handle the one that's sourced from our selected commit last so that it can override the other cells. // we'll handle the one that's sourced from our selected commit last so that it can override the other cells.
selectedPipes, nonSelectedPipes := slices.Partition(pipes, func(pipe *Pipe) bool { selectedPipes, nonSelectedPipes := utils.Partition(pipes, func(pipe *Pipe) bool {
return highlight && equalHashes(pipe.fromSha, selectedCommitSha) return highlight && equalHashes(pipe.fromSha, selectedCommitSha)
}) })

View File

@ -4,12 +4,12 @@ import (
"time" "time"
"github.com/jesseduffield/generics/set" "github.com/jesseduffield/generics/set"
"github.com/jesseduffield/generics/slices"
"github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/gui/style" "github.com/jesseduffield/lazygit/pkg/gui/style"
"github.com/jesseduffield/lazygit/pkg/theme" "github.com/jesseduffield/lazygit/pkg/theme"
"github.com/jesseduffield/lazygit/pkg/utils" "github.com/jesseduffield/lazygit/pkg/utils"
"github.com/kyokomi/emoji/v2" "github.com/kyokomi/emoji/v2"
"github.com/samber/lo"
) )
func GetReflogCommitListDisplayStrings(commits []*models.Commit, fullDescription bool, cherryPickedCommitShaSet *set.Set[string], diffName string, now time.Time, timeFormat string, shortTimeFormat string, parseEmoji bool) [][]string { func GetReflogCommitListDisplayStrings(commits []*models.Commit, fullDescription bool, cherryPickedCommitShaSet *set.Set[string], diffName string, now time.Time, timeFormat string, shortTimeFormat string, parseEmoji bool) [][]string {
@ -20,7 +20,7 @@ func GetReflogCommitListDisplayStrings(commits []*models.Commit, fullDescription
displayFunc = getDisplayStringsForReflogCommit displayFunc = getDisplayStringsForReflogCommit
} }
return slices.Map(commits, func(commit *models.Commit) []string { return lo.Map(commits, func(commit *models.Commit, _ int) []string {
diffed := commit.Sha == diffName diffed := commit.Sha == diffName
cherryPicked := cherryPickedCommitShaSet.Includes(commit.Sha) cherryPicked := cherryPickedCommitShaSet.Includes(commit.Sha)
return displayFunc(commit, return displayFunc(commit,

View File

@ -1,14 +1,14 @@
package presentation package presentation
import ( import (
"github.com/jesseduffield/generics/slices"
"github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/gui/presentation/icons" "github.com/jesseduffield/lazygit/pkg/gui/presentation/icons"
"github.com/jesseduffield/lazygit/pkg/theme" "github.com/jesseduffield/lazygit/pkg/theme"
"github.com/samber/lo"
) )
func GetRemoteBranchListDisplayStrings(branches []*models.RemoteBranch, diffName string) [][]string { func GetRemoteBranchListDisplayStrings(branches []*models.RemoteBranch, diffName string) [][]string {
return slices.Map(branches, func(branch *models.RemoteBranch) []string { return lo.Map(branches, func(branch *models.RemoteBranch, _ int) []string {
diffed := branch.FullName() == diffName diffed := branch.FullName() == diffName
return getRemoteBranchDisplayStrings(branch, diffed) return getRemoteBranchDisplayStrings(branch, diffed)
}) })

View File

@ -1,15 +1,15 @@
package presentation package presentation
import ( import (
"github.com/jesseduffield/generics/slices"
"github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/gui/presentation/icons" "github.com/jesseduffield/lazygit/pkg/gui/presentation/icons"
"github.com/jesseduffield/lazygit/pkg/gui/style" "github.com/jesseduffield/lazygit/pkg/gui/style"
"github.com/jesseduffield/lazygit/pkg/theme" "github.com/jesseduffield/lazygit/pkg/theme"
"github.com/samber/lo"
) )
func GetRemoteListDisplayStrings(remotes []*models.Remote, diffName string) [][]string { func GetRemoteListDisplayStrings(remotes []*models.Remote, diffName string) [][]string {
return slices.Map(remotes, func(remote *models.Remote) []string { return lo.Map(remotes, func(remote *models.Remote, _ int) []string {
diffed := remote.Name == diffName diffed := remote.Name == diffName
return getRemoteDisplayStrings(remote, diffed) return getRemoteDisplayStrings(remote, diffed)
}) })

View File

@ -1,14 +1,14 @@
package presentation package presentation
import ( import (
"github.com/jesseduffield/generics/slices"
"github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/gui/presentation/icons" "github.com/jesseduffield/lazygit/pkg/gui/presentation/icons"
"github.com/jesseduffield/lazygit/pkg/theme" "github.com/jesseduffield/lazygit/pkg/theme"
"github.com/samber/lo"
) )
func GetStashEntryListDisplayStrings(stashEntries []*models.StashEntry, diffName string) [][]string { func GetStashEntryListDisplayStrings(stashEntries []*models.StashEntry, diffName string) [][]string {
return slices.Map(stashEntries, func(stashEntry *models.StashEntry) []string { return lo.Map(stashEntries, func(stashEntry *models.StashEntry, _ int) []string {
diffed := stashEntry.RefName() == diffName diffed := stashEntry.RefName() == diffName
return getStashEntryDisplayStrings(stashEntry, diffed) return getStashEntryDisplayStrings(stashEntry, diffed)
}) })

View File

@ -1,13 +1,13 @@
package presentation package presentation
import ( import (
"github.com/jesseduffield/generics/slices"
"github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/theme" "github.com/jesseduffield/lazygit/pkg/theme"
"github.com/samber/lo"
) )
func GetSubmoduleListDisplayStrings(submodules []*models.SubmoduleConfig) [][]string { func GetSubmoduleListDisplayStrings(submodules []*models.SubmoduleConfig) [][]string {
return slices.Map(submodules, func(submodule *models.SubmoduleConfig) []string { return lo.Map(submodules, func(submodule *models.SubmoduleConfig, _ int) []string {
return getSubmoduleDisplayStrings(submodule) return getSubmoduleDisplayStrings(submodule)
}) })
} }

View File

@ -1,12 +1,12 @@
package presentation package presentation
import ( import (
"github.com/jesseduffield/generics/slices"
"github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/samber/lo"
) )
func GetSuggestionListDisplayStrings(suggestions []*types.Suggestion) [][]string { func GetSuggestionListDisplayStrings(suggestions []*types.Suggestion) [][]string {
return slices.Map(suggestions, func(suggestion *types.Suggestion) []string { return lo.Map(suggestions, func(suggestion *types.Suggestion, _ int) []string {
return getSuggestionDisplayStrings(suggestion) return getSuggestionDisplayStrings(suggestion)
}) })
} }

View File

@ -1,15 +1,15 @@
package presentation package presentation
import ( import (
"github.com/jesseduffield/generics/slices"
"github.com/jesseduffield/lazygit/pkg/commands/models" "github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/gui/presentation/icons" "github.com/jesseduffield/lazygit/pkg/gui/presentation/icons"
"github.com/jesseduffield/lazygit/pkg/gui/style" "github.com/jesseduffield/lazygit/pkg/gui/style"
"github.com/jesseduffield/lazygit/pkg/theme" "github.com/jesseduffield/lazygit/pkg/theme"
"github.com/samber/lo"
) )
func GetTagListDisplayStrings(tags []*models.Tag, diffName string) [][]string { func GetTagListDisplayStrings(tags []*models.Tag, diffName string) [][]string {
return slices.Map(tags, func(tag *models.Tag) []string { return lo.Map(tags, func(tag *models.Tag, _ int) []string {
diffed := tag.Name == diffName diffed := tag.Name == diffName
return getTagDisplayStrings(tag, diffed) return getTagDisplayStrings(tag, diffed)
}) })

View File

@ -5,7 +5,6 @@ import (
"strings" "strings"
"text/template" "text/template"
"github.com/jesseduffield/generics/slices"
"github.com/jesseduffield/gocui" "github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/config" "github.com/jesseduffield/lazygit/pkg/config"
"github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers" "github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers"
@ -193,7 +192,7 @@ func (self *HandlerCreator) confirmPrompt(prompt *config.CustomCommandPrompt, ha
} }
func (self *HandlerCreator) menuPrompt(prompt *config.CustomCommandPrompt, wrappedF func(string) error) error { func (self *HandlerCreator) menuPrompt(prompt *config.CustomCommandPrompt, wrappedF func(string) error) error {
menuItems := slices.Map(prompt.Options, func(option config.CustomCommandMenuOption) *types.MenuItem { menuItems := lo.Map(prompt.Options, func(option config.CustomCommandMenuOption, _ int) *types.MenuItem {
return &types.MenuItem{ return &types.MenuItem{
LabelColumns: []string{option.Name, style.FgYellow.Sprint(option.Description)}, LabelColumns: []string{option.Name, style.FgYellow.Sprint(option.Description)},
OnPress: func() error { OnPress: func() error {
@ -218,7 +217,7 @@ func (self *HandlerCreator) menuPromptFromCommand(prompt *config.CustomCommandPr
return self.c.Error(err) return self.c.Error(err)
} }
menuItems := slices.Map(candidates, func(candidate *commandMenuItem) *types.MenuItem { menuItems := lo.Map(candidates, func(candidate *commandMenuItem, _ int) *types.MenuItem {
return &types.MenuItem{ return &types.MenuItem{
LabelColumns: []string{candidate.label}, LabelColumns: []string{candidate.label},
OnPress: func() error { OnPress: func() error {

View File

@ -4,13 +4,13 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/jesseduffield/generics/slices"
"github.com/jesseduffield/gocui" "github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/config" "github.com/jesseduffield/lazygit/pkg/config"
"github.com/jesseduffield/lazygit/pkg/gui/context" "github.com/jesseduffield/lazygit/pkg/gui/context"
"github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers" "github.com/jesseduffield/lazygit/pkg/gui/controllers/helpers"
"github.com/jesseduffield/lazygit/pkg/gui/keybindings" "github.com/jesseduffield/lazygit/pkg/gui/keybindings"
"github.com/jesseduffield/lazygit/pkg/gui/types" "github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/samber/lo"
) )
// KeybindingCreator takes a custom command along with its handler and returns a corresponding keybinding // KeybindingCreator takes a custom command along with its handler and returns a corresponding keybinding
@ -73,7 +73,7 @@ func (self *KeybindingCreator) contextForContextKey(contextKey types.ContextKey)
} }
func formatUnknownContextError(customCommand config.CustomCommand) error { func formatUnknownContextError(customCommand config.CustomCommand) error {
allContextKeyStrings := slices.Map(context.AllContextKeys, func(key types.ContextKey) string { allContextKeyStrings := lo.Map(context.AllContextKeys, func(key types.ContextKey, _ int) string {
return string(key) return string(key)
}) })

View File

@ -3,8 +3,8 @@ package status
import ( import (
"time" "time"
"github.com/jesseduffield/generics/slices"
"github.com/jesseduffield/lazygit/pkg/utils" "github.com/jesseduffield/lazygit/pkg/utils"
"github.com/samber/lo"
"github.com/sasha-s/go-deadlock" "github.com/sasha-s/go-deadlock"
) )
@ -88,7 +88,7 @@ func (self *StatusManager) removeStatus(id int) {
self.mutex.Lock() self.mutex.Lock()
defer self.mutex.Unlock() defer self.mutex.Unlock()
self.statuses = slices.Filter(self.statuses, func(status appStatus) bool { self.statuses = lo.Filter(self.statuses, func(status appStatus, _ int) bool {
return status.id != id return status.id != id
}) })
} }

View File

@ -1,11 +1,11 @@
package gui package gui
import ( import (
"github.com/jesseduffield/generics/slices"
"github.com/jesseduffield/gocui" "github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/gui/keybindings" "github.com/jesseduffield/lazygit/pkg/gui/keybindings"
"github.com/jesseduffield/lazygit/pkg/theme" "github.com/jesseduffield/lazygit/pkg/theme"
"github.com/jesseduffield/lazygit/pkg/utils" "github.com/jesseduffield/lazygit/pkg/utils"
"github.com/samber/lo"
) )
type viewNameMapping struct { type viewNameMapping struct {
@ -14,7 +14,7 @@ type viewNameMapping struct {
} }
func (gui *Gui) orderedViews() []*gocui.View { func (gui *Gui) orderedViews() []*gocui.View {
return slices.Map(gui.orderedViewNameMappings(), func(v viewNameMapping) *gocui.View { return lo.Map(gui.orderedViewNameMappings(), func(v viewNameMapping, _ int) *gocui.View {
return *v.viewPtr return *v.viewPtr
}) })
} }

View File

@ -8,7 +8,6 @@ import (
"strconv" "strconv"
"strings" "strings"
"github.com/jesseduffield/generics/slices"
"github.com/jesseduffield/lazygit/pkg/integration/components" "github.com/jesseduffield/lazygit/pkg/integration/components"
"github.com/jesseduffield/lazygit/pkg/integration/tests" "github.com/jesseduffield/lazygit/pkg/integration/tests"
"github.com/samber/lo" "github.com/samber/lo"
@ -58,7 +57,7 @@ func getTestsToRun(testNames []string) []*components.IntegrationTest {
return allIntegrationTests return allIntegrationTests
} }
testNames = slices.Map(testNames, func(name string) string { testNames = lo.Map(testNames, func(name string, _ int) string {
// allowing full test paths to be passed for convenience // allowing full test paths to be passed for convenience
return strings.TrimSuffix( return strings.TrimSuffix(
regexp.MustCompile(`.*pkg/integration/tests/`).ReplaceAllString(name, ""), regexp.MustCompile(`.*pkg/integration/tests/`).ReplaceAllString(name, ""),

View File

@ -7,7 +7,6 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
"github.com/jesseduffield/generics/slices"
"github.com/jesseduffield/gocui" "github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazycore/pkg/utils" "github.com/jesseduffield/lazycore/pkg/utils"
"github.com/jesseduffield/lazygit/pkg/gui" "github.com/jesseduffield/lazygit/pkg/gui"
@ -15,6 +14,7 @@ import (
"github.com/jesseduffield/lazygit/pkg/integration/components" "github.com/jesseduffield/lazygit/pkg/integration/components"
"github.com/jesseduffield/lazygit/pkg/integration/tests" "github.com/jesseduffield/lazygit/pkg/integration/tests"
"github.com/jesseduffield/lazygit/pkg/secureexec" "github.com/jesseduffield/lazygit/pkg/secureexec"
"github.com/samber/lo"
) )
// This program lets you run integration tests from a TUI. See pkg/integration/README.md for more info. // This program lets you run integration tests from a TUI. See pkg/integration/README.md for more info.
@ -245,7 +245,7 @@ func (self *app) filterWithString(needle string) {
if needle == "" { if needle == "" {
self.filteredTests = self.allTests self.filteredTests = self.allTests
} else { } else {
self.filteredTests = slices.Filter(self.allTests, func(test *components.IntegrationTest) bool { self.filteredTests = lo.Filter(self.allTests, func(test *components.IntegrationTest, _ int) bool {
return strings.Contains(test.Name(), needle) return strings.Contains(test.Name(), needle)
}) })
} }

View File

@ -5,11 +5,11 @@ import (
"strconv" "strconv"
"strings" "strings"
"github.com/jesseduffield/generics/slices"
"github.com/jesseduffield/lazygit/pkg/commands/git_commands" "github.com/jesseduffield/lazygit/pkg/commands/git_commands"
"github.com/jesseduffield/lazygit/pkg/config" "github.com/jesseduffield/lazygit/pkg/config"
integrationTypes "github.com/jesseduffield/lazygit/pkg/integration/types" integrationTypes "github.com/jesseduffield/lazygit/pkg/integration/types"
"github.com/jesseduffield/lazygit/pkg/utils" "github.com/jesseduffield/lazygit/pkg/utils"
"github.com/samber/lo"
) )
// IntegrationTest describes an integration test that will be run against the lazygit gui. // IntegrationTest describes an integration test that will be run against the lazygit gui.
@ -102,7 +102,7 @@ func (self GitVersionRestriction) shouldRunOnVersion(version *git_commands.GitVe
return version.IsOlderThanVersion(before) return version.IsOlderThanVersion(before)
} }
if len(self.includes) != 0 { if len(self.includes) != 0 {
return slices.Some(self.includes, func(str string) bool { return lo.SomeBy(self.includes, func(str string) bool {
v, err := git_commands.ParseGitVersion(str) v, err := git_commands.ParseGitVersion(str)
if err != nil { if err != nil {
panic("Invalid git version string: " + str) panic("Invalid git version string: " + str)

View File

@ -9,18 +9,18 @@ import (
"strings" "strings"
"github.com/jesseduffield/generics/set" "github.com/jesseduffield/generics/set"
"github.com/jesseduffield/generics/slices"
"github.com/jesseduffield/lazycore/pkg/utils" "github.com/jesseduffield/lazycore/pkg/utils"
"github.com/jesseduffield/lazygit/pkg/integration/components" "github.com/jesseduffield/lazygit/pkg/integration/components"
"github.com/samber/lo"
) )
func GetTests() []*components.IntegrationTest { func GetTests() []*components.IntegrationTest {
// first we ensure that each test in this directory has actually been added to the above list. // first we ensure that each test in this directory has actually been added to the above list.
testCount := 0 testCount := 0
testNamesSet := set.NewFromSlice(slices.Map( testNamesSet := set.NewFromSlice(lo.Map(
tests, tests,
func(test *components.IntegrationTest) string { func(test *components.IntegrationTest, _ int) string {
return test.Name() return test.Name()
}, },
)) ))

View File

@ -3,7 +3,6 @@ package utils
import ( import (
"strings" "strings"
"github.com/jesseduffield/generics/slices"
"github.com/mattn/go-runewidth" "github.com/mattn/go-runewidth"
"github.com/samber/lo" "github.com/samber/lo"
) )
@ -117,15 +116,15 @@ func getPaddedDisplayStrings(stringArrays [][]string, columnConfigs []ColumnConf
} }
func getPadWidths(stringArrays [][]string) []int { func getPadWidths(stringArrays [][]string) []int {
maxWidth := slices.MaxBy(stringArrays, func(stringArray []string) int { maxWidth := MaxFn(stringArrays, func(stringArray []string) int {
return len(stringArray) return len(stringArray)
}) })
if maxWidth-1 < 0 { if maxWidth-1 < 0 {
return []int{} return []int{}
} }
return slices.Map(lo.Range(maxWidth-1), func(i int) int { return lo.Map(lo.Range(maxWidth-1), func(i int, _ int) int {
return slices.MaxBy(stringArrays, func(stringArray []string) int { return MaxFn(stringArrays, func(stringArray []string) int {
uncoloredStr := Decolorise(stringArray[i]) uncoloredStr := Decolorise(stringArray[i])
return runewidth.StringWidth(uncoloredStr) return runewidth.StringWidth(uncoloredStr)
@ -133,6 +132,16 @@ func getPadWidths(stringArrays [][]string) []int {
}) })
} }
func MaxFn[T any](items []T, fn func(T) int) int {
max := 0
for _, item := range items {
if fn(item) > max {
max = fn(item)
}
}
return max
}
// TruncateWithEllipsis returns a string, truncated to a certain length, with an ellipsis // TruncateWithEllipsis returns a string, truncated to a certain length, with an ellipsis
func TruncateWithEllipsis(str string, limit int) string { func TruncateWithEllipsis(str string, limit int) string {
if runewidth.StringWidth(str) > limit && limit <= 3 { if runewidth.StringWidth(str) > limit && limit <= 3 {

View File

@ -4,8 +4,8 @@ import (
"sort" "sort"
"strings" "strings"
"github.com/jesseduffield/generics/slices"
"github.com/sahilm/fuzzy" "github.com/sahilm/fuzzy"
"github.com/samber/lo"
) )
func FuzzySearch(needle string, haystack []string) []string { func FuzzySearch(needle string, haystack []string) []string {
@ -16,7 +16,7 @@ func FuzzySearch(needle string, haystack []string) []string {
matches := fuzzy.Find(needle, haystack) matches := fuzzy.Find(needle, haystack)
sort.Sort(matches) sort.Sort(matches)
return slices.Map(matches, func(match fuzzy.Match) string { return lo.Map(matches, func(match fuzzy.Match, _ int) string {
return match.Str return match.Str
}) })
} }

View File

@ -1,5 +1,7 @@
package utils package utils
import "golang.org/x/exp/slices"
// NextIndex returns the index of the element that comes after the given number // NextIndex returns the index of the element that comes after the given number
func NextIndex(numbers []int, currentNumber int) int { func NextIndex(numbers []int, currentNumber int) int {
for index, number := range numbers { for index, number := range numbers {
@ -124,3 +126,56 @@ func ValuesAtIndices[T any](slice []T, indices []int) []T {
} }
return result return result
} }
// returns two slices: the first is for elements that pass the test, the second for those that don't.
func Partition[T any](slice []T, test func(T) bool) ([]T, []T) {
left := make([]T, 0, len(slice))
right := make([]T, 0, len(slice))
for _, value := range slice {
if test(value) {
left = append(left, value)
} else {
right = append(right, value)
}
}
return left, right
}
// 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.
func Prepend[T any](slice []T, values ...T) []T {
return append(values, slice...)
}
// Removes the element at the given index. Intended usage is to reassign the result to the input slice.
func Remove[T any](slice []T, index int) []T {
return slices.Delete(slice, index, index+1)
}
// Removes the element at the 'fromIndex' and then inserts it at 'toIndex'.
// Operates on the input slice. Expected use is to reassign the result to the input slice.
func Move[T any](slice []T, fromIndex int, toIndex int) []T {
item := slice[fromIndex]
slice = Remove(slice, fromIndex)
return slices.Insert(slice, toIndex, item)
}
// Pops item from the end of the slice and returns it, along with the updated slice
// Mutates original slice. Intended usage is to reassign the slice result to the input slice.
func Pop[T any](slice []T) (T, []T) {
index := len(slice) - 1
value := slice[index]
slice = slice[0:index]
return value, slice
}
// Shifts item from the beginning of the slice and returns it, along with the updated slice.
// Mutates original slice. Intended usage is to reassign the slice result to the input slice.
func Shift[T any](slice []T) (T, []T) {
value := slice[0]
slice = slice[1:]
return value, slice
}

View File

@ -1,117 +0,0 @@
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)
}

View File

@ -1,57 +0,0 @@
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 check for equality with the
// element at the returned index is required.
func BinarySearch[E constraints.Ordered](x []E, target E) int {
return slices.BinarySearch(x, target)
}
// BinarySearchFunc uses binary search to find and return the smallest index i
// in [0, n) at which ok(i) is true, assuming that on the range [0, n),
// ok(i) == true implies ok(i+1) == true. That is, BinarySearchFunc requires
// that ok is false for some (possibly empty) prefix of the input range [0, n)
// and then true for the (possibly empty) remainder; BinarySearchFunc returns
// the first true index. If there is no such index, BinarySearchFunc returns n.
// (Note that the "not found" return value is not -1 as in, for instance,
// strings.Index.) Search calls ok(i) only for i in the range [0, n).
func BinarySearchFunc[E any](x []E, ok func(E) bool) int {
return slices.BinarySearchFunc(x, ok)
}

View File

@ -1,408 +0,0 @@
package slices
import (
"golang.org/x/exp/constraints"
"golang.org/x/exp/slices"
)
// This file contains the new functions that do not live in the official slices package.
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
}
// Produces a new slice, leaves the input slice untouched.
func Map[T any, V any](slice []T, f func(T) V) []V {
result := make([]V, 0, len(slice))
for _, value := range slice {
result = append(result, f(value))
}
return result
}
// Produces a new slice, leaves the input slice untouched.
func MapWithIndex[T any, V any](slice []T, f func(T, int) V) []V {
result := make([]V, 0, len(slice))
for i, value := range slice {
result = append(result, f(value, i))
}
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
// of the original slice is the lower bound
result := make([]V, 0, len(slice))
for _, value := range slice {
result = append(result, f(value)...)
}
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 {
result = append(result, subSlice...)
}
return result
}
func MapInPlace[T any](slice []T, f func(T) T) {
for i, value := range slice {
slice[i] = f(value)
}
}
// Produces a new slice, leaves the input slice untouched.
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
}
// Produces a new slice, leaves the input slice untouched.
func FilterWithIndex[T any](slice []T, f func(T, int) bool) []T {
result := make([]T, 0, len(slice))
for i, value := range slice {
if f(value, i) {
result = append(result, value)
}
}
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
for _, element := range slice {
if test(element) {
slice[newLength] = element
newLength++
}
}
return slice[:newLength]
}
// Produces a new slice, leaves the input slice untouched
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]
}
}
// Produces a new slice, leaves the input slice untouched.
func FilterMap[T any, E any](slice []T, test func(T) (E, bool)) []E {
result := make([]E, 0, len(slice))
for _, element := range slice {
mapped, ok := test(element)
if ok {
result = append(result, mapped)
}
}
return result
}
func FilterMapWithIndex[T any, E any](slice []T, test func(T, int) (E, bool)) []E {
result := make([]E, 0, len(slice))
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.
func Prepend[T any](slice []T, values ...T) []T {
return append(values, slice...)
}
// Removes the element at the given index. Intended usage is to reassign the result to the input slice.
func Remove[T any](slice []T, index int) []T {
return slices.Delete(slice, index, index+1)
}
// Removes the element at the 'fromIndex' and then inserts it at 'toIndex'.
// Operates on the input slice. Expected use is to reassign the result to the input slice.
func Move[T any](slice []T, fromIndex int, toIndex int) []T {
item := slice[fromIndex]
slice = Remove(slice, fromIndex)
return slices.Insert(slice, toIndex, item)
}
// Swaps two elements at the given indices.
// Operates on the input slice.
func Swap[T any](slice []T, index1 int, index2 int) {
slice[index1], slice[index2] = slice[index2], slice[index1]
}
// Similar to Append but we leave the original slice untouched and return a new slice
func Concat[T any](slice []T, values ...T) []T {
newSlice := make([]T, 0, len(slice)+len(values))
newSlice = append(newSlice, slice...)
newSlice = append(newSlice, values...)
return newSlice
}
func ContainsFunc[T any](slice []T, f func(T) bool) bool {
return IndexFunc(slice, f) != -1
}
// Pops item from the end of the slice and returns it, along with the updated slice
// Mutates original slice. Intended usage is to reassign the slice result to the input slice.
func Pop[T any](slice []T) (T, []T) {
index := len(slice) - 1
value := slice[index]
slice = slice[0:index]
return value, slice
}
// Shifts item from the beginning of the slice and returns it, along with the updated slice.
// Mutates original slice. Intended usage is to reassign the slice result to the input slice.
func Shift[T any](slice []T) (T, []T) {
value := slice[0]
slice = slice[1:]
return value, slice
}
func Partition[T any](slice []T, test func(T) bool) ([]T, []T) {
left := make([]T, 0, len(slice))
right := make([]T, 0, len(slice))
for _, value := range slice {
if test(value) {
left = append(left, value)
} else {
right = append(right, value)
}
}
return left, right
}
func MaxBy[T any, V constraints.Ordered](slice []T, f func(T) V) V {
if len(slice) == 0 {
return zero[V]()
}
max := f(slice[0])
for _, element := range slice[1:] {
value := f(element)
if value > max {
max = value
}
}
return max
}
func MinBy[T any, V constraints.Ordered](slice []T, f func(T) V) V {
if len(slice) == 0 {
return zero[V]()
}
min := f(slice[0])
for _, element := range slice[1:] {
value := f(element)
if value < min {
min = value
}
}
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
}
// Sometimes you need to find an element and then map it to some other value based on
// information you obtained while finding it. This function lets you do that
func FindMap[T any, V any](slice []T, f func(T) (V, bool)) (V, bool) {
for _, element := range slice {
if value, ok := f(element); ok {
return value, true
}
}
return zero[V](), 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 Sum[T constraints.Ordered](i []T) T {
sum := zero[T]()
for _, value := range i {
sum += value
}
return sum
}
func zero[T any]() T {
var value T
return value
}

1
vendor/modules.txt vendored
View File

@ -127,7 +127,6 @@ github.com/jbenet/go-context/io
## explicit; go 1.18 ## explicit; go 1.18
github.com/jesseduffield/generics/maps github.com/jesseduffield/generics/maps
github.com/jesseduffield/generics/set github.com/jesseduffield/generics/set
github.com/jesseduffield/generics/slices
# github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d # github.com/jesseduffield/go-git/v5 v5.1.2-0.20221018185014-fdd53fef665d
## explicit; go 1.13 ## explicit; go 1.13
github.com/jesseduffield/go-git/v5 github.com/jesseduffield/go-git/v5