Skip to content

Commit

Permalink
feat: add source code
Browse files Browse the repository at this point in the history
sources are moved from github.com/openware/pkg based on commit
6ec144033509b62d19a8dbff9e496f89dddee9b1
  • Loading branch information
maxpushka committed Sep 25, 2023
1 parent 3e5c697 commit af21e55
Show file tree
Hide file tree
Showing 4 changed files with 702 additions and 0 deletions.
150 changes: 150 additions & 0 deletions cli.go
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())
}
167 changes: 167 additions & 0 deletions cli_test.go
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")
})
}
Loading

0 comments on commit af21e55

Please sign in to comment.