mirror of
https://github.com/Jguer/yay.git
synced 2025-10-04 00:03:11 -04:00
Add parseNumberMenu()
This function is designed to replace the existing number menu in upcoming commits.
This commit is contained in:
parent
f0f20269a0
commit
6988537552
105
parser.go
105
parser.go
@ -4,6 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -38,6 +39,20 @@ func (set stringSet) toSlice() []string {
|
|||||||
return slice
|
return slice
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SliceToStringSet(in []string) stringSet {
|
||||||
|
set := make(stringSet)
|
||||||
|
|
||||||
|
for _, v := range in {
|
||||||
|
set.set(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return set
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeStringSet(in ...string) stringSet {
|
||||||
|
return SliceToStringSet(in)
|
||||||
|
}
|
||||||
|
|
||||||
// Parses command line arguments in a way we can interact with programmatically but
|
// Parses command line arguments in a way we can interact with programmatically but
|
||||||
// also in a way that can easily be passed to pacman later on.
|
// also in a way that can easily be passed to pacman later on.
|
||||||
type arguments struct {
|
type arguments struct {
|
||||||
@ -554,3 +569,93 @@ func (parser *arguments) parseCommandLine() (err error) {
|
|||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
//parses input for number menus
|
||||||
|
//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 anythign 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, 0)
|
||||||
|
exclude := make(intRanges, 0, 0)
|
||||||
|
otherInclude := make(stringSet)
|
||||||
|
otherExclude := make(stringSet)
|
||||||
|
|
||||||
|
words := strings.Fields(input)
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
99
parser_test.go
Normal file
99
parser_test.go
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
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 != r1.min || r1.max != r2.max {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func stringSetEqual(a, b stringSet) 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 {
|
||||||
|
if !b.get(n) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
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",
|
||||||
|
"1\t2 3 4\t\t \t 5",
|
||||||
|
"",
|
||||||
|
" \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{makeIntRange(1, 1), makeIntRange(2, 2), makeIntRange(3, 3), makeIntRange(4, 4), makeIntRange(5, 5)}, 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
7
query.go
7
query.go
@ -317,6 +317,13 @@ func min(a, b int) int {
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func max(a, b int) int {
|
||||||
|
if a < b {
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
// Queries the aur for information about specified packages.
|
// Queries the aur for information about specified packages.
|
||||||
// All packages should be queried in a single rpc request except when the number
|
// All packages should be queried in a single rpc request except when the number
|
||||||
// of packages exceeds the number set in config.RequestSplitN.
|
// of packages exceeds the number set in config.RequestSplitN.
|
||||||
|
@ -60,7 +60,7 @@ func TestParsing(t *testing.T) {
|
|||||||
branch != compare.Branch ||
|
branch != compare.Branch ||
|
||||||
!isEqual(protocols, compare.Protocols) {
|
!isEqual(protocols, compare.Protocols) {
|
||||||
|
|
||||||
t.Fatalf("Expected url=%+v branch=%+v protocols=%+v\ngot url=%+v branch=%+v protocols=%+v", url, branch, protocols, compare.URL, compare.Branch, compare.Protocols)
|
t.Fatalf("Test %d failed: Expected: url=%+v branch=%+v protocols=%+v\ngot url=%+v branch=%+v protocols=%+v", n+1, url, branch, protocols, compare.URL, compare.Branch, compare.Protocols)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user