Move IntRange definition to types package

This commit is contained in:
Jguer 2019-10-05 19:23:13 +01:00
parent b01790f752
commit bf89b3383c
No known key found for this signature in database
GPG Key ID: 6D6CC9BEA8556B35
10 changed files with 222 additions and 209 deletions

7
cmd.go
View File

@ -8,6 +8,7 @@ import (
alpm "github.com/Jguer/go-alpm"
"github.com/Jguer/yay/v9/pkg/completion"
"github.com/Jguer/yay/v9/pkg/types"
)
var cmdArgs = makeArguments()
@ -350,7 +351,7 @@ func displayNumberMenu(pkgS []string) (err error) {
return fmt.Errorf("Input too long")
}
include, exclude, _, otherExclude := parseNumberMenu(string(numberBuf))
include, exclude, _, otherExclude := types.ParseNumberMenu(string(numberBuf))
arguments := makeArguments()
isInclude := len(exclude) == 0 && len(otherExclude) == 0
@ -366,7 +367,7 @@ func displayNumberMenu(pkgS []string) (err error) {
return fmt.Errorf("Invalid Sort Mode. Fix with yay -Y --bottomup --save")
}
if (isInclude && include.get(target)) || (!isInclude && !exclude.get(target)) {
if (isInclude && include.Get(target)) || (!isInclude && !exclude.Get(target)) {
arguments.addTarget(pkg.DB().Name() + "/" + pkg.Name())
}
}
@ -383,7 +384,7 @@ func displayNumberMenu(pkgS []string) (err error) {
return fmt.Errorf("Invalid Sort Mode. Fix with yay -Y --bottomup --save")
}
if (isInclude && include.get(target)) || (!isInclude && !exclude.get(target)) {
if (isInclude && include.Get(target)) || (!isInclude && !exclude.Get(target)) {
arguments.addTarget("aur/" + pkg.Name)
}
}

View File

