forge

package module
v0.2.3 Latest Latest
Warning

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

Go to latest
Published: Mar 22, 2017 License: MIT Imports: 13 Imported by: 4

README

forge

Build Status GoDoc

Forge is a configuration syntax and parser.

Installation

go get github.com/brettlangdon/forge

Documentation

Documentation can be viewed on godoc: https://godoc.org/github.com/brettlangdon/forge

Example

You can see example usage in the example folder.

# example.cfg

# Global directives
global = "global value";
# Primary section
primary {
  string = "primary string value";
  single = 'single quotes are allowed too';

  # Semicolons are optional
  integer = 500
  float = 80.80
  boolean = true
  negative = FALSE
  nothing = NULL

  list = [50.5, true, false, "hello", 'world'];

  # Include external files
  include "./include*.cfg";
  # Primary-sub section
  sub {
      key = "primary sub key value";
  }
}

# Secondary section
secondary {
  another = "secondary another value";
  global_reference = global;
  primary_sub_key = primary.sub.key;
  another_again = .another;  # References secondary.another
  _under = 50;
}
package main

import (
	"fmt"
	"json"

	"github.com/brettlangdon/forge"
)

func main() {
	// Parse a `SectionValue` from `example.cfg`
	settings, err := forge.ParseFile("example.cfg")
	if err != nil {
		panic(err)
	}

	// Get a single value
	if settings.Exists("global") {
		// Get `global` casted as a string
		value, _ := settings.GetString("global")
		fmt.Printf("global = \"%s\"\r\n", value)
	}

	// Get a nested value
	value, err := settings.Resolve("primary.included_setting")
	fmt.Printf("primary.included_setting = \"%s\"\r\n", value.GetValue())

	// You can also traverse down the sections manually
	primary, err := settings.GetSection("primary")
	strVal, err := primary.GetString("included_setting")
	fmt.Printf("primary.included_setting = \"%s\"\r\n", strVal)

	// Convert settings to a map
	settingsMap := settings.ToMap()
	fmt.Printf("global = \"%s\"\r\n", settingsMap["global"])

	// Convert settings to JSON
	jsonBytes, err := settings.ToJSON()
	fmt.Printf("\r\n\r\n%s\r\n", string(jsonBytes))
}

Issues/Requests?

Please feel free to open a github issue for any issues you have or any feature requests.

Documentation

Overview

Package forge provides an api to deal with parsing configuration files.

Config file example:

# example.cfg
top_level = "a string";
primary {
  primary_int = 500;
  sub_section {
    sub_float = 50.5;  # End of line comment
  }
}
secondary {
  secondary_bool = true;
  secondary_null = null;

  list = [
    "any",
    'value',
    true,
    55.5,
  ]

  # Reference other config value
  local_ref = .secondary_null;
  global_ref = primary.sub_section.sub_float;

  # Include all files matching the provided pattern
  include "/etc/app/*.cfg";
}

Config file format:

IDENTIFIER: [_a-zA-Z]([_a-zA-Z0-9]+)?
NUMBERS: [0-9]+
END: ';' | '\n'

