// Package toml is a TOML markup language parser. // // This version supports the specification as described in // https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.4.0.md // // TOML Parsing // // TOML data may be parsed in two ways: by file, or by string. // // // load TOML data by filename // tree, err := toml.LoadFile("filename.toml") // // // load TOML data stored in a string // tree, err := toml.Load(stringContainingTomlData) // // Either way, the result is a TomlTree object that can be used to navigate the // structure and data within the original document. // // // Getting data from the TomlTree // // After parsing TOML data with Load() or LoadFile(), use the Has() and Get() // methods on the returned TomlTree, to find your way through the document data. // // if tree.Has('foo') { // fmt.Prinln("foo is: %v", tree.Get('foo')) // } // // Working with Paths // // Go-toml has support for basic dot-separated key paths on the Has(), Get(), Set() // and GetDefault() methods. These are the same kind of key paths used within the // TOML specification for struct tames. // // // looks for a key named 'baz', within struct 'bar', within struct 'foo' // tree.Has("foo.bar.baz") // // // returns the key at this path, if it is there // tree.Get("foo.bar.baz") // // TOML allows keys to contain '.', which can cause this syntax to be problematic // for some documents. In such cases, use the GetPath(), HasPath(), and SetPath(), // methods to explicitly define the path. This form is also faster, since // it avoids having to parse the passed key for '.' delimiters. // // // looks for a key named 'baz', within struct 'bar', within struct 'foo' // tree.HasPath(string{}{"foo","bar","baz"}) // // // returns the key at this path, if it is there // tree.GetPath(string{}{"foo","bar","baz"}) // // Note that this is distinct from the heavyweight query syntax supported by // TomlTree.Query() and the Query() struct (see below). // // Position Support // // Each element within the TomlTree is stored with position metadata, which is // invaluable for providing semantic feedback to a user. This helps in // situations where the TOML file parses correctly, but contains data that is // not correct for the application. In such cases, an error message can be // generated that indicates the problem line and column number in the source // TOML document. // // // load TOML data // tree, _ := toml.Load("filename.toml") // // // get an entry and report an error if it's the wrong type // element := tree.Get("foo") // if value, ok := element.(int64); !ok { // return fmt.Errorf("%v: Element 'foo' must be an integer", tree.GetPosition("foo")) // } // // // report an error if an expected element is missing // if !tree.Has("bar") { // return fmt.Errorf("%v: Expected 'bar' element", tree.GetPosition("")) // } // // Query Support // // The TOML query path implementation is based loosely on the JSONPath specification: // http://goessner.net/articles/JsonPath/ // // The idea behind a query path is to allow quick access to any element, or set // of elements within TOML document, with a single expression. // // result, err := tree.Query("$.foo.bar.baz") // // This is roughly equivalent to: // // next := tree.Get("foo") // if next != nil { // next = next.Get("bar") // if next != nil { // next = next.Get("baz") // } // } // result := next // // err is nil if any parsing exception occurs. // // If no node in the tree matches the query, result will simply contain an empty list of // items. // // As illustrated above, the query path is much more efficient, especially since // the structure of the TOML file can vary. Rather than making assumptions about // a document's structure, a query allows the programmer to make structured // requests into the document, and get zero or more values as a result. // // The syntax of a query begins with a root token, followed by any number // sub-expressions: // // $ // Root of the TOML tree. This must always come first. // .name // Selects child of this node, where 'name' is a TOML key // name. // ['name'] // Selects child of this node, where 'name' is a string // containing a TOML key name. // [index] // Selcts child array element at 'index'. // ..expr // Recursively selects all children, filtered by an a union, // index, or slice expression. // ..* // Recursive selection of all nodes at this point in the // tree. // .* // Selects all children of the current node. // [expr,expr] // Union operator - a logical 'or' grouping of two or more // sub-expressions: index, key name, or filter. // [start:end:step] // Slice operator - selects array elements from start to // end-1, at the given step. All three arguments are // optional. // [?(filter)] // Named filter expression - the function 'filter' is // used to filter children at this node. // // Query Indexes And Slices // // Index expressions perform no bounds checking, and will contribute no // values to the result set if the provided index or index range is invalid. // Negative indexes represent values from the end of the array, counting backwards. // // // select the last index of the array named 'foo' // tree.Query("$.foo[-1]") // // Slice expressions are supported, by using ':' to separate a start/end index pair. // // // select up to the first five elements in the array // tree.Query("$.foo[0:5]") // // Slice expressions also allow negative indexes for the start and stop // arguments. // // // select all array elements. // tree.Query("$.foo[0:-1]") // // Slice expressions may have an optional stride/step parameter: // // // select every other element // tree.Query("$.foo[0:-1:2]") // // Slice start and end parameters are also optional: // // // these are all equivalent and select all the values in the array // tree.Query("$.foo[:]") // tree.Query("$.foo[0:]") // tree.Query("$.foo[:-1]") // tree.Query("$.foo[0:-1:]") // tree.Query("$.foo[::1]") // tree.Query("$.foo[0::1]") // tree.Query("$.foo[:-1:1]") // tree.Query("$.foo[0:-1:1]") // // Query Filters // // Query filters are used within a Union [,] or single Filter [] expression. // A filter only allows nodes that qualify through to the next expression, // and/or into the result set. // // // returns children of foo that are permitted by the 'bar' filter. // tree.Query("$.foo[?(bar)]") // // There are several filters provided with the library: // // tree // Allows nodes of type TomlTree. // int // Allows nodes of type int64. // float // Allows nodes of type float64. // string // Allows nodes of type string. // time // Allows nodes of type time.Time. // bool // Allows nodes of type bool. // // Query Results // // An executed query returns a QueryResult object. This contains the nodes // in the TOML tree that qualify the query expression. Position information // is also available for each value in the set. // // // display the results of a query // results := tree.Query("$.foo.bar.baz") // for idx, value := results.Values() { // fmt.Println("%v: %v", results.Positions()[idx], value) // } // // Compiled Queries // // Queries may be executed directly on a TomlTree object, or compiled ahead // of time and executed discretely. The former is more convienent, but has the // penalty of having to recompile the query expression each time. // // // basic query // results := tree.Query("$.foo.bar.baz") // // // compiled query // query := toml.CompileQuery("$.foo.bar.baz") // results := query.Execute(tree) // // // run the compiled query again on a different tree // moreResults := query.Execute(anotherTree) // // User Defined Query Filters // // Filter expressions may also be user defined by using the SetFilter() // function on the Query object. The function must return true/false, which // signifies if the passed node is kept or discarded, respectively. // // // create a query that references a user-defined filter // query, _ := CompileQuery("$[?(bazOnly)]") // // // define the filter, and assign it to the query // query.SetFilter("bazOnly", func(node interface{}) bool{ // if tree, ok := node.(*TomlTree); ok { // return tree.Has("baz") // } // return false // reject all other node types // }) // // // run the query // query.Execute(tree) // package toml