Skip to content

Commit

Permalink
Allow alternative delimiter for child sections (#255)
Browse files Browse the repository at this point in the history
ini: added option for ChildSectionDelimiter
file: added default for ChildSectionDelimiter (".") to maintain current behavior by default
section:
  - append ChildSectionDelimiter instead of "." when checking if each section name begins with prefix
  - use ChildSectionDelimiter instead of "." when checking for LastIndex of delimiter
  • Loading branch information
irremotus committed Aug 16, 2020
1 parent 8e98c65 commit 29f972a
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 3 deletions.
3 changes: 3 additions & 0 deletions file.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ func newFile(dataSources []dataSource, opts LoadOptions) *File {
if len(opts.KeyValueDelimiterOnWrite) == 0 {
opts.KeyValueDelimiterOnWrite = "="
}
if len(opts.ChildSectionDelimiter) == 0 {
opts.ChildSectionDelimiter = "."
}

return &File{
BlockMode: true,
Expand Down
2 changes: 2 additions & 0 deletions ini.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ type LoadOptions struct {
KeyValueDelimiters string
// KeyValueDelimiters is the delimiter that are used to separate key and value output. By default, it is "=".
KeyValueDelimiterOnWrite string
// ChildSectionDelimiter is the delimiter that is used to separate child sections. By default, it is ".".
ChildSectionDelimiter string
// PreserveSurroundedQuote indicates whether to preserve surrounded quote (single and double quotes).
PreserveSurroundedQuote bool
// DebugFunc is called to collect debug information (currently only useful to debug parsing Python-style multiline values).
Expand Down
62 changes: 62 additions & 0 deletions ini_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1305,6 +1305,68 @@ GITHUB = U;n;k;n;w;o;n
})
})
})

Convey("with `ChildSectionDelimiter` ':'", func() {
Convey("Get all keys of parent sections", func() {
f := ini.Empty(ini.LoadOptions{ChildSectionDelimiter: ":"})
So(f, ShouldNotBeNil)

k, err := f.Section("package").NewKey("NAME", "ini")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
k, err = f.Section("package").NewKey("VERSION", "v1")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)
k, err = f.Section("package").NewKey("IMPORT_PATH", "gopkg.in/ini.v1")
So(err, ShouldBeNil)
So(k, ShouldNotBeNil)

keys := f.Section("package:sub:sub2").ParentKeys()
names := []string{"NAME", "VERSION", "IMPORT_PATH"}
So(len(keys), ShouldEqual, len(names))
for i, name := range names {
So(keys[i].Name(), ShouldEqual, name)
}
})

Convey("Getting and setting values", func() {
f, err := ini.LoadSources(ini.LoadOptions{ChildSectionDelimiter: ":"}, fullConf)
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)

Convey("Get parent-keys that are available to the child section", func() {
parentKeys := f.Section("package:sub").ParentKeys()
So(parentKeys, ShouldNotBeNil)
for _, k := range parentKeys {
So(k.Name(), ShouldEqual, "CLONE_URL")
}
})

Convey("Get parent section value", func() {
So(f.Section("package:sub").Key("CLONE_URL").String(), ShouldEqual, "https://gopkg.in/ini.v1")
So(f.Section("package:fake:sub").Key("CLONE_URL").String(), ShouldEqual, "https://gopkg.in/ini.v1")
})
})

Convey("Get child sections by parent name", func() {
f, err := ini.LoadSources(ini.LoadOptions{ChildSectionDelimiter: ":"}, []byte(`
[node]
[node:biz1]
[node:biz2]
[node.biz3]
[node.bizN]
`))
So(err, ShouldBeNil)
So(f, ShouldNotBeNil)

children := f.ChildSections("node")
names := []string{"node:biz1", "node:biz2"}
So(len(children), ShouldEqual, len(names))
for i, name := range names {
So(children[i].Name(), ShouldEqual, name)
}
})
})
})
}

Expand Down
6 changes: 3 additions & 3 deletions section.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ func (s *Section) GetKey(name string) (*Key, error) {
// Check if it is a child-section.
sname := s.name
for {
if i := strings.LastIndex(sname, "."); i > -1 {
if i := strings.LastIndex(sname, s.f.options.ChildSectionDelimiter); i > -1 {
sname = sname[:i]
sec, err := s.f.GetSection(sname)
if err != nil {
Expand Down Expand Up @@ -188,7 +188,7 @@ func (s *Section) ParentKeys() []*Key {
var parentKeys []*Key
sname := s.name
for {
if i := strings.LastIndex(sname, "."); i > -1 {
if i := strings.LastIndex(sname, s.f.options.ChildSectionDelimiter); i > -1 {
sname = sname[:i]
sec, err := s.f.GetSection(sname)
if err != nil {
Expand Down Expand Up @@ -245,7 +245,7 @@ func (s *Section) DeleteKey(name string) {
// For example, "[parent.child1]" and "[parent.child12]" are child sections
// of section "[parent]".
func (s *Section) ChildSections() []*Section {
prefix := s.name + "."
prefix := s.name + s.f.options.ChildSectionDelimiter
children := make([]*Section, 0, 3)
for _, name := range s.f.sectionList {
if strings.HasPrefix(name, prefix) {
Expand Down

0 comments on commit 29f972a

Please sign in to comment.