Skip to content

Commit 29f972a

Browse files
authored
Allow alternative delimiter for child sections (#255)
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
1 parent 8e98c65 commit 29f972a

File tree

4 files changed

+70
-3
lines changed

4 files changed

+70
-3
lines changed

file.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ func newFile(dataSources []dataSource, opts LoadOptions) *File {
5555
if len(opts.KeyValueDelimiterOnWrite) == 0 {
5656
opts.KeyValueDelimiterOnWrite = "="
5757
}
58+
if len(opts.ChildSectionDelimiter) == 0 {
59+
opts.ChildSectionDelimiter = "."
60+
}
5861

5962
return &File{
6063
BlockMode: true,

ini.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ type LoadOptions struct {
113113
KeyValueDelimiters string
114114
// KeyValueDelimiters is the delimiter that are used to separate key and value output. By default, it is "=".
115115
KeyValueDelimiterOnWrite string
116+
// ChildSectionDelimiter is the delimiter that is used to separate child sections. By default, it is ".".
117+
ChildSectionDelimiter string
116118
// PreserveSurroundedQuote indicates whether to preserve surrounded quote (single and double quotes).
117119
PreserveSurroundedQuote bool
118120
// DebugFunc is called to collect debug information (currently only useful to debug parsing Python-style multiline values).

ini_test.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1305,6 +1305,68 @@ GITHUB = U;n;k;n;w;o;n
13051305
})
13061306
})
13071307
})
1308+
1309+
Convey("with `ChildSectionDelimiter` ':'", func() {
1310+
Convey("Get all keys of parent sections", func() {
1311+
f := ini.Empty(ini.LoadOptions{ChildSectionDelimiter: ":"})
1312+
So(f, ShouldNotBeNil)
1313+
1314+
k, err := f.Section("package").NewKey("NAME", "ini")
1315+
So(err, ShouldBeNil)
1316+
So(k, ShouldNotBeNil)
1317+
k, err = f.Section("package").NewKey("VERSION", "v1")
1318+
So(err, ShouldBeNil)
1319+
So(k, ShouldNotBeNil)
1320+
k, err = f.Section("package").NewKey("IMPORT_PATH", "gopkg.in/ini.v1")
1321+
So(err, ShouldBeNil)
1322+
So(k, ShouldNotBeNil)
1323+
1324+
keys := f.Section("package:sub:sub2").ParentKeys()
1325+
names := []string{"NAME", "VERSION", "IMPORT_PATH"}
1326+
So(len(keys), ShouldEqual, len(names))
1327+
for i, name := range names {
1328+
So(keys[i].Name(), ShouldEqual, name)
1329+
}
1330+
})
1331+
1332+
Convey("Getting and setting values", func() {
1333+
f, err := ini.LoadSources(ini.LoadOptions{ChildSectionDelimiter: ":"}, fullConf)
1334+
So(err, ShouldBeNil)
1335+
So(f, ShouldNotBeNil)
1336+
1337+
Convey("Get parent-keys that are available to the child section", func() {
1338+
parentKeys := f.Section("package:sub").ParentKeys()
1339+
So(parentKeys, ShouldNotBeNil)
1340+
for _, k := range parentKeys {
1341+
So(k.Name(), ShouldEqual, "CLONE_URL")
1342+
}
1343+
})
1344+
1345+
Convey("Get parent section value", func() {
1346+
So(f.Section("package:sub").Key("CLONE_URL").String(), ShouldEqual, "https://gopkg.in/ini.v1")
1347+
So(f.Section("package:fake:sub").Key("CLONE_URL").String(), ShouldEqual, "https://gopkg.in/ini.v1")
1348+
})
1349+
})
1350+
1351+
Convey("Get child sections by parent name", func() {
1352+
f, err := ini.LoadSources(ini.LoadOptions{ChildSectionDelimiter: ":"}, []byte(`
1353+
[node]
1354+
[node:biz1]
1355+
[node:biz2]
1356+
[node.biz3]
1357+
[node.bizN]
1358+
`))
1359+
So(err, ShouldBeNil)
1360+
So(f, ShouldNotBeNil)
1361+
1362+
children := f.ChildSections("node")
1363+
names := []string{"node:biz1", "node:biz2"}
1364+
So(len(children), ShouldEqual, len(names))
1365+
for i, name := range names {
1366+
So(children[i].Name(), ShouldEqual, name)
1367+
}
1368+
})
1369+
})
13081370
})
13091371
}
13101372

section.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ func (s *Section) GetKey(name string) (*Key, error) {
121121
// Check if it is a child-section.
122122
sname := s.name
123123
for {
124-
if i := strings.LastIndex(sname, "."); i > -1 {
124+
if i := strings.LastIndex(sname, s.f.options.ChildSectionDelimiter); i > -1 {
125125
sname = sname[:i]
126126
sec, err := s.f.GetSection(sname)
127127
if err != nil {
@@ -188,7 +188,7 @@ func (s *Section) ParentKeys() []*Key {
188188
var parentKeys []*Key
189189
sname := s.name
190190
for {
191-
if i := strings.LastIndex(sname, "."); i > -1 {
191+
if i := strings.LastIndex(sname, s.f.options.ChildSectionDelimiter); i > -1 {
192192
sname = sname[:i]
193193
sec, err := s.f.GetSection(sname)
194194
if err != nil {
@@ -245,7 +245,7 @@ func (s *Section) DeleteKey(name string) {
245245
// For example, "[parent.child1]" and "[parent.child12]" are child sections
246246
// of section "[parent]".
247247
func (s *Section) ChildSections() []*Section {
248-
prefix := s.name + "."
248+
prefix := s.name + s.f.options.ChildSectionDelimiter
249249
children := make([]*Section, 0, 3)
250250
for _, name := range s.f.sectionList {
251251
if strings.HasPrefix(name, prefix) {

0 commit comments

Comments
 (0)