Git Product home page Git Product logo

confl's Introduction

Yet another Config Parser for go

This is a config parser most similar to Nginx, supports Json format, but with line-breaks, comments, etc. Also, like Nginx is more lenient.

Uses same syntax as https://github.com/vstakhov/libucl

Code Coverage GoDoc Build Status Go ReportCard

Use SublimeText Nginx Plugin for formatting.

Credit to BurntSushi/Toml and Apcera/Gnatsd from which this was derived.

Other Options

There are a variety of options for config with comments in Go, this project started before some of them which are now probably better options:

Example

# nice, a config with comments!

# support the name = value format
title = "conf Example"
# support json semicolon
title2 : "conf example2"
# support omitting = or : because key starts a line
title3 "conf example"
# note, we do not have to have quotes
title4 = Without Quotes

# for Sections we can use brackets
hand {
  name = "Tyrion"
  organization = "Lannisters"
  bio = "Imp"                 // comments on fields
  dob = 1979-05-27T07:32:00Z  # dates, and more comments on fields
}

// Note, double-slash comment
// section name/value that is quoted and json valid, including commas
address : {
  "street"  : "1 Sky Cell",
  "city"    : "Eyre",
  "region"  : "Vale of Arryn",
  "country" : "Westeros"
}

# sections can omit the colon, equal before bracket 
seenwith {
  # nested section
  # can be spaces or tabs for nesting
  jaime : {
    season = season1
    episode = "episode1"
  }

  cersei = {
    season = season1
    episode = "episode1"
  }

}


# Line breaks are OK when inside arrays
seasons = [
  "season1",
  "season2",
  "season3",
  "season4",
  "???"
]


# long strings can use parens to allow multi-line
description (
    we possibly
    can have
    multi line text with a block paren
    block ends with end paren on new line
)



And the corresponding Go types are:

type Config struct {
	Title       string
	Hand        HandOfKing
	Location    *Address `confl:"address"`
	Seenwith    map[string]Character
	Seasons     []string
	Description string
}

type HandOfKing struct {
	Name     string
	Org      string `json:"organization"`  // Reads either confl, or json attributes
	Bio      string
	DOB      time.Time
	Deceased bool
}

type Address struct {
	Street  string
	City    string
	Region  string
	ZipCode int
}

type Character struct {
	Episode string
	Season  string
}

Note that a case insensitive match will be tried if an exact match can't be found.

A working example of the above can be found in _examples/example.{go,conf}.

Examples

This package works similarly to how the Go standard library handles XML and JSON. Namely, data is loaded into Go values via reflection.

For the simplest example, consider a file as just a list of keys and values:

// Comments in Config
Age = 25
# another comment
Cats = [ "Cauchy", "Plato" ]
# now, using quotes on key
"Pi" = 3.14
Perfection = [ 6, 28, 496, 8128 ]
DOB = 1987-07-05T05:45:00Z

Which could be defined in Go as:

type Config struct {
  Age int
  Cats []string
  Pi float64
  Perfection []int
  DOB time.Time 
}

And then decoded with:

var conf Config
if err := confl.Unmarshal(byteData, &conf); err != nil {
  // handle error
}

You can also use struct tags if your struct field name doesn't map to a confl key value directly:

some_key_NAME = "wat"
type Config struct {
  ObscureKey string `confl:"some_key_NAME"`
}

Using the encoding.TextUnmarshaler interface

Here's an example that automatically parses duration strings into time.Duration values:

song [
	{
		name = "Thunder Road"
		duration = "4m49s"
	},
	{
		name = "Stairway to Heaven"
		duration = "8m03s"
	}
]

Which can be decoded with:

type song struct {
  Name     string
  Duration duration
}
type songs struct {
  Song []song
}
var favorites songs
if err := confl.Unmarshal(blob, &favorites); err != nil {
  log.Fatal(err)
}

for _, s := range favorites.Song {
  fmt.Printf("%s (%s)\n", s.Name, s.Duration)
}

And you'll also need a duration type that satisfies the encoding.TextUnmarshaler interface:

type duration struct {
	time.Duration
}

func (d *duration) UnmarshalText(text []byte) error {
	var err error
	d.Duration, err = time.ParseDuration(string(text))
	return err
}

confl's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

confl's Issues

the style of nginx's configuration, how to deal it?

location ~* .(otf|eot|woff|ttf|woff2)$ {
types {font/opentype otf;}
types {application/vnd.ms-fontobject eot;}
types {font/truetype ttf;}
types {application/font-woff woff;}
types {font/woff2 woff2;}
}

location / {
try_files $uri $uri/ /index.html =404;
expires off;
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Strict-Transport-Security "max-age=86400" always;
}

Just like nginx's configuration, how do i deal it ?

Multi-line string includes closing paren

$ cd $GOPATH/src/github.com/lytics/confl/_examples
$ go run example.go | tail -3
    multi line text with a block paren
    block ends with end paren on new line
)

This is even more obvious if you temporarily change the code to

    fmt.Printf("Description: %q\n", config.Description)

Panic on multi-line strings when the string contains an empty line

panic: runtime error: slice bounds out of range

goroutine 1 [running]:
.../vendor/github.com/lytics/confl.maybeRemoveIndents(0xc4201394b2, 0x2a8, 0x20, 0xc420063af8)
	.../vendor/github.com/lytics/confl/parse.go:304 +0x22b
.../vendor/github.com/lytics/confl.(*parser).processItem(0xc4200de4d0, 0x5, 0xc4201394b2, 0x2a8, 0x56, 0x0, 0x0)
	.../vendor/github.com/lytics/confl/parse.go:170 +0x61b
vendor/github.com/lytics/confl.parse(0xc420139000, 0x75c, 0xc420139000, 0x0, 0x1520c40)
	.../vendor/github.com/lytics/confl/parse.go:92 +0x322
vendor/github.com/lytics/confl.Decode(0xc420139000, 0x75c, 0x13093e0, 0x1520060, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
	.../vendor/github.com/lytics/confl/decode.go:110 +0x7c
vendor/github.com/lytics/confl.DecodeFile(0x7ffeefbffb4b, 0xf, 0x13093e0, 0x1520060, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
	..vendor/github.com/lytics/confl/decode.go:128 +0x16e

Infinite loop on bad input

Courtesy of https://github.com/dvyukov/go-fuzz

I'll submit a pull request to include this in the tree next..

package main

import (
    "fmt"

    "github.com/lytics/confl"
)

func main() {
    var v map[string]interface{}
    fmt.Println("about to hang")
    confl.Unmarshal([]byte("\x0e9\xbd\xbf\xefr"), &v)
    fmt.Println("never gets here")
}

Why not follow the encoding/* conventions?

encoding/json and friends have an API in the style of

func Marshal(val interface{}) ([]byte, error)
func Unmarshal(data []byte, v interface{}) error

func NewEncoder(w io.Writer) *Encoder
func (enc *Encoder) Encode(v interface{}) error

func NewDecoder(r io.Reader) *Decoder
func (dec *Decoder) Decode(v interface{}) error

Where "decode" means streaming operations and "marshal" operates on []byte.

Why not follow that? Right now, the confl API seems unlike good Go, and especially Decode taking a string comes off as very weird.

Apart from that, looks good. I've been wanting something like this for a while, and while https://github.com/hashicorp/hcl also looked promising, it seems confl integrates with the Go style of unmarshaling into a struct better.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.