gcfg

package
v0.0.0-...-31d8ec6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 7, 2013 License: GPL-3.0, BSD-2-Clause, BSD-3-Clause Imports: 8 Imported by: 0

Documentation

Overview

Package gcfg reads "gitconfig-like" text-based configuration files with "name=value" pairs grouped into sections (gcfg files). Support for writing gcfg files may be added later.

See ReadInto and the examples to get an idea of how to use it.

This package is still a work in progress, and both the supported syntax and the API is subject to change. See below for planned changes.

The syntax is based on that used by git config: http://git-scm.com/docs/git-config#_syntax . There are some (planned) differences compared to the git config format:

  • improve data portability:
  • must be encoded in UTF-8 (for now) and must not contain the 0 byte
  • include and "path" type is not supported (path type may be implementable as a user-defined type)
  • disallow potentially ambiguous or misleading definitions:
  • `[sec.sub]` format is not allowed (deprecated in gitconfig)
  • `[sec ""]` is not allowed
  • use `[sec]` for section name "sec" and empty subsection name
  • (planned) within a single file, definitions must be contiguous for each:
  • section: '[secA]' -> '[secB]' -> '[secA]' is an error
  • subsection: '[sec "A"]' -> '[sec "B"]' -> '[sec "A"]' is an error
  • multivalued variable: 'multi=a' -> 'other=x' -> 'multi=b' is an error

The package may be usable for handling some of the various "INI file" formats used by some programs and libraries, but achieving or maintaining compatibility with any of those is not a primary concern.

TODO:

  • format
  • define valid section and variable names
  • reconsider valid escape sequences (gitconfig doesn't support \r in value, \t in subsection name, etc.)
  • define handling of "implicit value" for types other than bool
  • consider handling of numeric values (decimal only by default?)
  • complete syntax documentation
  • reading
  • define internal representation structure
  • support multi-value variables
  • support multiple inputs (readers, strings, files)
  • support declaring encoding (?)
  • support automatic dereferencing of pointer fields (?)
  • support varying fields sets for subsections (?)
  • scanEnum
  • should use longest match (?)
  • support matching on unique prefix (?)
  • writing gcfg files
  • error handling
  • report position of extra characters in value
  • make error context accessible programmatically?
  • limit input size?
  • move TODOs to issue tracker (eventually)

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func ReadFileInto

func ReadFileInto(config interface{}, filename string) error

ReadFileInto reads gcfg formatted data from the file filename and sets the values into the corresponding fields in config. ReadFileInto is a wrapper for ReadInfo; see ReadInto(config, reader) for detailed description of how data is read and set into config.

func ReadInto

func ReadInto(config interface{}, reader io.Reader) error

ReadInto reads gcfg formatted data from reader and sets the values into the corresponding fields in config.

Config must be a pointer to a struct. Each section corresponds to a struct field in config, and each variable in a section corresponds to a data field in the section struct. The name of the field must match the name of the section or variable, ignoring case. Hyphens in section and variable names correspond to underscores in field names.

For sections with subsections, the corresponding field in config must be a map, rather than a struct, with string keys and pointer-to-struct values. Values for subsection variables are stored in the map with the subsection name used as the map key. (Note that unlike section and variable names, subsection names are case sensitive.) When using a map, and there is a section with the same section name but without a subsection name, its values are stored with the empty string used as the key.

The section structs in the config struct may contain arbitrary types. For string fields, the (unquoted and unescaped) value string is assigned to the field. For bool fields, the field is set to true if the value is "true", "yes", "on" or "1", and set to false if the value is "false", "no", "off" or "0", ignoring case. For all other types, fmt.Sscanf with the verb "%v" is used to parse the value string and set it to the field. This means that built-in Go types are parseable using the standard format, and any user-defined type is parseable if it implements the fmt.Scanner interface. Note that the value is considered invalid unless fmt.Scanner fully consumes the value string without error.

ReadInto panics if config is not a pointer to a struct, or if it encounters a field that is not of a suitable type (either a struct or a map with string keys and pointer-to-struct values).

See ReadStringInto for examples.

func ReadStringInto

func ReadStringInto(config interface{}, str string) error

ReadStringInto reads gcfg formatted data from str and sets the values into the corresponding fields in config. ReadStringInfo is a wrapper for ReadInfo; see ReadInto(config, reader) for detailed description of how data is read and set into config.

Example
package main

import (
	"fmt"
	"log"

	"code.google.com/p/gcfg"
)

func main() {
	cfgStr := `; Comment line
[section]
name=value # comment`
	cfg := struct {
		Section struct {
			Name string
		}
	}{}
	err := gcfg.ReadStringInto(&cfg, cfgStr)
	if err != nil {
		log.Fatalf("Failed to parse gcfg data: %s", err)
	}
	fmt.Println(cfg.Section.Name)
}
Output:

value
Example (Bool)
package main

import (
	"fmt"
	"log"

	"code.google.com/p/gcfg"
)

func main() {
	cfgStr := `; Comment line
[section]
switch=on`
	cfg := struct {
		Section struct {
			Switch bool
		}
	}{}
	err := gcfg.ReadStringInto(&cfg, cfgStr)
	if err != nil {
		log.Fatalf("Failed to parse gcfg data: %s", err)
	}
	fmt.Println(cfg.Section.Switch)
}
Output:

true
Example (Subsections)
package main

import (
	"fmt"
	"log"

	"code.google.com/p/gcfg"
)

func main() {
	cfgStr := `; Comment line
[profile "A"]
color = white

[profile "B"]
color = black
`
	cfg := struct {
		Profile map[string]*struct {
			Color string
		}
	}{}
	err := gcfg.ReadStringInto(&cfg, cfgStr)
	if err != nil {
		log.Fatalf("Failed to parse gcfg data: %s", err)
	}
	fmt.Printf("%s %s\n", cfg.Profile["A"].Color, cfg.Profile["B"].Color)
}
Output:

white black

Types

This section is empty.

Directories

Path Synopsis
Package scanner implements a scanner for gcfg configuration text.
Package scanner implements a scanner for gcfg configuration text.
Package token defines constants representing the lexical tokens of the gcfg configuration syntax and basic operations on tokens (printing, predicates).
Package token defines constants representing the lexical tokens of the gcfg configuration syntax and basic operations on tokens (printing, predicates).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL