Closed suntong closed 7 years ago
Hmm, in fact, I do hope that at least I can obtain orders that given on command line. Thx.
You can replace map with slice.Here is an example:
// main.go
package main
import "github.com/mkideal/cli"
import "strings"
import "strconv"
type KV struct {
Key string
Value int
}
type KVs []KV
// Decode implements cli.Decoder interface
func (kvs *KVs) Decode(s string) error {
i := strings.Index(s, "=")
if i >= 0 {
key := s[:i]
val, err := strconv.ParseInt(s[i+1:], 10, 64)
if err != nil {
return err
}
*kvs = append(*kvs, KV{key, int(val)})
}
return nil
}
type argT struct {
cli.Helper
Values KVs `cli:"D" usage:"define macro values"`
}
func main() {
cli.Run(new(argT), func(ctx *cli.Context) error {
ctx.JSONIndentln(ctx.Argv(), "", " ")
return nil
})
}
Then run it:
go run -Dx=1 -D y=2
perfect! Thanks a lot!
If I implement cli.Decoder interface on my own, is it possible to call the default behavior from it somehow?
I.e., can I make the following code any more simpler:
package main
import (
"strconv"
"strings"
"github.com/mkideal/cli"
)
type mapT map[string]int64
type argT struct {
Macros mapT `cli:"D" usage:"define macros"`
}
var keys = []string{}
// Decode implements cli.Decoder interface
func (maps *mapT) Decode(s string) error {
*maps = make(map[string]int64)
keys = []string{}
i := strings.Index(s, "=")
if i >= 0 {
key := s[:i]
val, err := strconv.ParseInt(s[i+1:], 10, 64)
if err != nil {
return err
}
keys = append(keys, key)
(*maps)[key] = val
}
return nil
}
func main() {
cli.Run(new(argT), func(ctx *cli.Context) error {
ctx.JSONln(ctx.Argv())
return nil
})
}
Also, when I run it, I miss "x":1
output. Why is that?
$ go run 106-2map.go -Dx=1 -D y=2
{"Macros":{"y":2}}
Oh, maybe I can collect my keys in a validator. Hmm..., guess not. validator is the last step. :-(
Also, when I run it, I miss "x":1 output. Why is that?
Replace this line
*maps = make(map[string]int64)
with
if (*maps) == nil {
*maps = make(map[string]int64)
}
is it possible to call the default behavior from it somehow?
You can implement mapT in a your own pkg, and export mapT(i.e. rename MapT). Then you reused it as following:
package main
import "yourpkg"
type argT struct {
Macros yourpkg.MapT `cli:"D" usage:"define macros"`
}
...
Another, MapT maybe implemented as following:
type MapStringToInt64 struct {
Keys []string
Values map[string]int64
}
// DecodeSlice implements cli.SliceDecoder
// NOTE: if SliceDecoder not implemented, the Decode method would be only invoked once
func (MapStringToInt64) DecodeSlice() {}
// Decode implements cli.Decoder interface
func (m *MapStringToInt64) Decode(s string) error {
if (m.Values) == nil {
m.Values = make(map[string]int64)
}
i := strings.Index(s, "=")
if i >= 0 {
key := s[:i]
val, err := strconv.ParseInt(s[i+1:], 10, 64)
if err != nil {
return err
}
m.Keys = append(m.Keys, key)
m.Values[key] = val
}
return nil
}
NOTE: you shoud pull latest cli
, SliceDecoder is a new feature.
I realize my mistake after sleeping on it. :-)
Thanks a lot for your reply and solution. Two thumbs up :+1:
NOTE: if SliceDecoder not implemented, the Decode method would be only invoked once
You meant it would be invoked only once per parameter, right? I.e., if I have 3 parameters, it would be invoked 3 times, right?
The go map is known to not preserver map orders. I.e., if we run the following sample code a couple of times,
The output might not always be the same. Is it possible to obtain/preserver output orders to that given on command line? I know the current data-structure
Macros map[string]int
need to be replaced by some cli specific types, i.e., API changes. So,Just asking. Thanks.