...

Package ini

import "github.com/xdrpp/stc/ini"
Overview
Index
Examples

Overview ▾

Ini file parser library.

Index ▾

Variables
func EscapeIniValue(val string) string
func IniParse(sink IniSink, filename string) error
func IniParseContents(sink IniSink, filename string, contents []byte) error
func IniQKey(s *IniSection, key string) string
func ValidIniKey(s string) bool
func ValidIniSection(s string) bool
func ValidIniSubsection(s string) bool
type BadKey
    func (err BadKey) Error() string
type BadValue
    func (err BadValue) Error() string
type GenericIniSink
    func NewGenericSink(args ...string) *GenericIniSink
    func (s *GenericIniSink) AddField(name string, ptr interface{})
    func (s *GenericIniSink) AddStruct(i interface{})
    func (s *GenericIniSink) IniSink() IniSink
    func (s *GenericIniSink) Item(ii IniItem) error
    func (s *GenericIniSink) SaveAll(ies *IniEdits, includeZero bool)
    func (s *GenericIniSink) String() string
type IniEditor
    func NewIniEdit(filename string, contents []byte) (*IniEditor, error)
    func (ie *IniEditor) Add(is *IniSection, key, value string)
    func (ie *IniEditor) Del(is *IniSection, key string)
    func (ie *IniEditor) Done(r IniRange)
    func (ie *IniEditor) Item(ii IniItem) error
    func (ie *IniEditor) Section(ss IniSecStart) error
    func (ie *IniEditor) Set(is *IniSection, key, value string)
    func (ie *IniEditor) String() string
    func (ie *IniEditor) WriteTo(w io.Writer) (int64, error)
type IniEdits
    func (ie *IniEdits) Add(sec string, args ...string) error
    func (ie *IniEdits) Apply(target *IniEditor)
    func (ie *IniEdits) Del(sec string, args ...string) error
    func (ie *IniEdits) Set(sec string, args ...string) error
type IniItem
    func (ii *IniItem) QKey() string
    func (ii *IniItem) Val() string
type IniRange
type IniSecStart
type IniSection
    func (s *IniSection) Eq(s2 *IniSection) bool
    func (s *IniSection) String() string
    func (s *IniSection) Valid() bool
type IniSink
type IniSinker
type IniSinks
    func (s IniSinks) Done(IniRange)
    func (s IniSinks) IniSink() IniSink
    func (s IniSinks) Init()
    func (s IniSinks) Item(ii IniItem) error
    func (s *IniSinks) Push(i IniSink)
    func (s IniSinks) Section(ss IniSecStart) error
    func (s IniSinks) String() string
type ParseError
    func (err ParseError) Error() string
type ParseErrors
    func (err ParseErrors) Error() string

Examples

GenericIniSink
IniParseContents

Package files

edit.go parser.go sinker.go

Variables

var ErrInvalidNumArgs = fmt.Errorf("invalid number of arguments")
var ErrInvalidSection = fmt.Errorf("syntactically invalid section")

func EscapeIniValue

func EscapeIniValue(val string) string

func IniParse

func IniParse(sink IniSink, filename string) error

Open, read, and parse an INI file. If the file is incorrectly formatted, will return an error of type ParseErrors.

func IniParseContents

func IniParseContents(sink IniSink, filename string, contents []byte) error

Parse the contents of an INI file. The filename argument is used only for error messages.

Example

Code:

package ini_test

import (
    "fmt"
    "github.com/xdrpp/stc/ini"
)

type IniDumper struct{}

func (IniDumper) Item(item ini.IniItem) error {
    if item.Value == nil {
        fmt.Printf("%s\n", item.QKey())
    } else {
        fmt.Printf("%s = %s\n", item.QKey(), *item.Value)
    }
    return nil
}

var contents = []byte(`
# discouraged (like git-config, you can't edit keys outside of sections)
bare-key = bare value
[section]
key1 = value1
[other "sub"]
key2 = value2
key3 # this one has no value
key4 = " value4"   ; this one started with a space
`)

func ExampleIniParseContents() {
    ini.IniParseContents(IniDumper{}, "(test)", contents)
    // Output:
    // bare-key = bare value
    // section.key1 = value1
    // other.sub.key2 = value2
    // other.sub.key3
    // other.sub.key4 =  value4
}

func IniQKey

func IniQKey(s *IniSection, key string) string

Produce a fully "qualified" key consisting of the section, optional subsection, and key separated by dots, as understood by the git-config command.

func ValidIniKey

func ValidIniKey(s string) bool

