diff options
| author | Shulhan <ms@kilabit.info> | 2019-05-25 05:09:04 +0700 |
|---|---|---|
| committer | Shulhan <ms@kilabit.info> | 2019-05-25 05:24:25 +0700 |
| commit | b986ada275d7682feee761d678f0d79a6c43f75d (patch) | |
| tree | acb8726f8bb71e47e4a45fd5594fd8c1901995de | |
| parent | 3df89617c363d3dc89b3afdd59c11324fd0174c5 (diff) | |
| download | pakakeh.go-b986ada275d7682feee761d678f0d79a6c43f75d.tar.xz | |
ini: add method to prune INI variables
Pruning the INI variables means removing the empty lines, the comments,
and merge section and subsection that have the same name into one
group.
| -rw-r--r-- | lib/ini/ini.go | 61 | ||||
| -rw-r--r-- | lib/ini/ini_example_test.go | 43 | ||||
| -rw-r--r-- | lib/ini/section.go | 27 |
3 files changed, 131 insertions, 0 deletions
diff --git a/lib/ini/ini.go b/lib/ini/ini.go index 69fe21e1..01807d5b 100644 --- a/lib/ini/ini.go +++ b/lib/ini/ini.go @@ -242,6 +242,67 @@ func (in *Ini) Gets(section, subsection, key string) (out []string) { } // +// Prune remove all empty lines, comments, and merge all section and +// subsection with the same name into one group. +// +func (in *Ini) Prune() { + newSecs := make([]*Section, 0, len(in.secs)) + + for _, sec := range in.secs { + if sec.mode == varModeEmpty { + continue + } + newSec := &Section{ + mode: varModeSection, + Name: sec.Name, + NameLower: sec.NameLower, + } + if len(sec.Sub) > 0 { + newSec.mode |= varModeSubsection + newSec.Sub = sec.Sub + } + for _, v := range sec.Vars { + if v.mode == varModeEmpty || v.mode == varModeComment { + continue + } + + newValue := v.Value + if len(v.Value) == 0 { + newValue = "true" + } + + newSec.AddUniqValue(v.Key, newValue) + } + newSecs = mergeSection(newSecs, newSec) + } + + in.secs = newSecs +} + +// +// mergeSection merge a section (and subsection) into slice. +// +func mergeSection(secs []*Section, newSec *Section) []*Section { + for x := 0; x < len(secs); x++ { + if secs[x].NameLower != newSec.NameLower { + continue + } + if secs[x].Sub != newSec.Sub { + continue + } + for _, v := range newSec.Vars { + if v.mode == varModeEmpty || v.mode == varModeComment { + continue + } + secs[x].AddUniqValue(v.KeyLower, v.Value) + } + return secs + } + secs = append(secs, newSec) + return secs +} + +// // Save the current parsed Ini into file `filename`. It will overwrite the // destination file if it's exist. // diff --git a/lib/ini/ini_example_test.go b/lib/ini/ini_example_test.go index 67c8966f..8ea5efbd 100644 --- a/lib/ini/ini_example_test.go +++ b/lib/ini/ini_example_test.go @@ -63,3 +63,46 @@ key=value3 // section::key2 = [true false] // section:sub:key = [value1 value2 value3] } + +func ExampleIni_Prune() { + input := []byte(` +[section] +key=value1 # comment +key2= ; another comment + +[section "sub"] +key=value1 + +; here is comment on section +[section] +key=value2 +key2=false + +[section "sub"] +key=value2 +key=value1 +`) + + in, err := Parse(input) + if err != nil { + log.Fatal(err) + } + + in.Prune() + + for _, sec := range in.secs { + fmt.Printf("%s", sec) + for _, v := range sec.Vars { + fmt.Printf("%s", v) + } + } + // Output: + // [section] + // key = value1 + // key2 = true + // key = value2 + // key2 = false + // [section "sub"] + // key = value2 + // key = value1 +} diff --git a/lib/ini/section.go b/lib/ini/section.go index bc09cc23..3ac2f542 100644 --- a/lib/ini/section.go +++ b/lib/ini/section.go @@ -173,6 +173,33 @@ func (sec *Section) AddComment(comment string) { } // +// AddUniqValue add a new variable with uniq value to section. +// If variable with the same key and value found, that variable will be moved +// to end of list, to make the last declared variable still at the end of +// list. +// +func (sec *Section) AddUniqValue(key, value string) { + keyLower := strings.ToLower(key) + for x := 0; x < len(sec.Vars); x++ { + if sec.Vars[x].KeyLower == keyLower { + if sec.Vars[x].Value == value { + tmp := sec.Vars[x] + sec.Vars = append(sec.Vars[:x], sec.Vars[x+1:]...) + sec.Vars = append(sec.Vars, tmp) + return + } + } + } + v := &Variable{ + mode: varModeValue, + Key: key, + KeyLower: keyLower, + Value: value, + } + sec.Vars = append(sec.Vars, v) +} + +// // Unset remove the variable with name `key` on current section. // // If key is empty, no variable will be removed, and it will return true. |
