diff --git a/_examples/032-jsoncfg/main.go b/_examples/032-jsoncfg/main.go new file mode 100644 index 0000000..a4bbe97 --- /dev/null +++ b/_examples/032-jsoncfg/main.go @@ -0,0 +1,29 @@ +package main + +import ( + "os" + + "github.com/mkideal/cli" +) + +type argT struct { + cli.Helper + Self *argT `json:"-" cli:"c,config" usage:"parse json config from file" parser:"jsoncfg" dft:"test.json"` + A string + B int + C bool +} + +func newArgT() *argT { + var argv = new(argT) + argv.Self = argv + return argv +} + +func main() { + os.Exit(cli.Run(newArgT(), func(ctx *cli.Context) error { + argv := ctx.Argv().(*argT) + ctx.JSONIndentln(argv, "", " ") + return nil + })) +} diff --git a/_examples/032-jsoncfg/test.json b/_examples/032-jsoncfg/test.json new file mode 100644 index 0000000..05e4862 --- /dev/null +++ b/_examples/032-jsoncfg/test.json @@ -0,0 +1,5 @@ +{ + "A": "a string", + "B": 12, + "C": true +} diff --git a/builtin.go b/builtin.go index 68d0fa5..b57f810 100644 --- a/builtin.go +++ b/builtin.go @@ -14,6 +14,16 @@ func (h Helper) AutoHelp() bool { return h.Help } +// Helper2 is builtin Help flag +type Helper2 struct { + Help bool `cli:"!h,help" usage:"Display help information" json:"-"` +} + +// AutoHelp implements AutoHelper interface +func (h Helper2) AutoHelp() bool { + return h.Help +} + // Deprecated: Addr is builtin host,port flag type Addr struct { Host string `cli:"host" usage:"specify host" dft:"0.0.0.0"` diff --git a/cliutil.go b/cliutil.go index 3392f00..caa77c5 100644 --- a/cliutil.go +++ b/cliutil.go @@ -7,6 +7,7 @@ import ( "io" "os" "os/exec" + "path/filepath" "strings" "github.com/labstack/gommon/color" @@ -93,7 +94,7 @@ func ReadJSON(r io.Reader, argv interface{}) error { return json.NewDecoder(r).Decode(argv) } -// ReadJSONFromFile is similar to ReadJSONFromFile, but read from file +// ReadJSONFromFile is similar to ReadJSON, but read from file func ReadJSONFromFile(filename string, argv interface{}) error { file, err := os.Open(filename) if err == nil { @@ -102,3 +103,24 @@ func ReadJSONFromFile(filename string, argv interface{}) error { } return err } + +// ReadJSONConfigFromFile is similar to ReadJSONFromFile, but allows reading file from where the executable file resides as well +func ReadJSONConfigFromFile(filename string, argv interface{}) error { + file, err := os.Open(filename) + if err == nil { + defer file.Close() + err = ReadJSON(file, argv) + } else { + exe, e := os.Executable() + if e != nil { + return e + } + // allow self-config .json files to go with the executable file, #40 + file, err = os.Open(filepath.Dir(exe) + string(filepath.Separator) + filename) + if err == nil { + defer file.Close() + err = ReadJSON(file, argv) + } + } + return err +} diff --git a/parser.go b/parser.go index 8557ffd..c6b78ea 100644 --- a/parser.go +++ b/parser.go @@ -26,6 +26,7 @@ func RegisterFlagParser(name string, creator FlagParserCreator) { func init() { RegisterFlagParser("json", newJSONParser) RegisterFlagParser("jsonfile", newJSONFileParser) + RegisterFlagParser("jsoncfg", newJSONConfigFileParser) RegisterFlagParser("url", newURLParser) } @@ -55,6 +56,19 @@ func (p JSONFileParser) Parse(s string) error { return ReadJSONFromFile(s, p.ptr) } +// JSON config file parser +type JSONConfigFileParser struct { + ptr interface{} +} + +func newJSONConfigFileParser(ptr interface{}) FlagParser { + return &JSONConfigFileParser{ptr} +} + +func (p JSONConfigFileParser) Parse(s string) error { + return ReadJSONConfigFromFile(s, p.ptr) +} + // URL parser type URLParser struct { ptr *url.URL