func (t *Tree) SetPathWithOptions(keys []string, opts SetOptions, value interface{}) {
	subtree := t
	for i, intermediateKey := range keys[:len(keys)-1] {
		nextTree, exists := subtree.values[intermediateKey]
		if !exists {
			nextTree = newTreeWithPosition(Position{Line: t.position.Line + i, Col: t.position.Col})
			subtree.values[intermediateKey] = nextTree  
		}
		switch node := nextTree.(type) {
		case *Tree:
			subtree = node
		case []*Tree:
			if len(node) == 0 {
				node = append(node, newTreeWithPosition(Position{Line: t.position.Line + i, Col: t.position.Col}))
				subtree.values[intermediateKey] = node
			}
			subtree = node[len(node)-1]
		}
	}
	var toInsert interface{}
	switch v := value.(type) {
	case *Tree:
		v.comment = opts.Comment
		v.commented = opts.Commented
		toInsert = value
	case []*Tree:
		for i := range v {
			v[i].commented = opts.Commented
		}
		toInsert = value
	case *tomlValue:
		v.comment = opts.Comment
		v.commented = opts.Commented
		v.multiline = opts.Multiline
		toInsert = v
	default:
		toInsert = &tomlValue{value: value,
			comment:   opts.Comment,
			commented: opts.Commented,
			multiline: opts.Multiline,
			position:  Position{Line: subtree.position.Line + len(subtree.values) + 1, Col: subtree.position.Col}}
	}
	subtree.values[keys[len(keys)-1]] = toInsert
}
SetPathWithOptions is the same as SetPath, but allows you to provide
formatting instructions to the key, that will be reused by Marshal().
package toml
import (
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"runtime"
	"strings"
)
type tomlValue struct {
	value     interface{}  
	comment   string
	commented bool
	multiline bool
	position  Position
}
type Tree struct {
	values    map[string]interface{}  
	comment   string
	commented bool
	inline    bool
	position  Position
}
func newTree() *Tree {
	return newTreeWithPosition(Position{})
}
func newTreeWithPosition(pos Position) *Tree {
	return &Tree{
		values:   make(map[string]interface{}),
		position: pos,
	}
}
func TreeFromMap(m map[string]interface{}) (*Tree, error) {
	result, err := toTree(m)
	if err != nil {
		return nil, err
	}
	return result.(*Tree), nil
}
func (t *Tree) Position() Position {
	return t.position
}
func (t *Tree) Has(key string) bool {
	if key == "" {
		return false
	}
	return t.HasPath(strings.Split(key, "."))
}
func (t *Tree) HasPath(keys []string) bool {
	return t.GetPath(keys) != nil
}
func (t *Tree) Keys() []string {
	keys := make([]string, len(t.values))
	i := 0
	for k := range t.values {
		keys[i] = k
		i++
	}
	return keys
}
func (t *Tree) Get(key string) interface{} {
	if key == "" {
		return t
	}
	return t.GetPath(strings.Split(key, "."))
}
func (t *Tree) GetPath(keys []string) interface{} {
	if len(keys) == 0 {
		return t
	}
	subtree := t
	for _, intermediateKey := range keys[:len(keys)-1] {
		value, exists := subtree.values[intermediateKey]
		if !exists {
			return nil
		}
		switch node := value.(type) {
		case *Tree:
			subtree = node
		case []*Tree:
			if len(node) == 0 {
				return nil
			}
			subtree = node[len(node)-1]
		default:
			return nil  
		}
	}
	switch node := subtree.values[keys[len(keys)-1]].(type) {
	case *tomlValue:
		return node.value
	default:
		return node
	}
}
func (t *Tree) GetArray(key string) interface{} {
	if key == "" {
		return t
	}
	return t.GetArrayPath(strings.Split(key, "."))
}
func (t *Tree) GetArrayPath(keys []string) interface{} {
	if len(keys) == 0 {
		return t
	}
	subtree := t
	for _, intermediateKey := range keys[:len(keys)-1] {
		value, exists := subtree.values[intermediateKey]
		if !exists {
			return nil
		}
		switch node := value.(type) {
		case *Tree:
			subtree = node
		case []*Tree:
			if len(node) == 0 {
				return nil
			}
			subtree = node[len(node)-1]
		default:
			return nil  
		}
	}
	switch node := subtree.values[keys[len(keys)-1]].(type) {
	case *tomlValue:
		switch n := node.value.(type) {
		case []interface{}:
			return getArray(n)
		default:
			return node.value
		}
	default:
		return node
	}
}
func getArray(n []interface{}) interface{} {
	var s []string
	var i64 []int64
	var f64 []float64
	var bl []bool
	for _, value := range n {
		switch v := value.(type) {
		case string:
			s = append(s, v)
		case int64:
			i64 = append(i64, v)
		case float64:
			f64 = append(f64, v)
		case bool:
			bl = append(bl, v)
		default:
			return n
		}
	}
	if len(s) == len(n) {
		return s
	} else if len(i64) == len(n) {
		return i64
	} else if len(f64) == len(n) {
		return f64
	} else if len(bl) == len(n) {
		return bl
	}
	return n
}
func (t *Tree) GetPosition(key string) Position {
	if key == "" {
		return t.position
	}
	return t.GetPositionPath(strings.Split(key, "."))
}
func (t *Tree) SetPositionPath(keys []string, pos Position) {
	if len(keys) == 0 {
		t.position = pos
		return
	}
	subtree := t
	for _, intermediateKey := range keys[:len(keys)-1] {
		value, exists := subtree.values[intermediateKey]
		if !exists {
			return
		}
		switch node := value.(type) {
		case *Tree:
			subtree = node
		case []*Tree:
			if len(node) == 0 {
				return
			}
			subtree = node[len(node)-1]
		default:
			return
		}
	}
	switch node := subtree.values[keys[len(keys)-1]].(type) {
	case *tomlValue:
		node.position = pos
		return
	case *Tree:
		node.position = pos
		return
	case []*Tree:
		if len(node) == 0 {
			return
		}
		node[len(node)-1].position = pos
		return
	}
}
func (t *Tree) GetPositionPath(keys []string) Position {
	if len(keys) == 0 {
		return t.position
	}
	subtree := t
	for _, intermediateKey := range keys[:len(keys)-1] {
		value, exists := subtree.values[intermediateKey]
		if !exists {
			return Position{0, 0}
		}
		switch node := value.(type) {
		case *Tree:
			subtree = node
		case []*Tree:
			if len(node) == 0 {
				return Position{0, 0}
			}
			subtree = node[len(node)-1]
		default:
			return Position{0, 0}
		}
	}
	switch node := subtree.values[keys[len(keys)-1]].(type) {
	case *tomlValue:
		return node.position
	case *Tree:
		return node.position
	case []*Tree:
		if len(node) == 0 {
			return Position{0, 0}
		}
		return node[len(node)-1].position
	default:
		return Position{0, 0}
	}
}
func (t *Tree) GetDefault(key string, def interface{}) interface{} {
	val := t.Get(key)
	if val == nil {
		return def
	}
	return val
}
type SetOptions struct {
	Comment   string
	Commented bool
	Multiline bool
}
func (t *Tree) SetWithOptions(key string, opts SetOptions, value interface{}) {
	t.SetPathWithOptions(strings.Split(key, "."), opts, value)
}