mirror of
https://github.com/mikefarah/yq.git
synced 2024-11-12 13:48:06 +00:00
Use cobra for cli for nicer cli-ness
This commit is contained in:
parent
1605938c2c
commit
1d5fbd5ad0
17
README.md
17
README.md
@ -12,7 +12,7 @@ go get github.com/mikefarah/yaml
|
|||||||
|
|
||||||
## Read examples
|
## Read examples
|
||||||
```
|
```
|
||||||
yaml <yaml file> <path>
|
yaml r <yaml file> <path>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Basic
|
### Basic
|
||||||
@ -23,14 +23,14 @@ b:
|
|||||||
```
|
```
|
||||||
then
|
then
|
||||||
```bash
|
```bash
|
||||||
yaml sample.yaml b.c
|
yaml r sample.yaml b.c
|
||||||
```
|
```
|
||||||
will output the value of '2'.
|
will output the value of '2'.
|
||||||
|
|
||||||
### Reading from STDIN
|
### Reading from STDIN
|
||||||
Given a sample.yaml file of:
|
Given a sample.yaml file of:
|
||||||
```bash
|
```bash
|
||||||
cat sample.yaml | yaml - b.c
|
cat sample.yaml | yaml r - b.c
|
||||||
```
|
```
|
||||||
will output the value of '2'.
|
will output the value of '2'.
|
||||||
|
|
||||||
@ -46,7 +46,7 @@ bob:
|
|||||||
```
|
```
|
||||||
then
|
then
|
||||||
```bash
|
```bash
|
||||||
yaml sample.yaml bob.*.cats
|
yaml r sample.yaml bob.*.cats
|
||||||
```
|
```
|
||||||
will output
|
will output
|
||||||
```yaml
|
```yaml
|
||||||
@ -62,7 +62,7 @@ b.x:
|
|||||||
```
|
```
|
||||||
then
|
then
|
||||||
```bash
|
```bash
|
||||||
yaml sample.yaml \"b.x\".c
|
yaml r sample.yaml \"b.x\".c
|
||||||
```
|
```
|
||||||
will output the value of '2'.
|
will output the value of '2'.
|
||||||
|
|
||||||
@ -79,7 +79,7 @@ b:
|
|||||||
```
|
```
|
||||||
then
|
then
|
||||||
```
|
```
|
||||||
yaml sample.yaml b.e[1].name
|
yaml r sample.yaml b.e[1].name
|
||||||
```
|
```
|
||||||
will output 'sam'
|
will output 'sam'
|
||||||
|
|
||||||
@ -95,7 +95,7 @@ b:
|
|||||||
```
|
```
|
||||||
then
|
then
|
||||||
```
|
```
|
||||||
yaml sample.yaml b.e[*].name
|
yaml r sample.yaml b.e[*].name
|
||||||
```
|
```
|
||||||
will output:
|
will output:
|
||||||
```
|
```
|
||||||
@ -121,7 +121,6 @@ b:
|
|||||||
c: cat
|
c: cat
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### Updating yaml in-place
|
### Updating yaml in-place
|
||||||
Given a sample.yaml file of:
|
Given a sample.yaml file of:
|
||||||
```yaml
|
```yaml
|
||||||
@ -130,6 +129,6 @@ b:
|
|||||||
```
|
```
|
||||||
then
|
then
|
||||||
```bash
|
```bash
|
||||||
yaml wi sample.yaml b.c cat
|
yaml w -i sample.yaml b.c cat
|
||||||
```
|
```
|
||||||
will update the sample.yaml file so that the value of 'c' is cat.
|
will update the sample.yaml file so that the value of 'c' is cat.
|
||||||
|
@ -6,7 +6,7 @@ go test
|
|||||||
|
|
||||||
# acceptance test
|
# acceptance test
|
||||||
go build
|
go build
|
||||||
X=$(./yaml sample.yaml b.c)
|
X=$(./yaml r sample.yaml b.c)
|
||||||
|
|
||||||
if [ $X != 2 ]
|
if [ $X != 2 ]
|
||||||
then
|
then
|
||||||
|
114
yaml.go
114
yaml.go
@ -2,7 +2,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/codegangsta/cli"
|
"github.com/spf13/cobra"
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
@ -11,74 +11,79 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var trimOutput = true
|
||||||
|
var writeInplace = false
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
app := cli.NewApp()
|
var cmdRead = &cobra.Command{
|
||||||
app.Name = "yaml"
|
Use: "read [yaml_file] [path]",
|
||||||
app.Usage = "command line tool for reading and writing yaml"
|
Aliases: []string{"r"},
|
||||||
app.Commands = []cli.Command{
|
Short: "yaml r sample.yaml a.b.c",
|
||||||
{
|
Example: `
|
||||||
Name: "read",
|
yaml read things.yaml a.b.c
|
||||||
Aliases: []string{"r"},
|
yaml r - a.b.c (reads from stdin)
|
||||||
Usage: "read <filename> <path>\n\te.g.: yaml read sample.yaml a.b.c\n\t(default) reads a property from a given yaml file\n",
|
yaml r things.yaml a.*.c
|
||||||
Action: readProperty,
|
yaml r things.yaml a.array[0].blah
|
||||||
},
|
yaml r things.yaml a.array[*].blah
|
||||||
{
|
`,
|
||||||
Name: "write",
|
Long: "Outputs the value of the given path in the yaml file to STDOUT",
|
||||||
Aliases: []string{"w"},
|
Run: readProperty,
|
||||||
Usage: "write <filename> <path> <value>\n\te.g.: yaml write sample.yaml a.b.c 5\n\tupdates a property from a given yaml file, outputs to stdout\n",
|
|
||||||
Action: writeProperty,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "write-inplace",
|
|
||||||
Aliases: []string{"wi"},
|
|
||||||
Usage: "wi <filename> <path> <value>\n\te.g.: yaml wi sample.yaml a.b.c 5\n\tupdates a property from a given yaml file and saves it to the given filename (sample.yaml)\n",
|
|
||||||
Action: writePropertyInPlace,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
app.Action = readProperty
|
|
||||||
app.Run(os.Args)
|
var cmdWrite = &cobra.Command{
|
||||||
|
Use: "write [yaml_file] [path] [value]",
|
||||||
|
Aliases: []string{"w"},
|
||||||
|
Short: "yaml w [--inplace/-i] sample.yaml a.b.c newValueForC",
|
||||||
|
Example: `
|
||||||
|
yaml write things.yaml a.b.c cat
|
||||||
|
yaml write --inplace things.yaml a.b.c cat
|
||||||
|
yaml w -i things.yaml a.b.c cat
|
||||||
|
`,
|
||||||
|
Long: `Updates the yaml file w.r.t the given path and value.
|
||||||
|
Outputs to STDOUT unless the inplace flag is used, in which case the file is updated instead.`,
|
||||||
|
Run: writeProperty,
|
||||||
|
}
|
||||||
|
cmdWrite.PersistentFlags().BoolVarP(&writeInplace, "inplace", "i", false, "update the yaml file inplace")
|
||||||
|
|
||||||
|
var rootCmd = &cobra.Command{Use: "yaml"}
|
||||||
|
rootCmd.PersistentFlags().BoolVarP(&trimOutput, "trim", "t", true, "trim yaml output")
|
||||||
|
rootCmd.AddCommand(cmdRead, cmdWrite)
|
||||||
|
rootCmd.Execute()
|
||||||
}
|
}
|
||||||
|
|
||||||
func readProperty(c *cli.Context) {
|
func readProperty(cmd *cobra.Command, args []string) {
|
||||||
|
|
||||||
var parsedData map[interface{}]interface{}
|
var parsedData map[interface{}]interface{}
|
||||||
|
|
||||||
readYaml(c, &parsedData)
|
readYaml(args, &parsedData)
|
||||||
|
|
||||||
if len(c.Args()) == 1 {
|
if len(args) == 1 {
|
||||||
printYaml(parsedData)
|
printYaml(parsedData)
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
var paths = parsePath(c.Args()[1])
|
var paths = parsePath(args[1])
|
||||||
|
|
||||||
printYaml(readMap(parsedData, paths[0], paths[1:len(paths)]))
|
printYaml(readMap(parsedData, paths[0], paths[1:len(paths)]))
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeProperty(c *cli.Context) {
|
func writeProperty(cmd *cobra.Command, args []string) {
|
||||||
printYaml(updateProperty(c))
|
if len(args) < 3 {
|
||||||
}
|
|
||||||
|
|
||||||
func writePropertyInPlace(c *cli.Context) {
|
|
||||||
updatedYaml := updateProperty(c)
|
|
||||||
ioutil.WriteFile(c.Args()[0], []byte(updatedYaml), 0644)
|
|
||||||
}
|
|
||||||
|
|
||||||
func updateProperty(c *cli.Context) string {
|
|
||||||
var parsedData map[interface{}]interface{}
|
|
||||||
readYaml(c, &parsedData)
|
|
||||||
|
|
||||||
if len(c.Args()) < 3 {
|
|
||||||
log.Fatalf("Must provide <filename> <path_to_update> <value>")
|
log.Fatalf("Must provide <filename> <path_to_update> <value>")
|
||||||
}
|
}
|
||||||
|
|
||||||
var paths = parsePath(c.Args()[1])
|
var parsedData map[interface{}]interface{}
|
||||||
|
readYaml(args, &parsedData)
|
||||||
|
|
||||||
write(parsedData, paths[0], paths[1:len(paths)], getValue(c.Args()[2]))
|
var paths = parsePath(args[1])
|
||||||
|
|
||||||
return yamlToString(parsedData)
|
write(parsedData, paths[0], paths[1:len(paths)], getValue(args[2]))
|
||||||
|
|
||||||
|
if writeInplace {
|
||||||
|
ioutil.WriteFile(args[0], []byte(yamlToString(parsedData)), 0644)
|
||||||
|
} else {
|
||||||
|
printYaml(parsedData)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getValue(argument string) interface{} {
|
func getValue(argument string) interface{} {
|
||||||
var value, err interface{}
|
var value, err interface{}
|
||||||
var inQuotes = argument[0] == '"'
|
var inQuotes = argument[0] == '"'
|
||||||
@ -108,19 +113,22 @@ func yamlToString(context interface{}) string {
|
|||||||
outStr := string(out)
|
outStr := string(out)
|
||||||
// trim the trailing new line as it's easier for a script to add
|
// trim the trailing new line as it's easier for a script to add
|
||||||
// it in if required than to remove it
|
// it in if required than to remove it
|
||||||
return strings.Trim(outStr, "\n ")
|
if trimOutput {
|
||||||
|
return strings.Trim(outStr, "\n ")
|
||||||
|
}
|
||||||
|
return outStr
|
||||||
}
|
}
|
||||||
|
|
||||||
func readYaml(c *cli.Context, parsedData *map[interface{}]interface{}) {
|
func readYaml(args []string, parsedData *map[interface{}]interface{}) {
|
||||||
if len(c.Args()) == 0 {
|
if len(args) == 0 {
|
||||||
log.Fatalf("Must provide filename")
|
log.Fatalf("Must provide filename")
|
||||||
}
|
}
|
||||||
|
|
||||||
var rawData []byte
|
var rawData []byte
|
||||||
if c.Args()[0] == "-" {
|
if args[0] == "-" {
|
||||||
rawData = readStdin()
|
rawData = readStdin()
|
||||||
} else {
|
} else {
|
||||||
rawData = readFile(c.Args()[0])
|
rawData = readFile(args[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
err := yaml.Unmarshal([]byte(rawData), &parsedData)
|
err := yaml.Unmarshal([]byte(rawData), &parsedData)
|
||||||
|
Loading…
Reference in New Issue
Block a user