Skip to content

Commit

Permalink
wip: refactoring app and global options logic
Browse files Browse the repository at this point in the history
  • Loading branch information
inhere committed Sep 7, 2022
1 parent 78e8fdf commit 41a4d39
Show file tree
Hide file tree
Showing 19 changed files with 319 additions and 166 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
go_version: [1.18, 1.19]
go_version: [1.17, 1.18, 1.19]

steps:
- name: Check out codes
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
[![Actions Status](https://github.com/gookit/gcli/workflows/action-tests/badge.svg)](https://github.com/gookit/gcli/actions)
[![GitHub tag (latest SemVer)](https://img.shields.io/github/tag/gookit/gcli)](https://github.com/gookit/gcli)
[![Codacy Badge](https://app.codacy.com/project/badge/Grade/4f071e6858fb4117b6c1376c9316d8ef)](https://www.codacy.com/gh/gookit/gcli/dashboard?utm_source=github.com&utm_medium=referral&utm_content=gookit/gcli&utm_campaign=Badge_Grade)
[![GoDoc](https://godoc.org/github.com/gookit/gcli?status.svg)](https://pkg.go.dev/github.com/gookit/gcli/v3)
[![Go Reference](https://pkg.go.dev/badge/github.com/gookit/goutil.svg)](https://pkg.go.dev/github.com/gookit/goutil)
[![Go Report Card](https://goreportcard.com/badge/github.com/gookit/gcli)](https://goreportcard.com/report/github.com/gookit/gcli)
[![Coverage Status](https://coveralls.io/repos/github/gookit/gcli/badge.svg?branch=master)](https://coveralls.io/github/gookit/gcli?branch=master)

Expand Down
2 changes: 1 addition & 1 deletion README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
[![Actions Status](https://github.com/gookit/gcli/workflows/action-tests/badge.svg)](https://github.com/gookit/gcli/actions)
[![GitHub tag (latest SemVer)](https://img.shields.io/github/tag/gookit/gcli)](https://github.com/gookit/gcli)
[![Codacy Badge](https://app.codacy.com/project/badge/Grade/4f071e6858fb4117b6c1376c9316d8ef)](https://www.codacy.com/gh/gookit/gcli/dashboard?utm_source=github.com&utm_medium=referral&utm_content=gookit/gcli&utm_campaign=Badge_Grade)
[![GoDoc](https://godoc.org/github.com/gookit/gcli?status.svg)](https://pkg.go.dev/github.com/gookit/gcli/v3)
[![Go Reference](https://pkg.go.dev/badge/github.com/gookit/goutil.svg)](https://pkg.go.dev/github.com/gookit/goutil)
[![Go Report Card](https://goreportcard.com/badge/github.com/gookit/gcli)](https://goreportcard.com/report/github.com/gookit/gcli)
[![Coverage Status](https://coveralls.io/repos/github/gookit/gcli/badge.svg?branch=master)](https://coveralls.io/github/gookit/gcli?branch=master)

Expand Down
8 changes: 4 additions & 4 deletions _examples/cliapp/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
// "github.com/gookit/gcli/v3/builtin/reverseproxy"
)

var customGOpt string

// local run:
//
// go run ./_examples/cliapp
Expand Down Expand Up @@ -42,10 +44,8 @@ func main() {
// disable global options
// gcli.GOpts().SetDisable()

var customGOpt string
app.GOptsBinder = func(gf *gcli.Flags) {
// gcli.Logf(gcli.VerbInfo, "custom add and global option flag")
gf.StrVar(&customGOpt, &gcli.FlagMeta{Name: "custom", Desc: "desc message for the option"})
app.BeforeAddOpts = func(opts *gcli.Flags) {
opts.StrVar(&customGOpt, &gcli.FlagMeta{Name: "custom", Desc: "desc message for the option"})
}

// app.Strict = true
Expand Down
7 changes: 7 additions & 0 deletions any.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
//go:build !go1.18
// +build !go1.18

package gcli

// alias of interface{}, use for go < 1.18
type any = interface{}
80 changes: 53 additions & 27 deletions app.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/gookit/color"
"github.com/gookit/gcli/v3/events"
"github.com/gookit/gcli/v3/helper"
"github.com/gookit/goutil/cflag"
"github.com/gookit/goutil/cliutil"
"github.com/gookit/goutil/strutil"
)
Expand Down Expand Up @@ -41,8 +42,10 @@ type Logo struct {

// AppConfig struct
type AppConfig struct {
RunBefore func() bool
RunAfter func() bool
BeforeRun func() bool
AfterRun func() bool
BeforeAddOpts func(opts *Flags)
AfterBindOpts func(app *App) bool
}

// App the cli app definition
Expand All @@ -55,6 +58,12 @@ type App struct {
// for manager commands
commandBase

AppConfig

fs *Flags
// app flag options
opts *GlobalOpts

// Name app name
Name string
// Desc app description
Expand Down Expand Up @@ -99,6 +108,7 @@ func NewApp(fns ...func(app *App)) *App {
app := &App{
Name: "GCliApp",
Desc: "This is my console application",
opts: newDefaultGlobalOpts(),
// set a default version.
// Version: "1.0.0",
// config
Expand All @@ -108,16 +118,21 @@ func NewApp(fns ...func(app *App)) *App {
commandBase: newCommandBase(),
}

app.fs = NewFlags("appOptions").WithConfigFn(func(opt *FlagsConfig) {
opt.WithoutType = true
opt.Alignment = AlignLeft
})

// internal core
Logf(VerbCrazy, "create new core on init application")
app.core = core{
cmdLine: CLI,
// init
Hooks: &Hooks{},
gFlags: NewFlags("app.GOptions").WithConfigFn(func(opt *FlagsConfig) {
opt.WithoutType = true
opt.Alignment = AlignLeft
}),
// gFlags: NewFlags("appOptions").WithConfigFn(func(opt *FlagsConfig) {
// opt.WithoutType = true
// opt.Alignment = AlignLeft
// }),
}

// init commandBase
Expand Down Expand Up @@ -153,25 +168,23 @@ func (app *App) Config(fn func(a *App)) {
func (app *App) bindingGlobalOpts() {
Logf(VerbDebug, "will begin binding global options")
// global options flag
// gf := flag.NewFlagSet(app.Args[0], flag.ContinueOnError)
gf := app.GlobalFlags()
fs := app.fs

// binding global options
// bindingCommonGOpts(gf)
gOpts.bindingFlags(gf)
app.opts.bindingFlags(fs)
// add more ...
gf.BoolOpt(&gOpts.showVer, "version", "V", false, "Display app version information")
fs.BoolOpt(&gOpts.ShowVersion, "version", "V", false, "Display app version information")
// This is a internal option
gf.BoolVar(&gOpts.inCompletion, &FlagMeta{
fs.BoolVar(&gOpts.inCompletion, &FlagMeta{
Name: "in-completion",
Desc: "generate completion scripts for bash/zsh",
// hidden it
Hidden: true,
})

// support binding custom global options
if app.GOptsBinder != nil {
app.GOptsBinder(gf)
if app.BeforeAddOpts != nil {
app.BeforeAddOpts(fs)
}
}

Expand Down Expand Up @@ -225,7 +238,7 @@ func (app *App) AddCommand(c *Command) {
// init command
c.app = app
// inherit global flags from application
c.core.gFlags = app.gFlags
// c.core.gFlags = app.gFlags

// do add command
app.commandBase.addCommand(app.Name, c)
Expand Down Expand Up @@ -275,46 +288,59 @@ func (app *App) AddAliases(name string, aliases ...string) {
// }

/*************************************************************
* run command
* parse global options
*************************************************************/

// parseGlobalOpts parse global options
func (app *App) parseGlobalOpts(args []string) (ok bool) {
// parseAppOpts parse global options
func (app *App) doParseOpts(args []string) error {
err := app.fs.Parse(args)
if err != nil {
if cflag.IsFlagHelpErr(err) {
return nil
}
Logf(VerbWarn, "parse global options err: <red>%s</>", err.Error())
}

return err
}

// parseAppOpts parse global options
func (app *App) parseAppOpts(args []string) (ok bool) {
Logf(VerbDebug, "will begin parse application options")

// parse global options
err := app.core.doParseGOpts(args)
err := app.doParseOpts(args)
if err != nil { // has error.
color.Error.Tips(err.Error())
return
}

app.args = app.gFlags.FSetArgs()
app.args = app.fs.FSetArgs()
if app.Fire(events.OnGOptionsParsed, map[string]any{"args": app.args}) {
Logf(VerbDebug, "stop continue on the event %s return True", events.OnGOptionsParsed)
return
}

// check global options
if gOpts.showHelp {
if app.opts.ShowHelp {
app.showApplicationHelp()
return
}

if gOpts.showVer {
if app.opts.ShowVersion {
app.showVersionInfo()
return
}

// disable color
if gOpts.NoColor {
if app.opts.NoColor {
color.Enable = false
}

Debugf("global option parsed, verbose level: <mgb>%s</>", gOpts.verbose.String())
Debugf("global option parsed, Verbose level: <mgb>%s</>", app.opts.Verbose.String())

// TODO show auto-completion for bash/zsh
if gOpts.inCompletion {
if app.opts.inCompletion {
app.showAutoCompletion(app.args)
return
}
Expand Down Expand Up @@ -468,7 +494,7 @@ func (app *App) Run(args []string) (code int) {
Debugf("will begin run cli application. args: %v", args)

// parse global flags
if false == app.parseGlobalOpts(args) {
if false == app.parseAppOpts(args) {
return app.exitOnEnd(code)
}

Expand Down Expand Up @@ -684,7 +710,7 @@ func (app *App) showApplicationHelp() {
// render help text template
s := helper.RenderText(AppHelpTemplate, map[string]any{
"Cs": app.commands,
"GOpts": app.gFlags.String(),
"GOpts": app.fs.String(),
// app version
"Version": app.Version,
"HasSubs": app.hasSubcommands,
Expand Down
25 changes: 24 additions & 1 deletion base.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package gcli

import (
"context"
"os"
"path"
"path/filepath"
Expand All @@ -11,6 +12,7 @@ import (
"github.com/gookit/color"
"github.com/gookit/gcli/v3/helper"
"github.com/gookit/goutil/cflag"
"github.com/gookit/goutil/maputil"
"github.com/gookit/goutil/mathutil"
"github.com/gookit/goutil/structs"
"github.com/gookit/goutil/strutil"
Expand Down Expand Up @@ -134,6 +136,27 @@ func (md *mapData) ClearData() {
* Command Line: command data
*************************************************************/

// Context struct
type Context struct {
maputil.Data
context.Context
// some common info
PID int
}

// NewCtx instance
func NewCtx() *Context {
return &Context{
Data: make(maputil.Data),
Context: context.Background(),
}
}

// Value get by key
func (ctx *Context) Value(key any) any {
return ctx.Data.Get(key.(string))
}

// cmdLine store common data for CLI
type cmdLine struct {
// pid for current application
Expand Down Expand Up @@ -273,7 +296,7 @@ func newCommandBase() commandBase {
nameMaxWidth: 12,
// cmdAliases: make(maputil.Aliases),
cmdAliases: structs.NewAliases(aliasNameCheck),
ExitOnEnd: true,
// ExitOnEnd: false,
}
}

Expand Down
64 changes: 1 addition & 63 deletions typevars.go → builtin/typevars.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
package gcli
package builtin

import (
"fmt"
"strconv"
"strings"

"github.com/gookit/goutil/strutil"
)
Expand Down Expand Up @@ -134,64 +133,3 @@ func (s *String) Split(sep string) []string {
func (s *String) Ints(sep string) []int {
return strutil.Ints(string(*s), sep)
}

/*************************************************************************
* verbose level
*************************************************************************/

// VerbLevel type.
type VerbLevel uint

// Int verbose level to int.
func (vl *VerbLevel) Int() int {
return int(*vl)
}

// String verbose level to string.
func (vl *VerbLevel) String() string {
return fmt.Sprintf("%d=%s", *vl, vl.Name())
}

// Upper verbose level to string.
func (vl *VerbLevel) Upper() string {
return strings.ToUpper(vl.Name())
}

// Name verbose level to string.
func (vl *VerbLevel) Name() string {
switch *vl {
case VerbQuiet:
return "quiet"
case VerbError:
return "error"
case VerbWarn:
return "warn"
case VerbInfo:
return "info"
case VerbDebug:
return "debug"
case VerbCrazy:
return "crazy"
}
return "unknown"
}

// Set value from option binding.
func (vl *VerbLevel) Set(value string) error {
// int: level value.
if iv, err := strconv.Atoi(value); err == nil {
if iv > int(VerbCrazy) {
*vl = VerbCrazy
} else if iv < 0 { // fallback to default level.
*vl = DefaultVerb
} else { // 0 - 5
*vl = VerbLevel(iv)
}

return nil
}

// string: level name.
*vl = name2verbLevel(value)
return nil
}

0 comments on commit 41a4d39

Please sign in to comment.