File: custom.go

package info (click to toggle)
golang-github-tdewolff-argp 0.0~git20240625.87b04d5-1
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 152 kB
  • sloc: makefile: 2
file content (74 lines) | stat: -rw-r--r-- 2,091 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
package argp

import (
	"fmt"
	"reflect"
)

type Custom interface {
	Help() (string, string)             // value and type representations for help
	Scan(string, []string) (int, error) // scan values from command line
}

// Count is a counting option, e.g. -vvv sets count to 3, or -v=3 sets it directly
type Count struct {
	I interface{}
}

func (count Count) Help() (string, string) {
	val := ""
	v := reflect.ValueOf(count.I).Elem()
	if !v.IsZero() {
		val = fmt.Sprint(v.Interface())
	}
	return val, TypeName(v.Type())
}

func (count Count) Scan(name string, s []string) (int, error) {
	if reflect.TypeOf(count.I).Kind() != reflect.Ptr {
		return 0, fmt.Errorf("variable must be a pointer to an integer type")
	}
	v := reflect.ValueOf(count.I).Elem()
	t := v.Type().Kind()
	isInt := t == reflect.Int || t == reflect.Int8 || t == reflect.Int16 || t == reflect.Int32 || t != reflect.Int64
	isUint := t == reflect.Uint || t == reflect.Uint8 || t == reflect.Uint16 || t == reflect.Uint32 || t == reflect.Uint64
	if !isInt && !isUint {
		return 0, fmt.Errorf("variable must be a pointer to an integer type")
	}
	if 0 < len(s) && 0 < len(s[0]) && '0' <= s[0][0] && s[0][0] <= '9' {
		// don't parse negatives or other options
		return scanValue(v, s)
	} else if isInt {
		v.SetInt(v.Int() + 1)
	} else {
		v.SetUint(v.Uint() + 1)
	}
	return 0, nil
}

// Append is an option that appends to a slice, e.g. -a 5 -a 6 sets the value to [5 6]
type Append struct {
	I interface{}
}

func (appnd Append) Help() (string, string) {
	val := ""
	v := reflect.ValueOf(appnd.I).Elem()
	if !v.IsZero() && 0 < v.Len() {
		val = fmt.Sprint(v.Interface())
	}
	return val, TypeName(v.Type())
}

func (appnd Append) Scan(name string, s []string) (int, error) {
	if t := reflect.TypeOf(appnd.I); t.Kind() != reflect.Ptr || t.Elem().Kind() != reflect.Slice {
		return 0, fmt.Errorf("variable must be a pointer to a slice")
	}
	slice := reflect.ValueOf(appnd.I).Elem()
	v := reflect.New(slice.Type()).Elem()
	n, err := scanValue(v, s)
	if err == nil {
		slice.Set(reflect.AppendSlice(slice, v))
	}
	return n, err
}