-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
sources are moved from github.com/openware/pkg based on commit 6ec144033509b62d19a8dbff9e496f89dddee9b1
- Loading branch information
Showing
4 changed files
with
702 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
package kli | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
"os" | ||
) | ||
|
||
// Cli - The main application object | ||
type Cli struct { | ||
version string | ||
rootCommand *Command | ||
defaultCommand *Command | ||
preRunCommand func(*Cli) error | ||
bannerFunction func(*Cli) string | ||
} | ||
|
||
// Action represents a function that gets called when the command is executed | ||
type Action func() error | ||
|
||
// NewCli - Creates a new Cli application object | ||
func NewCli(name, description, version string) *Cli { | ||
result := &Cli{ | ||
version: version, | ||
bannerFunction: defaultBannerFunction, | ||
} | ||
result.rootCommand = NewCommand(name, description) | ||
result.rootCommand.setApp(result) | ||
result.rootCommand.setParentCommandPath("") | ||
return result | ||
} | ||
|
||
// Version - Get the Application version string | ||
func (c *Cli) Version() string { | ||
return c.version | ||
} | ||
|
||
// Name - Get the Application Name | ||
func (c *Cli) Name() string { | ||
return c.rootCommand.name | ||
} | ||
|
||
// ShortDescription - Get the Application short description | ||
func (c *Cli) ShortDescription() string { | ||
return c.rootCommand.shortdescription | ||
} | ||
|
||
// SetBannerFunction is used to set the function that is called | ||
// to get the banner string. | ||
func (c *Cli) SetBannerFunction(fn func(*Cli) string) { | ||
c.bannerFunction = fn | ||
} | ||
|
||
// Abort prints the given error and terminates the application | ||
func (c *Cli) Abort(err error) { | ||
log.Fatal(err) | ||
os.Exit(1) | ||
} | ||
|
||
// AddCommand - Adds a command to the application | ||
func (c *Cli) AddCommand(command *Command) { | ||
c.rootCommand.AddCommand(command) | ||
} | ||
|
||
// PrintBanner prints the application banner! | ||
func (c *Cli) PrintBanner() { | ||
fmt.Println(c.bannerFunction(c)) | ||
fmt.Println("") | ||
} | ||
|
||
// PrintHelp - Prints the application's help | ||
func (c *Cli) PrintHelp() { | ||
c.rootCommand.PrintHelp() | ||
} | ||
|
||
// Run - Runs the application with the given arguments | ||
func (c *Cli) Run(args ...string) error { | ||
if c.preRunCommand != nil { | ||
err := c.preRunCommand(c) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
if len(args) == 0 { | ||
args = os.Args[1:] | ||
} | ||
return c.rootCommand.run(args) | ||
} | ||
|
||
// DefaultCommand - Sets the given command as the command to run when | ||
// no other commands given | ||
func (c *Cli) DefaultCommand(defaultCommand *Command) *Cli { | ||
c.defaultCommand = defaultCommand | ||
return c | ||
} | ||
|
||
// NewSubCommand - Creates a new SubCommand for the application | ||
func (c *Cli) NewSubCommand(name, description string) *Command { | ||
return c.rootCommand.NewSubCommand(name, description) | ||
} | ||
|
||
// PreRun - Calls the given function before running the specific command | ||
func (c *Cli) PreRun(callback func(*Cli) error) { | ||
c.preRunCommand = callback | ||
} | ||
|
||
// BoolFlag - Adds a boolean flag to the root command | ||
func (c *Cli) BoolFlag(name, description string, variable *bool) *Cli { | ||
c.rootCommand.BoolFlag(name, description, variable) | ||
return c | ||
} | ||
|
||
// StringFlag - Adds a string flag to the root command | ||
func (c *Cli) StringFlag(name, description string, variable *string) *Cli { | ||
c.rootCommand.StringFlag(name, description, variable) | ||
return c | ||
} | ||
|
||
// IntFlag - Adds an int flag to the root command | ||
func (c *Cli) IntFlag(name, description string, variable *int) *Cli { | ||
c.rootCommand.IntFlag(name, description, variable) | ||
return c | ||
} | ||
|
||
// Action - Define an action from this command | ||
func (c *Cli) Action(callback Action) *Cli { | ||
c.rootCommand.Action(callback) | ||
return c | ||
} | ||
|
||
// LongDescription - Sets the long description for the command | ||
func (c *Cli) LongDescription(longdescription string) *Cli { | ||
c.rootCommand.LongDescription(longdescription) | ||
return c | ||
} | ||
|
||
// OtherArgs - Returns the non-flag arguments passed to the cli. NOTE: This should only be called within the context of an action. | ||
func (c *Cli) OtherArgs() []string { | ||
return c.rootCommand.flags.Args() | ||
} | ||
|
||
// defaultBannerFunction prints a banner for the application. | ||
// If version is a blank string, it is ignored. | ||
func defaultBannerFunction(c *Cli) string { | ||
version := "" | ||
if len(c.Version()) > 0 { | ||
version = " " + c.Version() | ||
} | ||
return fmt.Sprintf("%s%s - %s", c.Name(), version, c.ShortDescription()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
package kli | ||
|
||
import ( | ||
"errors" | ||
"testing" | ||
) | ||
|
||
func TestCli(t *testing.T) { | ||
c := NewCli("test", "description", "0") | ||
|
||
t.Run("Run SetBannerFunction()", func(t *testing.T) { | ||
c.SetBannerFunction(func(*Cli) string { return "" }) | ||
}) | ||
|
||
// t.Run("Run Abort()", func(t *testing.T) { | ||
// cl := NewCli("test", "description", "0") | ||
// cl.Abort(errors.New("test error")) | ||
// }) | ||
|
||
t.Run("Run AddCommand()", func(t *testing.T) { | ||
c.AddCommand(&Command{name: "test"}) | ||
}) | ||
|
||
t.Run("Run PrintBanner()", func(t *testing.T) { | ||
c.PrintBanner() | ||
}) | ||
|
||
t.Run("Run Run()", func(t *testing.T) { | ||
c.Run("test") | ||
c.Run() | ||
|
||
c.preRunCommand = func(*Cli) error { return errors.New("testing coverage") } | ||
c.Run("test") | ||
}) | ||
|
||
t.Run("Run DefaultCommand()", func(t *testing.T) { | ||
c.DefaultCommand(&Command{}) | ||
}) | ||
|
||
t.Run("Run NewSubCommand()", func(t *testing.T) { | ||
c.NewSubCommand("name", "description") | ||
}) | ||
|
||
t.Run("Run PreRun()", func(t *testing.T) { | ||
c.PreRun(func(*Cli) error { return nil }) | ||
}) | ||
|
||
t.Run("Run BoolFlag()", func(t *testing.T) { | ||
var variable bool | ||
c.BoolFlag("bool", "description", &variable) | ||
}) | ||
|
||
t.Run("Run StringFlag()", func(t *testing.T) { | ||
var variable string | ||
c.StringFlag("string", "description", &variable) | ||
}) | ||
|
||
t.Run("Run IntFlag()", func(t *testing.T) { | ||
var variable int | ||
c.IntFlag("int", "description", &variable) | ||
}) | ||
|
||
t.Run("Run Action()", func(t *testing.T) { | ||
c.Action(func() error { return nil }) | ||
}) | ||
|
||
t.Run("Run LongDescription()", func(t *testing.T) { | ||
c.LongDescription("long description") | ||
}) | ||
} | ||
|
||
func TestCliEmpty(t *testing.T) { | ||
var mockCli *Cli | ||
t.Run("Run NewCli()", func(t *testing.T) { | ||
mockCli = NewCli("name", "description", "version") | ||
t.Log(mockCli) | ||
}) | ||
|
||
t.Run("Run defaultBannerFunction()", func(t *testing.T) { | ||
err := defaultBannerFunction(mockCli) | ||
t.Log(err) | ||
}) | ||
} | ||
|
||
func TestCliGlobalFlag(t *testing.T) { | ||
var rootCli *Cli | ||
|
||
t.Run("rcli -config app.yml create", func(t *testing.T) { | ||
var cnf string | ||
|
||
rootCli = NewCli("rcli", "description", "version") | ||
rootCli.StringFlag("config", "Application yaml configuration file", &cnf) | ||
rootCli.Action(func() error { | ||
t.Fail() | ||
return nil | ||
}) | ||
create := rootCli.NewSubCommand("create", "Create a sonic application") | ||
create.Action(func() error { | ||
t.Log("Running Create") | ||
return nil | ||
}) | ||
rootCli.Run("-config", "app.yml", "create") | ||
t.Logf("After Execution cnf: %s", cnf) | ||
}) | ||
|
||
t.Run("rcli -config app.yml create -v", func(t *testing.T) { | ||
var verb bool | ||
var cnf string | ||
|
||
rootCli = NewCli("rcli", "description", "version") | ||
rootCli.StringFlag("config", "Application yaml configuration file", &cnf) | ||
rootCli.Action(func() error { | ||
t.Fail() | ||
return nil | ||
}) | ||
create := rootCli.NewSubCommand("create", "Create a sonic application") | ||
create.BoolFlag("v", "Activate verbose", &verb) | ||
create.Action(func() error { | ||
if verb == false { | ||
t.Fail() | ||
} else { | ||
t.Log("Running Create with verbose") | ||
} | ||
return nil | ||
}) | ||
rootCli.Run("-config", "app.yml", "create", "-v") | ||
t.Logf("After Execution") | ||
}) | ||
|
||
t.Run("rcli create -f file.txt", func(t *testing.T) { | ||
var file string | ||
|
||
rootCli = NewCli("rcli", "description", "version") | ||
create := rootCli.NewSubCommand("create", "Create a sonic application") | ||
create.StringFlag("f", "Pass file", &file) | ||
create.Action(func() error { | ||
if file == "file.txt" { | ||
t.Log("Running Create with -f params") | ||
} else { | ||
t.Fail() | ||
} | ||
return nil | ||
}) | ||
rootCli.Run("create", "-f", "file.txt") | ||
t.Logf("After Execution") | ||
}) | ||
|
||
t.Run("rcli -c app.yml create -f file.txt", func(t *testing.T) { | ||
var cnf string | ||
var file string | ||
|
||
rootCli = NewCli("rcli", "description", "version") | ||
rootCli.StringFlag("c", "Pass file", &cnf) | ||
create := rootCli.NewSubCommand("create", "Create a sonic application") | ||
create.StringFlag("f", "Pass file", &file) | ||
create.Action(func() error { | ||
if file == "file.txt" && cnf == "app.yml" { | ||
t.Log("Running Create with -f -c flags") | ||
} else { | ||
t.Fail() | ||
} | ||
return nil | ||
}) | ||
rootCli.Run("-c", "app.yml", "create", "-f", "file.txt") | ||
t.Logf("After Execution") | ||
}) | ||
} |
Oops, something went wrong.