From ab2545f6076ede49fe7b0345f71eeb9ea86849a6 Mon Sep 17 00:00:00 2001 From: HenryLee Date: Sat, 15 Jul 2017 13:26:17 +0800 Subject: [PATCH 1/5] automatically add spaces after the comment symbol --- ini.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ini.go b/ini.go index f8827dd..f1888ed 100644 --- a/ini.go +++ b/ini.go @@ -414,6 +414,8 @@ func (f *File) WriteToIndent(w io.Writer, indent string) (n int64, err error) { if len(sec.Comment) > 0 { if sec.Comment[0] != '#' && sec.Comment[0] != ';' { sec.Comment = "; " + sec.Comment + } else { + sec.Comment = sec.Comment[:1] + " " + strings.TrimSpace(sec.Comment[1:]) } if _, err = buf.WriteString(sec.Comment + LineBreak); err != nil { return 0, err @@ -468,6 +470,8 @@ func (f *File) WriteToIndent(w io.Writer, indent string) (n int64, err error) { } if key.Comment[0] != '#' && key.Comment[0] != ';' { key.Comment = "; " + key.Comment + } else { + key.Comment = key.Comment[:1] + " " + strings.TrimSpace(key.Comment[1:]) } if _, err = buf.WriteString(key.Comment + LineBreak); err != nil { return 0, err From ec6a6c847271f001c7b27d36da9eb20a7acefc5b Mon Sep 17 00:00:00 2001 From: HenryLee Date: Sat, 15 Jul 2017 14:07:35 +0800 Subject: [PATCH 2/5] support read comment from struct 'comment' tag --- struct.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/struct.go b/struct.go index eeb8dab..e9a7a07 100644 --- a/struct.go +++ b/struct.go @@ -450,6 +450,12 @@ func (s *Section) reflectFrom(val reflect.Value) error { // Note: fieldName can never be empty here, ignore error. sec, _ = s.f.NewSection(fieldName) } + + // add comment from comment tag + if len(sec.Comment) == 0 { + sec.Comment = tpField.Tag.Get("comment") + } + if err = sec.reflectFrom(field); err != nil { return fmt.Errorf("error reflecting field (%s): %v", fieldName, err) } @@ -461,6 +467,12 @@ func (s *Section) reflectFrom(val reflect.Value) error { if err != nil { key, _ = s.NewKey(fieldName, "") } + + // add comment from comment tag + if len(key.Comment) == 0 { + key.Comment = tpField.Tag.Get("comment") + } + if err = reflectWithProperType(tpField.Type, key, field, parseDelim(tpField.Tag.Get("delim"))); err != nil { return fmt.Errorf("error reflecting field (%s): %v", fieldName, err) } From 78e3da3d5649a902cbb4f5d470f12b65a834f06c Mon Sep 17 00:00:00 2001 From: HenryLee Date: Sat, 15 Jul 2017 15:23:23 +0800 Subject: [PATCH 3/5] When the field type is time.Duration, use time string as the configuration value --- struct.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/struct.go b/struct.go index e9a7a07..2ef1c43 100644 --- a/struct.go +++ b/struct.go @@ -379,7 +379,11 @@ func reflectWithProperType(t reflect.Type, key *Key, field reflect.Value, delim case reflect.Bool: key.SetValue(fmt.Sprint(field.Bool())) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - key.SetValue(fmt.Sprint(field.Int())) + if t.String() == "time.Duration" { + key.SetValue(field.Interface().(time.Duration).String()) + } else { + key.SetValue(fmt.Sprint(field.Int())) + } case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: key.SetValue(fmt.Sprint(field.Uint())) case reflect.Float32, reflect.Float64: From 75c2a9ba5968ec7ca308ac8e9f18fe957ab989e1 Mon Sep 17 00:00:00 2001 From: henrylee2cn Date: Sat, 5 Aug 2017 18:19:50 +0800 Subject: [PATCH 4/5] helper.go: add SyncINI() --- README.md | 9 ++++-- README_ZH.md | 9 ++++-- helper.go | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+), 6 deletions(-) create mode 100644 helper.go diff --git a/README.md b/README.md index e67d51f..c7daa06 100644 --- a/README.md +++ b/README.md @@ -573,7 +573,7 @@ Why not? ```go type Embeded struct { - Dates []time.Time `delim:"|"` + Dates []time.Time `delim:"|" comment:"time data"` Places []string `ini:"places,omitempty"` None []int `ini:",omitempty"` } @@ -581,10 +581,10 @@ type Embeded struct { type Author struct { Name string `ini:"NAME"` Male bool - Age int + Age int `comment:"Author's age"` GPA float64 NeverMind string `ini:"-"` - *Embeded + *Embeded `comment:"Embeded section"` } func main() { @@ -605,10 +605,13 @@ So, what do I get? ```ini NAME = Unknwon Male = true +; Author's age Age = 21 GPA = 2.8 +; Embeded section [Embeded] +; time data Dates = 2015-08-07T22:14:22+08:00|2015-08-07T22:14:22+08:00 places = HangZhou,Boston ``` diff --git a/README_ZH.md b/README_ZH.md index 0cf4194..cd2a23b 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -564,7 +564,7 @@ p := &Person{ ```go type Embeded struct { - Dates []time.Time `delim:"|"` + Dates []time.Time `delim:"|" comment:"time data"` Places []string `ini:"places,omitempty"` None []int `ini:",omitempty"` } @@ -572,10 +572,10 @@ type Embeded struct { type Author struct { Name string `ini:"NAME"` Male bool - Age int + Age int `comment:"Author's age"` GPA float64 NeverMind string `ini:"-"` - *Embeded + *Embeded `comment:"Embeded section"` } func main() { @@ -596,10 +596,13 @@ func main() { ```ini NAME = Unknwon Male = true +; Author's age Age = 21 GPA = 2.8 +; Embeded section [Embeded] +; time data Dates = 2015-08-07T22:14:22+08:00|2015-08-07T22:14:22+08:00 places = HangZhou,Boston ``` diff --git a/helper.go b/helper.go new file mode 100644 index 0000000..4c55930 --- /dev/null +++ b/helper.go @@ -0,0 +1,79 @@ +package ini + +import ( + "os" + "path/filepath" + "reflect" + "strings" + "sync" + + "github.com/henrylee2cn/goutil" + "github.com/henrylee2cn/goutil/errors" +) + +// SyncINI quickly create your own configuration files. +// Struct tags reference `https://github.com/henrylee2cn/ini` +func SyncINI(structPtr interface{}, f func(onecUpdateFunc func() error) error, filename ...string) error { + t := reflect.TypeOf(structPtr) + if t.Kind() != reflect.Ptr { + return errors.New("SyncINI's param must be struct pointer type.") + } + t = t.Elem() + if t.Kind() != reflect.Struct { + return errors.New("SyncINI's param must be struct pointer type.") + } + + var fname string + if len(filename) > 0 { + fname = filename[0] + } else { + fname = strings.TrimSuffix(t.Name(), "Config") + fname = strings.TrimSuffix(fname, "INI") + fname = goutil.SnakeString(fname) + ".ini" + } + var cfg *File + var err error + var existed bool + cfg, err = Load(fname) + if err != nil { + os.MkdirAll(filepath.Dir(fname), 0777) + cfg, err = LooseLoad(fname) + if err != nil { + return err + } + } else { + existed = true + } + + err = cfg.MapTo(structPtr) + if err != nil { + return err + } + + var once sync.Once + var onecUpdateFunc = func() error { + var err error + once.Do(func() { + err = cfg.ReflectFrom(structPtr) + if err != nil { + return + } + err = cfg.SaveTo(fname) + if err != nil { + return + } + }) + return err + } + + if f != nil { + if err = f(onecUpdateFunc); err != nil { + return err + } + } + + if !existed { + return onecUpdateFunc() + } + return nil +} From 5ed75ffad86d0429239bb5beee483f40bad43d34 Mon Sep 17 00:00:00 2001 From: henrylee2cn Date: Sat, 5 Aug 2017 18:45:03 +0800 Subject: [PATCH 5/5] .gitignore: add *.zip *.rar --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index c5203bf..525d8bf 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ ini.sublime-project ini.sublime-workspace testdata/conf_reflect.ini .idea +*.zip +*.rar \ No newline at end of file