Skip to content

Commit

Permalink
Merge pull request #4 from jwaldrip/inherited-flags
Browse files Browse the repository at this point in the history
Inherited flags
  • Loading branch information
jwaldrip committed Oct 13, 2014
2 parents e429114 + 844e4d2 commit 34c731e
Show file tree
Hide file tree
Showing 14 changed files with 327 additions and 43 deletions.
1 change: 1 addition & 0 deletions Goopfile
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
github.com/onsi/ginkgo
github.com/onsi/gomega
github.com/mattn/goveralls
code.google.com/p/go.tools/cmd/cover
4 changes: 4 additions & 0 deletions Goopfile.lock
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
code.google.com/p/go-uuid #7dda39b2e7d5e265014674c5af696ba4186679e9
code.google.com/p/go.net #9cbdc6102a92af1201a1dbe68587693f2684e8a1
code.google.com/p/go.tools/cmd/cover #a9cbf58422bba01fd4a6c6db5c95530003e31c3a
code.google.com/p/goauth2 #afe77d958c701557ec5dc56f6936fcc194d15520
code.google.com/p/google-api-go-client #11626ef0c2fd66fd8c9a128f6ae38b77cd101f30
github.com/mattn/goveralls #89ffc28b5e4c741a73c4ce4dd63dcf5695ca627d
github.com/onsi/ginkgo #6bd31378f9b5c099a60ab96b89f8fa9b48678d44
github.com/onsi/gomega #a0ee4df1f2d58a75dd9d74e755615706d68e9ce9
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
test: install-deps
test:
@clear
goop exec sh -c "cd cli && go test"

Expand Down
75 changes: 63 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,20 @@ A go-lang library to help build self documenting command line applications.
get the package with:

```
go get github.com/jwaldrip/odin/cli
go get gopkg.in/jwaldrip/odin.v1/cli
```

import it with:

```go
import "gopkg.in/jwaldrip/odin.v1/cli"
```

