/
main.go
119 lines (98 loc) · 2.13 KB
/
main.go
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package main
import (
"flag"
"fmt"
"log"
"os"
"strconv"
"strings"
"al.essio.dev/pkg/tools/internal/seq"
"al.essio.dev/pkg/tools/internal/version"
)
var (
helpMode bool
versionMode bool
separator string
width uint
)
func init() {
flag.BoolVar(&helpMode, "help", false, "display this help and exit.")
flag.BoolVar(&versionMode, "version", false, "output version information and exit.")
flag.StringVar(&separator, "separator", `\n`, "use STRING to separate numbers.")
flag.UintVar(&width, "width", 0, "equalize width by padding with leading zeroes.")
flag.Usage = usage
flag.ErrHelp = nil
}
func main() {
log.SetFlags(0)
log.SetPrefix("seq: ")
log.SetOutput(os.Stderr)
flag.Parse()
handleHelpAndVersionModes()
separator, err := strconv.Unquote(`"` + separator + `"`)
if err != nil {
log.Fatal(err)
}
var (
start = 1
end = 0
incr = 1
)
switch flag.NArg() {
case 0:
log.Fatal("missing operand")
case 1:
end = parseIntArg(0)
if end < 0 {
start = 1
}
case 2:
start, end = parseIntArg(0), parseIntArg(1)
case 3:
start, incr, end = parseIntArg(0), parseIntArg(1), parseIntArg(2)
if incr < 0 {
log.Fatalf("%d is not a valid unsigned integer", incr)
}
default:
log.Fatal("too many operands")
}
bldr := strings.Builder{}
sequence := seq.NewInt(start, uint(incr), end, width)
for item := range sequence.Items() {
if bldr.Len() > 0 {
fmt.Printf("%s%s", bldr.String(), separator)
bldr.Reset()
}
bldr.WriteString(item)
}
fmt.Println(bldr.String())
if sequence.WidthExceeded() {
log.Fatal("width exceeded")
}
}
func handleHelpAndVersionModes() {
if helpMode {
usage()
os.Exit(0)
}
if versionMode {
version.PrintWithCopyright()
os.Exit(0)
}
}
func parseIntArg(i int) int {
out, err := strconv.Atoi(flag.Arg(i))
if err != nil {
log.Fatalf("%q is not a valid integer", flag.Arg(i))
}
return out
}
func usage() {
usageString := `Usage: seq [OPTION]... LAST
or: seq [OPTION]... FIRST LAST
or: seq [OPTION]... FIRST INCREMENT LAST
Print numbers from FIRST to LAST, in steps of INCREMENT.
`
_, _ = fmt.Fprintln(os.Stderr, usageString)
flag.PrintDefaults()
}