TOML to JSON cli tool (#85)
* Implement tomljson * Add note about tools in README
This commit is contained in:
@@ -81,6 +81,23 @@ if err != nil {
|
|||||||
The documentation and additional examples are available at
|
The documentation and additional examples are available at
|
||||||
[godoc.org](http://godoc.org/github.com/pelletier/go-toml).
|
[godoc.org](http://godoc.org/github.com/pelletier/go-toml).
|
||||||
|
|
||||||
|
## Tools
|
||||||
|
|
||||||
|
Go-toml provides two handy command line tools:
|
||||||
|
|
||||||
|
* `tomll`: Reads TOML files and lint them.
|
||||||
|
|
||||||
|
```
|
||||||
|
go install github.com/pelletier/go-toml/cmd/tomll
|
||||||
|
tomll --help
|
||||||
|
```
|
||||||
|
* `tomljson`: Reads a TOML file and outputs its JSON representation.
|
||||||
|
|
||||||
|
```
|
||||||
|
go install github.com/pelletier/go-toml/cmd/tomjson
|
||||||
|
tomljson --help
|
||||||
|
```
|
||||||
|
|
||||||
## Contribute
|
## Contribute
|
||||||
|
|
||||||
Feel free to report bugs and patches using GitHub's pull requests system on
|
Feel free to report bugs and patches using GitHub's pull requests system on
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/pelletier/go-toml"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"encoding/json"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
flag.Usage = func() {
|
||||||
|
fmt.Fprintln(os.Stderr, `tomljson can be used in two ways:
|
||||||
|
Writing to STDIN and reading from STDOUT:
|
||||||
|
cat file.toml | tomljson > file.json
|
||||||
|
|
||||||
|
Reading from a file name:
|
||||||
|
tomljson file.toml
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
flag.Parse()
|
||||||
|
os.Exit(processMain(flag.Args(), os.Stdin, os.Stdout, os.Stderr))
|
||||||
|
}
|
||||||
|
|
||||||
|
func processMain(files []string, defaultInput io.Reader, output io.Writer, errorOutput io.Writer) int {
|
||||||
|
// read from stdin and print to stdout
|
||||||
|
inputReader := defaultInput
|
||||||
|
|
||||||
|
if len(files) > 0 {
|
||||||
|
var err error
|
||||||
|
inputReader, err = os.Open(files[0])
|
||||||
|
if err != nil {
|
||||||
|
printError(err, errorOutput)
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s, err := reader(inputReader)
|
||||||
|
if err != nil {
|
||||||
|
printError(err, errorOutput)
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
io.WriteString(output, s + "\n")
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func printError(err error, output io.Writer) {
|
||||||
|
io.WriteString(output, err.Error() + "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func reader(r io.Reader) (string, error) {
|
||||||
|
tree, err := toml.LoadReader(r)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return mapToJson(tree)
|
||||||
|
}
|
||||||
|
|
||||||
|
func mapToJson(tree *toml.TomlTree) (string, error) {
|
||||||
|
treeMap := tree.ToMap()
|
||||||
|
bytes, err := json.MarshalIndent(treeMap, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return string(bytes[:]), nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"strings"
|
||||||
|
"bytes"
|
||||||
|
"os"
|
||||||
|
"io/ioutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func expectBufferEquality(t *testing.T, name string, buffer *bytes.Buffer, expected string) {
|
||||||
|
output := buffer.String()
|
||||||
|
if output != expected {
|
||||||
|
t.Errorf("incorrect %s:\n%s\n\nexpected %s:\n%s", name, output, name, expected)
|
||||||
|
t.Log([]rune(output))
|
||||||
|
t.Log([]rune(expected))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func expectProcessMainResults(t *testing.T, input string, args []string, exitCode int, expectedOutput string, expectedError string) {
|
||||||
|
inputReader := strings.NewReader(input)
|
||||||
|
outputBuffer := new(bytes.Buffer)
|
||||||
|
errorBuffer := new(bytes.Buffer)
|
||||||
|
|
||||||
|
returnCode := processMain(args, inputReader, outputBuffer, errorBuffer)
|
||||||
|
|
||||||
|
expectBufferEquality(t, "output", outputBuffer, expectedOutput)
|
||||||
|
expectBufferEquality(t, "error", errorBuffer, expectedError)
|
||||||
|
|
||||||
|
if returnCode != exitCode {
|
||||||
|
t.Error("incorrect return code:", returnCode, "expected", exitCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func TestProcessMainReadFromStdin(t *testing.T) {
|
||||||
|
input := `
|
||||||
|
[mytoml]
|
||||||
|
a = 42`
|
||||||
|
expectedOutput := `{
|
||||||
|
"mytoml": {
|
||||||
|
"a": 42
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
expectedError := ``
|
||||||
|
expectedExitCode := 0
|
||||||
|
|
||||||
|
expectProcessMainResults(t, input, []string{}, expectedExitCode, expectedOutput, expectedError)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessMainReadFromFile(t *testing.T) {
|
||||||
|
input := `
|
||||||
|
[mytoml]
|
||||||
|
a = 42`
|
||||||
|
|
||||||
|
|
||||||
|
tmpfile, err := ioutil.TempFile("", "example.toml")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if _, err := tmpfile.Write([]byte(input)); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer os.Remove(tmpfile.Name())
|
||||||
|
|
||||||
|
expectedOutput := `{
|
||||||
|
"mytoml": {
|
||||||
|
"a": 42
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
expectedError := ``
|
||||||
|
expectedExitCode := 0
|
||||||
|
|
||||||
|
expectProcessMainResults(t, ``, []string{tmpfile.Name()}, expectedExitCode, expectedOutput, expectedError)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProcessMainReadFromMissingFile(t *testing.T) {
|
||||||
|
expectedError := `open /this/file/does/not/exist: no such file or directory
|
||||||
|
`
|
||||||
|
expectProcessMainResults(t, ``, []string{"/this/file/does/not/exist"}, -1, ``, expectedError)
|
||||||
|
}
|
||||||
@@ -34,11 +34,12 @@ go build -o toml-test github.com/BurntSushi/toml-test
|
|||||||
# NOTE: this basically mocks an install without having to go back out to github for code
|
# NOTE: this basically mocks an install without having to go back out to github for code
|
||||||
mkdir -p src/github.com/pelletier/go-toml/cmd
|
mkdir -p src/github.com/pelletier/go-toml/cmd
|
||||||
cp *.go *.toml src/github.com/pelletier/go-toml
|
cp *.go *.toml src/github.com/pelletier/go-toml
|
||||||
cp cmd/*.go src/github.com/pelletier/go-toml/cmd
|
cp -R cmd/* src/github.com/pelletier/go-toml/cmd
|
||||||
go build -o test_program_bin src/github.com/pelletier/go-toml/cmd/test_program.go
|
go build -o test_program_bin src/github.com/pelletier/go-toml/cmd/test_program.go
|
||||||
|
|
||||||
# Run basic unit tests
|
# Run basic unit tests
|
||||||
go test -v github.com/pelletier/go-toml
|
go test github.com/pelletier/go-toml \
|
||||||
|
github.com/pelletier/go-toml/cmd/tomljson
|
||||||
|
|
||||||
# run the entire BurntSushi test suite
|
# run the entire BurntSushi test suite
|
||||||
if [[ $# -eq 0 ]] ; then
|
if [[ $# -eq 0 ]] ; then
|
||||||
|
|||||||
Reference in New Issue
Block a user