or using a a package manager like [Goop](https://github.com/nitrous-io/goop):

```
# Goopfile
github.com/jwaldrip/odin #v1.4.0
```

## Usage
Expand Down Expand Up @@ -87,37 +100,37 @@ package main
import (
"fmt"

"github.com/jwaldrip/odin/cli"
"gopkg.in/jwaldrip/odin.v1/cli"
)

// CLI is the odin CLI
var CLI = cli.New("0.0.1", "my cli", func(c cli.Command){
var app = cli.New("0.0.1", "my cli", func(c cli.Command){
if c.Flag("gopher").Get() == true {
fmt.Println("IT IS JUST GOPHERTASTIC!!!")
fmt.Println(IS JUST GOPHERTASTIC!!!")
} else {
fmt.Println("It is just fine")
fmt.Println("Is pretty dandy")
}
})
func init(){
CLI.DefineBoolFlag("gopher", false, "is it gophertastic?")
CLI.FlagAlias('g', "gopher")
app.DefineBoolFlag("gopher", false, "is it gophertastic?")
app.FlagAlias('g', "gopher")
}
func main(){
CLI.Start()
app.Start()
}
```
```
$ mycli
It is just fine
Is pretty dandy
$ mycli --gopher
IT IS JUST GOPHERTASTIC!!!
IS JUST GOPHERTASTIC!!!
$ mycli -g
IT IS JUST GOPHERTASTIC!!!
IS JUST GOPHERTASTIC!!!
```
### Required Parameters
Expand All @@ -135,7 +148,7 @@ cli.New(version string, description string, fn func(Command), params ...string)
*or at a later time...*
```go
cli.DefineParams(params ...string)
app.DefineParams(params ...string)
```
#### Accessing
Expand Down Expand Up @@ -196,6 +209,43 @@ cmd.Parent().Param("name")
cmd.Parent().Flag("name")
```
#### Flag Inheritence
In addition to accesing the parent params via the `Parent()` you can instruct a sub command to inherit a flag from its parent.
**example:**
```go
package main
import (
"fmt"
"github.com/jwaldrip/odin"
)
var app = cli.New("0.0.1", "sample command", func(Command){})
func init(){
app.DefineStringFlag("user", "", "the user")
subcmd := app.DefineSubCommand("action", "perform an action", func(c cli.Command){
fmt.Println("the user is:", c.Flag("user"))
fmt.Println("the action is:", c.Param("actionName"))
})
subcmd.DefineParams("actionName")
subcmd.InheritFlag("user")
}
func main(){
app.Start()
}
```
```
$ mycmd --user=jason action hello
the user is: jason
the action is: hello
```
### Self Documentation
#### Usage
Expand Down Expand Up @@ -241,6 +291,7 @@ greet-with 1.0.0
* Bash Completion
* Zsh Completion
* CLI Bootstrapping
* Param Inheritence
## Contributing
Expand Down
36 changes: 19 additions & 17 deletions cli/CLI.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,25 @@ import "github.com/jwaldrip/odin/cli/values"
type CLI struct {
ErrorHandling ErrorHandling

aliases map[rune]*Flag
description string
errOutput io.Writer
flags flagMap
flagsTerminated bool
flagValues map[*Flag]values.Value
fn func(Command)
name string
params paramsList
paramValues map[*Param]values.Value
paramsParsed bool
parent Command
stdOutput io.Writer
subCommands map[string]*SubCommand
unparsedArgs values.List
usage func()
version string
aliases map[rune]*Flag
description string
errOutput io.Writer
flags flagMap
flagsTerminated bool
flagValues map[*Flag]values.Value
fn func(Command)
inheritedFlags flagMap
name string
params paramsList
paramValues map[*Param]values.Value
paramsParsed bool
parent Command
propogatingFlags flagMap
stdOutput io.Writer
subCommands map[string]*SubCommand
unparsedArgs values.List
usage func()
version string
}

func (cmd *CLI) init(name, desc string, fn func(Command), paramNames ...string) {
Expand Down
39 changes: 39 additions & 0 deletions cli/FlagMap.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,29 @@ import "sort"
// flagMap is a map of flags with the name as a string key
type flagMap map[string]*Flag

func (fm flagMap) Merge(fm2 flagMap) flagMap {
mergedMap := make(flagMap)
if fm != nil {
for k, v := range fm {
mergedMap[k] = v
}
}
if fm2 != nil {
for k, v := range fm2 {
mergedMap[k] = v
}
}
return mergedMap
}

func (fm flagMap) Names() []string {
var keys []string
for k := range fm {
keys = append(keys, k)
}
return keys
}

// Sort returns a sorted list of flags
func (fm flagMap) Sort() []*Flag {
list := make(sort.StringSlice, len(fm))
Expand All @@ -20,3 +43,19 @@ func (fm flagMap) Sort() []*Flag {
}
return result
}

func (fm flagMap) Without(fm2 flagMap) flagMap {
diffedMap := make(flagMap)
if fm == nil {
return diffedMap
}
if fm2 == nil {
return fm
}
for k, v := range fm {
if _, exist := fm2[k]; !exist {
diffedMap[k] = v
}
}
return diffedMap
}
4 changes: 2 additions & 2 deletions cli/ParamsList.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ func (l paramsList) Compare(Y paramsList) paramsList {
// Names returns the list of parameters names as a slice of strings
func (l paramsList) Names() []string {
var names []string
for i := 0; i < len(l); i++ {
names = append(names, l[i].Name)
for _, item := range l {
names = append(names, item.Name)
}
return names
}
15 changes: 11 additions & 4 deletions cli/flag_access.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,7 @@ import (
// Flag returns the Value interface to the value of the named flag,
// returning nil if none exists.
func (cmd *CLI) Flag(name string) values.Value {
flag, ok := cmd.flags[name]
if !ok {
panic(fmt.Sprintf("flag not defined %v", name))
}
flag := cmd.getFlag(name)
value := cmd.flagValues[flag]
return value
}
Expand All @@ -25,3 +22,13 @@ func (cmd *CLI) Flags() values.Map {
}
return flags
}

func (cmd *CLI) getFlag(name string) *Flag {
var ok bool
var flag *Flag
flag, ok = cmd.inheritedFlags.Merge(cmd.flags)[name]
if !ok {
panic(fmt.Sprintf("flag not defined %v", name))
}
return flag
}
53 changes: 53 additions & 0 deletions cli/flag_inheritance.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package cli

// InheritFlags allow flag values inherit from the commands parent
func (cmd *CLI) InheritFlags(names ...string) {
for _, name := range names {
cmd.InheritFlag(name)
}
}

// InheritFlag allows a flags value to inherit from the commands parent
func (cmd *CLI) InheritFlag(name string) {
if cmd.parent == nil {
panic("command does not have a parent")
}
flag := cmd.parent.(*CLI).getFlag(name)
if cmd.inheritedFlags == nil {
cmd.inheritedFlags = make(flagMap)
}
cmd.inheritedFlags[name] = flag
}

func (cmd *CLI) setFlagValuesFromParent() {
for name, flag := range cmd.inheritedFlags {
if _, exist := cmd.flags[name]; !exist {
cmd.flagValues[flag] = cmd.parent.Flag(name)
}
}
}

// SubCommandsInheritFlags tells all subcommands to inherit flags
func (cmd *CLI) SubCommandsInheritFlags(names ...string) {
for _, name := range names {
cmd.SubCommandsInheritFlag(name)
}
}

// SubCommandsInheritFlag tells all subcommands to inherit a flag
func (cmd *CLI) SubCommandsInheritFlag(name string) {
flag := cmd.getFlag(name)
if cmd.propogatingFlags == nil {
cmd.propogatingFlags = make(flagMap)
}
cmd.propogatingFlags[name] = flag
}

func (cmd *CLI) copyPropogatingFlags() {
if cmd.parent == nil {
return
}
parentPropogatingFlags := cmd.parent.(*CLI).propogatingFlags
cmd.propogatingFlags = parentPropogatingFlags.Without(cmd.flags).Merge(cmd.propogatingFlags)
cmd.InheritFlags(parentPropogatingFlags.Names()...)
}
Loading

0 comments on commit 34c731e

Please sign in to comment.