feat(yay): simplify sort mode and use it for calculating number menu indices, fixes #1627

This commit is contained in:
jguer 2021-11-07 00:15:50 +01:00 committed by J Guerreiro
parent 53e8ec70f8
commit e38d0138a6
10 changed files with 69 additions and 95 deletions

4
cmd.go
View file

@ -274,7 +274,7 @@ func handlePrint(ctx context.Context, cmdArgs *parser.Arguments, dbExecutor db.E
double := cmdArgs.ExistsDouble("w", "news")
quiet := cmdArgs.ExistsArg("q", "quiet")
return news.PrintNewsFeed(ctx, config.Runtime.HTTPClient, dbExecutor.LastBuildTime(), config.SortMode, double, quiet)
return news.PrintNewsFeed(ctx, config.Runtime.HTTPClient, dbExecutor.LastBuildTime(), config.BottomUp, double, quiet)
case cmdArgs.ExistsDouble("c", "complete"):
return completion.Show(ctx, config.Runtime.HTTPClient, dbExecutor,
config.AURURL, config.Runtime.CompletionPath, config.CompletionInterval, true)
@ -357,7 +357,7 @@ 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 {
queryBuilder := query.NewSourceQueryBuilder(config.SortMode, config.SortBy, config.Runtime.Mode, config.SearchBy, config.SingleLineResults)
queryBuilder := query.NewSourceQueryBuilder(config.SortBy, config.Runtime.Mode, config.SearchBy, config.BottomUp, config.SingleLineResults)
queryBuilder.Execute(ctx, dbExecutor, config.Runtime.AURClient, pkgS)

View file

@ -12,7 +12,6 @@ import (
"strings"
"time"
"github.com/Jguer/yay/v11/pkg/settings"
"github.com/Jguer/yay/v11/pkg/text"
)
@ -61,7 +60,7 @@ type rss struct {
Channel channel `xml:"channel"`
}
func PrintNewsFeed(ctx context.Context, client *http.Client, cutOffDate time.Time, sortMode int, all, quiet bool) error {
func PrintNewsFeed(ctx context.Context, client *http.Client, cutOffDate time.Time, bottomUp, all, quiet bool) error {
req, err := http.NewRequestWithContext(ctx, "GET", "https://archlinux.org/feeds/news", nil)
if err != nil {
return err
@ -86,7 +85,7 @@ func PrintNewsFeed(ctx context.Context, client *http.Client, cutOffDate time.Tim
return err
}
if sortMode == settings.BottomUp {
if bottomUp {
for i := len(rssGot.Channel.Items) - 1; i >= 0; i-- {
rssGot.Channel.Items[i].print(cutOffDate, all, quiet)
}

View file

@ -107,7 +107,7 @@ func TestPrintNewsFeed(t *testing.T) {
type args struct {
cutOffDate time.Time
sortMode int
bottomUp bool
all bool
quiet bool
}
@ -116,10 +116,10 @@ func TestPrintNewsFeed(t *testing.T) {
args args
wantErr bool
}{
{name: "all-verbose", args: args{cutOffDate: time.Now(), all: true, quiet: false}, wantErr: false},
{name: "all-quiet", args: args{cutOffDate: lastNewsTime, all: true, quiet: true}, wantErr: false},
{name: "latest-quiet", args: args{cutOffDate: lastNewsTime, all: false, quiet: true}, wantErr: false},
{name: "latest-quiet-topdown", args: args{sortMode: 1, cutOffDate: lastNewsTime, all: false, quiet: true}, wantErr: false},
{name: "all-verbose", args: args{bottomUp: true, cutOffDate: time.Now(), all: true, quiet: false}, wantErr: false},
{name: "all-quiet", args: args{bottomUp: true, cutOffDate: lastNewsTime, all: true, quiet: true}, wantErr: false},
{name: "latest-quiet", args: args{bottomUp: true, cutOffDate: lastNewsTime, all: false, quiet: true}, wantErr: false},
{name: "latest-quiet-topdown", args: args{bottomUp: false, cutOffDate: lastNewsTime, all: false, quiet: true}, wantErr: false},
}
for _, tt := range tests {
tt := tt
@ -135,7 +135,7 @@ func TestPrintNewsFeed(t *testing.T) {
r, w, _ := os.Pipe()
os.Stdout = w
err := PrintNewsFeed(context.TODO(), &http.Client{}, tt.args.cutOffDate, tt.args.sortMode, tt.args.all, tt.args.quiet)
err := PrintNewsFeed(context.TODO(), &http.Client{}, tt.args.cutOffDate, tt.args.bottomUp, tt.args.all, tt.args.quiet)
assert.NoError(t, err)
w.Close()
@ -164,7 +164,7 @@ func TestPrintNewsFeedSameDay(t *testing.T) {
r, w, _ := os.Pipe()
os.Stdout = w
err := PrintNewsFeed(context.TODO(), &http.Client{}, lastNewsTime, 0, false, false)
err := PrintNewsFeed(context.TODO(), &http.Client{}, lastNewsTime, true, false, false)
assert.NoError(t, err)
w.Close()

View file

@ -13,13 +13,6 @@ 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{}

View file

@ -7,11 +7,11 @@ import (
"strings"
"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/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"
@ -29,7 +29,7 @@ const (
type SourceQueryBuilder struct {
repoQuery
aurQuery
sortMode int
bottomUp bool
sortBy string
targetMode parser.TargetMode
searchBy string
@ -37,14 +37,16 @@ type SourceQueryBuilder struct {
}
func NewSourceQueryBuilder(
sortMode int,
sortBy string,
targetMode parser.TargetMode,
searchBy string,
bottomUp,
singleLineResults bool,
) *SourceQueryBuilder {
return &SourceQueryBuilder{
sortMode: sortMode,
repoQuery: []alpm.IPackage{},
aurQuery: []aur.Pkg{},
bottomUp: bottomUp,
sortBy: sortBy,
targetMode: targetMode,
searchBy: searchBy,
@ -58,11 +60,11 @@ func (s *SourceQueryBuilder) Execute(ctx context.Context, dbExecutor db.Executor
pkgS = RemoveInvalidTargets(pkgS, s.targetMode)
if s.targetMode.AtLeastAUR() {
s.aurQuery, aurErr = queryAUR(ctx, aurClient, pkgS, s.searchBy, s.sortMode, s.sortBy)
s.aurQuery, aurErr = queryAUR(ctx, aurClient, pkgS, s.searchBy, s.bottomUp, s.sortBy)
}
if s.targetMode.AtLeastRepo() {
s.repoQuery = queryRepo(pkgS, dbExecutor, s.sortMode)
s.repoQuery = queryRepo(pkgS, dbExecutor, s.bottomUp)
}
if aurErr != nil && len(s.repoQuery) != 0 {
@ -72,29 +74,26 @@ func (s *SourceQueryBuilder) Execute(ctx context.Context, dbExecutor db.Executor
}
func (s *SourceQueryBuilder) Results(w io.Writer, dbExecutor db.Executor, verboseSearch SearchVerbosity) error {
if s.aurQuery == nil && s.repoQuery == nil {
if s.aurQuery == nil || s.repoQuery == nil {
return ErrNoQuery{}
}
switch s.sortMode {
case settings.TopDown:
if s.targetMode.AtLeastRepo() {
s.repoQuery.printSearch(w, dbExecutor, verboseSearch, s.sortMode, s.singleLineResults)
}
if s.bottomUp {
if s.targetMode.AtLeastAUR() {
s.aurQuery.printSearch(w, 1, dbExecutor, verboseSearch, s.sortMode, s.singleLineResults)
}
case settings.BottomUp:
if s.targetMode.AtLeastAUR() {
s.aurQuery.printSearch(w, 1, dbExecutor, verboseSearch, s.sortMode, s.singleLineResults)
s.aurQuery.printSearch(w, len(s.repoQuery)+1, dbExecutor, verboseSearch, s.bottomUp, s.singleLineResults)
}
if s.targetMode.AtLeastRepo() {
s.repoQuery.printSearch(w, dbExecutor, verboseSearch, s.sortMode, s.singleLineResults)
s.repoQuery.printSearch(w, dbExecutor, verboseSearch, s.bottomUp, s.singleLineResults)
}
} else {
if s.targetMode.AtLeastRepo() {
s.repoQuery.printSearch(w, dbExecutor, verboseSearch, s.bottomUp, s.singleLineResults)
}
if s.targetMode.AtLeastAUR() {
s.aurQuery.printSearch(w, len(s.repoQuery)+1, dbExecutor, verboseSearch, s.bottomUp, s.singleLineResults)
}
default:
return ErrInvalidSortMode{}
}
return nil
@ -113,13 +112,10 @@ func (s *SourceQueryBuilder) GetTargets(include, exclude intrange.IntRanges,
for i, pkg := range s.repoQuery {
var target int
switch s.sortMode {
case settings.TopDown:
target = i + 1
case settings.BottomUp:
if s.bottomUp {
target = len(s.repoQuery) - i
default:
return targets, ErrInvalidSortMode{}
} else {
target = i + 1
}
if (isInclude && include.Get(target)) || (!isInclude && !exclude.Get(target)) {
@ -130,13 +126,10 @@ func (s *SourceQueryBuilder) GetTargets(include, exclude intrange.IntRanges,
for i := range s.aurQuery {
var target int
switch s.sortMode {
case settings.TopDown:
target = i + 1 + len(s.repoQuery)
case settings.BottomUp:
if s.bottomUp {
target = len(s.aurQuery) - i + len(s.repoQuery)
default:
return targets, ErrInvalidSortMode{}
} else {
target = i + 1 + len(s.repoQuery)
}
if (isInclude && include.Get(target)) || (!isInclude && !exclude.Get(target)) {
@ -148,10 +141,10 @@ func (s *SourceQueryBuilder) GetTargets(include, exclude intrange.IntRanges,
}
// queryRepo handles repo searches. Creates a RepoSearch struct.
func queryRepo(pkgInputN []string, dbExecutor db.Executor, sortMode int) repoQuery {
func queryRepo(pkgInputN []string, dbExecutor db.Executor, bottomUp bool) repoQuery {
s := repoQuery(dbExecutor.SyncPackages(pkgInputN...))
if sortMode == settings.BottomUp {
if bottomUp {
s.Reverse()
}
@ -159,7 +152,7 @@ func queryRepo(pkgInputN []string, dbExecutor db.Executor, sortMode int) repoQue
}
// 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) {
func queryAUR(ctx context.Context, aurClient *aur.Client, pkgS []string, searchBy string, bottomUp bool, sortBy string) (aurQuery, error) {
var (
r []aur.Pkg
err error
@ -189,7 +182,7 @@ func queryAUR(ctx context.Context, aurClient *aur.Client, pkgS []string, searchB
sort.Sort(aurSortable{
aurQuery: r,
sortBy: sortBy,
sortMode: sortMode,
bottomUp: bottomUp,
})
return r, err
@ -229,7 +222,7 @@ func queryAUR(ctx context.Context, aurClient *aur.Client, pkgS []string, searchB
sort.Sort(aurSortable{
aurQuery: aq,
sortBy: sortBy,
sortMode: sortMode,
bottomUp: bottomUp,
})
return aq, err

View file

@ -10,7 +10,6 @@ import (
"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"
)
@ -22,7 +21,7 @@ type (
type aurSortable struct {
aurQuery
sortBy string
sortMode int
bottomUp bool
}
func (r repoQuery) Reverse() {
@ -61,7 +60,7 @@ func (q aurSortable) Less(i, j int) bool {
result = q.aurQuery[i].PackageBaseID < q.aurQuery[j].PackageBaseID
}
if q.sortMode == settings.BottomUp {
if q.bottomUp {
return !result
}
@ -97,24 +96,23 @@ func (q aurQuery) printSearch(
start int,
dbExecutor db.Executor,
searchMode SearchVerbosity,
sortMode int,
bottomUp,
singleLineResults bool,
) {
for i := range q {
if searchMode == Minimal {
_, _ = fmt.Fprintln(w, q[i].Name)
continue
}
var toprint string
if searchMode == NumberMenu {
switch sortMode {
case settings.TopDown:
toprint += text.Magenta(strconv.Itoa(start+i) + " ")
case settings.BottomUp:
if 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 {
toprint += text.Magenta(strconv.Itoa(start+i) + " ")
}
} else if searchMode == Minimal {
_, _ = fmt.Fprintln(w, q[i].Name)
continue
}
toprint += text.Bold(text.ColorHash("aur")) + "/" + text.Bold(q[i].Name) +
@ -150,22 +148,21 @@ func (q aurQuery) printSearch(
}
// PrintSearch receives a RepoSearch type and outputs pretty text.
func (r repoQuery) printSearch(w io.Writer, dbExecutor db.Executor, searchMode SearchVerbosity, sortMode int, singleLineResults bool) {
func (r repoQuery) printSearch(w io.Writer, dbExecutor db.Executor, searchMode SearchVerbosity, bottomUp, singleLineResults bool) {
for i, res := range r {
if searchMode == Minimal {
_, _ = fmt.Fprintln(w, res.Name())
continue
}
var toprint string
if searchMode == NumberMenu {
switch sortMode {
case settings.TopDown:
toprint += text.Magenta(strconv.Itoa(i+1) + " ")
case settings.BottomUp:
if bottomUp {
toprint += text.Magenta(strconv.Itoa(len(r)-i) + " ")
default:
text.Warnln(gotext.Get("invalid sort mode. Fix with yay -Y --bottomup --save"))
} else {
toprint += text.Magenta(strconv.Itoa(i+1) + " ")
}
} else if searchMode == Minimal {
_, _ = fmt.Fprintln(w, res.Name())
continue
}
toprint += text.Bold(text.ColorHash(res.DB().Name())) + "/" + text.Bold(res.Name()) +

View file

@ -134,12 +134,11 @@ func Test_aurQuery_printSearch(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
w := &strings.Builder{}
sortMode := 1
executor := mock.DBExecutor{}
text.UseColor = tt.useColor
// Fire
tt.q.printSearch(w, 1, executor, tt.args.searchMode, sortMode, tt.args.singleLineResults)
tt.q.printSearch(w, 1, executor, tt.args.searchMode, false, tt.args.singleLineResults)
got := w.String()
assert.Equal(t, tt.want, got)
@ -237,12 +236,11 @@ func Test_repoQuery_printSearch(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
w := &strings.Builder{}
sortMode := 1
executor := mock.DBExecutor{}
text.UseColor = tt.useColor
// Fire
tt.q.printSearch(w, executor, tt.args.searchMode, sortMode, tt.args.singleLineResults)
tt.q.printSearch(w, executor, tt.args.searchMode, false, tt.args.singleLineResults)
got := w.String()
assert.Equal(t, tt.want, got)

View file

@ -50,9 +50,9 @@ func (c *Configuration) handleOption(option, value string) bool {
case "notimeupdate":
c.TimeUpdate = false
case "topdown":
c.SortMode = TopDown
c.BottomUp = false
case "bottomup":
c.SortMode = BottomUp
c.BottomUp = true
case "singlelineresults":
c.SingleLineResults = true
case "doublelineresults":

View file

@ -21,12 +21,6 @@ import (
"github.com/Jguer/yay/v11/pkg/vcs"
)
const (
// Describes Sorting method for numberdisplay.
BottomUp = iota
TopDown
)
// HideMenus indicates if pacman's provider menus must be hidden.
var HideMenus = false
@ -60,8 +54,8 @@ type Configuration struct {
SudoBin string `json:"sudobin"`
SudoFlags string `json:"sudoflags"`
RequestSplitN int `json:"requestsplitn"`
SortMode int `json:"sortmode"`
CompletionInterval int `json:"completionrefreshtime"`
BottomUp bool `json:"bottomup"`
SudoLoop bool `json:"sudoloop"`
TimeUpdate bool `json:"timeupdate"`
Devel bool `json:"devel"`
@ -185,7 +179,7 @@ func DefaultConfig() *Configuration {
GpgFlags: "",
MFlags: "",
GitFlags: "",
SortMode: BottomUp,
BottomUp: true,
CompletionInterval: 7,
SortBy: "votes",
SearchBy: "name-desc",

View file

@ -18,7 +18,7 @@ import (
// 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, verbose bool) error {
queryBuilder := query.NewSourceQueryBuilder(config.SortMode, config.SortBy, config.Runtime.Mode, config.SearchBy, config.SingleLineResults)
queryBuilder := query.NewSourceQueryBuilder(config.SortBy, config.Runtime.Mode, config.SearchBy, config.BottomUp, config.SingleLineResults)
queryBuilder.Execute(ctx, dbExecutor, aurClient, pkgS)