Test if string is a valid INI file key. Valid keys start with a letter followed by zero or more alphanumeric characters or '-' characters.

func ValidIniSection

func ValidIniSection(s string) bool

Test if a string is a valid INI file section name. Section names cannot be the empty string and must consist only of alphanumeric characters and '-'.

func ValidIniSubsection

func ValidIniSubsection(s string) bool

Test if a string is a valid subsection name in an INI file. Specifically, subsection names may not contain a newline or NUL byte.

type BadKey

Error that an IniSink's Value method should return when there is a problem with the key, rather than a problem with the value. By default, the line and column number of an error will correspond to the start of the value, but with BadKey the error will point to the key.

type BadKey string

func (BadKey) Error

func (err BadKey) Error() string

type BadValue

Just a random error type useful for bad values in INI files. Exists for symmetry with BadKey, though BadValue is in no way special.

type BadValue string

func (BadValue) Error

func (err BadValue) Error() string

type GenericIniSink

A generic IniSink that uses fmt.Sscan to parse non-string fields.

type GenericIniSink struct {
    // If non-nil, only match this specific section (otherwise
    // ignore).
    Sec *IniSection

    // Pointers to the fields that should be parsed.
    Fields map[string]interface{}
}

Example

Code:

package ini_test

import (
    "fmt"
    "github.com/xdrpp/stc/ini"
    "strings"
)

type Foo struct {
    A_field           int
    AnotherField      string `ini:"the-field"`
    StillAnotherField bool
    StrVec            []string
    IntVec            []int
}

func trimSpace(i interface{}) string {
    s := fmt.Sprint(i)
    return strings.ReplaceAll(s, " \n", "\n")
}

func ExampleGenericIniSink() {
    var contents = []byte(`
[foo]
    A-field = 44
    the-field
    the-field = hello world
    StillAnotherField = true
    StrVec = a string
    StrVec = another string
    IntVec = 101
    IntVec = 102
    IntVec	 # This erases previous entries
    IntVec = 100
`)

    foo := Foo{}
    gs := ini.NewGenericSink("foo")
    gs.AddStruct(&foo)
    fmt.Println("=== before:")
    fmt.Print(trimSpace(gs))
    fmt.Println("=== after:")
    err := ini.IniParseContents(gs, "(test)", contents)
    if err != nil {
        fmt.Println(err)
    }
    fmt.Print(trimSpace(gs))
    // Unordered output:
    // [foo]
    // === before:
    // 	A-field = 0
    // 	the-field =
    // 	StillAnotherField = false
    // === after:
    // [foo]
    // 	A-field = 44
    // 	the-field = hello world
    // 	StillAnotherField = true
    //	StrVec = a string
    //	StrVec = another string
    //	IntVec = 100
    //
}

func NewGenericSink

func NewGenericSink(args ...string) *GenericIniSink

