commit 2dc87fb620b38fc93f7bff16ee47e3ec1f6321c5
parent 837a255e5a66252a880942ba5d86b9989dfa175a
Author: francoispqt <francois@parquet.ninja>
Date: Sun, 24 Jun 2018 20:06:43 +0800
improve args parsing and add documentation
Diffstat:
M | gojay/README.md | | | 32 | ++++++++++++++++++++------------ |
M | gojay/main.go | | | 93 | ++++++++++++++++++++++++++++++++++++++++++------------------------------------- |
D | gojay/tests/json.go | | | 284 | ------------------------------------------------------------------------------- |
3 files changed, 69 insertions(+), 340 deletions(-)
diff --git a/gojay/README.md b/gojay/README.md
@@ -10,30 +10,38 @@ go install github.com/francoispqt/gojay/gojay
## Generate code
-- for specific types in a go package, to stdout:
-```sh
-gojay -s github.com/francoispqt/gojay/gojay/tests -t A,B,StrSlice
-```
-or simply
+### Basic command
+
+The basic command is strait forward and easy to use:
```sh
-gojay github.com/francoispqt/gojay/gojay/tests A,B,StrSlice
+gojay github.com/some/package TypeA,TypeB,TypeC output.go
```
+If you just want to the output to stdout, omit the third parameter.
-- for specific types in a go package, write to a file:
+### Using flags
+
+- p package to parse, relative path to $GOPATH/src
+- s file/dir to path, can be a relative or absolute path
+- t types to generate (comma separated)
+- o output file (relative or absolute path)
+
+Examples:
+- Specific types in a go package, to stdout:
```sh
-gojay -s github.com/francoispqt/gojay/gojay/tests -t A,B,StrSlice -o output.go
+gojay -p github.com/francoispqt/gojay/gojay/tests -t A,B,StrSlice
```
-- for all types annotated by a //gojay:json (don't specify any type) in a package:
+- Specific types in a go package, write to a file:
```sh
-gojay -s github.com/francoispqt/gojay/gojay/tests -o output.go
+gojay -p github.com/francoispqt/gojay/gojay/tests -t A,B,StrSlice -o output.go
```
-- for types annotated in a specific file
+- Specific types in a go file, to stdout:
```sh
-gojay -s path/to/gofile.go -o output.go
+gojay -s somegofile.go -t SomeType
```
+
## Gojay tags
You can add tags to your structs to control:
diff --git a/gojay/main.go b/gojay/main.go
@@ -3,6 +3,7 @@
package main
import (
+ "errors"
"flag"
"io/ioutil"
"log"
@@ -12,9 +13,16 @@ import (
)
var dst = flag.String("o", "", "destination file to output generated implementations")
-var src = flag.String("s", "", "source dir or file")
+var src = flag.String("s", "", "source dir or file (absolute or relative path)")
+var pkg = flag.String("p", "", "go package")
var types = flag.String("t", "", "types to generate")
+var ErrNoPathProvided = errors.New("You must provide a path or a package name")
+
+type stringWriter interface {
+ WriteString(string) (int, error)
+}
+
func hasAnnotation(fP string) bool {
b, err := ioutil.ReadFile(fP)
if err != nil {
@@ -24,62 +32,69 @@ func hasAnnotation(fP string) bool {
}
func resolvePath(p string) (string, error) {
- if _, err := os.Stat(p); err != nil {
- if os.IsNotExist(err) {
- return filepath.Abs(os.Getenv("GOPATH") + "/src/" + *src)
- } else {
- return "", err
- }
+ if fullPath, err := filepath.Abs(p); err != nil {
+ return "", err
+ } else if _, err := os.Stat(fullPath); err != nil {
+ return "", err
+ } else {
+ return fullPath, nil
}
- return p, nil
}
// getPath returns either the path given as argument or current working directory
func getPath() (string, error) {
- var err error
- var p string
- if *src != "" { // if src is present parse from src
- p, err = filepath.Abs(*src)
- if err != nil {
- return "", err
- }
- return resolvePath(p)
+ // if pkg is set, resolve pkg path
+ if *pkg != "" {
+ return resolvePath(os.Getenv("GOPATH") + "/src/" + *pkg)
+ } else if *src != "" { // if src is present parse from src
+ return resolvePath(*src)
} else if len(os.Args) > 1 { // else if there is a command line arg, use it as path to a package $GOPATH/src/os.Args[1]
- p, err = filepath.Abs(os.Args[1])
- if err != nil {
- return "", err
- }
- return resolvePath(p)
- } else {
- p, err = os.Getwd()
- if err != nil {
- return "", err
- }
+ return resolvePath(os.Getenv("GOPATH") + "/src/" + os.Args[1])
}
- return p, nil
+ return "", ErrNoPathProvided
}
+// getTypes returns the types to be parsed
func getTypes() (t []string) {
if *types != "" { // if src is present parse from src
return strings.Split(*types, ",")
- } else if *src == "" && *dst == "" && len(os.Args) > 2 { // else if there is a command line arg, use it as path to a package $GOPATH/src/os.Args[1]
+ } else if *src == "." && *dst == "" && len(os.Args) > 2 { // else if there is a command line arg, use it as path to a package $GOPATH/src/os.Args[1]
return strings.Split(os.Args[2], ",")
}
return t
}
-func parseArgs() (p string, t []string, err error) {
+// getOutput returns the output
+func getOutput() (stringWriter, error) {
+ if *dst != "" {
+ p, err := filepath.Abs(*dst)
+ if err != nil {
+ return nil, err
+ }
+ return os.OpenFile(p, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600)
+ } else if len(os.Args) > 3 && *src == "" && *types == "" {
+ p, err := filepath.Abs(os.Args[3])
+ if err != nil {
+ return nil, err
+ }
+ return os.OpenFile(p, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600)
+ }
+ return os.Stdout, nil
+}
+
+func parseArgs() (p string, t []string, o stringWriter, err error) {
flag.Parse()
p, err = getPath()
if err != nil {
- return p, t, err
+ return p, t, o, err
}
t = getTypes()
- return p, t, err
+ o, err = getOutput()
+ return p, t, o, err
}
func main() {
- p, t, err := parseArgs()
+ p, t, o, err := parseArgs()
if err != nil {
log.Fatal(err)
}
@@ -96,16 +111,6 @@ func main() {
log.Fatal(err)
return
}
- // if has dst file, write to file
- if *dst != "" {
- f, err := os.OpenFile(*dst, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600)
- if err != nil {
- log.Fatal(err)
- return
- }
- f.WriteString(g.b.String())
- return
- }
- // else just print to stdout
- os.Stdout.WriteString(g.b.String())
+ // write content to output
+ o.WriteString(g.b.String())
}
diff --git a/gojay/tests/json.go b/gojay/tests/json.go
@@ -1,284 +0,0 @@
-// Code generated by GoJay. DO NOT EDIT.
-
-package tests
-
-import "github.com/francoispqt/gojay"
-
-// UnmarshalJSONArray implements gojay's UnmarshalerJSONArray
-func (v *StrSlice) UnmarshalJSONArray(dec *gojay.Decoder) error {
- var str string
- if err := dec.String(&str); err != nil {
- return err
- }
- *v = append(*v, str)
- return nil
-}
-
-// MarshalJSONArray implements gojay's MarshalerJSONArray
-func (v *StrSlice) MarshalJSONArray(enc *gojay.Encoder) {
- for _, s := range *v {
- enc.String(s)
- }
-}
-
-// IsNil implements gojay's MarshalerJSONArray
-func (v *StrSlice) IsNil() bool {
- return *v == nil || len(*v) == 0
-}
-
-// UnmarshalJSONArray implements gojay's UnmarshalerJSONArray
-func (v *IntSlice) UnmarshalJSONArray(dec *gojay.Decoder) error {
- var i int
- if err := dec.Int(&i); err != nil {
- return err
- }
- *v = append(*v, i)
- return nil
-}
-
-// MarshalJSONArray implements gojay's MarshalerJSONArray
-func (v *IntSlice) MarshalJSONArray(enc *gojay.Encoder) {
- for _, s := range *v {
- enc.Int(s)
- }
-}
-
-// IsNil implements gojay's MarshalerJSONArray
-func (v *IntSlice) IsNil() bool {
- return *v == nil || len(*v) == 0
-}
-
-// UnmarshalJSONArray implements gojay's UnmarshalerJSONArray
-func (v *BoolSlice) UnmarshalJSONArray(dec *gojay.Decoder) error {
- var b bool
- if err := dec.Bool(&b); err != nil {
- return err
- }
- *v = append(*v, b)
- return nil
-}
-
-// MarshalJSONArray implements gojay's MarshalerJSONArray
-func (v *BoolSlice) MarshalJSONArray(enc *gojay.Encoder) {
- for _, s := range *v {
- enc.Bool(s)
- }
-}
-
-// IsNil implements gojay's MarshalerJSONArray
-func (v *BoolSlice) IsNil() bool {
- return *v == nil || len(*v) == 0
-}
-
-// UnmarshalJSONArray implements gojay's UnmarshalerJSONArray
-func (v *StructSlice) UnmarshalJSONArray(dec *gojay.Decoder) error {
- var s = &A{}
- if err := dec.Object(s); err != nil {
- return err
- }
- *v = append(*v, s)
- return nil
-}
-
-// MarshalJSONArray implements gojay's MarshalerJSONArray
-func (v *StructSlice) MarshalJSONArray(enc *gojay.Encoder) {
- for _, s := range *v {
- enc.Object(s)
- }
-}
-
-// IsNil implements gojay's MarshalerJSONArray
-func (v *StructSlice) IsNil() bool {
- return *v == nil || len(*v) == 0
-}
-
-// UnmarshalJSONArray implements gojay's UnmarshalerJSONArray
-func (v *SliceSlice) UnmarshalJSONArray(dec *gojay.Decoder) error {
- var s = make(StrSlice, 0)
- if err := dec.Array(&s); err != nil {
- return err
- }
- *v = append(*v, &s)
- return nil
-}
-
-// MarshalJSONArray implements gojay's MarshalerJSONArray
-func (v *SliceSlice) MarshalJSONArray(enc *gojay.Encoder) {
- for _, s := range *v {
- enc.Array(s)
- }
-}
-
-// IsNil implements gojay's MarshalerJSONArray
-func (v *SliceSlice) IsNil() bool {
- return *v == nil || len(*v) == 0
-}
-
-// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject
-func (v *A) UnmarshalJSONObject(dec *gojay.Decoder, k string) error {
- switch k {
- case "string":
- return dec.String(&v.Str)
- case "bool":
- return dec.Bool(&v.Bool)
- case "int":
- return dec.Int(&v.Int)
- case "int64":
- return dec.Int64(&v.Int64)
- case "int32":
- return dec.Int32(&v.Int32)
- case "int16":
- return dec.Int16(&v.Int16)
- case "int8":
- return dec.Int8(&v.Int8)
- case "uint64":
- return dec.Uint64(&v.Uint64)
- case "uint32":
- return dec.Uint32(&v.Uint32)
- case "uint16":
- return dec.Uint16(&v.Uint16)
- case "uint8":
- return dec.Uint8(&v.Uint8)
- case "bval":
- if v.Bval == nil {
- v.Bval = &B{}
- }
- return dec.Object(v.Bval)
- case "arrval":
- if v.Arrval == nil {
- arr := make(StrSlice, 0)
- v.Arrval = &arr
- }
- return dec.Array(v.Arrval)
- }
- return nil
-}
-
-// NKeys returns the number of keys to unmarshal
-func (v *A) NKeys() int { return 13 }
-
-// MarshalJSONObject implements gojay's MarshalerJSONObject
-func (v *A) MarshalJSONObject(enc *gojay.Encoder) {
- enc.StringKey("string", v.Str)
- enc.BoolKey("bool", v.Bool)
- enc.IntKey("int", v.Int)
- enc.Int64Key("int64", v.Int64)
- enc.Int32Key("int32", v.Int32)
- enc.Int16Key("int16", v.Int16)
- enc.Int8Key("int8", v.Int8)
- enc.Uint64Key("uint64", v.Uint64)
- enc.Uint32Key("uint32", v.Uint32)
- enc.Uint16Key("uint16", v.Uint16)
- enc.Uint8Key("uint8", v.Uint8)
- enc.ObjectKey("bval", v.Bval)
- enc.ArrayKey("arrval", v.Arrval)
-}
-
-// IsNil returns wether the structure is nil value or not
-func (v *A) IsNil() bool { return v == nil }
-
-// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject
-func (v *B) UnmarshalJSONObject(dec *gojay.Decoder, k string) error {
- switch k {
- case "str":
- return dec.String(&v.Str)
- case "bool":
- return dec.Bool(&v.Bool)
- case "int":
- return dec.Int(&v.Int)
- case "int64":
- return dec.Int64(&v.Int64)
- case "int32":
- return dec.Int32(&v.Int32)
- case "int16":
- return dec.Int16(&v.Int16)
- case "int8":
- return dec.Int8(&v.Int8)
- case "uint64":
- return dec.Uint64(&v.Uint64)
- case "uint32":
- return dec.Uint32(&v.Uint32)
- case "uint16":
- return dec.Uint16(&v.Uint16)
- case "uint8":
- return dec.Uint8(&v.Uint8)
- case "strPtr":
- return dec.String(v.StrPtr)
- case "boolPtr":
- return dec.Bool(v.BoolPtr)
- case "intPtr":
- return dec.Int(v.IntPtr)
- case "int64Ptr":
- return dec.Int64(v.Int64Ptr)
- case "int32Ptr":
- return dec.Int32(v.Int32Ptr)
- case "int16Ptr":
- return dec.Int16(v.Int16Ptr)
- case "int8Ptr":
- return dec.Int8(v.Int8Ptr)
- case "uint64Ptr":
- return dec.Uint64(v.Uint64Ptr)
- case "uint32Ptr":
- return dec.Uint32(v.Uint32Ptr)
- case "uint16Ptr":
- return dec.Uint16(v.Uint16Ptr)
- case "uint8PTr":
- return dec.Uint8(v.Uint8PTr)
- }
- return nil
-}
-
-// NKeys returns the number of keys to unmarshal
-func (v *B) NKeys() int { return 22 }
-
-// MarshalJSONObject implements gojay's MarshalerJSONObject
-func (v *B) MarshalJSONObject(enc *gojay.Encoder) {
- enc.StringKey("str", v.Str)
- enc.BoolKey("bool", v.Bool)
- enc.IntKey("int", v.Int)
- enc.Int64Key("int64", v.Int64)
- enc.Int32Key("int32", v.Int32)
- enc.Int16Key("int16", v.Int16)
- enc.Int8Key("int8", v.Int8)
- enc.Uint64Key("uint64", v.Uint64)
- enc.Uint32Key("uint32", v.Uint32)
- enc.Uint16Key("uint16", v.Uint16)
- enc.Uint8Key("uint8", v.Uint8)
- enc.StringKey("strPtr", *v.StrPtr)
- enc.BoolKey("boolPtr", *v.BoolPtr)
- enc.IntKey("intPtr", *v.IntPtr)
- enc.Int64Key("int64Ptr", *v.Int64Ptr)
- enc.Int32Key("int32Ptr", *v.Int32Ptr)
- enc.Int16Key("int16Ptr", *v.Int16Ptr)
- enc.Int8Key("int8Ptr", *v.Int8Ptr)
- enc.Uint64Key("uint64Ptr", *v.Uint64Ptr)
- enc.Uint32Key("uint32Ptr", *v.Uint32Ptr)
- enc.Uint16Key("uint16Ptr", *v.Uint16Ptr)
- enc.Uint8Key("uint8PTr", *v.Uint8PTr)
-}
-
-// IsNil returns wether the structure is nil value or not
-func (v *B) IsNil() bool { return v == nil }
-
-// UnmarshalJSONObject implements gojay's UnmarshalerJSONObject
-func (v MapStringInt) UnmarshalJSONObject(dec *gojay.Decoder, k string) error {
- var i int
- if err := dec.Int(&i); err != nil {
- return err
- }
- v[k] = i
- return nil
-}
-
-// NKeys returns the number of keys to unmarshal
-func (v MapStringInt) NKeys() int { return 0 }
-
-// MarshalJSONObject implements gojay's MarshalerJSONObject
-func (v MapStringInt) MarshalJSONObject(enc *gojay.Encoder) {
- for k, s := range v {
- enc.IntKey(k, s)
- }
-}
-
-// IsNil returns wether the structure is nil value or not
-func (v MapStringInt) IsNil() bool { return v == nil || len(v) == 0 }