Skip to content

Commit 373511b

Browse files
author
Andreas Behringer
committed
Initial commit
1 parent 1b82994 commit 373511b

File tree

5 files changed

+315
-0
lines changed

5 files changed

+315
-0
lines changed

argumentative.go

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
package argumentative
2+
3+
import (
4+
"fmt"
5+
)
6+
7+
type Flags struct {
8+
boolflags map[string]BoolFlag
9+
stringflags map[string]StringFlag
10+
positionals []Positional
11+
12+
shortflags map[byte]string
13+
}
14+
15+
func (f *Flags) Flags() *Flags {
16+
if f.stringflags == nil {
17+
f.boolflags = make(map[string]BoolFlag)
18+
f.stringflags = make(map[string]StringFlag)
19+
f.shortflags = make(map[byte]string)
20+
}
21+
22+
return f
23+
}
24+
25+
func (f *Flags) AddString(longflag string, shortflag string, required bool, defaultvalue string, description string) *string {
26+
f.stringflags[longflag] = NewStringFlag(longflag, shortflag, required, defaultvalue, description)
27+
if shortflag != "" {
28+
f.shortflags[shortflag[0]] = longflag
29+
}
30+
return f.stringflags[longflag].Value
31+
}
32+
33+
func (f *Flags) AddBool(longflag string, shortflag string, description string) *bool {
34+
f.boolflags[longflag] = NewBoolFlag(longflag, shortflag, description)
35+
if shortflag != "" {
36+
f.shortflags[shortflag[0]] = longflag
37+
}
38+
return f.boolflags[longflag].Value
39+
}
40+
41+
func (f *Flags) AddPositional(longflag string, required bool, defaultvalue string, description string) *string {
42+
f.positionals = append(f.positionals, NewPositional(longflag, required, defaultvalue, description))
43+
return f.positionals[len(f.positionals)-1].Value
44+
}
45+
46+
func (f *Flags) isFlag(name string) bool {
47+
return name[0] == '-'
48+
}
49+
50+
func (f *Flags) GetFlagName(name string) string {
51+
var longname string
52+
if len(name) > 1 && name[0] == '-' {
53+
if len(name) > 2 && name[1] == '-' {
54+
longname = name[2:]
55+
} else {
56+
longname = f.shortflags[name[1]]
57+
}
58+
return longname
59+
}
60+
return ""
61+
}
62+
63+
func (f *Flags) Validate() (err error) {
64+
for _, flag := range f.stringflags {
65+
if flag.Required && *flag.Value == "" {
66+
return fmt.Errorf("flag %s missing", flag.Longflag)
67+
}
68+
}
69+
for _, positional := range f.positionals {
70+
if positional.Required && *positional.Value == "" {
71+
return fmt.Errorf("positional argument %s missing", positional.Longflag)
72+
}
73+
}
74+
return nil
75+
}
76+
77+
func (f *Flags) Parse(args []string) (err error) {
78+
positional := 0
79+
i := 1
80+
for i < len(args) {
81+
if f.isFlag(args[i]) {
82+
// Parse flags with string values
83+
if _, ok := f.stringflags[f.GetFlagName(args[i])]; ok {
84+
*f.stringflags[f.GetFlagName(args[i])].Value = args[i+1]
85+
i += 1
86+
} else
87+
// Parse flags the switch to true if exists
88+
if _, ok := f.boolflags[f.GetFlagName(args[i])]; ok {
89+
*f.boolflags[f.GetFlagName(args[i])].Value = true
90+
} else {
91+
return fmt.Errorf("unknown flag %s", args[i])
92+
}
93+
} else if positional < len(f.positionals) {
94+
*f.positionals[positional].Value = args[i]
95+
positional += 1
96+
} else {
97+
return fmt.Errorf("unknown positional argument %s", args[i])
98+
}
99+
i += 1
100+
}
101+
return f.Validate()
102+
}
103+
104+
func (f *Flags) Usage(name string, description string, err error) {
105+
if err != nil {
106+
fmt.Println("Error:", err)
107+
} else {
108+
fmt.Println(name)
109+
fmt.Println(description)
110+
}
111+
output := "\nUsage: " + name
112+
if len(f.stringflags) > 0 || len(f.boolflags) > 0 {
113+
for _, flag := range f.boolflags {
114+
output += flag.GetShortDescription()
115+
}
116+
for _, flag := range f.stringflags {
117+
output += flag.GetShortDescription()
118+
}
119+
}
120+
if len(f.positionals) > 0 {
121+
for _, positional := range f.positionals {
122+
output += positional.GetShortDescription()
123+
}
124+
}
125+
126+
fmt.Println(output)
127+
128+
if len(f.boolflags) > 0 {
129+
fmt.Println("\nFlags:")
130+
for _, flag := range f.boolflags {
131+
fmt.Println(flag.GetLongDescription())
132+
}
133+
}
134+
135+
if len(f.stringflags) > 0 {
136+
fmt.Println("\nOptions:")
137+
for _, flag := range f.stringflags {
138+
fmt.Println(flag.GetLongDescription())
139+
}
140+
}
141+
142+
if len(f.positionals) > 0 {
143+
fmt.Println("\nPositional arguments:")
144+
for _, positional := range f.positionals {
145+
fmt.Println(positional.GetLongDescription())
146+
}
147+
}
148+
149+
}

