mirror of
https://github.com/mikefarah/yq.git
synced 2024-11-12 05:38:04 +00:00
Auto output format (#1599)
* Use file extension to auto detect output format! * Use file extension to auto detect output format! * formatting
This commit is contained in:
parent
2c14c98408
commit
08a6cb65fe
@ -15,8 +15,11 @@ testInputJson() {
|
|||||||
EOL
|
EOL
|
||||||
|
|
||||||
read -r -d '' expected << EOM
|
read -r -d '' expected << EOM
|
||||||
mike:
|
{
|
||||||
things: cool
|
"mike": {
|
||||||
|
"things": "cool"
|
||||||
|
}
|
||||||
|
}
|
||||||
EOM
|
EOM
|
||||||
|
|
||||||
X=$(./yq test.json)
|
X=$(./yq test.json)
|
||||||
@ -26,19 +29,38 @@ EOM
|
|||||||
assertEquals "$expected" "$X"
|
assertEquals "$expected" "$X"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
testInputJsonOutputYaml() {
|
||||||
|
cat >test.json <<EOL
|
||||||
|
{ "mike" : { "things": "cool" } }
|
||||||
|
EOL
|
||||||
|
|
||||||
|
read -r -d '' expected << EOM
|
||||||
|
mike:
|
||||||
|
things: cool
|
||||||
|
EOM
|
||||||
|
|
||||||
|
X=$(./yq test.json -oy)
|
||||||
|
assertEquals "$expected" "$X"
|
||||||
|
|
||||||
|
X=$(./yq ea test.json -oy)
|
||||||
|
assertEquals "$expected" "$X"
|
||||||
|
}
|
||||||
|
|
||||||
testInputProperties() {
|
testInputProperties() {
|
||||||
cat >test.properties <<EOL
|
cat >test.properties <<EOL
|
||||||
mike.things = hello
|
mike.things = hello
|
||||||
EOL
|
EOL
|
||||||
|
|
||||||
read -r -d '' expected << EOM
|
read -r -d '' expected << EOM
|
||||||
mike:
|
mike.things = hello
|
||||||
things: hello
|
|
||||||
EOM
|
EOM
|
||||||
|
|
||||||
X=$(./yq e test.properties)
|
X=$(./yq e test.properties)
|
||||||
assertEquals "$expected" "$X"
|
assertEquals "$expected" "$X"
|
||||||
|
|
||||||
|
X=$(./yq test.properties)
|
||||||
|
assertEquals "$expected" "$X"
|
||||||
|
|
||||||
X=$(./yq ea test.properties)
|
X=$(./yq ea test.properties)
|
||||||
assertEquals "$expected" "$X"
|
assertEquals "$expected" "$X"
|
||||||
}
|
}
|
||||||
@ -49,8 +71,7 @@ mike.things = hello
|
|||||||
EOL
|
EOL
|
||||||
|
|
||||||
read -r -d '' expected << EOM
|
read -r -d '' expected << EOM
|
||||||
mike:
|
mike.things = hello
|
||||||
things: hello
|
|
||||||
EOM
|
EOM
|
||||||
|
|
||||||
X=$(cat /dev/null | ./yq e test.properties)
|
X=$(cat /dev/null | ./yq e test.properties)
|
||||||
@ -68,10 +89,9 @@ banana,4
|
|||||||
EOL
|
EOL
|
||||||
|
|
||||||
read -r -d '' expected << EOM
|
read -r -d '' expected << EOM
|
||||||
- fruit: apple
|
fruit,yumLevel
|
||||||
yumLevel: 5
|
apple,5
|
||||||
- fruit: banana
|
banana,4
|
||||||
yumLevel: 4
|
|
||||||
EOM
|
EOM
|
||||||
|
|
||||||
X=$(./yq e test.csv)
|
X=$(./yq e test.csv)
|
||||||
@ -83,12 +103,9 @@ EOM
|
|||||||
|
|
||||||
testInputCSVUTF8() {
|
testInputCSVUTF8() {
|
||||||
read -r -d '' expected << EOM
|
read -r -d '' expected << EOM
|
||||||
- id: 1
|
id,first,last
|
||||||
first: john
|
1,john,smith
|
||||||
last: smith
|
1,jane,smith
|
||||||
- id: 1
|
|
||||||
first: jane
|
|
||||||
last: smith
|
|
||||||
EOM
|
EOM
|
||||||
|
|
||||||
X=$(./yq utf8.csv)
|
X=$(./yq utf8.csv)
|
||||||
@ -103,10 +120,9 @@ banana 4
|
|||||||
EOL
|
EOL
|
||||||
|
|
||||||
read -r -d '' expected << EOM
|
read -r -d '' expected << EOM
|
||||||
- fruit: apple
|
fruit yumLevel
|
||||||
yumLevel: 5
|
apple 5
|
||||||
- fruit: banana
|
banana 4
|
||||||
yumLevel: 4
|
|
||||||
EOM
|
EOM
|
||||||
|
|
||||||
X=$(./yq e test.tsv)
|
X=$(./yq e test.tsv)
|
||||||
@ -125,9 +141,7 @@ testInputXml() {
|
|||||||
EOL
|
EOL
|
||||||
|
|
||||||
read -r -d '' expected << EOM
|
read -r -d '' expected << EOM
|
||||||
cat:
|
<cat legs="4">BiBi</cat>
|
||||||
+content: BiBi
|
|
||||||
+@legs: "4"
|
|
||||||
EOM
|
EOM
|
||||||
|
|
||||||
X=$(./yq e test.xml)
|
X=$(./yq e test.xml)
|
||||||
@ -145,11 +159,8 @@ testInputXmlNamespaces() {
|
|||||||
EOL
|
EOL
|
||||||
|
|
||||||
read -r -d '' expected << EOM
|
read -r -d '' expected << EOM
|
||||||
+p_xml: version="1.0"
|
<?xml version="1.0"?>
|
||||||
map:
|
<map xmlns="some-namespace" xmlns:xsi="some-instance" xsi:schemaLocation="some-url"></map>
|
||||||
+@xmlns: some-namespace
|
|
||||||
+@xmlns:xsi: some-instance
|
|
||||||
+@xsi:schemaLocation: some-url
|
|
||||||
EOM
|
EOM
|
||||||
|
|
||||||
X=$(./yq e test.xml)
|
X=$(./yq e test.xml)
|
||||||
@ -159,25 +170,6 @@ EOM
|
|||||||
assertEquals "$expected" "$X"
|
assertEquals "$expected" "$X"
|
||||||
}
|
}
|
||||||
|
|
||||||
testInputXmlRoundtrip() {
|
|
||||||
cat >test.xml <<EOL
|
|
||||||
<?xml version="1.0"?>
|
|
||||||
<!DOCTYPE config SYSTEM "/etc/iwatch/iwatch.dtd" >
|
|
||||||
<map xmlns="some-namespace" xmlns:xsi="some-instance" xsi:schemaLocation="some-url">Meow</map>
|
|
||||||
EOL
|
|
||||||
|
|
||||||
read -r -d '' expected << EOM
|
|
||||||
<?xml version="1.0"?>
|
|
||||||
<!DOCTYPE config SYSTEM "/etc/iwatch/iwatch.dtd" >
|
|
||||||
<map xmlns="some-namespace" xmlns:xsi="some-instance" xsi:schemaLocation="some-url">Meow</map>
|
|
||||||
EOM
|
|
||||||
|
|
||||||
X=$(./yq -o=xml test.xml)
|
|
||||||
assertEquals "$expected" "$X"
|
|
||||||
|
|
||||||
X=$(./yq ea -o=xml test.xml)
|
|
||||||
assertEquals "$expected" "$X"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
testInputXmlStrict() {
|
testInputXmlStrict() {
|
||||||
@ -192,11 +184,11 @@ testInputXmlStrict() {
|
|||||||
</root>
|
</root>
|
||||||
EOL
|
EOL
|
||||||
|
|
||||||
X=$(./yq --xml-strict-mode test.xml -o=xml 2>&1)
|
X=$(./yq --xml-strict-mode test.xml 2>&1)
|
||||||
assertEquals 1 $?
|
assertEquals 1 $?
|
||||||
assertEquals "Error: bad file 'test.xml': XML syntax error on line 7: invalid character entity &writer;" "$X"
|
assertEquals "Error: bad file 'test.xml': XML syntax error on line 7: invalid character entity &writer;" "$X"
|
||||||
|
|
||||||
X=$(./yq ea --xml-strict-mode test.xml -o=xml 2>&1)
|
X=$(./yq ea --xml-strict-mode test.xml 2>&1)
|
||||||
assertEquals "Error: bad file 'test.xml': XML syntax error on line 7: invalid character entity &writer;" "$X"
|
assertEquals "Error: bad file 'test.xml': XML syntax error on line 7: invalid character entity &writer;" "$X"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,9 +198,7 @@ testInputXmlGithubAction() {
|
|||||||
EOL
|
EOL
|
||||||
|
|
||||||
read -r -d '' expected << EOM
|
read -r -d '' expected << EOM
|
||||||
cat:
|
<cat legs="4">BiBi</cat>
|
||||||
+content: BiBi
|
|
||||||
+@legs: "4"
|
|
||||||
EOM
|
EOM
|
||||||
|
|
||||||
X=$(cat /dev/null | ./yq e test.xml)
|
X=$(cat /dev/null | ./yq e test.xml)
|
||||||
|
@ -120,7 +120,7 @@ EOM
|
|||||||
}
|
}
|
||||||
|
|
||||||
testInputXmlNamespaces() {
|
testInputXmlNamespaces() {
|
||||||
cat >test.yml <<EOL
|
cat >test.xml <<EOL
|
||||||
<?xml version="1.0"?>
|
<?xml version="1.0"?>
|
||||||
<map xmlns="some-namespace" xmlns:xsi="some-instance" xsi:schemaLocation="some-url">
|
<map xmlns="some-namespace" xmlns:xsi="some-instance" xsi:schemaLocation="some-url">
|
||||||
</map>
|
</map>
|
||||||
@ -134,10 +134,10 @@ map:
|
|||||||
+@xsi:schemaLocation: some-url
|
+@xsi:schemaLocation: some-url
|
||||||
EOM
|
EOM
|
||||||
|
|
||||||
X=$(./yq e -p=xml test.yml)
|
X=$(./yq e -p=xml test.xml)
|
||||||
assertEquals "$expected" "$X"
|
assertEquals "$expected" "$X"
|
||||||
|
|
||||||
X=$(./yq ea -p=xml test.yml)
|
X=$(./yq ea -p=xml test.xml)
|
||||||
assertEquals "$expected" "$X"
|
assertEquals "$expected" "$X"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,8 +6,9 @@ var unwrapScalar = false
|
|||||||
|
|
||||||
var writeInplace = false
|
var writeInplace = false
|
||||||
var outputToJSON = false
|
var outputToJSON = false
|
||||||
var outputFormat = "yaml"
|
|
||||||
var inputFormatDefault = "yaml"
|
var outputFormat = ""
|
||||||
|
|
||||||
var inputFormat = ""
|
var inputFormat = ""
|
||||||
|
|
||||||
var exitStatus = false
|
var exitStatus = false
|
||||||
|
@ -75,12 +75,7 @@ func evaluateAll(cmd *cobra.Command, args []string) (cmdError error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
inputFilename := ""
|
decoder, err := configureDecoder(true)
|
||||||
if len(args) > 0 {
|
|
||||||
inputFilename = args[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
decoder, err := configureDecoder(true, inputFilename)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -100,12 +100,7 @@ func evaluateSequence(cmd *cobra.Command, args []string) (cmdError error) {
|
|||||||
|
|
||||||
printer := yqlib.NewPrinter(encoder, printerWriter)
|
printer := yqlib.NewPrinter(encoder, printerWriter)
|
||||||
|
|
||||||
inputFilename := ""
|
decoder, err := configureDecoder(false)
|
||||||
if len(args) > 0 {
|
|
||||||
inputFilename = args[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
decoder, err := configureDecoder(false, inputFilename)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
23
cmd/root.go
23
cmd/root.go
@ -53,25 +53,6 @@ yq -P sample.json
|
|||||||
logging.SetBackend(backend)
|
logging.SetBackend(backend)
|
||||||
yqlib.InitExpressionParser()
|
yqlib.InitExpressionParser()
|
||||||
|
|
||||||
outputFormatType, err := yqlib.OutputFormatFromString(outputFormat)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if outputFormatType == yqlib.YamlOutputFormat ||
|
|
||||||
outputFormatType == yqlib.PropsOutputFormat {
|
|
||||||
unwrapScalar = true
|
|
||||||
}
|
|
||||||
if unwrapScalarFlag.IsExplicitySet() {
|
|
||||||
unwrapScalar = unwrapScalarFlag.IsSet()
|
|
||||||
}
|
|
||||||
|
|
||||||
//copy preference form global setting
|
|
||||||
yqlib.ConfiguredYamlPreferences.UnwrapScalar = unwrapScalar
|
|
||||||
|
|
||||||
yqlib.ConfiguredYamlPreferences.PrintDocSeparators = !noDocSeparators
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -84,8 +65,8 @@ yq -P sample.json
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
rootCmd.PersistentFlags().StringVarP(&outputFormat, "output-format", "o", "yaml", "[yaml|y|json|j|props|p|xml|x] output format type.")
|
rootCmd.PersistentFlags().StringVarP(&outputFormat, "output-format", "o", "auto", "[auto|a|yaml|y|json|j|props|p|xml|x] output format type.")
|
||||||
rootCmd.PersistentFlags().StringVarP(&inputFormat, "input-format", "p", "", "[yaml|y|props|p|xml|x] parse format for input. Note that json is a subset of yaml.")
|
rootCmd.PersistentFlags().StringVarP(&inputFormat, "input-format", "p", "auto", "[auto|a|yaml|y|props|p|xml|x] parse format for input. Note that json is a subset of yaml.")
|
||||||
|
|
||||||
rootCmd.PersistentFlags().StringVar(&yqlib.ConfiguredXMLPreferences.AttributePrefix, "xml-attribute-prefix", yqlib.ConfiguredXMLPreferences.AttributePrefix, "prefix for xml attributes")
|
rootCmd.PersistentFlags().StringVar(&yqlib.ConfiguredXMLPreferences.AttributePrefix, "xml-attribute-prefix", yqlib.ConfiguredXMLPreferences.AttributePrefix, "prefix for xml attributes")
|
||||||
rootCmd.PersistentFlags().StringVar(&yqlib.ConfiguredXMLPreferences.ContentName, "xml-content-name", yqlib.ConfiguredXMLPreferences.ContentName, "name for xml content (if no attribute name is present).")
|
rootCmd.PersistentFlags().StringVar(&yqlib.ConfiguredXMLPreferences.ContentName, "xml-content-name", yqlib.ConfiguredXMLPreferences.ContentName, "name for xml content (if no attribute name is present).")
|
||||||
|
49
cmd/utils.go
49
cmd/utils.go
@ -53,15 +53,52 @@ func initCommand(cmd *cobra.Command, args []string) (string, []string, error) {
|
|||||||
return "", nil, fmt.Errorf("cannot pass files in when using null-input flag")
|
return "", nil, fmt.Errorf("cannot pass files in when using null-input flag")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inputFilename := ""
|
||||||
|
if len(args) > 0 {
|
||||||
|
inputFilename = args[0]
|
||||||
|
}
|
||||||
|
if inputFormat == "" || inputFormat == "auto" || inputFormat == "a" {
|
||||||
|
|
||||||
|
inputFormat = yqlib.FormatFromFilename(inputFilename)
|
||||||
|
if outputFormat == "" || outputFormat == "auto" || outputFormat == "a" {
|
||||||
|
outputFormat = yqlib.FormatFromFilename(inputFilename)
|
||||||
|
}
|
||||||
|
} else if outputFormat == "" || outputFormat == "auto" || outputFormat == "a" {
|
||||||
|
// backwards compatibility -
|
||||||
|
// before this was introduced, `yq -pcsv things.csv`
|
||||||
|
// would produce *yaml* output.
|
||||||
|
//
|
||||||
|
outputFormat = yqlib.FormatFromFilename(inputFilename)
|
||||||
|
if inputFilename != "-" {
|
||||||
|
yqlib.GetLogger().Warning("yq default output is now 'auto' (based on the filename extension). Normally yq would output '%v', but for backwards compatibility 'yaml' has been set. Please use -oy to specify yaml, or drop the -p flag.", outputFormat)
|
||||||
|
}
|
||||||
|
outputFormat = "yaml"
|
||||||
|
}
|
||||||
|
|
||||||
|
outputFormatType, err := yqlib.OutputFormatFromString(outputFormat)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return "", nil, err
|
||||||
|
}
|
||||||
|
yqlib.GetLogger().Debug("Using outputformat %v", outputFormat)
|
||||||
|
|
||||||
|
if outputFormatType == yqlib.YamlOutputFormat ||
|
||||||
|
outputFormatType == yqlib.PropsOutputFormat {
|
||||||
|
unwrapScalar = true
|
||||||
|
}
|
||||||
|
if unwrapScalarFlag.IsExplicitySet() {
|
||||||
|
unwrapScalar = unwrapScalarFlag.IsSet()
|
||||||
|
}
|
||||||
|
|
||||||
|
//copy preference form global setting
|
||||||
|
yqlib.ConfiguredYamlPreferences.UnwrapScalar = unwrapScalar
|
||||||
|
|
||||||
|
yqlib.ConfiguredYamlPreferences.PrintDocSeparators = !noDocSeparators
|
||||||
|
|
||||||
return expression, args, nil
|
return expression, args, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func configureDecoder(evaluateTogether bool, inputFilename string) (yqlib.Decoder, error) {
|
func configureDecoder(evaluateTogether bool) (yqlib.Decoder, error) {
|
||||||
if inputFormat == "" {
|
|
||||||
inputFormat = yqlib.InputFormatFromFilename(inputFilename, inputFormatDefault)
|
|
||||||
} else {
|
|
||||||
yqlib.GetLogger().Debugf("user specified inputFormat '%s'", inputFormat)
|
|
||||||
}
|
|
||||||
yqlibInputFormat, err := yqlib.InputFormatFromString(inputFormat)
|
yqlibInputFormat, err := yqlib.InputFormatFromString(inputFormat)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -1,5 +1 @@
|
|||||||
date: "2022-11-25"
|
<cat>3</cat>
|
||||||
raw:
|
|
||||||
id: 1
|
|
||||||
XML: text_outside_1<Tag1 />text_outside_2<Tag2Kling Klong</Tag2>text_outside_3
|
|
||||||
time: 09:19:00
|
|
@ -39,21 +39,22 @@ func InputFormatFromString(format string) (InputFormat, error) {
|
|||||||
case "tsv", "t":
|
case "tsv", "t":
|
||||||
return TSVObjectInputFormat, nil
|
return TSVObjectInputFormat, nil
|
||||||
default:
|
default:
|
||||||
return 0, fmt.Errorf("unknown format '%v' please use [yaml|xml|props]", format)
|
return 0, fmt.Errorf("unknown format '%v' please use [yaml|json|props|csv|tsv|xml]", format)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func InputFormatFromFilename(filename string, defaultFormat string) string {
|
func FormatFromFilename(filename string) string {
|
||||||
|
|
||||||
if filename != "" {
|
if filename != "" {
|
||||||
GetLogger().Debugf("checking filename '%s' for inputFormat", filename)
|
GetLogger().Debugf("checking file extension '%s' for auto format detection", filename)
|
||||||
nPos := strings.LastIndex(filename, ".")
|
nPos := strings.LastIndex(filename, ".")
|
||||||
if nPos > -1 {
|
if nPos > -1 {
|
||||||
inputFormat := filename[nPos+1:]
|
format := filename[nPos+1:]
|
||||||
GetLogger().Debugf("detected inputFormat '%s'", inputFormat)
|
GetLogger().Debugf("detected format '%s'", format)
|
||||||
return inputFormat
|
return format
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GetLogger().Debugf("using default inputFormat '%s'", defaultFormat)
|
GetLogger().Debugf("using default inputFormat 'yaml'")
|
||||||
return defaultFormat
|
return "yaml"
|
||||||
}
|
}
|
||||||
|
@ -30,4 +30,3 @@ func filterOperator(d *dataTreeNavigator, context Context, expressionNode *Expre
|
|||||||
}
|
}
|
||||||
return context.ChildContext(results), nil
|
return context.ChildContext(results), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,22 +7,22 @@ import (
|
|||||||
var filterOperatorScenarios = []expressionScenario{
|
var filterOperatorScenarios = []expressionScenario{
|
||||||
{
|
{
|
||||||
description: "Filter array",
|
description: "Filter array",
|
||||||
document: `[1,2,3]`,
|
document: `[1,2,3]`,
|
||||||
expression: `filter(. < 3)`,
|
expression: `filter(. < 3)`,
|
||||||
expected: []string{
|
expected: []string{
|
||||||
"D0, P[], (!!seq)::[1, 2]\n",
|
"D0, P[], (!!seq)::[1, 2]\n",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
skipDoc: true,
|
skipDoc: true,
|
||||||
document: `[1,2,3]`,
|
document: `[1,2,3]`,
|
||||||
expression: `filter(. > 1)`,
|
expression: `filter(. > 1)`,
|
||||||
expected: []string{
|
expected: []string{
|
||||||
"D0, P[], (!!seq)::[2, 3]\n",
|
"D0, P[], (!!seq)::[2, 3]\n",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
skipDoc: true,
|
skipDoc: true,
|
||||||
description: "Filter array to empty",
|
description: "Filter array to empty",
|
||||||
document: `[1,2,3]`,
|
document: `[1,2,3]`,
|
||||||
expression: `filter(. > 4)`,
|
expression: `filter(. > 4)`,
|
||||||
@ -31,7 +31,7 @@ var filterOperatorScenarios = []expressionScenario{
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
skipDoc: true,
|
skipDoc: true,
|
||||||
description: "Filter empty array",
|
description: "Filter empty array",
|
||||||
document: `[]`,
|
document: `[]`,
|
||||||
expression: `filter(. > 1)`,
|
expression: `filter(. > 1)`,
|
||||||
|
@ -33,11 +33,11 @@ const (
|
|||||||
|
|
||||||
func OutputFormatFromString(format string) (PrinterOutputFormat, error) {
|
func OutputFormatFromString(format string) (PrinterOutputFormat, error) {
|
||||||
switch format {
|
switch format {
|
||||||
case "yaml", "y":
|
case "yaml", "y", "yml":
|
||||||
return YamlOutputFormat, nil
|
return YamlOutputFormat, nil
|
||||||
case "json", "j":
|
case "json", "j":
|
||||||
return JSONOutputFormat, nil
|
return JSONOutputFormat, nil
|
||||||
case "props", "p":
|
case "props", "p", "properties":
|
||||||
return PropsOutputFormat, nil
|
return PropsOutputFormat, nil
|
||||||
case "csv", "c":
|
case "csv", "c":
|
||||||
return CSVOutputFormat, nil
|
return CSVOutputFormat, nil
|
||||||
|
Loading…
Reference in New Issue
Block a user