conf

package module
v1.0.4 Latest Latest
Warning

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

Go to latest
Published: Jun 12, 2022 License: MIT Imports: 4 Imported by: 1

README

Go Reference Go Report Card Build Status codecov

Package conf parses configuration data and populates a Go struct with the results.

The package documentation contains the configuration EBNF but here are some syntax examples:

Comments

# Lines beginning with punctuation are comments.
; Any punctuation except [] can begin a comment.
^ Just know that syntax highlighters won't always know what to do!

Keys and Values

key = value
keys can have spaces = values run until the end of the line
keys.can.have.punctuation = so can values!

values can be quoted = 'This value is quoted!'
quotes preserve whitespace = `
This value
spans
4 lines!`

# Quotes are only recognized if they are matching runes at the beginning and end of a value.
not quoted = asdf '" fdsa

# Quotes can be used to add quote characters to the parsed value.
quotes picked up = `"Hello!" said Dave.`

Invalid Keys

# Invalid - whitespace must be followed by [a-z0-9]
key . = oops

# Invalid - multiple punctuation not allowed
key.. = oops again

# Invalid - punctuation must join [a-z0-9] to [a-z0-9] without whitespace
key . key_extra = nope

Sections

Create a section with square brackets:

# These values are global
key1 = value1
key2 = value2

# This is a section named: color
[ color ]
name = red
rgb = #ff0000

Lists Require No Special Syntax

Create lists in your configuration by simply repeating keys or sections:

fruits = apples
fruits = oranges
fruits = bananas

[ color ]
name = red
rgb = ff0000

[ color ]
name = blue
rgb = 0000ff

[ color ]
name = green
rgb = 00ff00

Easily Populate a Conf Struct

Create a struct matching the configuration.

This struct is for the configuration just prior:

type T struct {
    Fruits []string `conf:"fruits"`

    Color []struct {
        Name string `conf:"name"`
        Rgb  string `conf:"rgb"`
    } `conf:"color"`
}

Consume the configuration either as a string or file.

conf, err := conf.String(s)
if err != nil {
    fmt.Println(err.Error())
}

We're using FillByTag to map the lowercase config values to our uppercase struct members:

var t T
if err = conf.FillByTag("conf", &t); err != nil {
    fmt.Println(err.Error())
}
fmt.Printf("%v\n", t.Fruits)
for _, color := range t.Color {
    fmt.Printf("%v %v\n", color.Name, color.Rgb)
}

Documentation

Overview

Package conf can parse configuration text and populate structs with the results.

Basic Syntax

Example:

# Lines beginning with punctuation are comments.
; Also a comment!

# key=value pairs are assigned to the current section or the global section
# if no section has been defined yet.

key1 = value1
key with spaces = value with spaces!

quote1 = 'This value is "quoted"'
quote2 = "  whitespace
is preserved in
quoted values!   "
quote3 = `backticks quote too!`

# Create a section with [ section-name ]
[ section ]
# This key value pair goes into a section named: section
key = value

[ sections can also have spaces ]
keys.can.have.punctuation.too = neat!

Repetition

Both keys and sections can be turned into lists by repeating them:

fruits = apples
fruits = oranges
fruits = bananas

[ color ]
name = red
rgb = ff0000

[ color ]
name = blue
rgb = 0000ff

[ color ]
name = green
rgb = 00ff00

Fill

Use Conf.Fill() and Conf.FillByTag() to populate parsed configuration into your structures. Examples are provided below.

Configuration EBNF

Here lies the EBNF for configuration syntax:

conf
	: line*
	;

line
	: comment
	| section
	| key_value
	;

section
	: '[' key ']'
	;

key_value
	: key '=' value
	;

key
	: [a-z0-9]+ key_extend*
	;

key_extend
	: punct [a-z0-9]+
	: ws+ [a-z0-9]+
	;

