Skip to content

Commit 78f46db

Browse files
Merge pull request #5 from whutchinson98/cli-definition
2 parents 53eb719 + 3159bf5 commit 78f46db

File tree

4 files changed

+194
-4
lines changed

4 files changed

+194
-4
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,4 @@ fmt:
3737
## build: Build binary into bin/ directory
3838
.PHONY: build
3939
build:
40-
go build -ldflags="-w -s" -o bin/app ./...
40+
go build -ldflags="-w -s" -o bin ./...

cmd/main.go

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,19 @@
11
package main
22

3-
import "fmt"
3+
import (
4+
"fmt"
5+
"os"
6+
7+
"github.com/rog-golang-buddies/internal/parser"
8+
)
49

510
func main() {
6-
// Feel free to delete this file.
7-
fmt.Println("Hello Gophers")
11+
commands, flags, err := parser.ParseCliArguments(os.Args[1:])
12+
13+
if err != nil {
14+
panic(err)
15+
}
16+
17+
fmt.Printf("CLI Commands: %v\n", commands)
18+
fmt.Printf("CLI Flags: %v\n", flags)
819
}

internal/parser/parse_cli.go

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package parser
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
)
7+
8+
func ParseCliArguments(arguments []string) ([]string, map[string]interface{}, error) {
9+
var commands []string
10+
11+
flags := map[string]interface{}{}
12+
13+
flagsStarted := false
14+
var lastValueWasFlag bool
15+
var lastValueFlag string
16+
17+
for _, value := range arguments {
18+
if !flagsStarted && !strings.Contains(value, "-") {
19+
commands = append(commands, value)
20+
continue
21+
}
22+
23+
// Check if the string is a flag
24+
var isFlag bool
25+
26+
if strings.Contains(value, "-") {
27+
flagsStarted = true
28+
isFlag = true
29+
}
30+
31+
// add value to the last value flag
32+
if lastValueWasFlag {
33+
// The current value is also a flag so we just add true to the flags value
34+
flag := strings.ReplaceAll(lastValueFlag, "-", "")
35+
36+
if flag == "" {
37+
return nil, nil, fmt.Errorf("empty flag was passed in")
38+
}
39+
40+
if flags[flag] != nil {
41+
return nil, nil, fmt.Errorf("flag %v was set multiple times", flag)
42+
}
43+
if isFlag {
44+
flags[flag] = true
45+
} else {
46+
flags[flag] = value
47+
}
48+
lastValueWasFlag = false
49+
lastValueFlag = ""
50+
51+
} else {
52+
// the last value was not a flag
53+
// if this value is also not a flag the user entered in 2 values for a single flag
54+
if !isFlag {
55+
return nil, nil, fmt.Errorf("invalid number of parameters. Unexpected value %v", value)
56+
}
57+
}
58+
59+
// Used for next iteration
60+
if isFlag {
61+
lastValueFlag = value
62+
lastValueWasFlag = true
63+
}
64+
}
65+
66+
if lastValueWasFlag {
67+
flag := strings.ReplaceAll(lastValueFlag, "-", "")
68+
if flag == "" {
69+
return nil, nil, fmt.Errorf("empty flag was passed in")
70+
}
71+
if flags[flag] != nil {
72+
return nil, nil, fmt.Errorf("flag %v was set multiple times", flag)
73+
}
74+
flags[flag] = true
75+
}
76+
77+
return commands, flags, nil
78+
}

