Skip to content

Commit

Permalink
Merge pull request #5 from whutchinson98/cli-definition
Browse files Browse the repository at this point in the history
  • Loading branch information
whutchinson98 authored Jul 12, 2022
2 parents 53eb719 + 3159bf5 commit 78f46db
Show file tree
Hide file tree
Showing 4 changed files with 194 additions and 4 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,4 @@ fmt:
## build: Build binary into bin/ directory
.PHONY: build
build:
go build -ldflags="-w -s" -o bin/app ./...
go build -ldflags="-w -s" -o bin ./...
17 changes: 14 additions & 3 deletions cmd/main.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
package main

import "fmt"
import (
"fmt"
"os"

"github.com/rog-golang-buddies/internal/parser"
)

func main() {
// Feel free to delete this file.
fmt.Println("Hello Gophers")
commands, flags, err := parser.ParseCliArguments(os.Args[1:])

if err != nil {
panic(err)
}

fmt.Printf("CLI Commands: %v\n", commands)
fmt.Printf("CLI Flags: %v\n", flags)
}
78 changes: 78 additions & 0 deletions internal/parser/parse_cli.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package parser

import (
"fmt"
"strings"
)

func ParseCliArguments(arguments []string) ([]string, map[string]interface{}, error) {
var commands []string

flags := map[string]interface{}{}

flagsStarted := false
var lastValueWasFlag bool
var lastValueFlag string

for _, value := range arguments {
if !flagsStarted && !strings.Contains(value, "-") {
commands = append(commands, value)
continue
}

// Check if the string is a flag
var isFlag bool

if strings.Contains(value, "-") {
flagsStarted = true
isFlag = true
}

// add value to the last value flag
if lastValueWasFlag {
// The current value is also a flag so we just add true to the flags value
flag := strings.ReplaceAll(lastValueFlag, "-", "")

if flag == "" {
return nil, nil, fmt.Errorf("empty flag was passed in")
}

if flags[flag] != nil {
return nil, nil, fmt.Errorf("flag %v was set multiple times", flag)
}
if isFlag {
flags[flag] = true
} else {
flags[flag] = value
}
lastValueWasFlag = false
lastValueFlag = ""

} else {
// the last value was not a flag
// if this value is also not a flag the user entered in 2 values for a single flag
if !isFlag {
return nil, nil, fmt.Errorf("invalid number of parameters. Unexpected value %v", value)
}
}

// Used for next iteration
if isFlag {
lastValueFlag = value
lastValueWasFlag = true
}
}

if lastValueWasFlag {
flag := strings.ReplaceAll(lastValueFlag, "-", "")
if flag == "" {
return nil, nil, fmt.Errorf("empty flag was passed in")
}
if flags[flag] != nil {
return nil, nil, fmt.Errorf("flag %v was set multiple times", flag)
}
flags[flag] = true
}

return commands, flags, nil
}
101 changes: 101 additions & 0 deletions internal/parser/parse_cli_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package parser

import (
"testing"
)

func TestParseCliArguments(t *testing.T) {

t.Run("Correctly gets commands", func(t *testing.T) {
commands, _, _ := ParseCliArguments([]string{"test_command1", "test_command2"})

if len(commands) != 2 {
t.Fatalf("Invalid command length. Expected %v got %v\n", 2, len(commands))
}

if commands[0] != "test_command1" {
t.Fatalf("Error in commands expected %v got %v\n", "test_command1", commands[0])
}

if commands[1] != "test_command2" {
t.Fatalf("Error in commands expected %v got %v\n", "test_command2", commands[1])
}
})

t.Run("Correctly creates flags that have values", func(t *testing.T) {
_, flags, _ := ParseCliArguments([]string{"test_command1", "--foo", "bar", "--baz", "foo"})

if len(flags) != 2 {
t.Fatalf("Invalid flags length. Expected %v got %v\n", 2, len(flags))
}

if flags["foo"] != "bar" {
t.Fatalf("Error in flags expected %v got %v\n", "bar", flags["foo"])
}

if flags["baz"] != "foo" {
t.Fatalf("Error in flags expected %v got %v\n", "foo", flags["baz"])
}
})

t.Run("Correctly creates flags that are booleans", func(t *testing.T) {
_, flags, _ := ParseCliArguments([]string{"test_command1", "--foo", "--baz", "foo"})

if len(flags) != 2 {
t.Fatalf("Invalid flags length. Expected %v got %v\n", 2, len(flags))
}

if flags["foo"] != true {
t.Fatalf("Error in flags expected %v got %v\n", true, flags["foo"])
}

if flags["baz"] != "foo" {
t.Fatalf("Error in flags expected %v got %v\n", "foo", flags["baz"])
}
})
t.Run("Correctly errors if you enter too many values for a given flag", func(t *testing.T) {
_, _, err := ParseCliArguments([]string{"test_command1", "--foo", "value1", "value2", "--bar"})

if err == nil {
t.Fatalf("Error was expected but not received")
}

if err.Error() != "invalid number of parameters. Unexpected value value2" {
t.Fatalf("Error message incorrect. Expected \"%v\" got \"%v\"", "invalid number of parameters. Unexpected value value2", err.Error())
}
})
t.Run("Correctly errors if you try to pass in the same flag twice", func(t *testing.T) {
_, _, err := ParseCliArguments([]string{"test_command1", "--foo", "value1", "--foo", "--bar"})

if err == nil {
t.Fatalf("Error was expected but not received")
}

if err.Error() != "flag foo was set multiple times" {
t.Fatalf("Error message incorrect. Expected \"%v\" got \"%v\"", "flag foo was set multiple times", err.Error())
}
})
t.Run("Correctly errors if you try to pass in the same flag twice, duplicate flag is the last value", func(t *testing.T) {
_, _, err := ParseCliArguments([]string{"test_command1", "--foo", "value1", "--bar", "--foo"})

if err == nil {
t.Fatalf("Error was expected but not received")
}

if err.Error() != "flag foo was set multiple times" {
t.Fatalf("Error message incorrect. Expected \"%v\" got \"%v\"", "flag foo was set multiple times", err.Error())
}
})
t.Run("Correctly errors if you pass in empty -", func(t *testing.T) {
_, _, err := ParseCliArguments([]string{"test_command1", "--", "value1", "--bar", "--foo"})

if err == nil {
t.Fatalf("Error was expected but not received")
}

if err.Error() != "empty flag was passed in" {
t.Fatalf("Error message incorrect. Expected \"%v\" got \"%v\"", "empty flag was passed in", err.Error())
}
})

}

0 comments on commit 78f46db

Please sign in to comment.