diff --git a/internal/utils/utils_str.go b/internal/utils/utils_str.go index 73e2eac39..f5891b03d 100644 --- a/internal/utils/utils_str.go +++ b/internal/utils/utils_str.go @@ -7,6 +7,7 @@ package utils import ( + "bytes" "strings" ) @@ -141,3 +142,21 @@ func FormatCmdKey(s string) string { func FormatEnvKey(s string) string { return strings.ToUpper(strings.Replace(s, ".", "_", -1)) } + +// StripSlashes un-quotes a quoted string by AddSlashes. +func StripSlashes(str string) string { + var buf bytes.Buffer + l, skip := len(str), false + for i, char := range str { + if skip { + skip = false + } else if char == '\\' { + if i+1 < l && str[i+1] == '\\' { + skip = true + } + continue + } + buf.WriteRune(char) + } + return buf.String() +} diff --git a/os/gcfg/gcfg.go b/os/gcfg/gcfg.go index 4bf0f5f68..0e080afab 100644 --- a/os/gcfg/gcfg.go +++ b/os/gcfg/gcfg.go @@ -13,9 +13,9 @@ import ( "github.com/gogf/gf/v2/container/gmap" "github.com/gogf/gf/v2/container/gvar" + "github.com/gogf/gf/v2/internal/command" "github.com/gogf/gf/v2/internal/intlog" "github.com/gogf/gf/v2/internal/utils" - "github.com/gogf/gf/v2/os/gcmd" "github.com/gogf/gf/v2/os/genv" ) @@ -166,8 +166,8 @@ func (c *Config) GetWithCmd(ctx context.Context, pattern string, def ...interfac return nil, err } if value == nil { - if v := gcmd.GetOpt(utils.FormatCmdKey(pattern)); v != nil { - return v, nil + if v := command.GetOpt(utils.FormatCmdKey(pattern)); v != "" { + return gvar.New(v), nil } if len(def) > 0 { return gvar.New(def[0]), nil diff --git a/os/gcfg/gcfg_adapter_file.go b/os/gcfg/gcfg_adapter_file.go index fa546cf64..ce1d297c4 100644 --- a/os/gcfg/gcfg_adapter_file.go +++ b/os/gcfg/gcfg_adapter_file.go @@ -15,8 +15,8 @@ import ( "github.com/gogf/gf/v2/encoding/gjson" "github.com/gogf/gf/v2/errors/gcode" "github.com/gogf/gf/v2/errors/gerror" + "github.com/gogf/gf/v2/internal/command" "github.com/gogf/gf/v2/internal/intlog" - "github.com/gogf/gf/v2/os/gcmd" "github.com/gogf/gf/v2/os/gfile" "github.com/gogf/gf/v2/os/gfsnotify" "github.com/gogf/gf/v2/os/gres" @@ -62,7 +62,7 @@ func NewAdapterFile(file ...string) (*AdapterFile, error) { name = file[0] } else { // Custom default configuration file name from command line or environment. - if customFile := gcmd.GetOptWithEnv(commandEnvKeyForFile).String(); customFile != "" { + if customFile := command.GetOptWithEnv(commandEnvKeyForFile); customFile != "" { name = customFile } } @@ -72,7 +72,7 @@ func NewAdapterFile(file ...string) (*AdapterFile, error) { jsonMap: gmap.NewStrAnyMap(true), } // Customized dir path from env/cmd. - if customPath := gcmd.GetOptWithEnv(commandEnvKeyForPath).String(); customPath != "" { + if customPath := command.GetOptWithEnv(commandEnvKeyForPath); customPath != "" { if gfile.Exists(customPath) { if err = c.SetPath(customPath); err != nil { return nil, err diff --git a/os/gcmd/gcmd.go b/os/gcmd/gcmd.go index 08f55f44d..bac250a06 100644 --- a/os/gcmd/gcmd.go +++ b/os/gcmd/gcmd.go @@ -18,7 +18,8 @@ import ( ) const ( - CtxKeyParser gctx.StrKey = `GoFrameCommandParser` + CtxKeyParser gctx.StrKey = `CtxKeyParser` + CtxKeyCommand gctx.StrKey = `CtxKeyCommand` ) const ( diff --git a/os/gcmd/gcmd_command.go b/os/gcmd/gcmd_command.go index b946f9828..259a1058d 100644 --- a/os/gcmd/gcmd_command.go +++ b/os/gcmd/gcmd_command.go @@ -28,8 +28,9 @@ type Command struct { Additional string // Additional info about this command, which will be appended to the end of help info. NeedArgs bool // NeedArgs specifies this command needs arguments. Strict bool // Strict parsing options, which means it returns error if invalid option given. + Config string // Config node name, which also retrieves the values from config component along with command line. parent *Command // Parent command for internal usage. - commands []Command // Sub commands of this command. + commands []*Command // Sub commands of this command. } // Function is a custom command callback function that is bound to a certain argument. @@ -57,8 +58,18 @@ var ( } ) +// CommandFromCtx retrieves and returns Command from context. +func CommandFromCtx(ctx context.Context) *Command { + if v := ctx.Value(CtxKeyCommand); v != nil { + if p, ok := v.(*Command); ok { + return p + } + } + return nil +} + // AddCommand adds one or more sub-commands to current command. -func (c *Command) AddCommand(commands ...Command) error { +func (c *Command) AddCommand(commands ...*Command) error { for _, cmd := range commands { cmd.Name = gstr.Trim(cmd.Name) if cmd.Name == "" { @@ -73,7 +84,7 @@ func (c *Command) AddCommand(commands ...Command) error { // AddObject adds one or more sub-commands to current command using struct object. func (c *Command) AddObject(objects ...interface{}) error { var ( - commands []Command + commands []*Command ) for _, object := range objects { rootCommand, err := NewFromObject(object) diff --git a/os/gcmd/gcmd_command_help.go b/os/gcmd/gcmd_command_help.go index 29c7facf4..d1a983d97 100644 --- a/os/gcmd/gcmd_command_help.go +++ b/os/gcmd/gcmd_command_help.go @@ -110,16 +110,22 @@ func (c *Command) Print() { // Example. if c.Examples != "" { buffer.WriteString("EXAMPLE\n") - buffer.WriteString(prefix) - buffer.WriteString(gstr.WordWrap(gstr.Trim(c.Examples), maxLineChars, "\n"+prefix)) + for _, line := range gstr.SplitAndTrim(c.Examples, "\n") { + buffer.WriteString(prefix) + buffer.WriteString(gstr.WordWrap(gstr.Trim(line), maxLineChars, "\n"+prefix)) + buffer.WriteString("\n") + } buffer.WriteString("\n") } // Description. if c.Description != "" { buffer.WriteString("DESCRIPTION\n") - buffer.WriteString(prefix) - buffer.WriteString(gstr.WordWrap(gstr.Trim(c.Description), maxLineChars, "\n"+prefix)) + for _, line := range gstr.SplitAndTrim(c.Description, "\n") { + buffer.WriteString(prefix) + buffer.WriteString(gstr.WordWrap(gstr.Trim(line), maxLineChars, "\n"+prefix)) + buffer.WriteString("\n") + } buffer.WriteString("\n") } diff --git a/os/gcmd/gcmd_command_object.go b/os/gcmd/gcmd_command_object.go index eaadf570b..af4282b21 100644 --- a/os/gcmd/gcmd_command_object.go +++ b/os/gcmd/gcmd_command_object.go @@ -37,7 +37,7 @@ var ( ) // NewFromObject creates and returns a root command object using given object. -func NewFromObject(object interface{}) (rootCmd Command, err error) { +func NewFromObject(object interface{}) (rootCmd *Command, err error) { originValueAndKind := utils.OriginValueAndKind(object) if originValueAndKind.OriginKind != reflect.Struct { err = gerror.Newf( @@ -55,12 +55,12 @@ func NewFromObject(object interface{}) (rootCmd Command, err error) { var ( nameSet = gset.NewStrSet() rootCommandName = gmeta.Get(object, tagNameRoot).String() - subCommands []Command + subCommands []*Command ) for i := 0; i < originValueAndKind.InputValue.NumMethod(); i++ { var ( method = originValueAndKind.InputValue.Method(i) - methodCommand Command + methodCommand *Command ) methodCommand, err = newCommandFromMethod(object, method) if err != nil { @@ -93,7 +93,7 @@ func NewFromObject(object interface{}) (rootCmd Command, err error) { return } -func newCommandFromObjectMeta(object interface{}) (command Command, err error) { +func newCommandFromObjectMeta(object interface{}) (command *Command, err error) { var ( metaData = gmeta.Data(object) ) @@ -130,7 +130,7 @@ func newCommandFromObjectMeta(object interface{}) (command Command, err error) { return } -func newCommandFromMethod(object interface{}, method reflect.Value) (command Command, err error) { +func newCommandFromMethod(object interface{}, method reflect.Value) (command *Command, err error) { var ( reflectType = method.Type() ) diff --git a/os/gcmd/gcmd_command_run.go b/os/gcmd/gcmd_command_run.go index 7a700ebe6..8cc3bbb2d 100644 --- a/os/gcmd/gcmd_command_run.go +++ b/os/gcmd/gcmd_command_run.go @@ -12,7 +12,10 @@ import ( "fmt" "os" + "github.com/gogf/gf/v2/os/gcfg" "github.com/gogf/gf/v2/text/gstr" + "github.com/gogf/gf/v2/util/gconv" + "github.com/gogf/gf/v2/util/gutil" ) // Run calls custom function that bound to this command. @@ -53,6 +56,8 @@ func (c *Command) RunWithValue(ctx context.Context) (value interface{}, err erro } func (c *Command) doRun(ctx context.Context, parser *Parser) (value interface{}, err error) { + ctx = context.WithValue(ctx, CtxKeyCommand, c) + // Check built-in help command. if parser.ContainsOpt(helpOptionName) || parser.ContainsOpt(helpOptionNameShort) { if c.HelpFunc != nil { @@ -84,7 +89,6 @@ func (c *Command) reParse(ctx context.Context, parser *Parser) (*Parser, error) if len(c.Options) == 0 { return parser, nil } - var ( optionKey string supportedOptions = make(map[string]bool) @@ -97,7 +101,30 @@ func (c *Command) reParse(ctx context.Context, parser *Parser) (*Parser, error) } supportedOptions[optionKey] = !option.Orphan } - return Parse(supportedOptions, c.Strict) + parser, err := Parse(supportedOptions, c.Strict) + if err != nil { + return nil, err + } + // Retrieve option values from config component if it has "config" tag. + if c.Config != "" && gcfg.Instance().Available(ctx) { + value, err := gcfg.Instance().Get(ctx, c.Config) + if err != nil { + return nil, err + } + configMap := value.Map() + for optionName, _ := range parser.passedOptions { + // The command line has the high priority. + if parser.ContainsOpt(optionName) { + continue + } + // Merge the config value into parser. + foundKey, foundValue := gutil.MapPossibleItemByKey(configMap, optionName) + if foundKey != "" { + parser.parsedOptions[optionName] = gconv.String(foundValue) + } + } + } + return parser, nil } // searchCommand recursively searches the command according given arguments. @@ -109,13 +136,13 @@ func (c *Command) searchCommand(args []string) *Command { // If this command needs argument, // it then gives all its left arguments to it. if cmd.NeedArgs { - return &cmd + return cmd } // Recursively searching the command. if cmd.Name == args[0] { leftArgs := args[1:] if len(leftArgs) == 0 { - return &cmd + return cmd } return cmd.searchCommand(leftArgs) } diff --git a/os/gcmd/gcmd_z_unit_feature_object_test.go b/os/gcmd/gcmd_z_unit_feature_object1_test.go similarity index 100% rename from os/gcmd/gcmd_z_unit_feature_object_test.go rename to os/gcmd/gcmd_z_unit_feature_object1_test.go diff --git a/os/gcmd/gcmd_z_unit_feature_object2_test.go b/os/gcmd/gcmd_z_unit_feature_object2_test.go new file mode 100644 index 000000000..2d16b6f09 --- /dev/null +++ b/os/gcmd/gcmd_z_unit_feature_object2_test.go @@ -0,0 +1,135 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +// go test *.go -bench=".*" -benchmem + +package gcmd_test + +import ( + "context" + "os" + "testing" + + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gcmd" + "github.com/gogf/gf/v2/os/gctx" + "github.com/gogf/gf/v2/test/gtest" + "github.com/gogf/gf/v2/util/gtag" +) + +type commandBuild struct { + g.Meta `name:"build" root:"build" args:"true" brief:"{commandBuildBrief}" dc:"{commandBuildDc}" eg:"{commandBuildEg}" ad:"{commandBuildAd}"` + nodeNameInConfigFile string // nodeNameInConfigFile is the node name for compiler configurations in configuration file. + packedGoFileName string // packedGoFileName specifies the file name for packing common folders into one single go file. +} + +const ( + commandBuildBrief = `cross-building go project for lots of platforms` + commandBuildEg = ` +gf build main.go +gf build main.go --pack public,template +gf build main.go --cgo +gf build main.go -m none +gf build main.go -n my-app -a all -s all +gf build main.go -n my-app -a amd64,386 -s linux -p . +gf build main.go -n my-app -v 1.0 -a amd64,386 -s linux,windows,darwin -p ./docker/bin +` + commandBuildDc = ` +The "build" command is most commonly used command, which is designed as a powerful wrapper for +"go build" command for convenience cross-compiling usage. +It provides much more features for building binary: +1. Cross-Compiling for many platforms and architectures. +2. Configuration file support for compiling. +3. Build-In Variables. +` + commandBuildAd = ` +PLATFORMS + darwin amd64,arm64 + freebsd 386,amd64,arm + linux 386,amd64,arm,arm64,ppc64,ppc64le,mips,mipsle,mips64,mips64le + netbsd 386,amd64,arm + openbsd 386,amd64,arm + windows 386,amd64 +` + // https://golang.google.cn/doc/install/source + commandBuildPlatforms = ` + darwin amd64 + darwin arm64 + ios amd64 + ios arm64 + freebsd 386 + freebsd amd64 + freebsd arm + linux 386 + linux amd64 + linux arm + linux arm64 + linux ppc64 + linux ppc64le + linux mips + linux mipsle + linux mips64 + linux mips64le + netbsd 386 + netbsd amd64 + netbsd arm + openbsd 386 + openbsd amd64 + openbsd arm + windows 386 + windows amd64 + android arm + dragonfly amd64 + plan9 386 + plan9 amd64 + solaris amd64 +` +) + +func init() { + gtag.Sets(map[string]string{ + `commandBuildBrief`: commandBuildBrief, + `commandBuildDc`: commandBuildDc, + `commandBuildEg`: commandBuildEg, + `commandBuildAd`: commandBuildAd, + }) +} + +type commandBuildInput struct { + g.Meta `name:"build" config:"gfcli.build"` + Name string `short:"n" name:"name" brief:"output binary name"` + Version string `short:"v" name:"version" brief:"output binary version"` + Arch string `short:"a" name:"arch" brief:"output binary architecture, multiple arch separated with ','"` + System string `short:"s" name:"system" brief:"output binary system, multiple os separated with ','"` + Output string `short:"o" name:"output" brief:"output binary path, used when building single binary file"` + Path string `short:"p" name:"path" brief:"output binary directory path, default is './bin'" d:"./bin"` + Extra string `short:"e" name:"extra" brief:"extra custom \"go build\" options"` + Mod string `short:"m" name:"mod" brief:"like \"-mod\" option of \"go build\", use \"-m none\" to disable go module"` + Cgo bool `short:"c" name:"cgo" brief:"enable or disable cgo feature, it's disabled in default" orphan:"true"` + Pack string `name:"pack" brief:"pack specified folder into temporary go file before building and removes it after built"` +} +type commandBuildOutput struct{} + +func (c commandBuild) Index(ctx context.Context, in commandBuildInput) (out *commandBuildOutput, err error) { + return +} + +func TestNewFromObject(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + var ( + ctx = gctx.New() + ) + cmd, err := gcmd.NewFromObject(commandBuild{ + nodeNameInConfigFile: "gfcli.build", + packedGoFileName: "build_pack_data.go", + }) + t.AssertNil(err) + + os.Args = []string{"build", "-h"} + err = cmd.Run(ctx) + t.AssertNil(err) + }) +} diff --git a/os/gcmd/gcmd_z_unit_test.go b/os/gcmd/gcmd_z_unit_test.go index e8245cb79..e3589c764 100644 --- a/os/gcmd/gcmd_z_unit_test.go +++ b/os/gcmd/gcmd_z_unit_test.go @@ -81,7 +81,7 @@ func Test_Command(t *testing.T) { Name: "gf", } // env - commandEnv := gcmd.Command{ + commandEnv := &gcmd.Command{ Name: "env", Func: func(ctx context.Context, parser *gcmd.Parser) error { fmt.Println("env") @@ -89,7 +89,7 @@ func Test_Command(t *testing.T) { }, } // test - commandTest := gcmd.Command{ + commandTest := &gcmd.Command{ Name: "test", Brief: "test brief", Description: "test description current Golang environment variables", @@ -145,7 +145,7 @@ func Test_Command_Print(t *testing.T) { Use 'gf help COMMAND' or 'gf COMMAND -h' for detail about a command, which has '...' in the tail of their comments.`, } // env - commandEnv := gcmd.Command{ + commandEnv := &gcmd.Command{ Name: "env", Brief: "show current Golang environment variables, long brief.long brief.long brief.long brief.long brief.long brief.long brief.long brief.", Description: "show current Golang environment variables", @@ -157,7 +157,7 @@ Use 'gf help COMMAND' or 'gf COMMAND -h' for detail about a command, which has ' g.Log().Fatal(ctx, err) } // get - commandGet := gcmd.Command{ + commandGet := &gcmd.Command{ Name: "get", Brief: "install or update GF to system in default...", Description: "show current Golang environment variables", @@ -212,7 +212,7 @@ gf build main.go -n my-app -v 1.0 -a amd64,386 -s linux,windows,darwin -p ./dock return nil }, } - if err = c.AddCommand(commandBuild); err != nil { + if err = c.AddCommand(&commandBuild); err != nil { g.Log().Fatal(ctx, err) } c.Run(ctx) diff --git a/os/genv/genv.go b/os/genv/genv.go index 0cc9e57c3..573a714c9 100644 --- a/os/genv/genv.go +++ b/os/genv/genv.go @@ -12,8 +12,8 @@ import ( "strings" "github.com/gogf/gf/v2/container/gvar" + "github.com/gogf/gf/v2/internal/command" "github.com/gogf/gf/v2/internal/utils" - "github.com/gogf/gf/v2/os/gcmd" ) // All returns a copy of strings representing the environment, @@ -94,8 +94,8 @@ func GetWithCmd(key string, def ...interface{}) *gvar.Var { return gvar.New(v) } cmdKey := utils.FormatCmdKey(key) - if v := gcmd.GetOpt(cmdKey); !v.IsEmpty() { - return v + if v := command.GetOpt(cmdKey); v != "" { + return gvar.New(v) } if len(def) > 0 { return gvar.New(def[0]) diff --git a/os/genv/genv_must.go b/os/genv/genv_must.go new file mode 100644 index 000000000..3ee5539f2 --- /dev/null +++ b/os/genv/genv_must.go @@ -0,0 +1,21 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package genv + +// MustSet performs as Set, but it panics if any error occurs. +func MustSet(key, value string) { + if err := Set(key, value); err != nil { + panic(err) + } +} + +// MustRemove performs as Remove, but it panics if any error occurs. +func MustRemove(key ...string) { + if err := Remove(key...); err != nil { + panic(err) + } +} diff --git a/os/gproc/gproc.go b/os/gproc/gproc.go index 328763dd6..ca2f777ab 100644 --- a/os/gproc/gproc.go +++ b/os/gproc/gproc.go @@ -84,7 +84,10 @@ func Uptime() time.Duration { // The command `cmd` reads the input parameters from input pipe `in`, and writes its output automatically // to output pipe `out`. func Shell(cmd string, out io.Writer, in io.Reader) error { - p := NewProcess(getShell(), append([]string{getShellOption()}, parseCommand(cmd)...)) + p := NewProcess( + getShell(), + append([]string{getShellOption()}, parseCommand(cmd)...), + ) p.Stdin = in p.Stdout = out return p.Run() @@ -92,18 +95,26 @@ func Shell(cmd string, out io.Writer, in io.Reader) error { // ShellRun executes given command `cmd` synchronously and outputs the command result to the stdout. func ShellRun(cmd string) error { - p := NewProcess(getShell(), append([]string{getShellOption()}, parseCommand(cmd)...)) + p := NewProcess( + getShell(), + append([]string{getShellOption()}, parseCommand(cmd)...), + ) return p.Run() } // ShellExec executes given command `cmd` synchronously and returns the command result. func ShellExec(cmd string, environment ...[]string) (string, error) { - buf := bytes.NewBuffer(nil) - p := NewProcess(getShell(), append([]string{getShellOption()}, parseCommand(cmd)...), environment...) + var ( + buf = bytes.NewBuffer(nil) + p = NewProcess( + getShell(), + append([]string{getShellOption()}, parseCommand(cmd)...), + environment..., + ) + ) p.Stdout = buf p.Stderr = buf - err := p.Run() - return buf.String(), err + return buf.String(), p.Run() } // parseCommand parses command `cmd` into slice arguments. @@ -147,7 +158,7 @@ func parseCommand(cmd string) (args []string) { return } -// getShell returns the shell command depending on current working operation system. +// getShell returns the shell command depending on current working operating system. // It returns "cmd.exe" for windows, and "bash" or "sh" for others. func getShell() string { switch runtime.GOOS { @@ -183,7 +194,7 @@ func getShellOption() string { // SearchBinary searches the binary `file` in current working folder and PATH environment. func SearchBinary(file string) string { - // Check if it's absolute path of exists at current working directory. + // Check if it is absolute path of exists at current working directory. if gfile.Exists(file) { return file } @@ -204,6 +215,7 @@ func SearchBinaryPath(file string) string { if gfile.Ext(file) != ".exe" { file += ".exe" } + default: array = gstr.SplitAndTrim(genv.Get("PATH").String(), ":") } diff --git a/os/gproc/gproc_must.go b/os/gproc/gproc_must.go new file mode 100644 index 000000000..5e7584f01 --- /dev/null +++ b/os/gproc/gproc_must.go @@ -0,0 +1,34 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gproc + +import ( + "io" +) + +// MustShell performs as Shell, but it panics if any error occurs. +func MustShell(cmd string, out io.Writer, in io.Reader) { + if err := Shell(cmd, out, in); err != nil { + panic(err) + } +} + +// MustShellRun performs as ShellRun, but it panics if any error occurs. +func MustShellRun(cmd string) { + if err := ShellRun(cmd); err != nil { + panic(err) + } +} + +// MustShellExec performs as ShellExec, but it panics if any error occurs. +func MustShellExec(cmd string, environment ...[]string) string { + result, err := ShellExec(cmd, environment...) + if err != nil { + panic(err) + } + return result +} diff --git a/os/gstructs/gstructs_field.go b/os/gstructs/gstructs_field.go index 359a3a590..8bc0aa234 100644 --- a/os/gstructs/gstructs_field.go +++ b/os/gstructs/gstructs_field.go @@ -8,9 +8,9 @@ package gstructs import ( "reflect" - "regexp" "strings" + "github.com/gogf/gf/v2/internal/utils" "github.com/gogf/gf/v2/util/gtag" ) @@ -18,10 +18,6 @@ const ( jsonTagName = `json` ) -var ( - tagMapRegex = regexp.MustCompile(`([\w\-]+):"(.+?)"`) -) - // Tag returns the value associated with key in the tag string. If there is no // such key in the tag, Tag returns the empty string. func (f *Field) Tag(key string) string { @@ -67,13 +63,10 @@ func (f *Field) TagStr() string { // TagMap returns all the tag of the field along with its value string as map. func (f *Field) TagMap() map[string]string { var ( - data = map[string]string{} - match = tagMapRegex.FindAllStringSubmatch(f.TagStr(), -1) + data = ParseTag(f.TagStr()) ) - for _, m := range match { - if len(m) == 3 { - data[m[1]] = gtag.Parse(m[2]) - } + for k, v := range data { + data[k] = utils.StripSlashes(gtag.Parse(v)) } return data } diff --git a/protocol/goai/goai.go b/protocol/goai/goai.go index 58158e462..c8cbb9148 100644 --- a/protocol/goai/goai.go +++ b/protocol/goai/goai.go @@ -96,6 +96,8 @@ var ( "sm": "summary", "des": "description", "dc": "description", + "eg": "example", + "egs": "examples", } ) diff --git a/protocol/goai/goai_path.go b/protocol/goai/goai_path.go index 92fb81572..566c51042 100644 --- a/protocol/goai/goai_path.go +++ b/protocol/goai/goai_path.go @@ -34,7 +34,7 @@ type Path struct { Parameters Parameters `json:"parameters,omitempty" yaml:"parameters,omitempty"` } -// Paths is specified by OpenAPI/Swagger standard version 3.0. +// Paths are specified by OpenAPI/Swagger standard version 3.0. type Paths map[string]Path const ( diff --git a/text/gstr/gstr.go b/text/gstr/gstr.go index e783a9a0b..277e5ff85 100644 --- a/text/gstr/gstr.go +++ b/text/gstr/gstr.go @@ -442,20 +442,7 @@ func AddSlashes(str string) string { // StripSlashes un-quotes a quoted string by AddSlashes. func StripSlashes(str string) string { - var buf bytes.Buffer - l, skip := len(str), false - for i, char := range str { - if skip { - skip = false - } else if char == '\\' { - if i+1 < l && str[i+1] == '\\' { - skip = true - } - continue - } - buf.WriteRune(char) - } - return buf.String() + return utils.StripSlashes(str) } // QuoteMeta returns a version of str with a backslash character (\) diff --git a/util/gmode/gmode.go b/util/gmode/gmode.go index 71c2152ea..624bb91b1 100644 --- a/util/gmode/gmode.go +++ b/util/gmode/gmode.go @@ -11,7 +11,7 @@ package gmode import ( "github.com/gogf/gf/v2/debug/gdebug" - "github.com/gogf/gf/v2/os/gcmd" + "github.com/gogf/gf/v2/internal/command" "github.com/gogf/gf/v2/os/gfile" ) @@ -58,7 +58,7 @@ func SetProduct() { func Mode() string { // If current mode is not set, do this auto check. if currentMode == NOT_SET { - if v := gcmd.GetOptWithEnv(commandEnvKey).String(); v != "" { + if v := command.GetOptWithEnv(commandEnvKey); v != "" { // Mode configured from command argument of environment. currentMode = v } else {