internal/parser/parse_cli_test.go

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
package parser
2+
3+
import (
4+
"testing"
5+
)
6+
7+
func TestParseCliArguments(t *testing.T) {
8+
9+
t.Run("Correctly gets commands", func(t *testing.T) {
10+
commands, _, _ := ParseCliArguments([]string{"test_command1", "test_command2"})
11+
12+
if len(commands) != 2 {
13+
t.Fatalf("Invalid command length. Expected %v got %v\n", 2, len(commands))
14+
}
15+
16+
if commands[0] != "test_command1" {
17+
t.Fatalf("Error in commands expected %v got %v\n", "test_command1", commands[0])
18+
}
19+
20+
if commands[1] != "test_command2" {
21+
t.Fatalf("Error in commands expected %v got %v\n", "test_command2", commands[1])
22+
}
23+
})
24+
25+
t.Run("Correctly creates flags that have values", func(t *testing.T) {
26+
_, flags, _ := ParseCliArguments([]string{"test_command1", "--foo", "bar", "--baz", "foo"})
27+
28+
if len(flags) != 2 {
29+
t.Fatalf("Invalid flags length. Expected %v got %v\n", 2, len(flags))
30+
}
31+
32+
if flags["foo"] != "bar" {
33+
t.Fatalf("Error in flags expected %v got %v\n", "bar", flags["foo"])
34+
}
35+
36+
if flags["baz"] != "foo" {
37+
t.Fatalf("Error in flags expected %v got %v\n", "foo", flags["baz"])
38+
}
39+
})
40+
41+
t.Run("Correctly creates flags that are booleans", func(t *testing.T) {
42+
_, flags, _ := ParseCliArguments([]string{"test_command1", "--foo", "--baz", "foo"})
43+
44+
if len(flags) != 2 {
45+
t.Fatalf("Invalid flags length. Expected %v got %v\n", 2, len(flags))
46+
}
47+
48+
if flags["foo"] != true {
49+
t.Fatalf("Error in flags expected %v got %v\n", true, flags["foo"])
50+
}
51+
52+
if flags["baz"] != "foo" {
53+
t.Fatalf("Error in flags expected %v got %v\n", "foo", flags["baz"])
54+
}
55+
})
56+
t.Run("Correctly errors if you enter too many values for a given flag", func(t *testing.T) {
57+
_, _, err := ParseCliArguments([]string{"test_command1", "--foo", "value1", "value2", "--bar"})
58+
59+
if err == nil {
60+
t.Fatalf("Error was expected but not received")
61+
}
62+
63+
if err.Error() != "invalid number of parameters. Unexpected value value2" {
64+
t.Fatalf("Error message incorrect. Expected \"%v\" got \"%v\"", "invalid number of parameters. Unexpected value value2", err.Error())
65+
}
66+
})
67+
t.Run("Correctly errors if you try to pass in the same flag twice", func(t *testing.T) {
68+
_, _, err := ParseCliArguments([]string{"test_command1", "--foo", "value1", "--foo", "--bar"})
69+
70+
if err == nil {
71+
t.Fatalf("Error was expected but not received")
72+
}
73+
74+
if err.Error() != "flag foo was set multiple times" {
75+
t.Fatalf("Error message incorrect. Expected \"%v\" got \"%v\"", "flag foo was set multiple times", err.Error())
76+
}
77+
})
78+
t.Run("Correctly errors if you try to pass in the same flag twice, duplicate flag is the last value", func(t *testing.T) {
79+
_, _, err := ParseCliArguments([]string{"test_command1", "--foo", "value1", "--bar", "--foo"})
80+
81+
if err == nil {
82+
t.Fatalf("Error was expected but not received")
83+
}
84+
85+
if err.Error() != "flag foo was set multiple times" {
86+
t.Fatalf("Error message incorrect. Expected \"%v\" got \"%v\"", "flag foo was set multiple times", err.Error())
87+
}
88+
})
89+
t.Run("Correctly errors if you pass in empty -", func(t *testing.T) {
90+
_, _, err := ParseCliArguments([]string{"test_command1", "--", "value1", "--bar", "--foo"})
91+
92+
if err == nil {
93+
t.Fatalf("Error was expected but not received")
94+
}
95+
96+
if err.Error() != "empty flag was passed in" {
97+
t.Fatalf("Error message incorrect. Expected \"%v\" got \"%v\"", "empty flag was passed in", err.Error())
98+
}
99+
})
100+
101+
}

0 commit comments

Comments
 (0)