@ -544,7 +544,7 @@ func cleanNumberMenu(bases []Base, installed types.StringSet, hasClean bool) ([]
return nil, err
}
cInclude, cExclude, cOtherInclude, cOtherExclude := parseNumberMenu(cleanInput)
cInclude, cExclude, cOtherInclude, cOtherExclude := types.ParseNumberMenu(cleanInput)
cIsInclude := len(cExclude) == 0 && len(cOtherExclude) == 0
if cOtherInclude.Get("abort") || cOtherInclude.Get("ab") {
@ -564,7 +564,7 @@ func cleanNumberMenu(bases []Base, installed types.StringSet, hasClean bool) ([]
continue
}
if !cIsInclude && cExclude.get(len(bases)-i) {
if !cIsInclude && cExclude.Get(len(bases)-i) {
continue
}
@ -583,12 +583,12 @@ func cleanNumberMenu(bases []Base, installed types.StringSet, hasClean bool) ([]
continue
}
if cIsInclude && (cInclude.get(len(bases)-i) || cOtherInclude.Get(pkg)) {
if cIsInclude && (cInclude.Get(len(bases)-i) || cOtherInclude.Get(pkg)) {
toClean = append(toClean, base)
continue
}
if !cIsInclude && (!cExclude.get(len(bases)-i) && !cOtherExclude.Get(pkg)) {
if !cIsInclude && (!cExclude.Get(len(bases)-i) && !cOtherExclude.Get(pkg)) {
toClean = append(toClean, base)
continue
}
@ -629,7 +629,7 @@ func editDiffNumberMenu(bases []Base, installed types.StringSet, diff bool) ([]B
}
}
eInclude, eExclude, eOtherInclude, eOtherExclude := parseNumberMenu(editInput)
eInclude, eExclude, eOtherInclude, eOtherExclude := types.ParseNumberMenu(editInput)
eIsInclude := len(eExclude) == 0 && len(eOtherExclude) == 0
if eOtherInclude.Get("abort") || eOtherInclude.Get("ab") {
@ -644,7 +644,7 @@ func editDiffNumberMenu(bases []Base, installed types.StringSet, diff bool) ([]B
anyInstalled = anyInstalled || installed.Get(b.Name)
}
if !eIsInclude && eExclude.get(len(bases)-i) {
if !eIsInclude && eExclude.Get(len(bases)-i) {
continue
}
@ -663,11 +663,11 @@ func editDiffNumberMenu(bases []Base, installed types.StringSet, diff bool) ([]B
continue
}
if eIsInclude && (eInclude.get(len(bases)-i) || eOtherInclude.Get(pkg)) {
if eIsInclude && (eInclude.Get(len(bases)-i) || eOtherInclude.Get(pkg)) {
toEdit = append(toEdit, base)
}
if !eIsInclude && (!eExclude.get(len(bases)-i) && !eOtherExclude.Get(pkg)) {
if !eIsInclude && (!eExclude.Get(len(bases)-i) && !eOtherExclude.Get(pkg)) {
toEdit = append(toEdit, base)
}
}

View File

@ -8,7 +8,6 @@ import (
"os"
"strconv"
"strings"
"unicode"
"github.com/Jguer/yay/v9/pkg/types"
rpc "github.com/mikkeloscar/aur"
@ -832,70 +831,6 @@ func (parser *arguments) extractYayOptions() {
config.AURURL = strings.TrimRight(config.AURURL, "/")
}
//parses input for number menus split by spaces or commas
//supports individual selection: 1 2 3 4
//supports range selections: 1-4 10-20
//supports negation: ^1 ^1-4
//
//include and excule holds numbers that should be added and should not be added
//respectively. other holds anything that can't be parsed as an int. This is
//intended to allow words inside of number menus. e.g. 'all' 'none' 'abort'
//of course the implementation is up to the caller, this function mearley parses
//the input and organizes it
func parseNumberMenu(input string) (intRanges, intRanges, types.StringSet, types.StringSet) {
include := make(intRanges, 0)
exclude := make(intRanges, 0)
otherInclude := make(types.StringSet)
otherExclude := make(types.StringSet)
words := strings.FieldsFunc(input, func(c rune) bool {
return unicode.IsSpace(c) || c == ','
})
for _, word := range words {
var num1 int
var num2 int
var err error
invert := false
other := otherInclude
if word[0] == '^' {
invert = true
other = otherExclude
word = word[1:]
}
ranges := strings.SplitN(word, "-", 2)
num1, err = strconv.Atoi(ranges[0])
if err != nil {
other.Set(strings.ToLower(word))
continue
}
if len(ranges) == 2 {
num2, err = strconv.Atoi(ranges[1])
if err != nil {
other.Set(strings.ToLower(word))
continue
}
} else {
num2 = num1
}
mi := min(num1, num2)
ma := max(num1, num2)
if !invert {
include = append(include, makeIntRange(mi, ma))
} else {
exclude = append(exclude, makeIntRange(mi, ma))
}
}
return include, exclude, otherInclude, otherExclude
}
// Crude html parsing, good enough for the arch news
// This is only displayed in the terminal so there should be no security
// concerns

View File

@ -1,83 +0,0 @@
package main
import (
"testing"
"github.com/Jguer/yay/v9/pkg/types"
)
func intRangesEqual(a, b intRanges) bool {
if a == nil && b == nil {
return true
}
if a == nil || b == nil {
return false
}
if len(a) != len(b) {
return false
}
for n := range a {
r1 := a[n]
r2 := b[n]
if r1.min != r2.min || r1.max != r2.max {
return false
}
}
return true
}
func TestParseNumberMenu(t *testing.T) {
type result struct {
Include intRanges
Exclude intRanges
OtherInclude types.StringSet
OtherExclude types.StringSet
}
inputs := []string{
"1 2 3 4 5",
"1-10 5-15",
"10-5 90-85",
"1 ^2 ^10-5 99 ^40-38 ^123 60-62",
"abort all none",
"a-b ^a-b ^abort",
"1\t2 3 4\t\t \t 5",
"1 2,3, 4, 5,6 ,7 ,8",
"",
" \t ",
"A B C D E",
}
expected := []result{
{intRanges{makeIntRange(1, 1), makeIntRange(2, 2), makeIntRange(3, 3), makeIntRange(4, 4), makeIntRange(5, 5)}, intRanges{}, make(types.StringSet), make(types.StringSet)},
{intRanges{makeIntRange(1, 10), makeIntRange(5, 15)}, intRanges{}, make(types.StringSet), make(types.StringSet)},
{intRanges{makeIntRange(5, 10), makeIntRange(85, 90)}, intRanges{}, make(types.StringSet), make(types.StringSet)},
{intRanges{makeIntRange(1, 1), makeIntRange(99, 99), makeIntRange(60, 62)}, intRanges{makeIntRange(2, 2), makeIntRange(5, 10), makeIntRange(38, 40), makeIntRange(123, 123)}, make(types.StringSet), make(types.StringSet)},
{intRanges{}, intRanges{}, types.MakeStringSet("abort", "all", "none"), make(types.StringSet)},
{intRanges{}, intRanges{}, types.MakeStringSet("a-b"), types.MakeStringSet("abort", "a-b")},
{intRanges{makeIntRange(1, 1), makeIntRange(2, 2), makeIntRange(3, 3), makeIntRange(4, 4), makeIntRange(5, 5)}, intRanges{}, make(types.StringSet), make(types.StringSet)},
{intRanges{makeIntRange(1, 1), makeIntRange(2, 2), makeIntRange(3, 3), makeIntRange(4, 4), makeIntRange(5, 5), makeIntRange(6, 6), makeIntRange(7, 7), makeIntRange(8, 8)}, intRanges{}, make(types.StringSet), make(types.StringSet)},
{intRanges{}, intRanges{}, make(types.StringSet), make(types.StringSet)},
{intRanges{}, intRanges{}, make(types.StringSet), make(types.StringSet)},
{intRanges{}, intRanges{}, types.MakeStringSet("a", "b", "c", "d", "e"), make(types.StringSet)},
}
for n, in := range inputs {
res := expected[n]
include, exclude, otherInclude, otherExclude := parseNumberMenu(in)
if !intRangesEqual(include, res.Include) ||
!intRangesEqual(exclude, res.Exclude) ||
!types.StringSetEqual(otherInclude, res.OtherInclude) ||
!types.StringSetEqual(otherExclude, res.OtherExclude) {
t.Fatalf("Test %d Failed: Expected: include=%+v exclude=%+v otherInclude=%+v otherExclude=%+v got include=%+v excluive=%+v otherInclude=%+v otherExclude=%+v",
n+1, res.Include, res.Exclude, res.OtherInclude, res.OtherExclude, include, exclude, otherInclude, otherExclude)
}
}
}

146
pkg/types/intrange.go Normal file
View File

@ -0,0 +1,146 @@
package types
import (
"strconv"
"strings"
"unicode"
)
// IntRange stores a max and min amount for range
type IntRange struct {
min int
max int
}
// IntRanges is a slice of IntRange
type IntRanges []IntRange
func makeIntRange(min, max int) IntRange {
return IntRange{
min,
max,
}
}
// Get returns true if the argument n is included in the closed range
// between min and max
func (r IntRange) Get(n int) bool {
return n >= r.min && n <= r.max
}
// Get returns true if the argument n is included in the closed range
// between min and max of any of the provided IntRanges
func (rs IntRanges) Get(n int) bool {
for _, r := range rs {
if r.Get(n) {
return true
}
}
return false
}
// Min returns min value between a and b
func Min(a, b int) int {
if a < b {
return a
}
return b
}
// Max returns max value between a and b
func Max(a, b int) int {
if a < b {
return b
}
return a
}
func intRangesEqual(a, b IntRanges) bool {
if a == nil && b == nil {
return true
}
if a == nil || b == nil {
return false
}
if len(a) != len(b) {
return false
}
for n := range a {
r1 := a[n]
r2 := b[n]
if r1.min != r2.min || r1.max != r2.max {
return false
}
}
return true
}
// ParseNumberMenu parses input for number menus split by spaces or commas
//supports individual selection: 1 2 3 4
//supports range selections: 1-4 10-20
//supports negation: ^1 ^1-4
//
//include and excule holds numbers that should be added and should not be added
//respectively. other holds anything that can't be parsed as an int. This is
//intended to allow words inside of number menus. e.g. 'all' 'none' 'abort'
//of course the implementation is up to the caller, this function mearley parses
//the input and organizes it
func ParseNumberMenu(input string) (IntRanges, IntRanges, StringSet, StringSet) {
include := make(IntRanges, 0)
exclude := make(IntRanges, 0)
otherInclude := make(StringSet)
otherExclude := make(StringSet)
words := strings.FieldsFunc(input, func(c rune) bool {
return unicode.IsSpace(c) || c == ','
})
for _, word := range words {
var num1 int
var num2 int
var err error
invert := false
other := otherInclude
if word[0] == '^' {
invert = true
other = otherExclude
word = word[1:]
}
ranges := strings.SplitN(word, "-", 2)
num1, err = strconv.Atoi(ranges[0])
if err != nil {
other.Set(strings.ToLower(word))
continue
}
if len(ranges) == 2 {
num2, err = strconv.Atoi(ranges[1])
if err != nil {
other.Set(strings.ToLower(word))
continue
}
} else {
num2 = num1
}
mi := Min(num1, num2)
ma := Max(num1, num2)
if !invert {
include = append(include, makeIntRange(mi, ma))
} else {
exclude = append(exclude, makeIntRange(mi, ma))
}
}
return include, exclude, otherInclude, otherExclude
}

View File

@ -0,0 +1,56 @@
package types
import "testing"
func TestParseNumberMenu(t *testing.T) {
type result struct {
Include IntRanges
Exclude IntRanges
OtherInclude StringSet
OtherExclude StringSet
}
inputs := []string{
"1 2 3 4 5",
"1-10 5-15",
"10-5 90-85",
"1 ^2 ^10-5 99 ^40-38 ^123 60-62",
"abort all none",
"a-b ^a-b ^abort",
"-9223372036854775809-9223372036854775809",
"1\t2 3 4\t\t \t 5",
"1 2,3, 4, 5,6 ,7 ,8",
"",
" \t ",
"A B C D E",
}
expected := []result{
{IntRanges{makeIntRange(1, 1), makeIntRange(2, 2), makeIntRange(3, 3), makeIntRange(4, 4), makeIntRange(5, 5)}, IntRanges{}, make(StringSet), make(StringSet)},
{IntRanges{makeIntRange(1, 10), makeIntRange(5, 15)}, IntRanges{}, make(StringSet), make(StringSet)},
{IntRanges{makeIntRange(5, 10), makeIntRange(85, 90)}, IntRanges{}, make(StringSet), make(StringSet)},
{IntRanges{makeIntRange(1, 1), makeIntRange(99, 99), makeIntRange(60, 62)}, IntRanges{makeIntRange(2, 2), makeIntRange(5, 10), makeIntRange(38, 40), makeIntRange(123, 123)}, make(StringSet), make(StringSet)},
{IntRanges{}, IntRanges{}, MakeStringSet("abort", "all", "none"), make(StringSet)},
{IntRanges{}, IntRanges{}, MakeStringSet("a-b"), MakeStringSet("abort", "a-b")},
{IntRanges{}, IntRanges{}, MakeStringSet("-9223372036854775809-9223372036854775809"), make(StringSet)},
{IntRanges{makeIntRange(1, 1), makeIntRange(2, 2), makeIntRange(3, 3), makeIntRange(4, 4), makeIntRange(5, 5)}, IntRanges{}, make(StringSet), make(StringSet)},
{IntRanges{makeIntRange(1, 1), makeIntRange(2, 2), makeIntRange(3, 3), makeIntRange(4, 4), makeIntRange(5, 5), makeIntRange(6, 6), makeIntRange(7, 7), makeIntRange(8, 8)}, IntRanges{}, make(StringSet), make(StringSet)},
{IntRanges{}, IntRanges{}, make(StringSet), make(StringSet)},
{IntRanges{}, IntRanges{}, make(StringSet), make(StringSet)},
{IntRanges{}, IntRanges{}, MakeStringSet("a", "b", "c", "d", "e"), make(StringSet)},
}
for n, in := range inputs {
res := expected[n]
include, exclude, otherInclude, otherExclude := ParseNumberMenu(in)
if !intRangesEqual(include, res.Include) ||
!intRangesEqual(exclude, res.Exclude) ||
!StringSetEqual(otherInclude, res.OtherInclude) ||
!StringSetEqual(otherExclude, res.OtherExclude) {
t.Fatalf("Test %d Failed: Expected: include=%+v exclude=%+v otherInclude=%+v otherExclude=%+v got include=%+v excluive=%+v otherInclude=%+v otherExclude=%+v",
n+1, res.Include, res.Exclude, res.OtherInclude, res.OtherExclude, include, exclude, otherInclude, otherExclude)
}
}
}

View File

@ -177,8 +177,8 @@ func (u upSlice) print() {
packNameLen := len(pack.StylizedNameWithRepository())
version, _ := getVersionDiff(pack.LocalVersion, pack.RemoteVersion)
packVersionLen := len(version)
longestName = max(packNameLen, longestName)
longestVersion = max(packVersionLen, longestVersion)
longestName = types.Max(packNameLen, longestName)
longestVersion = types.Max(packVersionLen, longestVersion)
}
namePadding := fmt.Sprintf("%%-%ds ", longestName)

View File

@ -497,7 +497,7 @@ func aurInfo(names []string, warnings *aurWarnings) ([]*rpc.Pkg, error) {
}
for n := 0; n < len(names); n += config.RequestSplitN {
max := min(len(names), n+config.RequestSplitN)
max := types.Min(len(names), n+config.RequestSplitN)
wg.Add(1)
go makeRequest(n, max)
}

View File

@ -359,7 +359,7 @@ func upgradePkgs(aurUp, repoUp upSlice) (types.StringSet, types.StringSet, error
//upgrade menu asks you which packages to NOT upgrade so in this case
//include and exclude are kind of swapped
//include, exclude, other := parseNumberMenu(string(numberBuf))
include, exclude, otherInclude, otherExclude := parseNumberMenu(numbers)
include, exclude, otherInclude, otherExclude := types.ParseNumberMenu(numbers)
isInclude := len(exclude) == 0 && len(otherExclude) == 0
@ -368,11 +368,11 @@ func upgradePkgs(aurUp, repoUp upSlice) (types.StringSet, types.StringSet, error
ignore.Set(pkg.Name)
}
if isInclude && !include.get(len(repoUp)-i+len(aurUp)) {
if isInclude && !include.Get(len(repoUp)-i+len(aurUp)) {
continue
}
if !isInclude && (exclude.get(len(repoUp)-i+len(aurUp)) || otherExclude.Get(pkg.Repository)) {
if !isInclude && (exclude.Get(len(repoUp)-i+len(aurUp)) || otherExclude.Get(pkg.Repository)) {
continue
}
@ -384,11 +384,11 @@ func upgradePkgs(aurUp, repoUp upSlice) (types.StringSet, types.StringSet, error
continue
}
if isInclude && !include.get(len(aurUp)-i) {
if isInclude && !include.Get(len(aurUp)-i) {
aurNames.Set(pkg.Name)
}
if !isInclude && (exclude.get(len(aurUp)-i) || otherExclude.Get(pkg.Repository)) {
if !isInclude && (exclude.Get(len(aurUp)-i) || otherExclude.Get(pkg.Repository)) {
aurNames.Set(pkg.Name)
}
}

View File

@ -6,48 +6,6 @@ import (
const gitEmptyTree = "4b825dc642cb6eb9a060e54bf8d69288fbee4904"
type intRange struct {
min int
max int
}
func makeIntRange(min, max int) intRange {
return intRange{
min,
max,
}
}
func (r intRange) get(n int) bool {
return n >= r.min && n <= r.max
}
type intRanges []intRange
func (rs intRanges) get(n int) bool {
for _, r := range rs {
if r.get(n) {
return true
}
}
return false
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
func max(a, b int) int {
if a < b {
return b
}
return a
}
func stringSliceEqual(a, b []string) bool {
if a == nil && b == nil {
return true