git-project-manager/cmd/util_fzf.go

141 lines
4.0 KiB
Go
Raw Normal View History

2023-12-08 21:52:26 +00:00
package cmd
import (
"context"
fzf "github.com/ktr0731/go-fuzzyfinder"
"gitlab.sweetwater.com/it/devops/tools/gitlab-project-manager/internal/gitlab"
"gitlab.sweetwater.com/it/devops/tools/gitlab-project-manager/internal/projects"
)
2023-12-10 16:15:52 +00:00
// This will try to find a project by alias if a search term
// is given, otherwise will fuzzy find by project
2023-12-08 21:52:26 +00:00
func fzfFindProject(searchString string) *gitlab.Project {
var project *gitlab.Project
if searchString != "" {
project = fzfSearchProjectAliases(searchString)
} else {
var err error
project, err = fzfProject(rootCmd.Context())
if project == nil || err != nil {
return nil
}
}
return project
}
2023-12-10 16:15:52 +00:00
// This will fuzzy search only aliases, preferring an exact
// match if one is given
2023-12-08 21:52:26 +00:00
func fzfSearchProjectAliases(searchString string) *gitlab.Project {
var project *gitlab.Project
var alias *projects.ProjectAlias
if alias = cache.GetAliasByName(searchString); alias != nil {
project = cache.GetProjectByAlias(alias)
plog.Info("Perfect alias match... flawless")
} else {
// Get fuzzy if we don't have an exact match
aliases := cache.FuzzyFindAlias(searchString)
if len(aliases) > 1 {
2023-12-10 16:15:52 +00:00
// If multiple aliases were found, switch over to project
// by alias mode with merging
// alias = fzfAliasFromAliases(rootCmd.Context(), aliases)
project, _ = fzfProjectFromAliases(rootCmd.Context(), aliases)
2023-12-08 21:52:26 +00:00
} else if len(aliases) == 1 {
alias = aliases[0]
2023-12-10 16:15:52 +00:00
project = cache.GetProjectByAlias(alias)
2023-12-08 21:52:26 +00:00
}
}
return project
}
2023-12-10 16:15:52 +00:00
// Given a list of aliases, will fuzzy-find and return
// a single one. Replaced by fzfProjectFromAliases in fzfSearchProjectAliases
// as merging is preferred, but can be used if it's ever desirable to
// return a single alias from all aliases
2023-12-08 21:52:26 +00:00
func fzfAliasFromAliases(ctx context.Context, aliases []*projects.ProjectAlias) *projects.ProjectAlias {
var alias *projects.ProjectAlias
i, err := fzf.Find(
aliases,
func(i int) string {
return aliases[i].Alias + " -> " + cache.GetProjectByAlias(aliases[i]).PathWithNamespace
},
fzf.WithContext(ctx),
fzf.WithHeader("Choose an Alias"),
)
if err != nil {
plog.Error("Failed to fzf alias slice", plog.Args("error", err))
} else {
alias = aliases[i]
}
return alias
}
2023-12-10 16:15:52 +00:00
// Given a list of aliases, merge them together and use the resulting
// list of projects to return a project
func fzfProjectFromAliases(ctx context.Context, aliases []*projects.ProjectAlias) (
*gitlab.Project, error) {
mergedProjects := projectsFromAliases(aliases)
if len(mergedProjects) == 1 {
return mergedProjects[0], nil
}
2023-12-10 16:15:52 +00:00
return fzfProjectFromProjects(ctx, mergedProjects)
}
func projectsFromAliases(aliases []*projects.ProjectAlias) []*gitlab.Project {
projects := make([]*gitlab.Project, 0)
ALIASES:
for _, a := range aliases {
for _, p := range projects {
// Already have it
if a.ProjectID == p.ID {
continue ALIASES
}
}
projects = append(projects, cache.GetProjectByAlias(a))
}
return projects
}
2023-12-09 04:13:17 +00:00
// If a bool=true is provided, will only allow selection of projects
// that have at least one alias defined
func fzfProject(ctx context.Context, mustHaveAlias ...bool) (*gitlab.Project, error) {
var searchableProjects []*gitlab.Project
if len(mustHaveAlias) == 1 && mustHaveAlias[0] {
searchableProjects = cache.GetProjectsWithAliases()
} else {
searchableProjects = cache.Projects
}
2023-12-10 16:15:52 +00:00
return fzfProjectFromProjects(ctx, searchableProjects)
}
2023-12-09 04:13:17 +00:00
2023-12-10 16:15:52 +00:00
// Takes a list of projects and performs a fuzzyfind
func fzfProjectFromProjects(ctx context.Context, projects []*gitlab.Project) (
*gitlab.Project, error) {
i, err := fzf.Find(projects,
2023-12-09 04:13:17 +00:00
func(i int) string {
2023-12-10 16:15:52 +00:00
// Display the project along with its aliases
return cache.GetProjectStringWithAliases(projects[i])
2023-12-09 04:13:17 +00:00
},
fzf.WithPreviewWindow(
func(i, width, height int) string {
2023-12-10 16:15:52 +00:00
return cache.ProjectString(projects[i])
2023-12-09 04:13:17 +00:00
},
),
2023-12-08 21:52:26 +00:00
fzf.WithContext(ctx),
fzf.WithHeader("Fuzzy find yourself a project"),
)
if err != nil || i < 0 {
return nil, err
}
2023-12-10 16:15:52 +00:00
return projects[i], nil
2023-12-08 21:52:26 +00:00
}
func fzfPreviewWindow(i, w, h int) string {
p := cache.Projects[i]
return cache.ProjectString(p)
}