NewGenericSink([section [, subsection])

func (*GenericIniSink) AddField

func (s *GenericIniSink) AddField(name string, ptr interface{})

Add a field to be parsed

func (*GenericIniSink) AddStruct

func (s *GenericIniSink) AddStruct(i interface{})

Populate a GenericIniSink with fields of a struct, using the field name or or the ini struct field tag (`ini:"field-name"`) if one exists. Tag `ini:"-"` says to ignore a field. Note that i must be a pointer to a structure or this function will panic.

func (*GenericIniSink) IniSink

func (s *GenericIniSink) IniSink() IniSink

func (*GenericIniSink) Item

func (s *GenericIniSink) Item(ii IniItem) error

func (*GenericIniSink) SaveAll

func (s *GenericIniSink) SaveAll(ies *IniEdits, includeZero bool)

Save the current state of an Ini-parsable structure to a set of IniEdits. This is useful for creating an initial file. If includeZero is true, then all fields are saved; otherwise, only ones with non-default values are saved.

func (*GenericIniSink) String

func (s *GenericIniSink) String() string

type IniEditor

You can parse an INI file into an IniEditor, Set, Del, or Add key-value pairs, then write out the result using WriteTo. Preserves most comments and file ordering.

type IniEditor struct {
    // contains filtered or unexported fields
}

func NewIniEdit

func NewIniEdit(filename string, contents []byte) (*IniEditor, error)

Create an IniEdit for a file with contents. Note that filename is only used for parse errors; the file must already be read before calling this function.

func (*IniEditor) Add

func (ie *IniEditor) Add(is *IniSection, key, value string)

Add a new instance of key to the file without deleting any previous instance of the key.

func (*IniEditor) Del

func (ie *IniEditor) Del(is *IniSection, key string)

Delete all instances of a key from the file.

func (*IniEditor) Done

func (ie *IniEditor) Done(r IniRange)

Called by IniParseContents; do not call directly.

func (*IniEditor) Item

func (ie *IniEditor) Item(ii IniItem) error

Called by IniParseContents; do not call directly.

func (*IniEditor) Section

func (ie *IniEditor) Section(ss IniSecStart) error

Called by IniParseContents; do not call directly.

func (*IniEditor) Set

func (ie *IniEditor) Set(is *IniSection, key, value string)

Replace all instances of key with a single one equal to value.

func (*IniEditor) String

func (ie *IniEditor) String() string

func (*IniEditor) WriteTo

func (ie *IniEditor) WriteTo(w io.Writer) (int64, error)

Write the contents of IniEditor to a Writer after applying edits have been made.

type IniEdits

A bunch of edits to be applied to an INI file.

type IniEdits []func(*IniEditor)

func (*IniEdits) Add

func (ie *IniEdits) Add(sec string, args ...string) error

Add a key, value pair. Invoke as Add(sec, subsec, key, value) or Add(sec, key, value).

func (*IniEdits) Apply

func (ie *IniEdits) Apply(target *IniEditor)

Apply edits.

func (*IniEdits) Del

func (ie *IniEdits) Del(sec string, args ...string) error

Delete a key. Invoke as Del(sec, subsec, key) or Del(sec, key).

func (*IniEdits) Set

func (ie *IniEdits) Set(sec string, args ...string) error

Add a key, value pair. Invoke as Set(sec, subsec, key, value) or Set(sec, key, value).

type IniItem

type IniItem struct {
    *IniSection
    Key   string
    Value *string
    IniRange
}

func (*IniItem) QKey

func (ii *IniItem) QKey() string

Returns the Key qualified by the section (see IniQKey).

func (*IniItem) Val

func (ii *IniItem) Val() string

Returns Value or an empty string if Value is nil.

type IniRange

type IniRange struct {
    // The text of a key, value pair or section header lies between
    // StartIndex and EndIndex.  If PrevEndIndex != StartIndex, then
    // the bytes between PrevEndIndex and StartIndex constitute a
    // comment or blank lines.
    StartIndex, EndIndex, PrevEndIndex int

    // The entire input file
    Input []byte
}

type IniSecStart

type IniSecStart struct {
    IniSection
    IniRange
}

type IniSection

Section of an INI file. A nil *IniSection corresponds to the "section-free" part of the file before the first section, which the git-config man page says is not valid, but the git-config tool halfway supports.

type IniSection struct {
    Section    string
    Subsection *string
}

func (*IniSection) Eq

func (s *IniSection) Eq(s2 *IniSection) bool

True if two *IniSection have the same contents.

func (*IniSection) String

func (s *IniSection) String() string

Renders as [section] or [section "subsection"]. The nil *IniSection renders as an empty string. Panics if the subsection includes the illegal characters '\n' or '\000'.

func (*IniSection) Valid

func (s *IniSection) Valid() bool

Returns false if either the section or subsection is illegal. Returns true for a nil *IniSection.

type IniSink

Type that receives and processes the parsed INI file. Note that if there is also Section(IniSecStart)error method, this is called at the start of sections, and if there is a Done(IniRange) method it is called at the end of the file.

type IniSink interface {
    // optional:
    // Section(IniSecStart) error
    // Init()
    // Done()
    //
    Item(IniItem) error
}

type IniSinker

type IniSinker interface {
    IniSink() IniSink
}

type IniSinks

type IniSinks []IniSink

func (IniSinks) Done

func (s IniSinks) Done(IniRange)

func (IniSinks) IniSink

func (s IniSinks) IniSink() IniSink

func (IniSinks) Init

func (s IniSinks) Init()

func (IniSinks) Item

func (s IniSinks) Item(ii IniItem) error

func (*IniSinks) Push

func (s *IniSinks) Push(i IniSink)

func (IniSinks) Section

func (s IniSinks) Section(ss IniSecStart) error

func (IniSinks) String

func (s IniSinks) String() string

type ParseError

A single parse error in an IniFile.

type ParseError struct {
    File          string
    Lineno, Colno int
    Msg           string
}

func (ParseError) Error

func (err ParseError) Error() string

type ParseErrors

The collection of parse errors that resulted from parsing a file.

type ParseErrors []ParseError

func (ParseErrors) Error

func (err ParseErrors) Error() string