Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor args parsing with go-arg library #73

Merged
merged 1 commit into from
Feb 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 37 additions & 56 deletions cli/append.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,32 @@ const (
// AppendCommand container for all 'append' parameters
type AppendCommand struct {
name string
args *AppendCommandArgs

client *client.Client
Source string
Target string
Mode AppendMode
}

// AppendCommandArgs provides a struct for go-arg parsing
type AppendCommandArgs struct {
Source string `arg:"positional,required"`
Target string `arg:"positional,required"`
Force bool `arg:"-f,--force" help:"Overwrite key if exists"`
Skip bool `arg:"-s,--skip" help:"Skip key if exists (default)"`
Rename bool `arg:"-r,--rename" help:"Rename key if exists"`
}

// Description provides detail on what the command does
func (AppendCommandArgs) Description() string {
return "appends the contents of one secret to another"
}

// NewAppendCommand creates a new AppendCommand parameter container
func NewAppendCommand(c *client.Client) *AppendCommand {
return &AppendCommand{
name: "append",
client: c,
args: &AppendCommandArgs{},
Mode: ModeSkip,
}
}
Expand All @@ -48,75 +62,42 @@ func (cmd *AppendCommand) GetName() string {
return cmd.name
}

// IsSane returns true if command is sane
func (cmd *AppendCommand) IsSane() bool {
return cmd.Source != "" && cmd.Target != "" && cmd.Mode != ModeInvalid
}

func isFlag(flag string) bool {
return strings.HasPrefix(flag, "-")
}

func parseFlag(flag string) AppendMode {
switch strings.TrimSpace(flag) {
case "-f", "--force":
return ModeOverwrite
case "", "-s", "--skip":
return ModeSkip
case "-r", "--rename":
return ModeRename
default:
return ModeInvalid
}
}

func (cmd *AppendCommand) parseArgs(src, dest, flag string) bool {
cmd.Source = src
cmd.Target = dest
mode := parseFlag(flag)
cmd.Mode = mode
if mode == ModeInvalid {
return false
}
return true
// GetArgs provides the struct holding arguments for the command
func (cmd *AppendCommand) GetArgs() interface{} {
return cmd.args
}

// tryParse returns true when parsing succeeded, false otherwise
func (cmd *AppendCommand) tryParse(args []string) (success bool) {
if len(args) == 3 {
return cmd.parseArgs(args[1], args[2], "--skip") // --skip is default
}
if len(args) == 4 {
// flag can be given at the end or immediately after `append`
if isFlag(args[3]) {
return cmd.parseArgs(args[1], args[2], args[3])
}
if isFlag(args[1]) {
return cmd.parseArgs(args[2], args[3], args[1])
}
}
// wrong number of params or flag at incorrect position
return false
// IsSane returns true if command is sane
func (cmd *AppendCommand) IsSane() bool {
return cmd.args.Source != "" && cmd.args.Target != "" && cmd.Mode != ModeInvalid
}

// PrintUsage print command usage
func (cmd *AppendCommand) PrintUsage() {
log.UserInfo("Usage:\nappend <from> <to> [-f|--force|-r|--rename|-s|--skip]")
fmt.Println(Help(cmd))
}

// Parse parses the arguments and returns true on success; otherwise it prints usage and returns false
// Parse parses the arguments into the Command and Args structs
func (cmd *AppendCommand) Parse(args []string) error {
success := cmd.tryParse(args)
if !success {
return fmt.Errorf("cannot parse arguments")
_, err := parseCommandArgs(args, cmd)
if err != nil {
return err
}

if cmd.args.Skip == true {
cmd.Mode = ModeSkip
} else if cmd.args.Force == true {
cmd.Mode = ModeOverwrite
} else if cmd.args.Rename == true {
cmd.Mode = ModeRename
}
return nil
}

// Run executes 'append' with given AppendCommand's parameters
func (cmd *AppendCommand) Run() int {
newSrcPwd := cmdPath(cmd.client.Pwd, cmd.Source)
newTargetPwd := cmdPath(cmd.client.Pwd, cmd.Target)
newSrcPwd := cmdPath(cmd.client.Pwd, cmd.args.Source)
newTargetPwd := cmdPath(cmd.client.Pwd, cmd.args.Target)

src := cmd.client.GetType(newSrcPwd)
if src != client.LEAF {
Expand Down
44 changes: 44 additions & 0 deletions cli/args.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package cli

import (
"bytes"

"github.com/alexflint/go-arg"
)

func parseCommandArgs(args []string, cmd Command) (*arg.Parser, error) {
p, err := argParser(args, cmd)
if err != nil {
return nil, err
}

if len(args) > 1 {
err = p.Parse(args[1:])
} else {
err = p.Parse([]string{})
}
if err != nil {
return nil, err
}
return p, nil
}

func argParser(args []string, cmd Command) (*arg.Parser, error) {
return arg.NewParser(arg.Config{Program: args[0]}, cmd.GetArgs())
}

// Usage returns usage information
func Usage(cmd Command) string {
var b bytes.Buffer
p, _ := argParser([]string{cmd.GetName()}, cmd)
p.WriteUsage(&b)
return b.String()
}

// Help returns extended usage information
func Help(cmd Command) string {
var b bytes.Buffer
p, _ := argParser([]string{cmd.GetName()}, cmd)
p.WriteHelp(&b)
return b.String()
}
32 changes: 25 additions & 7 deletions cli/cat.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,35 @@ package cli

import (
"fmt"

"github.com/fishi0x01/vsh/client"
"github.com/fishi0x01/vsh/log"
)

// CatCommand container for all 'cat' parameters
type CatCommand struct {
name string
args *CatCommandArgs

client *client.Client
Path string
}

// CatCommandArgs provides a struct for go-arg parsing
type CatCommandArgs struct {
Path string `arg:"positional,required" help:"path to display contents"`
}

// Description provides detail on what the command does
func (CatCommandArgs) Description() string {
return "displays the content of a secret"
}

// NewCatCommand creates a new CatCommand parameter container
func NewCatCommand(c *client.Client) *CatCommand {
return &CatCommand{
name: "cat",
client: c,
args: &CatCommandArgs{},
}
}

Expand All @@ -27,28 +39,34 @@ func (cmd *CatCommand) GetName() string {
return cmd.name
}

// GetArgs provides the struct holding arguments for the command
func (cmd *CatCommand) GetArgs() interface{} {
return cmd.args
}

// IsSane returns true if command is sane
func (cmd *CatCommand) IsSane() bool {
return cmd.Path != ""
return cmd.args.Path != ""
}

// PrintUsage print command usage
func (cmd *CatCommand) PrintUsage() {
log.UserInfo("Usage:\ncat <secret>")
fmt.Println(Help(cmd))
}

// Parse given arguments and return status
func (cmd *CatCommand) Parse(args []string) error {
if len(args) != 2 {
return fmt.Errorf("cannot parse arguments")
_, err := parseCommandArgs(args, cmd)
if err != nil {
return err
}
cmd.Path = args[1]

return nil
}

// Run executes 'cat' with given CatCommand's parameters
func (cmd *CatCommand) Run() int {
absPath := cmdPath(cmd.client.Pwd, cmd.Path)
absPath := cmdPath(cmd.client.Pwd, cmd.args.Path)
t := cmd.client.GetType(absPath)

if t == client.LEAF {
Expand Down
31 changes: 24 additions & 7 deletions cli/cd.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,27 @@ import (
// CdCommand container for all 'cd' parameters
type CdCommand struct {
name string
args *CdCommandArgs

client *client.Client
Path string
}

// CdCommandArgs provides a struct for go-arg parsing
type CdCommandArgs struct {
Path string `arg:"positional,required" help:"change cwd to path"`
}

// Description provides detail on what the command does
func (CdCommandArgs) Description() string {
return "changes the working path"
}

// NewCdCommand creates a new CdCommand parameter container
func NewCdCommand(c *client.Client) *CdCommand {
return &CdCommand{
name: "cd",
client: c,
args: &CdCommandArgs{},
}
}

Expand All @@ -29,28 +40,34 @@ func (cmd *CdCommand) GetName() string {
return cmd.name
}

// GetArgs provides the struct holding arguments for the command
func (cmd *CdCommand) GetArgs() interface{} {
return cmd.args
}

// IsSane returns true if command is sane
func (cmd *CdCommand) IsSane() bool {
return cmd.Path != ""
return cmd.args.Path != ""
}

// PrintUsage print command usage
func (cmd *CdCommand) PrintUsage() {
log.UserInfo("Usage:\ncd <path>")
fmt.Println(Help(cmd))
}

// Parse given arguments and return status
func (cmd *CdCommand) Parse(args []string) error {
if len(args) != 2 {
return fmt.Errorf("cannot parse arguments")
_, err := parseCommandArgs(args, cmd)
if err != nil {
return err
}
cmd.Path = args[1]

return nil
}

// Run executes 'cd' with given CdCommand's parameters
func (cmd *CdCommand) Run() int {
newPwd := cmdPath(cmd.client.Pwd, cmd.Path)
newPwd := cmdPath(cmd.client.Pwd, cmd.args.Path)

t := cmd.client.GetType(newPwd)

Expand Down
Loading