Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c01d1270ff | |||
| 66540cf1fc | |||
| 05bcc0fb0d |
+3
-2
@@ -1,8 +1,9 @@
|
|||||||
sudo: false
|
sudo: false
|
||||||
language: go
|
language: go
|
||||||
go:
|
go:
|
||||||
- 1.8.5
|
- 1.8.x
|
||||||
- 1.9.2
|
- 1.9.x
|
||||||
|
- 1.10.x
|
||||||
- tip
|
- tip
|
||||||
matrix:
|
matrix:
|
||||||
allow_failures:
|
allow_failures:
|
||||||
|
|||||||
@@ -17,13 +17,12 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
flag.Usage = func() {
|
flag.Usage = func() {
|
||||||
fmt.Fprintln(os.Stderr, `tomljson can be used in two ways:
|
fmt.Fprintln(os.Stderr, "tomljson can be used in two ways:")
|
||||||
Writing to STDIN and reading from STDOUT:
|
fmt.Fprintln(os.Stderr, "Writing to STDIN and reading from STDOUT:")
|
||||||
cat file.toml | tomljson > file.json
|
fmt.Fprintln(os.Stderr, " cat file.toml | tomljson > file.json")
|
||||||
|
fmt.Fprintln(os.Stderr, "")
|
||||||
Reading from a file name:
|
fmt.Fprintln(os.Stderr, "Reading from a file name:")
|
||||||
tomljson file.toml
|
fmt.Fprintln(os.Stderr, " tomljson file.toml")
|
||||||
`)
|
|
||||||
}
|
}
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
os.Exit(processMain(flag.Args(), os.Stdin, os.Stdout, os.Stderr))
|
os.Exit(processMain(flag.Args(), os.Stdin, os.Stdout, os.Stderr))
|
||||||
|
|||||||
+8
-9
@@ -17,15 +17,14 @@ import (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
flag.Usage = func() {
|
flag.Usage = func() {
|
||||||
fmt.Fprintln(os.Stderr, `tomll can be used in two ways:
|
fmt.Fprintln(os.Stderr, "tomll can be used in two ways:")
|
||||||
Writing to STDIN and reading from STDOUT:
|
fmt.Fprintln(os.Stderr, "Writing to STDIN and reading from STDOUT:")
|
||||||
cat file.toml | tomll > file.toml
|
fmt.Fprintln(os.Stderr, " cat file.toml | tomll > file.toml")
|
||||||
|
fmt.Fprintln(os.Stderr, "")
|
||||||
Reading and updating a list of files:
|
fmt.Fprintln(os.Stderr, "Reading and updating a list of files:")
|
||||||
tomll a.toml b.toml c.toml
|
fmt.Fprintln(os.Stderr, " tomll a.toml b.toml c.toml")
|
||||||
|
fmt.Fprintln(os.Stderr, "")
|
||||||
When given a list of files, tomll will modify all files in place without asking.
|
fmt.Fprintln(os.Stderr, "When given a list of files, tomll will modify all files in place without asking.")
|
||||||
`)
|
|
||||||
}
|
}
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
// read from stdin and print to stdout
|
// read from stdin and print to stdout
|
||||||
|
|||||||
+12
-3
@@ -11,10 +11,13 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const tagKeyMultiline = "multiline"
|
||||||
|
|
||||||
type tomlOpts struct {
|
type tomlOpts struct {
|
||||||
name string
|
name string
|
||||||
comment string
|
comment string
|
||||||
commented bool
|
commented bool
|
||||||
|
multiline bool
|
||||||
include bool
|
include bool
|
||||||
omitempty bool
|
omitempty bool
|
||||||
}
|
}
|
||||||
@@ -187,7 +190,7 @@ func (e *Encoder) QuoteMapKeys(v bool) *Encoder {
|
|||||||
// A = [
|
// A = [
|
||||||
// 1,
|
// 1,
|
||||||
// 2,
|
// 2,
|
||||||
// 3
|
// 3,
|
||||||
// ]
|
// ]
|
||||||
func (e *Encoder) ArraysWithOneElementPerLine(v bool) *Encoder {
|
func (e *Encoder) ArraysWithOneElementPerLine(v bool) *Encoder {
|
||||||
e.arraysOneElementPerLine = v
|
e.arraysOneElementPerLine = v
|
||||||
@@ -230,7 +233,12 @@ func (e *Encoder) valueToTree(mtype reflect.Type, mval reflect.Value) (*Tree, er
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
tval.SetWithComment(opts.name, opts.comment, opts.commented, val)
|
|
||||||
|
tval.SetWithOptions(opts.name, SetOptions{
|
||||||
|
Comment: opts.comment,
|
||||||
|
Commented: opts.commented,
|
||||||
|
Multiline: opts.multiline,
|
||||||
|
}, val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case reflect.Map:
|
case reflect.Map:
|
||||||
@@ -559,7 +567,8 @@ func tomlOptions(vf reflect.StructField) tomlOpts {
|
|||||||
comment = c
|
comment = c
|
||||||
}
|
}
|
||||||
commented, _ := strconv.ParseBool(vf.Tag.Get("commented"))
|
commented, _ := strconv.ParseBool(vf.Tag.Get("commented"))
|
||||||
result := tomlOpts{name: vf.Name, comment: comment, commented: commented, include: true, omitempty: false}
|
multiline, _ := strconv.ParseBool(vf.Tag.Get(tagKeyMultiline))
|
||||||
|
result := tomlOpts{name: vf.Name, comment: comment, commented: commented, multiline: multiline, include: true, omitempty: false}
|
||||||
if parse[0] != "" {
|
if parse[0] != "" {
|
||||||
if parse[0] == "-" && len(parse) == 1 {
|
if parse[0] == "-" && len(parse) == 1 {
|
||||||
result.include = false
|
result.include = false
|
||||||
|
|||||||
+1
-1
@@ -775,7 +775,7 @@ func TestMarshalArrayOnePerLine(t *testing.T) {
|
|||||||
B = [
|
B = [
|
||||||
1,
|
1,
|
||||||
2,
|
2,
|
||||||
3
|
3,
|
||||||
]
|
]
|
||||||
C = [1]
|
C = [1]
|
||||||
`)
|
`)
|
||||||
|
|||||||
@@ -2,12 +2,13 @@ package query
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pelletier/go-toml"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/pelletier/go-toml"
|
||||||
)
|
)
|
||||||
|
|
||||||
type queryTestNode struct {
|
type queryTestNode struct {
|
||||||
@@ -406,8 +407,7 @@ func TestQueryFilterFn(t *testing.T) {
|
|||||||
|
|
||||||
assertQueryPositions(t, string(buff),
|
assertQueryPositions(t, string(buff),
|
||||||
"$..[?(float)]",
|
"$..[?(float)]",
|
||||||
[]interface{}{
|
[]interface{}{ // no float values in document
|
||||||
// no float values in document
|
|
||||||
})
|
})
|
||||||
|
|
||||||
tv, _ := time.Parse(time.RFC3339, "1979-05-27T07:32:00Z")
|
tv, _ := time.Parse(time.RFC3339, "1979-05-27T07:32:00Z")
|
||||||
|
|||||||
@@ -23,9 +23,6 @@ function git_clone() {
|
|||||||
# Remove potential previous runs
|
# Remove potential previous runs
|
||||||
rm -rf src test_program_bin toml-test
|
rm -rf src test_program_bin toml-test
|
||||||
|
|
||||||
# Run go vet
|
|
||||||
go vet ./...
|
|
||||||
|
|
||||||
go get github.com/pelletier/go-buffruneio
|
go get github.com/pelletier/go-buffruneio
|
||||||
go get github.com/davecgh/go-spew/spew
|
go get github.com/davecgh/go-spew/spew
|
||||||
go get gopkg.in/yaml.v2
|
go get gopkg.in/yaml.v2
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ type tomlValue struct {
|
|||||||
value interface{} // string, int64, uint64, float64, bool, time.Time, [] of any of this list
|
value interface{} // string, int64, uint64, float64, bool, time.Time, [] of any of this list
|
||||||
comment string
|
comment string
|
||||||
commented bool
|
commented bool
|
||||||
|
multiline bool
|
||||||
position Position
|
position Position
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,6 +176,63 @@ func (t *Tree) GetDefault(key string, def interface{}) interface{} {
|
|||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetOptions arguments are supplied to the SetWithOptions and SetPathWithOptions functions to modify marshalling behaviour.
|
||||||
|
// The default values within the struct are valid default options.
|
||||||
|
type SetOptions struct {
|
||||||
|
Comment string
|
||||||
|
Commented bool
|
||||||
|
Multiline bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetWithOptions is the same as Set, but allows you to provide formatting
|
||||||
|
// instructions to the key, that will be used by Marshal().
|
||||||
|
func (t *Tree) SetWithOptions(key string, opts SetOptions, value interface{}) {
|
||||||
|
t.SetPathWithOptions(strings.Split(key, "."), opts, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetPathWithOptions is the same as SetPath, but allows you to provide
|
||||||
|
// formatting instructions to the key, that will be reused by Marshal().
|
||||||
|
func (t *Tree) SetPathWithOptions(keys []string, opts SetOptions, value interface{}) {
|
||||||
|
subtree := t
|
||||||
|
for _, intermediateKey := range keys[:len(keys)-1] {
|
||||||
|
nextTree, exists := subtree.values[intermediateKey]
|
||||||
|
if !exists {
|
||||||
|
nextTree = newTree()
|
||||||
|
subtree.values[intermediateKey] = nextTree // add new element here
|
||||||
|
}
|
||||||
|
switch node := nextTree.(type) {
|
||||||
|
case *Tree:
|
||||||
|
subtree = node
|
||||||
|
case []*Tree:
|
||||||
|
// go to most recent element
|
||||||
|
if len(node) == 0 {
|
||||||
|
// create element if it does not exist
|
||||||
|
subtree.values[intermediateKey] = append(node, newTree())
|
||||||
|
}
|
||||||
|
subtree = node[len(node)-1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var toInsert interface{}
|
||||||
|
|
||||||
|
switch value.(type) {
|
||||||
|
case *Tree:
|
||||||
|
tt := value.(*Tree)
|
||||||
|
tt.comment = opts.Comment
|
||||||
|
toInsert = value
|
||||||
|
case []*Tree:
|
||||||
|
toInsert = value
|
||||||
|
case *tomlValue:
|
||||||
|
tt := value.(*tomlValue)
|
||||||
|
tt.comment = opts.Comment
|
||||||
|
toInsert = tt
|
||||||
|
default:
|
||||||
|
toInsert = &tomlValue{value: value, comment: opts.Comment, commented: opts.Commented, multiline: opts.Multiline}
|
||||||
|
}
|
||||||
|
|
||||||
|
subtree.values[keys[len(keys)-1]] = toInsert
|
||||||
|
}
|
||||||
|
|
||||||
// Set an element in the tree.
|
// Set an element in the tree.
|
||||||
// Key is a dot-separated path (e.g. a.b.c).
|
// Key is a dot-separated path (e.g. a.b.c).
|
||||||
// Creates all necessary intermediate trees, if needed.
|
// Creates all necessary intermediate trees, if needed.
|
||||||
|
|||||||
+50
-6
@@ -12,7 +12,41 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// encodes a string to a TOML-compliant string value
|
// Encodes a string to a TOML-compliant multi-line string value
|
||||||
|
// This function is a clone of the existing encodeTomlString function, except that whitespace characters
|
||||||
|
// are preserved. Quotation marks and backslashes are also not escaped.
|
||||||
|
func encodeMultilineTomlString(value string) string {
|
||||||
|
var b bytes.Buffer
|
||||||
|
|
||||||
|
for _, rr := range value {
|
||||||
|
switch rr {
|
||||||
|
case '\b':
|
||||||
|
b.WriteString(`\b`)
|
||||||
|
case '\t':
|
||||||
|
b.WriteString("\t")
|
||||||
|
case '\n':
|
||||||
|
b.WriteString("\n")
|
||||||
|
case '\f':
|
||||||
|
b.WriteString(`\f`)
|
||||||
|
case '\r':
|
||||||
|
b.WriteString("\r")
|
||||||
|
case '"':
|
||||||
|
b.WriteString(`"`)
|
||||||
|
case '\\':
|
||||||
|
b.WriteString(`\`)
|
||||||
|
default:
|
||||||
|
intRr := uint16(rr)
|
||||||
|
if intRr < 0x001F {
|
||||||
|
b.WriteString(fmt.Sprintf("\\u%0.4X", intRr))
|
||||||
|
} else {
|
||||||
|
b.WriteRune(rr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return b.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encodes a string to a TOML-compliant string value
|
||||||
func encodeTomlString(value string) string {
|
func encodeTomlString(value string) string {
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
|
|
||||||
@@ -45,6 +79,15 @@ func encodeTomlString(value string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func tomlValueStringRepresentation(v interface{}, indent string, arraysOneElementPerLine bool) (string, error) {
|
func tomlValueStringRepresentation(v interface{}, indent string, arraysOneElementPerLine bool) (string, error) {
|
||||||
|
// this interface check is added to dereference the change made in the writeTo function.
|
||||||
|
// That change was made to allow this function to see formatting options.
|
||||||
|
tv, ok := v.(*tomlValue)
|
||||||
|
if ok {
|
||||||
|
v = tv.value
|
||||||
|
} else {
|
||||||
|
tv = &tomlValue{}
|
||||||
|
}
|
||||||
|
|
||||||
switch value := v.(type) {
|
switch value := v.(type) {
|
||||||
case uint64:
|
case uint64:
|
||||||
return strconv.FormatUint(value, 10), nil
|
return strconv.FormatUint(value, 10), nil
|
||||||
@@ -58,6 +101,9 @@ func tomlValueStringRepresentation(v interface{}, indent string, arraysOneElemen
|
|||||||
}
|
}
|
||||||
return strings.ToLower(strconv.FormatFloat(value, 'f', -1, 32)), nil
|
return strings.ToLower(strconv.FormatFloat(value, 'f', -1, 32)), nil
|
||||||
case string:
|
case string:
|
||||||
|
if tv.multiline {
|
||||||
|
return "\"\"\"\n" + encodeMultilineTomlString(value) + "\"\"\"", nil
|
||||||
|
}
|
||||||
return "\"" + encodeTomlString(value) + "\"", nil
|
return "\"" + encodeTomlString(value) + "\"", nil
|
||||||
case []byte:
|
case []byte:
|
||||||
b, _ := v.([]byte)
|
b, _ := v.([]byte)
|
||||||
@@ -91,12 +137,10 @@ func tomlValueStringRepresentation(v interface{}, indent string, arraysOneElemen
|
|||||||
|
|
||||||
stringBuffer.WriteString("[\n")
|
stringBuffer.WriteString("[\n")
|
||||||
|
|
||||||
for i, value := range values {
|
for _, value := range values {
|
||||||
stringBuffer.WriteString(valueIndent)
|
stringBuffer.WriteString(valueIndent)
|
||||||
stringBuffer.WriteString(value)
|
stringBuffer.WriteString(value)
|
||||||
if i != len(values)-1 {
|
stringBuffer.WriteString(`,`)
|
||||||
stringBuffer.WriteString(`,`)
|
|
||||||
}
|
|
||||||
stringBuffer.WriteString("\n")
|
stringBuffer.WriteString("\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,7 +176,7 @@ func (t *Tree) writeTo(w io.Writer, indent, keyspace string, bytesCount int64, a
|
|||||||
return bytesCount, fmt.Errorf("invalid value type at %s: %T", k, t.values[k])
|
return bytesCount, fmt.Errorf("invalid value type at %s: %T", k, t.values[k])
|
||||||
}
|
}
|
||||||
|
|
||||||
repr, err := tomlValueStringRepresentation(v.value, indent, arraysOneElementPerLine)
|
repr, err := tomlValueStringRepresentation(v, indent, arraysOneElementPerLine)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return bytesCount, err
|
return bytesCount, err
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user