Final Toml-Path Solution

* Refactored type names and file names to mesh with existing TOML library more closely
* Added QueryResult structure that provides values and position data
* Added Query() method to TomlTree type
* Tests, tests, and more tests
* Fixed bug where positions returned from some tables were invalid
* Added test case for bug patch

The bugfix was an interesting case. Position information wasn't being
set in cases where createPath was called.  So table names like [foo.bar]
would result in table 'foo' having no position.
This commit is contained in:
eanderton
2014-09-10 21:32:04 -04:00
parent 2811a1a3c9
commit 081f3db916
15 changed files with 713 additions and 779 deletions
+31 -22
View File
@@ -199,7 +199,7 @@ func (t *TomlTree) SetPath(keys []string, value interface{}) {
// and tree[a][b][c]
//
// Returns nil on success, error object on failure
func (t *TomlTree) createSubTree(keys []string) error {
func (t *TomlTree) createSubTree(keys []string, pos Position) error {
subtree := t
for _, intermediateKey := range keys {
if intermediateKey == "" {
@@ -207,8 +207,10 @@ func (t *TomlTree) createSubTree(keys []string) error {
}
nextTree, exists := subtree.values[intermediateKey]
if !exists {
nextTree = newTomlTree()
subtree.values[intermediateKey] = nextTree
tree := newTomlTree()
tree.position = pos
subtree.values[intermediateKey] = tree
nextTree = tree
}
switch node := nextTree.(type) {
@@ -317,6 +319,14 @@ func (t *TomlTree) toToml(indent, keyspace string) string {
return result
}
func (t *TomlTree) Query(query string) (*QueryResult, error) {
if q, err := Compile(query); err != nil {
return nil, err
} else {
return q.Execute(t), nil
}
}
// ToString generates a human-readable representation of the current tree.
// Output spans multiple lines, and is suitable for ingest by a TOML parser
func (t *TomlTree) ToString() string {
@@ -325,27 +335,26 @@ func (t *TomlTree) ToString() string {
// Load creates a TomlTree from a string.
func Load(content string) (tree *TomlTree, err error) {
defer func() {
if r := recover(); r != nil {
if _, ok := r.(runtime.Error); ok {
panic(r)
}
err = errors.New(r.(string))
}
}()
_, flow := lex(content)
tree = parse(flow)
return
defer func() {
if r := recover(); r != nil {
if _, ok := r.(runtime.Error); ok {
panic(r)
}
err = errors.New(r.(string))
}
}()
tree = parseToml(lexToml(content))
return
}
// LoadFile creates a TomlTree from a file.
func LoadFile(path string) (tree *TomlTree, err error) {
buff, ferr := ioutil.ReadFile(path)
if ferr != nil {
err = ferr
} else {
s := string(buff)
tree, err = Load(s)
}
return
buff, ferr := ioutil.ReadFile(path)
if ferr != nil {
err = ferr
} else {
s := string(buff)
tree, err = Load(s)
}
return
}