BOOL: 'true' | 'false'
NULL: 'null'
INTEGER: ('-')? NUMBERS
FLOAT: ('-')? NUMBERS '.' NUMBERS
STRING: ['"] .* ['"]
REFERENCE: (IDENTIFIER)? ('.' IDENTIFIER)+
VALUE: BOOL | NULL | INTEGER | FLOAT | STRING | REFERENCE
LIST: '[' (VALUE | LIST) (',' NEWLINE* (VALUE | LIST))+ ']'

INCLUDE: 'include ' STRING END
DIRECTIVE: (IDENTIFIER '=' (VALUE | LIST) | INCLUDE) END
SECTION: IDENTIFIER '{' (DIRECTIVE | SECTION)* '}'
COMMENT: '#' .* '\n'

CONFIG_FILE: (COMMENT | DIRECTIVE | SECTION)*

Values

  • String: Any value enclosed in double or single quotes (e.g. "string" or 'string'). Double quotes, single quotes, and backslashes can be escaped with backslashes (e.g. "\"quoted\"", '\'quoted\”, and "\\<--backslash")
  • Integer: Any number without decimal places (e.g. 500)
  • Float: Any number with decimal places (e.g. 500.55)
  • Boolean: The identifiers 'true' or 'false' of any case (e.g. TRUE, True, true, FALSE, False, false)
  • Null: The identifier 'null' of any case (e.g. NULL, Null, null)
  • List: A list value is any number of other values separated by commas and surrounded by brackets. (e.g. [50.5, 'some', "string", true, false])
  • Global reference: An identifier which may contain periods, the references are resolved from the global section (e.g. global_value, section.sub_section.value)
  • Local reference: An identifier which main contain periods which starts with a period, the references are resolved from the settings current section (e.g. .value, .sub_section.value)

Directives

  • Comment: A comment is a pound symbol ('#') followed by any text any which ends with a newline (e.g. '# I am a comment\n') A comment can either be on a line of it's own or at the end of any line. Nothing can come after the comment until after the newline.
  • Directive: A directive is a setting, a identifier and a value. They are in the format '<identifier> = <value>;' All directives must end in either a semicolon or newline. The value can be any of the types defined above.
  • Section: A section is a grouping of directives under a common name. They are in the format '<section_name> { <directives> }'. All sections must be wrapped in braces ('{', '}') and must all have a name. They do not end in a semicolon. Sections may be left empty, they do not have to contain any directives.
  • Include: An include statement tells the config parser to include the contents of another config file where the include statement is defined. Includes are in the format 'include "<pattern>";'. The <pattern> can be any glob like pattern which is compatible with `path.filepath.Match` http://golang.org/pkg/path/filepath/#Match
Example
package main

import (
	"fmt"

	"github.com/brettlangdon/forge"
)

func main() {
	// Parse a `SectionValue` from `example.cfg`
	settings, err := forge.ParseFile("example.cfg")
	if err != nil {
		panic(err)
	}

	// Get a single value
	if settings.Exists("global") {
		// Get `global` casted as a string
		value, _ := settings.GetString("global")
		fmt.Printf("global = \"%s\"\r\n", value)
	}

	// Get a nested value
	value, err := settings.Resolve("primary.included_setting")
	fmt.Printf("primary.included_setting = \"%s\"\r\n", value.GetValue())

	// You can also traverse down the sections manually
	primary, err := settings.GetSection("primary")
	strVal, err := primary.GetString("included_setting")
	fmt.Printf("primary.included_setting = \"%s\"\r\n", strVal)

	// Convert settings to a map
	settingsMap := settings.ToMap()
	fmt.Printf("global = \"%s\"\r\n", settingsMap["global"])

	// Convert settings to JSON
	jsonBytes, err := settings.ToJSON()
	fmt.Printf("\r\n\r\n%s\r\n", string(jsonBytes))
}
Output:

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// ErrNotExists represents a nonexistent value error
	ErrNotExists = errors.New("value does not exist")
)

Functions

This section is empty.

Types

type List added in v0.1.5

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

List struct used for holding data neede for Reference data type

func NewList added in v0.1.5

func NewList() *List

NewList will create and initialize a new List value

func (*List) Append added in v0.1.5

func (list *List) Append(value Value)

Append will append a new Value on the end of the internal list

func (*List) Get added in v0.1.5

func (list *List) Get(idx int) (Value, error)

Get will return the Value at the index

func (*List) GetBoolean added in v0.1.5

func (list *List) GetBoolean(idx int) (bool, error)

GetBoolean will try to get the value stored at the index as a bool will respond with an error if the value does not exist or cannot be converted to a bool

func (*List) GetFloat added in v0.1.5

func (list *List) GetFloat(idx int) (float64, error)

GetFloat will try to get the value stored at the index as a float64 will respond with an error if the value does not exist or cannot be converted to a float64

func (*List) GetInteger added in v0.1.5

func (list *List) GetInteger(idx int) (int64, error)

GetInteger will try to get the value stored at the index as a int64 will respond with an error if the value does not exist or cannot be converted to a int64

func (*List) GetList added in v0.1.5

func (list *List) GetList(idx int) (*List, error)

GetList will try to get the value stored at the index as a List will respond with an error if the value does not exist or is not a List

func (*List) GetString added in v0.1.5

func (list *List) GetString(idx int) (string, error)

GetString will try to get the value stored at the index as a string will respond with an error if the value does not exist or cannot be converted to a string

func (*List) GetType added in v0.1.5

func (list *List) GetType() ValueType

GetType will simply return back LIST

func (*List) GetValue added in v0.1.5

func (list *List) GetValue() interface{}

GetValue will resolve and return the value from the underlying list this is necessary to inherit from Value

func (*List) GetValues added in v0.1.5

func (list *List) GetValues() []Value

GetValues will return back the list of underlygin values

func (*List) Length added in v0.1.5

func (list *List) Length() int

Length will return back the total number of items in the list

func (*List) Set added in v0.1.5

func (list *List) Set(idx int, value Value)

Set will set the new Value at the index

func (*List) UpdateValue added in v0.1.5

func (list *List) UpdateValue(value interface{}) error

UpdateValue will set the underlying list value

type Parser

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

Parser is a struct to hold data necessary for parsing a config from a scanner

func NewFileParser

func NewFileParser(filename string) (*Parser, error)

NewFileParser will create and initialize a new Parser from a provided from a filename string

func NewParser

func NewParser(reader io.Reader) *Parser

NewParser will create and initialize a new Parser from a provided io.Reader

func (*Parser) GetSettings

func (parser *Parser) GetSettings() *Section

GetSettings will fetch the parsed settings from this Parser

func (*Parser) Parse

func (parser *Parser) Parse() error

Parse will tell the Parser to parse all settings from the config

type Primative

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

Primative struct for holding data about primative values

func NewBoolean

func NewBoolean(value bool) *Primative

NewBoolean will create and initialize a new Boolean type primative value

func NewFloat

func NewFloat(value float64) *Primative

NewFloat will create and initialize a new Float type primative value

func NewInteger

func NewInteger(value int64) *Primative

NewInteger will create and initialize a new Integer type primative value

func NewNull

func NewNull() *Primative

NewNull will create and initialize a new Null type primative value

func NewPrimative

func NewPrimative(value interface{}) (*Primative, error)

NewPrimative will create a new empty Primative and call UpdateValue with the provided value

func NewString

func NewString(value string) *Primative

NewString will create and initialize a new String type primative value

func (*Primative) AsBoolean

func (primative *Primative) AsBoolean() (bool, error)

AsBoolean tries to convert/return the value stored in this primative as a bool

func (*Primative) AsFloat

func (primative *Primative) AsFloat() (float64, error)

AsFloat tries to convert/return the value stored in this primative as a float64

func (*Primative) AsInteger

func (primative *Primative) AsInteger() (int64, error)

AsInteger tries to convert/return the value stored in this primative as a int64

func (*Primative) AsNull

func (primative *Primative) AsNull() (interface{}, error)

AsNull tries to convert/return the value stored in this primative as a null

func (*Primative) AsString

func (primative *Primative) AsString() (string, error)

AsString tries to convert/return the value stored in this primative as a string

func (*Primative) GetType

func (primative *Primative) GetType() ValueType

GetType will return the ValueType associated with this primative

func (*Primative) GetValue

func (primative *Primative) GetValue() interface{}

GetValue returns the raw interface{} value assigned to this primative

func (*Primative) String

func (primative *Primative) String() string

func (*Primative) UpdateValue

func (primative *Primative) UpdateValue(value interface{}) error

UpdateValue will update the internal value and stored ValueType for this primative

type Reference

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

Reference struct used for holding data neede for Reference data type

func NewReference

func NewReference(name string, section *Section) *Reference

NewReference will create and initialize a new Reference value

func (*Reference) GetType

func (reference *Reference) GetType() ValueType

GetType will simply return back REFERENCE

func (*Reference) GetValue

func (reference *Reference) GetValue() interface{}

GetValue will resolve and return the value from the underlying reference

func (*Reference) UpdateValue

func (reference *Reference) UpdateValue(value interface{}) error

UpdateValue will simply throw an error since it is not allowed for References

type Scanner

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

Scanner struct used to hold data necessary for parsing tokens from the input reader

func NewScanner

func NewScanner(reader io.Reader) *Scanner

NewScanner creates and initializes a new *Scanner from an io.Readerx

func (*Scanner) NextToken

func (scanner *Scanner) NextToken() token.Token

NextToken will read in the next valid token from the Scanner

type Section

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

Section struct holds a map of values

func NewSection

func NewSection() *Section

NewSection will create and initialize a new Section

func ParseBytes

func ParseBytes(data []byte) (*Section, error)

ParseBytes takes a []byte representation of the config file, parses it and responds with `*Section` and potentially an `error` if it cannot properly parse the config

Example
package main

import (
	"fmt"

	"github.com/brettlangdon/forge"
)

func main() {
	// Parse a `SectionValue` from []byte containing the config
	data := []byte("amount = 500;")
	settings, err := forge.ParseBytes(data)
	if err != nil {
		panic(err)
	}

	fmt.Println(settings.GetInteger("amount"))
}
Output:

func ParseFile

func ParseFile(filename string) (*Section, error)

ParseFile takes a string filename for the config file, parses it and responds with `*Section` and potentially an `error` if it cannot properly parse the configf

Example
package main

import (
	"fmt"

	"github.com/brettlangdon/forge"
)

func main() {
	// Parse a `SectionValue` from `example.cfg`
	settings, err := forge.ParseFile("example.cfg")
	if err != nil {
		panic(err)
	}
	fmt.Println(settings)
}
Output:

func ParseReader

func ParseReader(reader io.Reader) (*Section, error)

ParseReader takes an `io.Reader` representation of the config file, parses it and responds with `*Section` and potentially an `error` if it cannot properly parse the config

Example
package main

import (
	"bytes"
	"fmt"

	"github.com/brettlangdon/forge"
)

func main() {
	// Parse a `SectionValue` from []byte containing the config
	data := []byte("amount = 500;")
	reader := bytes.NewBuffer(data)
	settings, err := forge.ParseReader(reader)
	if err != nil {
		panic(err)
	}

	fmt.Println(settings.GetInteger("amount"))
}
Output:

func ParseString

func ParseString(data string) (*Section, error)

ParseString takes a string representation of the config file, parses it and responds with `*Section` and potentially an `error` if it cannot properly parse the config

Example
package main

import (
	"fmt"

	"github.com/brettlangdon/forge"
)

func main() {
	// Parse a `SectionValue` from string containing the config
	data := "amount = 500;"
	settings, err := forge.ParseString(data)
	if err != nil {
		panic(err)
	}

	fmt.Println(settings.GetInteger("amount"))
}
Output:

func (*Section) AddComment

func (section *Section) AddComment(comment string)

AddComment will append a new comment into the section

func (*Section) AddInclude

func (section *Section) AddInclude(filename string)

AddInclude will append a new filename into the section

func (*Section) AddSection

func (section *Section) AddSection(name string) *Section

AddSection adds a new child section to this Section with the provided name

func (*Section) Exists

func (section *Section) Exists(name string) bool

Exists returns true when a value stored under the key exists

func (*Section) Get

func (section *Section) Get(name string) (Value, error)

Get the value (Primative or Section) stored under the name will respond with an error if the value does not exist

func (*Section) GetBoolean

func (section *Section) GetBoolean(name string) (bool, error)

GetBoolean will try to get the value stored under name as a bool will respond with an error if the value does not exist or cannot be converted to a bool

func (*Section) GetComments

func (section *Section) GetComments() []string

GetComments will return all the comments were defined for this Section

func (*Section) GetFloat

func (section *Section) GetFloat(name string) (float64, error)

GetFloat will try to get the value stored under name as a float64 will respond with an error if the value does not exist or cannot be converted to a float64

func (*Section) GetIncludes

func (section *Section) GetIncludes() []string

GetIncludes will return the filenames of all the includes were parsed for this Section

func (*Section) GetInteger

func (section *Section) GetInteger(name string) (int64, error)

GetInteger will try to get the value stored under name as a int64 will respond with an error if the value does not exist or cannot be converted to a int64

func (*Section) GetList added in v0.1.5

func (section *Section) GetList(name string) (*List, error)

GetList will try to get the value stored under name as a List will respond with an error if the value does not exist or is not a List

func (*Section) GetParent

func (section *Section) GetParent() *Section

GetParent will get the parent section associated with this Section or nil if it does not have one

func (*Section) GetSection

func (section *Section) GetSection(name string) (*Section, error)

GetSection will try to get the value stored under name as a Section will respond with an error if the value does not exist or is not a Section

func (*Section) GetString

func (section *Section) GetString(name string) (string, error)

GetString will try to get the value stored under name as a string will respond with an error if the value does not exist or cannot be converted to a string

func (*Section) GetType

func (section *Section) GetType() ValueType

GetType will respond with the ValueType of this Section (hint, always SECTION)

func (*Section) GetValue

func (section *Section) GetValue() interface{}

GetValue retrieves the raw underlying value stored in this Section

func (*Section) HasParent

func (section *Section) HasParent() bool

HasParent will return true if this Section has a parent

func (*Section) Keys added in v0.1.1

func (section *Section) Keys() []string

Keys will return back a list of all setting names in this Section

func (*Section) Merge added in v0.2.1

func (section *Section) Merge(source *Section) error

Merge merges the given section to current section. Settings from source section overwites the values in the current section

func (*Section) Resolve

func (section *Section) Resolve(name string) (Value, error)

Resolve will recursively try to fetch the provided value and will respond with an error if the name does not exist or tries to be resolved through a non-section value

func (*Section) Set

func (section *Section) Set(name string, value Value)

Set will set a value (Primative or Section) to the provided name

func (*Section) SetBoolean

func (section *Section) SetBoolean(name string, value bool)

SetBoolean will set the value for name as a bool

func (*Section) SetFloat

func (section *Section) SetFloat(name string, value float64)

SetFloat will set the value for name as a float64

func (*Section) SetInteger

func (section *Section) SetInteger(name string, value int64)

SetInteger will set the value for name as a int64

func (*Section) SetNull

func (section *Section) SetNull(name string)

SetNull will set the value for name as nil

func (*Section) SetString

func (section *Section) SetString(name string, value string)

SetString will set the value for name as a string

func (*Section) ToJSON

func (section *Section) ToJSON() ([]byte, error)

ToJSON will convert this Section and all it's underlying values and Sections into JSON as a []byte

func (*Section) ToMap

func (section *Section) ToMap() map[string]interface{}

ToMap will convert this Section and all it's underlying values and Sections into a map[string]interface{}

func (*Section) UpdateValue

func (section *Section) UpdateValue(value interface{}) error

UpdateValue updates the raw underlying value stored in this Section

type Value

type Value interface {
	GetType() ValueType
	GetValue() interface{}
	UpdateValue(interface{}) error
}

Value is the base interface for Primative and Section data types

type ValueType

type ValueType int

ValueType is an int type for representing the types of values forge can handle

const (
	// UNKNOWN ValueType
	UNKNOWN ValueType = iota

	// BOOLEAN ValueType
	BOOLEAN
	// FLOAT ValueType
	FLOAT
	// INTEGER ValueType
	INTEGER
	// NULL ValueType
	NULL
	// STRING ValueType
	STRING

	// LIST ValueType
	LIST
	// REFERENCE ValueType
	REFERENCE
	// SECTION ValueType
	SECTION
)

func (ValueType) String

func (valueType ValueType) String() string

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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