boolflag.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package argumentative
2+
3+
import (
4+
"fmt"
5+
)
6+
7+
type BoolFlag struct {
8+
Longflag string
9+
Shortflag string
10+
Description string
11+
Required bool
12+
Value *bool
13+
}
14+
15+
func NewBoolFlag(longflag string, shortflag string, description string) BoolFlag {
16+
flag := BoolFlag{
17+
Longflag: longflag,
18+
Shortflag: shortflag,
19+
Description: description,
20+
Value: new(bool),
21+
}
22+
*flag.Value = false
23+
24+
return flag
25+
}
26+
27+
func (f *BoolFlag) GetLongDescription() string {
28+
flagnames := ""
29+
if f.Shortflag != "" {
30+
flagnames += "-" + f.Shortflag + ", "
31+
}
32+
flagnames += "--" + f.Longflag
33+
output := fmt.Sprintf("%-25s", flagnames)
34+
if f.Description != "" {
35+
output += f.Description
36+
}
37+
return output
38+
}
39+
40+
func (f *BoolFlag) GetShortDescription() string {
41+
output := " ["
42+
if f.Shortflag != "" {
43+
output += "-" + f.Shortflag
44+
} else {
45+
output += "--" + f.Longflag
46+
}
47+
output += "]"
48+
return output
49+
}

go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module github.com/behringer24/argumentative
2+
3+
go 1.20

positional.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package argumentative
2+
3+
import (
4+
"fmt"
5+
)
6+
7+
type Positional struct {
8+
Longflag string
9+
Description string
10+
Required bool
11+
Default string
12+
Value *string
13+
}
14+
15+
func NewPositional(longflag string, required bool, defaultvalue string, description string) Positional {
16+
positional := Positional{
17+
Longflag: longflag,
18+
Description: description,
19+
Required: required,
20+
Default: defaultvalue,
21+
Value: new(string),
22+
}
23+
if defaultvalue != "" {
24+
*positional.Value = defaultvalue
25+
}
26+
27+
return positional
28+
}
29+
30+
func (f *Positional) GetLongDescription() string {
31+
output := fmt.Sprintf("%-25s", f.Longflag)
32+
if f.Description != "" {
33+
output += f.Description
34+
}
35+
if f.Default != "" {
36+
output += " (Default: " + f.Default + ")"
37+
}
38+
return output
39+
}
40+
41+
func (f *Positional) GetShortDescription() string {
42+
output := " "
43+
if !f.Required {
44+
output += "["
45+
}
46+
output += f.Longflag
47+
if !f.Required {
48+
output += "]"
49+
}
50+
return output
51+
}

stringflag.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package argumentative
2+
3+
import (
4+
"fmt"
5+
)
6+
7+
type StringFlag struct {
8+
Longflag string
9+
Shortflag string
10+
Description string
11+
Required bool
12+
Default string
13+
Value *string
14+
}
15+
16+
func NewStringFlag(longflag string, shortflag string, required bool, defaultvalue string, description string) StringFlag {
17+
flag := StringFlag{
18+
Longflag: longflag,
19+
Shortflag: shortflag,
20+
Description: description,
21+
Required: required,
22+
Default: defaultvalue,
23+
Value: new(string),
24+
}
25+
if defaultvalue != "" {
26+
*flag.Value = defaultvalue
27+
}
28+
29+
return flag
30+
}
31+
32+
func (f *StringFlag) GetLongDescription() string {
33+
flagnames := ""
34+
if f.Shortflag != "" {
35+
flagnames += "-" + f.Shortflag + ", "
36+
}
37+
flagnames += "--" + f.Longflag
38+
output := fmt.Sprintf("%-25s", flagnames)
39+
if f.Description != "" {
40+
output += f.Description
41+
}
42+
if f.Default != "" {
43+
output += " (Default: " + f.Default + ")"
44+
}
45+
46+
return output
47+
}
48+
49+
func (f *StringFlag) GetShortDescription() string {
50+
output := " "
51+
if !f.Required {
52+
output += "["
53+
}
54+
if f.Shortflag != "" {
55+
output += "-" + f.Shortflag
56+
} else {
57+
output += "--" + f.Longflag
58+
}
59+
if !f.Required {
60+
output += "]"
61+
}
62+
return output
63+
}

0 commit comments

Comments
 (0)