func (app *App) RunCmd(name string, args []string) int {
	return app.doRunCmd(name, args)
}
RunCmd running an top command with custom args

Usage:
app.Exec("top")
app.Exec("top", []string{"-a", "val0", "arg0"})
// can add sub command on args
app.Exec("top", []string{"sub", "-o", "abc"})
package gcli
import (
	"fmt"
	"os"
	"strings"
	"text/template"
	"github.com/gookit/color"
	"github.com/gookit/gcli/v3/helper"
	"github.com/gookit/goutil/cliutil"
	"github.com/gookit/goutil/strutil"
)
type Handler interface {
	Creator() *Command
	Config(c *Command)
	Execute(c *Command, args []string) error
}
type Logo struct {
	Text  string  
	Style string  
}
type App struct {
	core
	commandBase
	Name string
	Desc string
	Func func(app *App, args []string) error
	ExitOnEnd bool
	ExitFunc func(int)
	args []string
	cleanArgs []string
	hasSubcommands bool
	defaultCommand string
}
func New(fns ...func(app *App)) *App {
	return NewApp(fns...)
}
func NewApp(fns ...func(app *App)) *App {
	app := &App{
		Name: "GCliApp",
		Desc: "This is my console application",
		ExitOnEnd: true,
		commandBase: newCommandBase(),
	}
	Logf(VerbCrazy, "create new core on init application")
	app.core = core{
		cmdLine: CLI,
		Hooks: &Hooks{},
		gFlags: NewFlags("app.GOptions").WithOptions(func(opt *FlagsOption) {
			opt.WithoutType = true
			opt.NameDescOL = true
			opt.Alignment = AlignLeft
		}),
	}
	Logf(VerbCrazy, "create new commandBase on init application")
	app.Version = "1.0.0"
	if len(fns) > 0 {
		for _, fn := range fns {
			fn(app)
		}
	}
	return app
}
func NotExitOnEnd() func(*App) {
	return func(app *App) {
		app.ExitOnEnd = false
	}
}
func (app *App) Config(fn func(a *App)) {
	if fn != nil {
		fn(app)
	}
}
func (app *App) bindingGlobalOpts() {
	Logf(VerbDebug, "will begin binding global options")
	gf := app.GlobalFlags()
	gOpts.bindingFlags(gf)
	gf.BoolOpt(&gOpts.showVer, "version", "V", false, "Display app version information")
	gf.BoolVar(&gOpts.inCompletion, &FlagMeta{
		Name: "in-completion",
		Desc: "generate completion scripts for bash/zsh",
		Hidden: true,
	})
	if app.GOptsBinder != nil {
		app.GOptsBinder(gf)
	}
}
func (app *App) initialize() {
	if app.initialized {
		return
	}
	Logf(VerbCrazy, "initialize the application")
	if app.core.Hooks == nil {
		app.core.Hooks = &Hooks{}
	}
	app.core.AddVars(app.core.innerHelpVars())
	app.bindingGlobalOpts()
	if !app.HasHook(EvtAppRunError) {
		app.On(EvtAppRunError, defaultErrHandler)
	}
	app.Fire(EvtAppInit, nil)
	app.initialized = true
}
func (app *App) Add(c *Command, more ...*Command) {
	app.AddCommand(c)
	if len(more) > 0 {
		for _, cmd := range more {
			app.AddCommand(cmd)
		}
	}
}
func (app *App) AddCommand(c *Command) {
	app.initialize()
	c.app = app
	c.core.gFlags = app.gFlags
	app.commandBase.addCommand(app.Name, c)
	if c.HasCommands() {
		app.hasSubcommands = true
	}
	app.Fire(EvtCmdInit, c)
}
func (app *App) AddHandler(h Handler) {
	c := h.Creator()
	c.Func = h.Execute
	h.Config(c)
	app.AddCommand(c)
}
func (app *App) AddAliases(name string, aliases ...string) {
	c := app.FindByPath(name)
	if c == nil {
		panicf("the command '%s' is not exists", name)
	}
	for _, alias := range aliases {
		if app.IsCommand(alias) {
			panicf("The name '%s' has been used as an command name", alias)
		}
		app.cmdAliases.AddAlias(name, alias)
	}
}
func (app *App) parseGlobalOpts(args []string) (ok bool) {
	Logf(VerbDebug, "will begin parse global options")
	err := app.core.doParseGOpts(args)
	if err != nil {  
		color.Error.Tips(err.Error())
		return
	}
	app.args = app.gFlags.FSetArgs()
	app.Fire(EvtGOptionsParsed, app.args)
	if gOpts.showHelp {
		app.showApplicationHelp()
		return
	}
	if gOpts.showVer {
		app.showVersionInfo()
		return
	}
	if gOpts.NoColor {
		color.Enable = false
	}
	Debugf("global option parsed, verbose level: <mgb>%s</>", gOpts.verbose.String())
	if gOpts.inCompletion {
		app.showAutoCompletion(app.args)
		return
	}
	return true
}
func (app *App) prepareRun() (code int, name string) {
	name = app.findCommandName()
	if name == HelpCommand {
		if len(app.args) == 0 {  
			app.showApplicationHelp()
			return
		}
		code = app.showCommandHelp(app.args)
		return
	}
	if name == "" {
		if app.Func != nil {
			code = app.doRunFunc(app.args)
			return
		}
		app.showApplicationHelp()
		return
	}
	if app.inputName == "" {
		Logf(VerbDebug, "input the command is not an registered: %s", name)
		if stop := app.Fire(EvtAppCmdNotFound, name); stop == false {
			stop = app.Fire(EvtCmdNotFound, name)
			if stop == false {
				app.showCommandTips(name)
			}
		}
		return
	}
	app.commandName = name
	return GOON, name
}
func (app *App) findCommandName() (name string) {
	args := app.args
	if len(args) == 0 {
		name = app.defaultCommand
		if name == "" {
			return
		}
		if false == app.IsCommand(name) {
			Logf(VerbError, "the default command '<cyan>%s</>' is invalid", name)
			return ""  
		}
		return name
	}
	name = strings.TrimSpace(args[0])
	if name == "" || name[0] == '-' {
		return ""
	}
	if !goodCmdId.MatchString(name) {
		Logf(VerbWarn, "the input command name(%s) string is invalid", name)
		return ""
	}
	rawName := name
	nodes := splitPath2names(name)
	if len(nodes) > 1 {
		name = nodes[0]
		name = app.ResolveAlias(name)
		Debugf("input(args[0]) is an command ID, expand it. '%s' -> '%s'", rawName, name)
	} else {
		rName := app.ResolveAlias(name)
		nodes = splitPath2names(rName)
		if len(nodes) > 1 {
			name = nodes[0]
			Debugf("real command is an command ID, expand it. '%s' -> '%s'", rName, name)
		} else {
			name = rName
		}
	}
	if len(nodes) > 1 {
		app.args = append(nodes[1:], args[1:]...)
	} else {
		app.args = args[1:]
	}
	if app.IsCommand(name) {
		app.inputName = rawName
		Debugf("the raw input command: '<cyan>%s</>'; now, name: '<green>%s</>', args: %v", rawName, name, app.args)
		return name
	}
	Logf(VerbInfo, "the input command name '%s' is not exists. nodes: %v", rawName, nodes)
	return rawName
}
func (app *App) RunLine(argsLine string) int {
	args := cliutil.ParseLine(argsLine)
	return app.Run(args)
}
func (app *App) Run(args []string) (code int) {
	app.initialize()
	if args == nil {
		args = os.Args[1:]  
	}
	Debugf("will begin run cli application. args: %v", args)
	if false == app.parseGlobalOpts(args) {
		return app.exitOnEnd(code)
	}
	Logf(VerbCrazy, "begin run console application, PID: %d", app.PID())
	var name string
	code, name = app.prepareRun()
	if code != GOON {
		return app.exitOnEnd(code)
	}
	app.Fire(EvtAppPrepareAfter, name)
	code = app.doRunCmd(name, app.args)
	Debugf("command '%s' run complete, exit with code: %d", name, code)
	return app.exitOnEnd(code)
}