mirror of
https://github.com/Jguer/yay.git
synced 2024-11-07 17:47:21 +01:00
b8debd1ae7
* replace context.TODO() in tests context.Background() * remove mock TODOs * prettier * apply missing linting
131 lines
2.6 KiB
Go
131 lines
2.6 KiB
Go
package intrange
|
|
|
|
import (
|
|
"strconv"
|
|
"strings"
|
|
"unicode"
|
|
|
|
"github.com/Jguer/yay/v11/pkg/stringset"
|
|
)
|
|
|
|
// 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
|
|
}
|
|
|
|
// 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) (include, exclude IntRanges,
|
|
otherInclude, otherExclude stringset.StringSet,
|
|
) {
|
|
include = make(IntRanges, 0)
|
|
exclude = make(IntRanges, 0)
|
|
otherInclude = make(stringset.StringSet)
|
|
otherExclude = make(stringset.StringSet)
|
|
|
|
words := strings.FieldsFunc(input, func(c rune) bool {
|
|
return unicode.IsSpace(c) || c == ','
|
|
})
|
|
|
|
for _, word := range words {
|
|
var (
|
|
num1 int
|
|
num2 int
|
|
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
|
|
}
|