Skip to content

Commit

Permalink
refactor: refactor the help string-vars handle logic
Browse files Browse the repository at this point in the history
- rename helper.HelpVars to gcli.HelpReplacer
  • Loading branch information
inhere committed Oct 17, 2022
1 parent dcbe38d commit 5120a1f
Show file tree
Hide file tree
Showing 12 changed files with 160 additions and 172 deletions.
11 changes: 4 additions & 7 deletions app.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,12 @@ func NewApp(fns ...func(app *App)) *App {
Logf(VerbCrazy, "create a new cli application, and create base ")

// init base
app.Ctx = gCtx
app.base = newBase()
app.opts = newGlobalOpts()

// set a default version
app.Version = "1.0.0"
app.Context = gCtx

for _, fn := range fns {
fn(app)
Expand Down Expand Up @@ -151,7 +151,7 @@ func (app *App) initialize() {
Logf(VerbCrazy, "initialize the cli application")

// init some info
app.initHelpVars()
app.initHelpReplacer()
app.bindAppOpts()

// add default error handler.
Expand Down Expand Up @@ -209,7 +209,7 @@ func (app *App) AddCommand(c *Command) {
// init command
c.app = app
// inherit some from application
c.Context = app.Context
c.Ctx = app.Ctx

// do add command
app.addCommand(app.Name, c)
Expand Down Expand Up @@ -472,7 +472,7 @@ func (app *App) Run(args []string) (code int) {
return app.exitOnEnd(code)
}

Logf(VerbCrazy, "begin run console application, PID: %d", app.PID())
Logf(VerbCrazy, "begin run console application, PID: %d", app.Ctx.PID())

var name string
code, name = app.prepareRun()
Expand Down Expand Up @@ -528,9 +528,6 @@ func (app *App) doRunCmd(name string, args []string) (code int) {
}

func (app *App) doRunFunc(args []string) (code int) {
// app bind args TODO
// app.ParseArgs(args)

// do execute command
if err := app.Func(app, args); err != nil {
code = ERR
Expand Down
16 changes: 8 additions & 8 deletions app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ var (
Desc: "an simple command",
Func: func(c *gcli.Command, args []string) error {
dump.Println(c.Path(), args)
c.Set("simple", "simple command")
c.Ctx.Set("simple", "simple command")
return nil
},
}
Expand All @@ -45,7 +45,7 @@ var (
Name: "sub1",
Desc: "desc for top1.sub1",
Func: func(c *gcli.Command, args []string) error {
c.Set("msg", c.App().Get("top1:sub1"))
c.Ctx.Set("msg", c.App().Ctx.Get("top1:sub1"))
return nil
},
},
Expand Down Expand Up @@ -291,36 +291,36 @@ func TestApp_Run_subcommand(t *testing.T) {
is := assert.New(t)
id := "top1:sub1"

appWithMl.Set(id, "TestApp_Run_subcommand")
appWithMl.Ctx.Set(id, "TestApp_Run_subcommand")
appWithMl.Run([]string{"top1", "sub1"})

c := appWithMl.FindCommand(id)
is.NotEmpty(c)
is.Eq("TestApp_Run_subcommand", c.Get("msg"))
is.Eq("TestApp_Run_subcommand", c.Ctx.Get("msg"))
}

func TestApp_Run_by_cmd_ID(t *testing.T) {
is := assert.New(t)

appWithMl.SetValue("top1:sub1", "TestApp_Run_by_cmd_ID")
appWithMl.Ctx.Set("top1:sub1", "TestApp_Run_by_cmd_ID")
appWithMl.Run([]string{"top1:sub1"})

c := appWithMl.FindCommand("top1:sub1")
is.NotEmpty(c)
is.Eq("TestApp_Run_by_cmd_ID", c.GetVal("msg"))
is.Eq("TestApp_Run_by_cmd_ID", c.Ctx.Get("msg"))
}

func TestApp_AddAliases_and_run(t *testing.T) {
is := assert.New(t)
id := "top1:sub1"

appWithMl.AddAliases(id, "ts1")
appWithMl.SetValue(id, "TestApp_AddAliases_and_run")
appWithMl.Ctx.Set(id, "TestApp_AddAliases_and_run")
appWithMl.Run([]string{"ts1"})

c := appWithMl.FindCommand(id)
is.NotEmpty(c)
is.Eq("TestApp_AddAliases_and_run", c.GetVal("msg"))
is.Eq("TestApp_AddAliases_and_run", c.Ctx.Get("msg"))
}

func TestApp_showCommandHelp(t *testing.T) {
Expand Down
50 changes: 20 additions & 30 deletions base.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"strings"

"github.com/gookit/color"
"github.com/gookit/gcli/v3/helper"
"github.com/gookit/goutil/maputil"
"github.com/gookit/goutil/structs"
)
Expand Down Expand Up @@ -125,36 +124,27 @@ func (ctx *Context) hasHelpKeywords() bool {
return strings.HasSuffix(ctx.argLine, " -h") || strings.HasSuffix(ctx.argLine, " --help")
}

// SetValue to ctx
func (ctx *Context) SetValue(key string, val any) {
ctx.Set(key, val)
}

// GetVal from ctx
func (ctx *Context) GetVal(key string) interface{} {
return ctx.Get(key)
}

// ResetData from ctx
func (ctx *Context) ResetData() {
ctx.Data = make(maputil.Data)
}

/*************************************************************
* command Base
* command base
*************************************************************/

// will inject to every Command
type base struct {
color.SimplePrinter
// Hooks manage. allowed hooks: "init", "before", "after", "error"
*Hooks
*Context
color.SimplePrinter
// HelpVars help message replace vars.
helper.HelpVars
// TODO tplVars for render help template text.
tplVars map[string]any
// HelpReplacer help message replace pairs.
HelpReplacer
// helpVars custom add vars for render help template.
helpVars map[string]any

// Ctx for command
Ctx *Context
// Logo ASCII logo setting
Logo *Logo
// Version app version. like "1.0.1"
Expand Down Expand Up @@ -200,25 +190,25 @@ func newBase() base {
// cmdAliases: make(maputil.Aliases),
cmdAliases: structs.NewAliases(aliasNameCheck),
// ExitOnEnd: false,
tplVars: make(map[string]any),
helpVars: make(map[string]any),
// Context: NewCtx(),
}
}

// init common basic help vars
func (b *base) initHelpVars() {
b.AddVars(map[string]string{
"pid": b.PIDString(),
"workDir": b.workDir,
"binFile": b.binFile,
"binName": b.binName,
func (b *base) initHelpReplacer() {
b.AddReplaces(map[string]string{
"pid": b.Ctx.PIDString(),
"workDir": b.Ctx.workDir,
"binFile": b.Ctx.binFile,
"binName": b.Ctx.binName,
})
}

// ResetData from ctx
func (b *base) ResetData() {
if b.Context != nil {
b.Context.ResetData()
if b.Ctx != nil {
b.Ctx.ResetData()
}
}

Expand Down Expand Up @@ -392,7 +382,7 @@ func (b *base) AliasesMapping() map[string]string {
return b.cmdAliases.Mapping()
}

// AddTplVar to instance.
func (b *base) AddTplVar(key string, val any) {
b.tplVars[key] = val
// AddHelpVar to instance.
func (b *base) AddHelpVar(key string, val any) {
b.helpVars[key] = val
}
4 changes: 2 additions & 2 deletions base_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ func TestApp_On_CmdNotFound_redirect(t *testing.T) {
buf.Reset()
simpleCmd.Init()
simpleCmd.ResetData()
assert.Eq(t, nil, simpleCmd.GetVal("simple"))
assert.Eq(t, nil, simpleCmd.Ctx.Get("simple"))

cli := newNotExitApp()
cli.Add(simpleCmd)
Expand All @@ -128,7 +128,7 @@ func TestApp_On_CmdNotFound_redirect(t *testing.T) {

err := ctx.App.Exec(simpleCmd.Name, nil)
assert.NoErr(t, err)
buf.WriteString("value:" + simpleCmd.Data.Str("simple"))
buf.WriteString("value:" + simpleCmd.Ctx.Str("simple"))
return true
})

Expand Down
18 changes: 9 additions & 9 deletions cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,9 +178,9 @@ func (c *Command) IsDisabled() bool {
return c.disabled
}

// Runnable reports whether the command can be run; otherwise
// IsRunnable reports whether the command can be run; otherwise
// it is a documentation pseudo-command such as import path.
func (c *Command) Runnable() bool {
func (c *Command) IsRunnable() bool {
return c.Func != nil
}

Expand Down Expand Up @@ -208,7 +208,7 @@ func (c *Command) AddCommand(sub *Command) {
// inherit standalone value
sub.standalone = c.standalone
// inherit something from parent
sub.Context = c.Context
sub.Ctx = c.Ctx

// initialize command
c.initialize()
Expand Down Expand Up @@ -291,22 +291,22 @@ func (c *Command) initCommandBase(cName string) {
c.Hooks = &Hooks{}
}

if c.Context == nil {
if c.Ctx == nil {
Logf(VerbDebug, "cmd: %s - use the gCtx as command context", cName)
c.Context = gCtx
c.Ctx = gCtx
}

binWithPath := c.binName + " " + c.Path()
binWithPath := c.Ctx.binName + " " + c.Path()

c.initHelpVars()
c.AddVars(map[string]string{
c.initHelpReplacer()
c.AddReplaces(map[string]string{
"cmd": cName,
// binName with command name
"binWithCmd": binWithPath,
// binName with command path
"binWithPath": binWithPath,
// binFile with command
"fullCmd": c.binFile + " " + cName,
"fullCmd": c.Ctx.binFile + " " + cName,
})

c.base.cmdNames = make(map[string]int)
Expand Down
12 changes: 6 additions & 6 deletions cmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func TestNewCommand(t *testing.T) {
})

is.NotEmpty(c)
is.False(c.Runnable())
is.False(c.IsRunnable())
is.Nil(c.App())

err := c.Run([]string{})
Expand Down Expand Up @@ -55,7 +55,7 @@ func TestCommand_NewErrf(t *testing.T) {
})

is.NotEmpty(c)
is.True(c.Runnable())
is.True(c.IsRunnable())

err := c.Run(simpleArgs)
is.Err(err)
Expand Down Expand Up @@ -277,8 +277,8 @@ var c0 = gcli.NewCommand("test", "desc for test command", func(c *gcli.Command)
c.AddArg("arg1", "arg1 desc")
c.Func = func(c *gcli.Command, args []string) error {
bf.WriteString("name=" + c.Name)
c.Set("name", c.Name)
c.Set("args", args)
c.Ctx.Set("name", c.Name)
c.Ctx.Set("args", args)
// dump.P(c.ID(), "command Func is exec")
return nil
}
Expand Down Expand Up @@ -357,8 +357,8 @@ func TestCommand_Run_parseOptions(t *testing.T) {

// dump.P(gcli.GOpts(), c0.Context)
is.NoErr(err)
is.Eq("test", c0.Get("name"))
is.Eq([]string{"txt"}, c0.Get("args"))
is.Eq("test", c0.Ctx.Get("name"))
is.Eq([]string{"txt"}, c0.Ctx.Get("args"))

is.Eq(10, int0)
is.Eq("abc", str0)
Expand Down
61 changes: 61 additions & 0 deletions hooks.go → ext.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package gcli

import (
"context"
"fmt"
"strings"

"github.com/gookit/gcli/v3/events"
"github.com/gookit/goutil/maputil"
Expand Down Expand Up @@ -168,3 +170,62 @@ func (hc *HookCtx) WithApp(a *App) *HookCtx {
hc.App = a
return hc
}

/*************************************************************
* app/cmd help string-var replacer
*************************************************************/

// HelpVarFormat allow string replace on render help info.
//
// Default support:
//
// "{$binName}" "{$cmd}" "{$fullCmd}" "{$workDir}"
const HelpVarFormat = "{$%s}"

// HelpReplacer provide string var replace for render help template.
type HelpReplacer struct {
VarOpen, VarClose string

// replaces you can add string-var map for render help info.
replaces map[string]string
}

// AddReplace get command name. AddReplace
func (hv *HelpReplacer) AddReplace(name, value string) {
if hv.replaces == nil {
hv.replaces = make(map[string]string)
}
hv.replaces[name] = value
}

// AddReplaces add multi tpl vars.
func (hv *HelpReplacer) AddReplaces(vars map[string]string) {
for n, v := range vars {
hv.AddReplace(n, v)
}
}

// GetReplace get a help var by name
func (hv *HelpReplacer) GetReplace(name string) string {
return hv.replaces[name]
}

// Replaces get all tpl vars.
func (hv *HelpReplacer) Replaces() map[string]string {
return hv.replaces
}

// ReplacePairs replace string vars in the input text.
func (hv *HelpReplacer) ReplacePairs(input string) string {
// if not use var
if !strings.Contains(input, "{$") {
return input
}

var ss []string
for n, v := range hv.replaces {
ss = append(ss, fmt.Sprintf(HelpVarFormat, n), v)
}

return strings.NewReplacer(ss...).Replace(input)
}
Loading

0 comments on commit 5120a1f

Please sign in to comment.