func (f *File) RemoveKey(key string) {
	name, k := f.NameSplitFunc(key)
	section := f.GetSection(name)
	if section == nil {
		return
	}
	section.RemoveKey(k)
}
RemoveKey removes a key and its value from file with name in form of
section.key.

If no section is specified, then the empty (first) section is used.

Uses File's NameSplitFunc to split the key.
package parser
import (
	"bytes"
	"fmt"
	"os"
)
type File struct {
	lines []*Line
	sections []*Section
	SectionManipFunc func(string) string
	SectionNameFunc func(string) string
	SectionCompFunc func(string, string) bool
	KeyManipFunc func(string) string
	KeyCompFunc func(string, string) bool
	ValueManipFunc func(string) string
	NameSplitFunc func(string) (string, string)
}
func NewFile(lines []*Line) *File {
	ret := &File{
		lines:    lines,
		sections: make([]*Section, 0),
		SectionManipFunc: SectionManipFunc,
		SectionNameFunc:  SectionNameFunc,
		SectionCompFunc:  nil,
		KeyManipFunc:     KeyManipFunc,
		KeyCompFunc:      KeyCompFunc,
		ValueManipFunc:   ValueManipFunc,
		NameSplitFunc:    NameSplitFunc,
	}
	lastSection := NewSection(position{}, "", "", nil)
	lastSection.file = ret
	ret.sections = append(ret.sections, lastSection)
	for _, l := range lines {
		switch l.item.(type) {
		case *Section:
			lastSection, _ = l.item.(*Section)
			lastSection.file = ret
			ret.sections = append(ret.sections, lastSection)
		case *KeyValuePair:
			kvp, _ := l.item.(*KeyValuePair)
			lastSection.keys = append(lastSection.keys, kvp.key)
		}
	}
	return ret
}
func (f File) String() string {
	var buf bytes.Buffer
	for _, l := range f.lines {
		buf.WriteString(l.String())
	}
	return buf.String()
}
func (f *File) Write(filename string) error {
	file, err := os.Create(filename)
	if err != nil {
		return err
	}
	defer file.Close()
	_, err = file.WriteString(f.String())
	return err
}
func (f *File) LineCount() int {
	return len(f.lines)
}
func (f *File) RawSectionNames() []string {
	names := make([]string, len(f.sections))
	for i, s := range f.sections {
		names[i] = s.RawName()
	}
	return names
}
func (f *File) SectionNames() []string {
	names := make([]string, len(f.sections))
	for i, s := range f.sections {
		names[i] = s.Name()
	}
	return names
}
func (f *File) AddSectionRaw(name string) *Section {
	if f.sectionNameComp(name, "") {
		return f.GetSection("")
	}
	s := NewSection(position{}, name, "", nil)
	s.file = f
	f.sections = append(f.sections, s)
	if len(f.lines) > 0 && f.lines[len(f.lines)-1].item == nil {
		f.lines[len(f.lines)-1].item = s
	} else {
		le := DefaultLineEnding
		if len(f.lines) > 0 {
			le = f.lines[0].le
		}
		l := NewLine(position{}, "", s, le)
		f.lines = append(f.lines, l)
	}
	return s
}
func (f *File) AddSection(name string) *Section {
	return f.AddSectionRaw(f.SectionManipFunc(name))
}
func (f *File) sectionNameComp(a, b string) bool {
	if f.SectionCompFunc != nil {
		return f.SectionCompFunc(a, b)
	}
	return f.SectionNameFunc(a) == f.SectionNameFunc(b)
}
func (f *File) getSection(name string) (*Section, int) {
	n := f.SectionManipFunc(name)
	if f.sectionNameComp(n, "") {
		return f.sections[0], 0
	}
	for idx, line := range f.lines {
		if s, ok := line.item.(*Section); ok && f.sectionNameComp(n, s.name) {
			return s, idx
		}
	}
	return nil, -1
}
func (f *File) GetSection(name string) *Section {
	s, _ := f.getSection(name)
	return s
}
func (f *File) SetMap(values map[string]map[string]string) {
	for name, keys := range values {
		section := f.GetSection(name)
		if section == nil {
			section = f.AddSection(name)
		}
		for k, v := range keys {
			section.SetKey(k, v)
		}
	}
}
func (f *File) GetMap() map[string]map[string]string {
	ret := make(map[string]map[string]string)
	for _, section := range f.sections {
		s := make(map[string]string)
		for _, key := range section.keys {
			s[f.KeyManipFunc(key)] = f.ValueManipFunc(section.GetRaw(key))
		}
		ret[section.Name()] = s
	}
	return ret
}
func (f *File) SetMapFlat(values map[string]string) {
	for key, value := range values {
		f.SetKey(key, value)
	}
}
func (f *File) GetMapFlat() map[string]string {
	ret := make(map[string]string)
	for _, section := range f.sections {
		name := section.Name()
		if section.name != "" {
			name = fmt.Sprintf("%s%s", name, DefaultNameKeySeparator)
		}
		for _, key := range section.keys {
			ret[fmt.Sprintf("%s%s", name, key)] = f.ValueManipFunc(section.GetRaw(key))
		}
	}
	return ret
}
func (f *File) RenameSectionRaw(name, value string) {
	s := f.GetSection(name)
	s.name = value
}
func (f *File) RenameSection(name, value string) {
	f.RenameSectionRaw(name, f.SectionManipFunc(value))
}
func (f *File) RemoveSection(name string) {
	section, start := f.getSection(name)
	if section == nil {
		return
	}
	le := f.lines[0].le
	end := start + 1
	for ; end < len(f.lines); end++ {
		if _, ok := f.lines[end].item.(*Section); ok {
			break
		}
	}
	f.lines = append(f.lines[:start], f.lines[end:]...)
	if len(f.lines) < 1 {
		line := NewLine(position{}, "", nil, le)
		f.lines = []*Line{line}
	}
	pos := -1
	for idx, s := range f.sections {
		if section == s {
			pos = idx
			break
		}
	}
	f.sections = append(f.sections[:pos], f.sections[pos+1:]...)
}
func (f *File) SetKey(key, value string) {
	name, k := f.NameSplitFunc(key)
	section := f.GetSection(name)
	if section == nil {
		section = f.AddSection(name)
	}
	section.SetKey(k, value)
}
func (f *File) GetKey(key string) string {
	name, k := f.NameSplitFunc(key)
	section := f.GetSection(name)
	if section == nil {
		return ""
	}
	return section.Get(k)
}