204 lines
4.1 KiB
Plaintext
204 lines
4.1 KiB
Plaintext
Heading 2 Recipes
|
|
class mt-12
|
|
|
|
Heading 3 Parse object properties
|
|
class mb-2
|
|
Markdown
|
|
Read known properties from a Terrace block and write them to a struct.
|
|
CodeBlock go
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"terrace.go"
|
|
)
|
|
|
|
type Config struct {
|
|
StringProperty string
|
|
NumericProperty int
|
|
}
|
|
|
|
func main() {
|
|
input := `object
|
|
string_property An example string
|
|
numeric_property 42`
|
|
|
|
reader := &StringReader{reader: strings.NewReader(input)}
|
|
doc := terrace.NewTerraceDocument(reader, ' ')
|
|
|
|
config := Config{}
|
|
|
|
for {
|
|
node, err := doc.Next()
|
|
if err == io.EOF {
|
|
break
|
|
}
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
if node.Head() == "object" {
|
|
objectLevel := node.Level()
|
|
for {
|
|
node, err := doc.Next()
|
|
if err == io.EOF {
|
|
break
|
|
}
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
if node.Level() <= objectLevel {
|
|
// We've exited the object block
|
|
break
|
|
}
|
|
|
|
switch node.Head() {
|
|
case "string_property":
|
|
config.StringProperty = node.Tail()
|
|
case "numeric_property":
|
|
if val, err := strconv.Atoi(node.Tail()); err == nil {
|
|
config.NumericProperty = val
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fmt.Printf("%+v\n", config)
|
|
// {StringProperty:An example string NumericProperty:42}
|
|
}
|
|
|
|
Markdown
|
|
Read *all* properties as strings from a Terrace block and write them to a map.
|
|
CodeBlock go
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"strings"
|
|
|
|
"terrace.go"
|
|
)
|
|
|
|
func main() {
|
|
input := `object
|
|
property1 Value 1
|
|
property2 Value 2
|
|
random_property igazi3ii4quaC5OdoB5quohnah1beeNg`
|
|
|
|
reader := &StringReader{reader: strings.NewReader(input)}
|
|
doc := terrace.NewTerraceDocument(reader, ' ')
|
|
|
|
output := make(map[string]string)
|
|
|
|
for {
|
|
node, err := doc.Next()
|
|
if err == io.EOF {
|
|
break
|
|
}
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
if node.Head() == "object" {
|
|
objectLevel := node.Level()
|
|
for {
|
|
node, err := doc.Next()
|
|
if err == io.EOF {
|
|
break
|
|
}
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
if node.Level() <= objectLevel {
|
|
// We've exited the object block
|
|
break
|
|
}
|
|
|
|
// Skip empty lines
|
|
if node.Content() == "" {
|
|
continue
|
|
}
|
|
// Add any properties to the map as strings using the
|
|
// line Head() as the key and Tail() as the value
|
|
output[node.Head()] = node.Tail()
|
|
}
|
|
}
|
|
}
|
|
|
|
fmt.Printf("%+v\n", output)
|
|
// map[property1:Value 1 property2:Value 2 random_property:igazi3ii4quaC5OdoB5quohnah1beeNg]
|
|
}
|
|
|
|
Heading 3 Process nested blocks
|
|
class mb-2
|
|
Markdown
|
|
Handle hierarchically nested blocks with recursive processing.
|
|
CodeBlock go
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"strings"
|
|
|
|
"terrace.go"
|
|
)
|
|
|
|
type Block struct {
|
|
Name string
|
|
Content string
|
|
Children []Block
|
|
}
|
|
|
|
func parseBlock(doc *terrace.TerraceDocument, parentLevel int) []Block {
|
|
var blocks []Block
|
|
|
|
for {
|
|
node, err := doc.Next()
|
|
if err == io.EOF {
|
|
break
|
|
}
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
// If we've returned to the parent level or higher, we're done
|
|
if node.Level() <= parentLevel {
|
|
break
|
|
}
|
|
|
|
block := Block{
|
|
Name: node.Head(),
|
|
Content: node.Tail(),
|
|
}
|
|
|
|
// Parse any nested children
|
|
block.Children = parseBlock(doc, node.Level())
|
|
blocks = append(blocks, block)
|
|
}
|
|
|
|
return blocks
|
|
}
|
|
|
|
func main() {
|
|
input := `root
|
|
section1 Section 1 Content
|
|
subsection1 Subsection 1 Content
|
|
subsection2 Subsection 2 Content
|
|
section2 Section 2 Content
|
|
nested
|
|
deeply Nested Content`
|
|
|
|
reader := &StringReader{reader: strings.NewReader(input)}
|
|
doc := terrace.NewTerraceDocument(reader, ' ')
|
|
|
|
blocks := parseBlock(doc, -1)
|
|
|
|
fmt.Printf("%+v\n", blocks)
|
|
} |