value
	: ['] ~[']* [']
	: ["] ~["]* ["]
	: [`] ~[`]* [`]
	: ~[rn]*
	;

comment
	: punct ~[rn]*
	;

punct
	: [!@#$%&*()_+=\|;:'"``,.<>/?~-^]
	;

ws
	: [ t]
	;

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Conf

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

Conf is a parsed configuration.

func File

func File(file string) (*Conf, error)

File returns a Conf type by reading and parsing the given file.

func String

func String(s string) (*Conf, error)

String returns a Conf type by parsing the given string of configuration data.

func (*Conf) Fill

func (me *Conf) Fill(target interface{}) error

Fill places the data from the configuration into the given target which should be a pointer to struct.

Example
package main

import (
	"fmt"

	"github.com/nofeaturesonlybugs/conf"
)

func main() {
	type T struct {
		First  string
		Second string

		Numbers struct {
			N []int
		}
	}
	s := `
First = I'm first!
Second = ...and I'm second.

[ Numbers ]
N = 42
N = 3
	`
	conf, err := conf.String(s)
	if err != nil {
		fmt.Println(err.Error())
	}
	var t T
	if err = conf.Fill(&t); err != nil {
		fmt.Println(err.Error())
	}
	fmt.Printf("First= %v\n", t.First)
	fmt.Printf("Second= %v\n", t.Second)
	fmt.Printf("N[0]= %v\n", t.Numbers.N[0])
	fmt.Printf("N[1]= %v\n", t.Numbers.N[1])
}
Output:

First= I'm first!
Second= ...and I'm second.
N[0]= 42
N[1]= 3
Example (WithRepetition)
package main

import (
	"fmt"

	"github.com/nofeaturesonlybugs/conf"
)

func main() {
	type T struct {
		Fruits []string

		Color []struct {
			Name string
			Rgb  string
		}
	}
	s := `
Fruits = apples
Fruits = oranges
Fruits = bananas

[ Color ]
Name = red
Rgb = ff0000

[ Color ]
Name = blue
Rgb = 0000ff

[ Color ]
Name = green
Rgb = 00ff00
		`
	conf, err := conf.String(s)
	if err != nil {
		fmt.Println(err.Error())
	}
	var t T
	if err = conf.Fill(&t); err != nil {
		fmt.Println(err.Error())
	}
	fmt.Printf("%v\n", t.Fruits)
	for _, color := range t.Color {
		fmt.Printf("%v %v\n", color.Name, color.Rgb)
	}

}
Output:

[apples oranges bananas]
red ff0000
blue 0000ff
green 00ff00

func (*Conf) FillByTag

func (me *Conf) FillByTag(tag string, target interface{}) error

FillByTag places the data from the configuration into the given target which should be a pointer to struct.

Example
package main

import (
	"fmt"

	"github.com/nofeaturesonlybugs/conf"
)

func main() {
	type T struct {
		First  string `conf:"first"`
		Second string `conf:"second"`

		Numbers struct {
			N []int `conf:"n"`
		} `conf:"numbers"`
	}
	s := `
first = I'm first!
second = ...and I'm second.

[ numbers ]
n = 42
n = 3
	`
	conf, err := conf.String(s)
	if err != nil {
		fmt.Println(err.Error())
	}
	var t T
	if err = conf.FillByTag("conf", &t); err != nil {
		fmt.Println(err.Error())
	}
	fmt.Printf("First= %v\n", t.First)
	fmt.Printf("Second= %v\n", t.Second)
	fmt.Printf("N[0]= %v\n", t.Numbers.N[0])
	fmt.Printf("N[1]= %v\n", t.Numbers.N[1])
}
Output:

First= I'm first!
Second= ...and I'm second.
N[0]= 42
N[1]= 3
Example (WithRepetition)
package main

import (
	"fmt"

	"github.com/nofeaturesonlybugs/conf"
)

func main() {
	type T struct {
		Fruits []string `conf:"fruits"`

		Color []struct {
			Name string `conf:"name"`
			Rgb  string `conf:"rgb"`
		} `conf:"color"`
	}
	s := `
fruits = apples
fruits = oranges
fruits = bananas

[ color ]
name = red
rgb = ff0000

[ color ]
name = blue
rgb = 0000ff

[ color ]
name = green
rgb = 00ff00
		`
	conf, err := conf.String(s)
	if err != nil {
		fmt.Println(err.Error())
	}
	var t T
	if err = conf.FillByTag("conf", &t); err != nil {
		fmt.Println(err.Error())
	}
	fmt.Printf("%v\n", t.Fruits)
	for _, color := range t.Color {
		fmt.Printf("%v %v\n", color.Name, color.Rgb)
	}

}
Output:

[apples oranges bananas]
red ff0000
blue 0000ff
green 00ff00

Directories

Path Synopsis
Package parser is the configurable parser for the conf package.
Package parser is the configurable parser for the conf package.

Jump to

Keyboard shortcuts

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