chore(query): unify search in number menu selection and normal search

This commit is contained in:
jguer 2021-10-16 10:07:39 +02:00 committed by J Guerreiro
parent 44cf54795d
commit 9eb73899fe
8 changed files with 450 additions and 391 deletions

109
cmd.go
View File

@ -5,7 +5,6 @@ import (
"context"
"fmt"
"net/http"
"os"
"strings"
alpm "github.com/Jguer/go-alpm/v2"
@ -310,7 +309,6 @@ func handleGetpkgbuild(ctx context.Context, cmdArgs *parser.Arguments, dbExecuto
}
func handleYogurt(ctx context.Context, cmdArgs *parser.Arguments, dbExecutor db.Executor) error {
config.SearchMode = numberMenu
return displayNumberMenu(ctx, cmdArgs.Targets, dbExecutor, cmdArgs)
}
@ -319,13 +317,7 @@ func handleSync(ctx context.Context, cmdArgs *parser.Arguments, dbExecutor db.Ex
switch {
case cmdArgs.ExistsArg("s", "search"):
if cmdArgs.ExistsArg("q", "quiet") {
config.SearchMode = minimal
} else {
config.SearchMode = detailed
}
return syncSearch(ctx, targets, config.Runtime.AURClient, dbExecutor)
return syncSearch(ctx, targets, config.Runtime.AURClient, dbExecutor, !cmdArgs.ExistsArg("q", "quiet"))
case cmdArgs.ExistsArg("p", "print", "print-format"):
return config.Runtime.CmdBuilder.Show(config.Runtime.CmdBuilder.BuildPacmanCmd(ctx,
cmdArgs, config.Runtime.Mode, settings.NoConfirm))
@ -362,107 +354,30 @@ func handleRemove(ctx context.Context, cmdArgs *parser.Arguments, localCache *vc
// NumberMenu presents a CLI for selecting packages to install.
func displayNumberMenu(ctx context.Context, pkgS []string, dbExecutor db.Executor, cmdArgs *parser.Arguments) error {
var (
aurErr error
aq aurQuery
pq repoQuery
lenaq, lenpq int
)
queryBuilder := query.NewSourceQueryBuilder(config.SortMode, config.SortBy, config.Runtime.Mode, config.SearchBy)
pkgS = query.RemoveInvalidTargets(pkgS, config.Runtime.Mode)
queryBuilder.Execute(ctx, dbExecutor, config.Runtime.AURClient, pkgS)
if config.Runtime.Mode.AtLeastAUR() {
aq, aurErr = narrowSearch(ctx, config.Runtime.AURClient, pkgS, true)
lenaq = len(aq)
}
if config.Runtime.Mode.AtLeastRepo() {
pq = queryRepo(pkgS, dbExecutor)
lenpq = len(pq)
}
if aurErr != nil {
text.Errorln(gotext.Get("Error during AUR search: %s\n", aurErr))
text.Warnln(gotext.Get("Showing repo packages only"))
}
if lenpq == 0 && lenaq == 0 {
return fmt.Errorf(gotext.Get("no packages match search"))
}
switch config.SortMode {
case settings.TopDown:
if config.Runtime.Mode.AtLeastRepo() {
pq.printSearch(dbExecutor)
}
if config.Runtime.Mode.AtLeastAUR() {
aq.printSearch(lenpq+1, dbExecutor)
}
case settings.BottomUp:
if config.Runtime.Mode.AtLeastAUR() {
aq.printSearch(lenpq+1, dbExecutor)
}
if config.Runtime.Mode.AtLeastRepo() {
pq.printSearch(dbExecutor)
}
default:
return fmt.Errorf(gotext.Get("invalid sort mode. Fix with yay -Y --bottomup --save"))
if err := queryBuilder.Results(dbExecutor, query.NumberMenu); err != nil {
return err
}
text.Infoln(gotext.Get("Packages to install (eg: 1 2 3, 1-3 or ^4)"))
text.Info()
reader := bufio.NewReader(os.Stdin)
numberBuf, overflow, err := reader.ReadLine()
numberBuf, err := text.GetInput("", false)
if err != nil {
return err
}
if overflow {
return fmt.Errorf(gotext.Get("input too long"))
include, exclude, _, otherExclude := intrange.ParseNumberMenu(numberBuf)
targets, err := queryBuilder.GetTargets(include, exclude, otherExclude)
if err != nil {
return err
}
include, exclude, _, otherExclude := intrange.ParseNumberMenu(string(numberBuf))
arguments := cmdArgs.CopyGlobal()
isInclude := len(exclude) == 0 && len(otherExclude) == 0
for i, pkg := range pq {
var target int
switch config.SortMode {
case settings.TopDown:
target = i + 1
case settings.BottomUp:
target = len(pq) - i
default:
return fmt.Errorf(gotext.Get("invalid sort mode. Fix with yay -Y --bottomup --save"))
}
if (isInclude && include.Get(target)) || (!isInclude && !exclude.Get(target)) {
arguments.AddTarget(pkg.DB().Name() + "/" + pkg.Name())
}
}
for i := range aq {
var target int
switch config.SortMode {
case settings.TopDown:
target = i + 1 + len(pq)
case settings.BottomUp:
target = len(aq) - i + len(pq)
default:
return fmt.Errorf(gotext.Get("invalid sort mode. Fix with yay -Y --bottomup --save"))
}
if (isInclude && include.Get(target)) || (!isInclude && !exclude.Get(target)) {
arguments.AddTarget("aur/" + aq[i].Name)
}
}
arguments.AddTarget(targets...)
if len(arguments.Targets) == 0 {
fmt.Println(gotext.Get(" there is nothing to do"))

View File

@ -2,13 +2,6 @@ package main
import "github.com/Jguer/yay/v11/pkg/settings"
// Verbosity settings for search.
const (
numberMenu = iota
detailed
minimal
)
var (
yayVersion = "11.0.1" // To be set by compiler.
localePath = "/usr/share/locale" // To be set by compiler.

28
pkg/query/errors.go Normal file
View File

@ -0,0 +1,28 @@
package query
import (
"github.com/leonelquinteros/gotext"
)
// ErrAURSearch means that it was not possible to connect to the AUR.
type ErrAURSearch struct {
inner error
}
func (e ErrAURSearch) Error() string {
return gotext.Get("Error during AUR search: %s\n", e.inner.Error())
}
// ErrInvalidSortMode means that the sort mode provided was not valid.
type ErrInvalidSortMode struct{}
func (e ErrInvalidSortMode) Error() string {
return gotext.Get("invalid sort mode. Fix with yay -Y --bottomup --save")
}
// ErrNoQuery means that query was not executed.
type ErrNoQuery struct{}
func (e ErrNoQuery) Error() string {
return gotext.Get("no query was executed")
}

223
pkg/query/source.go Normal file
View File

@ -0,0 +1,223 @@
package query
import (
"context"
"sort"
"strings"
"github.com/Jguer/aur"
"github.com/leonelquinteros/gotext"
"github.com/Jguer/yay/v11/pkg/db"
"github.com/Jguer/yay/v11/pkg/intrange"
"github.com/Jguer/yay/v11/pkg/settings"
"github.com/Jguer/yay/v11/pkg/settings/parser"
"github.com/Jguer/yay/v11/pkg/stringset"
"github.com/Jguer/yay/v11/pkg/text"
)
type SearchVerbosity int
// Verbosity settings for search.
const (
NumberMenu SearchVerbosity = iota
Detailed
Minimal
)
type SourceQueryBuilder struct {
repoQuery
aurQuery
sortMode int
sortBy string
targetMode parser.TargetMode
searchBy string
}
func NewSourceQueryBuilder(sortMode int, sortBy string, targetMode parser.TargetMode, searchBy string) *SourceQueryBuilder {
return &SourceQueryBuilder{
sortMode: sortMode,
sortBy: sortBy,
targetMode: targetMode,
searchBy: searchBy,
}
}
func (s *SourceQueryBuilder) Execute(ctx context.Context, dbExecutor db.Executor, aurClient *aur.Client, pkgS []string) {
var aurErr error
pkgS = RemoveInvalidTargets(pkgS, s.targetMode)
if s.targetMode.AtLeastAUR() {
s.aurQuery, aurErr = queryAUR(ctx, aurClient, pkgS, s.searchBy, s.sortMode, s.sortBy)
}
if s.targetMode.AtLeastRepo() {
s.repoQuery = queryRepo(pkgS, dbExecutor, s.sortMode)
}
if aurErr != nil && len(s.repoQuery) != 0 {
text.Errorln(ErrAURSearch{inner: aurErr})
text.Warnln(gotext.Get("Showing repo packages only"))
}
}
func (s *SourceQueryBuilder) Results(dbExecutor db.Executor, verboseSearch SearchVerbosity) error {
if s.aurQuery == nil && s.repoQuery == nil {
return ErrNoQuery{}
}
switch s.sortMode {
case settings.TopDown:
if s.targetMode.AtLeastRepo() {
s.repoQuery.printSearch(dbExecutor, verboseSearch, s.sortMode)
}
if s.targetMode.AtLeastAUR() {
s.aurQuery.printSearch(1, dbExecutor, verboseSearch, s.sortMode)
}
case settings.BottomUp:
if s.targetMode.AtLeastAUR() {
s.aurQuery.printSearch(1, dbExecutor, verboseSearch, s.sortMode)
}
if s.targetMode.AtLeastRepo() {
s.repoQuery.printSearch(dbExecutor, verboseSearch, s.sortMode)
}
default:
return ErrInvalidSortMode{}
}
return nil
}
func (s *SourceQueryBuilder) GetTargets(include, exclude intrange.IntRanges,
otherExclude stringset.StringSet) ([]string, error) {
isInclude := len(exclude) == 0 && len(otherExclude) == 0
var targets []string
for i, pkg := range s.repoQuery {
var target int
switch s.sortMode {
case settings.TopDown:
target = i + 1
case settings.BottomUp:
target = len(s.repoQuery) - i
default:
return targets, ErrInvalidSortMode{}
}
if (isInclude && include.Get(target)) || (!isInclude && !exclude.Get(target)) {
targets = append(targets, pkg.DB().Name()+"/"+pkg.Name())
}
}
for i := range s.aurQuery {
var target int
switch s.sortMode {
case settings.TopDown:
target = i + 1 + len(s.repoQuery)
case settings.BottomUp:
target = len(s.aurQuery) - i + len(s.repoQuery)
default:
return targets, ErrInvalidSortMode{}
}
if (isInclude && include.Get(target)) || (!isInclude && !exclude.Get(target)) {
targets = append(targets, "aur/"+s.aurQuery[i].Name)
}
}
return targets, nil
}
// queryRepo handles repo searches. Creates a RepoSearch struct.
func queryRepo(pkgInputN []string, dbExecutor db.Executor, sortMode int) repoQuery {
s := repoQuery(dbExecutor.SyncPackages(pkgInputN...))
if sortMode == settings.BottomUp {
s = sort.Reverse(s).(repoQuery)
}
return s
}
// queryAUR searches AUR and narrows based on subarguments.
func queryAUR(ctx context.Context, aurClient *aur.Client, pkgS []string, searchBy string, sortMode int, sortBy string) (aurQuery, error) {
var (
r []aur.Pkg
err error
usedIndex int
)
by := getSearchBy(searchBy)
if len(pkgS) == 0 {
return nil, nil
}
for i, word := range pkgS {
r, err = aurClient.Search(ctx, word, by)
if err == nil {
usedIndex = i
break
}
}
if err != nil {
return nil, err
}
if len(pkgS) == 1 {
sort.Sort(aurSortable{
aurQuery: r,
sortBy: sortBy,
sortMode: sortMode,
})
return r, err
}
var (
aq aurQuery
n int
)
for i := range r {
match := true
for j, pkgN := range pkgS {
if usedIndex == j {
continue
}
name := strings.ToLower(r[i].Name)
desc := strings.ToLower(r[i].Description)
targ := strings.ToLower(pkgN)
if !(strings.Contains(name, targ) || strings.Contains(desc, targ)) {
match = false
break
}
}
if match {
n++
aq = append(aq, r[i])
}
}
sort.Sort(aurSortable{
aurQuery: aq,
sortBy: sortBy,
sortMode: sortMode,
})
return aq, err
}

180
pkg/query/types.go Normal file
View File

@ -0,0 +1,180 @@
package query
import (
"fmt"
"strconv"
"github.com/Jguer/aur"
"github.com/Jguer/go-alpm/v2"
"github.com/leonelquinteros/gotext"
"github.com/Jguer/yay/v11/pkg/db"
"github.com/Jguer/yay/v11/pkg/settings"
"github.com/Jguer/yay/v11/pkg/text"
)
type (
aurQuery []aur.Pkg // Query is a collection of Results.
repoQuery []alpm.IPackage // Query holds the results of a repository search.
)
type aurSortable struct {
aurQuery
sortBy string
sortMode int
}
func (r repoQuery) Len() int {
return len(r)
}
func (r repoQuery) Swap(i, j int) {
r[i], r[j] = r[j], r[i]
}
func (r repoQuery) Less(i, j int) bool {
return text.LessRunes([]rune(r[i].Name()), []rune(r[j].Name()))
}
func (q aurSortable) Len() int {
return len(q.aurQuery)
}
func (q aurSortable) Less(i, j int) bool {
var result bool
switch q.sortBy {
case "votes":
result = q.aurQuery[i].NumVotes > q.aurQuery[j].NumVotes
case "popularity":
result = q.aurQuery[i].Popularity > q.aurQuery[j].Popularity
case "name":
result = text.LessRunes([]rune(q.aurQuery[i].Name), []rune(q.aurQuery[j].Name))
case "base":
result = text.LessRunes([]rune(q.aurQuery[i].PackageBase), []rune(q.aurQuery[j].PackageBase))
case "submitted":
result = q.aurQuery[i].FirstSubmitted < q.aurQuery[j].FirstSubmitted
case "modified":
result = q.aurQuery[i].LastModified < q.aurQuery[j].LastModified
case "id":
result = q.aurQuery[i].ID < q.aurQuery[j].ID
case "baseid":
result = q.aurQuery[i].PackageBaseID < q.aurQuery[j].PackageBaseID
}
if q.sortMode == settings.BottomUp {
return !result
}
return result
}
func (q aurSortable) Swap(i, j int) {
q.aurQuery[i], q.aurQuery[j] = q.aurQuery[j], q.aurQuery[i]
}
func getSearchBy(value string) aur.By {
switch value {
case "name":
return aur.Name
case "maintainer":
return aur.Maintainer
case "depends":
return aur.Depends
case "makedepends":
return aur.MakeDepends
case "optdepends":
return aur.OptDepends
case "checkdepends":
return aur.CheckDepends
default:
return aur.NameDesc
}
}
// PrintSearch handles printing search results in a given format.
func (q aurQuery) printSearch(start int, dbExecutor db.Executor, searchMode SearchVerbosity, sortMode int) {
for i := range q {
var toprint string
if searchMode == NumberMenu {
switch sortMode {
case settings.TopDown:
toprint += text.Magenta(strconv.Itoa(start+i) + " ")
case settings.BottomUp:
toprint += text.Magenta(strconv.Itoa(len(q)+start-i-1) + " ")
default:
text.Warnln(gotext.Get("invalid sort mode. Fix with yay -Y --bottomup --save"))
}
} else if searchMode == Minimal {
fmt.Println(q[i].Name)
continue
}
toprint += text.Bold(text.ColorHash("aur")) + "/" + text.Bold(q[i].Name) +
" " + text.Cyan(q[i].Version) +
text.Bold(" (+"+strconv.Itoa(q[i].NumVotes)) +
" " + text.Bold(strconv.FormatFloat(q[i].Popularity, 'f', 2, 64)+") ")
if q[i].Maintainer == "" {
toprint += text.Bold(text.Red(gotext.Get("(Orphaned)"))) + " "
}
if q[i].OutOfDate != 0 {
toprint += text.Bold(text.Red(gotext.Get("(Out-of-date: %s)", text.FormatTime(q[i].OutOfDate)))) + " "
}
if pkg := dbExecutor.LocalPackage(q[i].Name); pkg != nil {
if pkg.Version() != q[i].Version {
toprint += text.Bold(text.Green(gotext.Get("(Installed: %s)", pkg.Version())))
} else {
toprint += text.Bold(text.Green(gotext.Get("(Installed)")))
}
}
toprint += "\n " + q[i].Description
fmt.Println(toprint)
}
}
// PrintSearch receives a RepoSearch type and outputs pretty text.
func (r repoQuery) printSearch(dbExecutor db.Executor, searchMode SearchVerbosity, sortMode int) {
for i, res := range r {
var toprint string
if searchMode == NumberMenu {
switch sortMode {
case settings.TopDown:
toprint += text.Magenta(strconv.Itoa(i+1) + " ")
case settings.BottomUp:
toprint += text.Magenta(strconv.Itoa(len(r)-i) + " ")
default:
text.Warnln(gotext.Get("invalid sort mode. Fix with yay -Y --bottomup --save"))
}
} else if searchMode == Minimal {
fmt.Println(res.Name())
continue
}
toprint += text.Bold(text.ColorHash(res.DB().Name())) + "/" + text.Bold(res.Name()) +
" " + text.Cyan(res.Version()) +
text.Bold(" ("+text.Human(res.Size())+
" "+text.Human(res.ISize())+") ")
packageGroups := dbExecutor.PackageGroups(res)
if len(packageGroups) != 0 {
toprint += fmt.Sprint(packageGroups, " ")
}
if pkg := dbExecutor.LocalPackage(res.Name()); pkg != nil {
if pkg.Version() != res.Version() {
toprint += text.Bold(text.Green(gotext.Get("(Installed: %s)", pkg.Version())))
} else {
toprint += text.Bold(text.Green(gotext.Get("(Installed)")))
}
}
toprint += "\n " + res.Description()
fmt.Println(toprint)
}
}

View File

@ -60,7 +60,6 @@ type Configuration struct {
SudoBin string `json:"sudobin"`
SudoFlags string `json:"sudoflags"`
RequestSplitN int `json:"requestsplitn"`
SearchMode int `json:"-"`
SortMode int `json:"sortmode"`
CompletionInterval int `json:"completionrefreshtime"`
SudoLoop bool `json:"sudoloop"`

View File

@ -11,102 +11,12 @@ import (
"github.com/Jguer/yay/v11/pkg/db"
"github.com/Jguer/yay/v11/pkg/query"
"github.com/Jguer/yay/v11/pkg/settings"
"github.com/Jguer/yay/v11/pkg/settings/parser"
"github.com/Jguer/yay/v11/pkg/stringset"
"github.com/Jguer/yay/v11/pkg/text"
"github.com/Jguer/yay/v11/pkg/upgrade"
)
// PrintSearch handles printing search results in a given format.
func (q aurQuery) printSearch(start int, dbExecutor db.Executor) {
for i := range q {
var toprint string
if config.SearchMode == numberMenu {
switch config.SortMode {
case settings.TopDown:
toprint += text.Magenta(strconv.Itoa(start+i) + " ")
case settings.BottomUp:
toprint += text.Magenta(strconv.Itoa(len(q)+start-i-1) + " ")
default:
text.Warnln(gotext.Get("invalid sort mode. Fix with yay -Y --bottomup --save"))
}
} else if config.SearchMode == minimal {
fmt.Println(q[i].Name)
continue
}
toprint += text.Bold(text.ColorHash("aur")) + "/" + text.Bold(q[i].Name) +
" " + text.Cyan(q[i].Version) +
text.Bold(" (+"+strconv.Itoa(q[i].NumVotes)) +
" " + text.Bold(strconv.FormatFloat(q[i].Popularity, 'f', 2, 64)+") ")
if q[i].Maintainer == "" {
toprint += text.Bold(text.Red(gotext.Get("(Orphaned)"))) + " "
}
if q[i].OutOfDate != 0 {
toprint += text.Bold(text.Red(gotext.Get("(Out-of-date: %s)", text.FormatTime(q[i].OutOfDate)))) + " "
}
if pkg := dbExecutor.LocalPackage(q[i].Name); pkg != nil {
if pkg.Version() != q[i].Version {
toprint += text.Bold(text.Green(gotext.Get("(Installed: %s)", pkg.Version())))
} else {
toprint += text.Bold(text.Green(gotext.Get("(Installed)")))
}
}
toprint += "\n " + q[i].Description
fmt.Println(toprint)
}
}
// PrintSearch receives a RepoSearch type and outputs pretty text.
func (s repoQuery) printSearch(dbExecutor db.Executor) {
for i, res := range s {
var toprint string
if config.SearchMode == numberMenu {
switch config.SortMode {
case settings.TopDown:
toprint += text.Magenta(strconv.Itoa(i+1) + " ")
case settings.BottomUp:
toprint += text.Magenta(strconv.Itoa(len(s)-i) + " ")
default:
text.Warnln(gotext.Get("invalid sort mode. Fix with yay -Y --bottomup --save"))
}
} else if config.SearchMode == minimal {
fmt.Println(res.Name())
continue
}
toprint += text.Bold(text.ColorHash(res.DB().Name())) + "/" + text.Bold(res.Name()) +
" " + text.Cyan(res.Version()) +
text.Bold(" ("+text.Human(res.Size())+
" "+text.Human(res.ISize())+") ")
packageGroups := dbExecutor.PackageGroups(res)
if len(packageGroups) != 0 {
toprint += fmt.Sprint(packageGroups, " ")
}
if pkg := dbExecutor.LocalPackage(res.Name()); pkg != nil {
if pkg.Version() != res.Version() {
toprint += text.Bold(text.Green(gotext.Get("(Installed: %s)", pkg.Version())))
} else {
toprint += text.Bold(text.Green(gotext.Get("(Installed)")))
}
}
toprint += "\n " + res.Description()
fmt.Println(toprint)
}
}
// Pretty print a set of packages from the same package base.
// PrintInfo prints package info like pacman -Si.
func PrintInfo(a *aur.Pkg, extendedInfo bool) {
text.PrintInfoValue(gotext.Get("Repository"), "aur")

203
query.go
View File

@ -2,15 +2,11 @@ package main
import (
"context"
"errors"
"fmt"
"os"
"sort"
"strings"
aur "github.com/Jguer/aur"
alpm "github.com/Jguer/go-alpm/v2"
"github.com/leonelquinteros/gotext"
"github.com/Jguer/yay/v11/pkg/db"
"github.com/Jguer/yay/v11/pkg/query"
@ -20,192 +16,18 @@ import (
"github.com/Jguer/yay/v11/pkg/text"
)
// Query is a collection of Results.
type aurQuery []aur.Pkg
// Query holds the results of a repository search.
type repoQuery []alpm.IPackage
func (s repoQuery) Reverse() {
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
s[i], s[j] = s[j], s[i]
}
}
func (q aurQuery) Len() int {
return len(q)
}
func (q aurQuery) Less(i, j int) bool {
var result bool
switch config.SortBy {
case "votes":
result = q[i].NumVotes > q[j].NumVotes
case "popularity":
result = q[i].Popularity > q[j].Popularity
case "name":
result = text.LessRunes([]rune(q[i].Name), []rune(q[j].Name))
case "base":
result = text.LessRunes([]rune(q[i].PackageBase), []rune(q[j].PackageBase))
case "submitted":
result = q[i].FirstSubmitted < q[j].FirstSubmitted
case "modified":
result = q[i].LastModified < q[j].LastModified
case "id":
result = q[i].ID < q[j].ID
case "baseid":
result = q[i].PackageBaseID < q[j].PackageBaseID
}
if config.SortMode == settings.BottomUp {
return !result
}
return result
}
func (q aurQuery) Swap(i, j int) {
q[i], q[j] = q[j], q[i]
}
func getSearchBy(value string) aur.By {
switch value {
case "name":
return aur.Name
case "maintainer":
return aur.Maintainer
case "depends":
return aur.Depends
case "makedepends":
return aur.MakeDepends
case "optdepends":
return aur.OptDepends
case "checkdepends":
return aur.CheckDepends
default:
return aur.NameDesc
}
}
// NarrowSearch searches AUR and narrows based on subarguments.
func narrowSearch(ctx context.Context, aurClient *aur.Client, pkgS []string, sortS bool) (aurQuery, error) {
var (
r []aur.Pkg
err error
usedIndex int
)
by := getSearchBy(config.SearchBy)
if len(pkgS) == 0 {
return nil, nil
}
for i, word := range pkgS {
r, err = aurClient.Search(ctx, word, by)
if err == nil {
usedIndex = i
break
}
}
if err != nil {
return nil, err
}
if len(pkgS) == 1 {
if sortS {
sort.Sort(aurQuery(r))
}
return r, err
}
var (
aq aurQuery
n int
)
for i := range r {
match := true
for j, pkgN := range pkgS {
if usedIndex == j {
continue
}
name := strings.ToLower(r[i].Name)
desc := strings.ToLower(r[i].Description)
targ := strings.ToLower(pkgN)
if !(strings.Contains(name, targ) || strings.Contains(desc, targ)) {
match = false
break
}
}
if match {
n++
aq = append(aq, r[i])
}
}
if sortS {
sort.Sort(aq)
}
return aq, err
}
// SyncSearch presents a query to the local repos and to the AUR.
func syncSearch(ctx context.Context, pkgS []string, aurClient *aur.Client, dbExecutor db.Executor) (err error) {
pkgS = query.RemoveInvalidTargets(pkgS, config.Runtime.Mode)
func syncSearch(ctx context.Context, pkgS []string, aurClient *aur.Client, dbExecutor db.Executor, verbose bool) error {
queryBuilder := query.NewSourceQueryBuilder(config.SortMode, config.SortBy, config.Runtime.Mode, config.SearchBy)
var (
aurErr error
aq aurQuery
pq repoQuery
)
queryBuilder.Execute(ctx, dbExecutor, aurClient, pkgS)
if config.Runtime.Mode.AtLeastAUR() {
aq, aurErr = narrowSearch(ctx, aurClient, pkgS, true)
searchMode := query.Minimal
if verbose {
searchMode = query.Detailed
}
if config.Runtime.Mode.AtLeastRepo() {
pq = queryRepo(pkgS, dbExecutor)
}
switch config.SortMode {
case settings.TopDown:
if config.Runtime.Mode.AtLeastRepo() {
pq.printSearch(dbExecutor)
}
if config.Runtime.Mode.AtLeastAUR() {
aq.printSearch(1, dbExecutor)
}
case settings.BottomUp:
if config.Runtime.Mode.AtLeastAUR() {
aq.printSearch(1, dbExecutor)
}
if config.Runtime.Mode.AtLeastRepo() {
pq.printSearch(dbExecutor)
}
default:
return errors.New(gotext.Get("invalid sort mode. Fix with yay -Y --bottomup --save"))
}
if aurErr != nil {
text.Errorln(gotext.Get("error during AUR search: %s", aurErr))
text.Warnln(gotext.Get("Showing repo packages only"))
}
return nil
return queryBuilder.Results(dbExecutor, searchMode)
}
// SyncInfo serves as a pacman -Si for repo packages and AUR packages.
@ -265,17 +87,6 @@ func syncInfo(ctx context.Context, cmdArgs *parser.Arguments, pkgS []string, dbE
return err
}
// Search handles repo searches. Creates a RepoSearch struct.
func queryRepo(pkgInputN []string, dbExecutor db.Executor) repoQuery {
s := repoQuery(dbExecutor.SyncPackages(pkgInputN...))
if config.SortMode == settings.BottomUp {
s.Reverse()
}
return s
}
// PackageSlices separates an input slice into aur and repo slices.
func packageSlices(toCheck []string, dbExecutor db.Executor) (aurNames, repoNames []string) {
for _, _pkg := range toCheck {