diff --git a/pkg/yqlib/path_parser.go b/pkg/yqlib/path_parser.go index 5d0ed6cf..f8163cca 100644 --- a/pkg/yqlib/path_parser.go +++ b/pkg/yqlib/path_parser.go @@ -4,17 +4,17 @@ type PathParser interface { ParsePath(path string) []string } -type parser struct{} +type pathParser struct{} func NewPathParser() PathParser { - return &parser{} + return &pathParser{} } -func (p *parser) ParsePath(path string) []string { +func (p *pathParser) ParsePath(path string) []string { return p.parsePathAccum([]string{}, path) } -func (p *parser) parsePathAccum(paths []string, remaining string) []string { +func (p *pathParser) parsePathAccum(paths []string, remaining string) []string { head, tail := p.nextYamlPath(remaining) if tail == "" { return append(paths, head) @@ -22,7 +22,7 @@ func (p *parser) parsePathAccum(paths []string, remaining string) []string { return p.parsePathAccum(append(paths, head), tail) } -func (p *parser) nextYamlPath(path string) (pathElement string, remaining string) { +func (p *pathParser) nextYamlPath(path string) (pathElement string, remaining string) { switch path[0] { case '[': // e.g [0].blah.cat -> we need to return "0" and "blah.cat" @@ -36,7 +36,7 @@ func (p *parser) nextYamlPath(path string) (pathElement string, remaining string } } -func (p *parser) search(path string, matchingChars []uint8, skipNext bool) (pathElement string, remaining string) { +func (p *pathParser) search(path string, matchingChars []uint8, skipNext bool) (pathElement string, remaining string) { for i := 0; i < len(path); i++ { var char = path[i] if p.contains(matchingChars, char) { @@ -55,7 +55,7 @@ func (p *parser) search(path string, matchingChars []uint8, skipNext bool) (path return path, "" } -func (p *parser) contains(matchingChars []uint8, candidate uint8) bool { +func (p *pathParser) contains(matchingChars []uint8, candidate uint8) bool { for _, a := range matchingChars { if a == candidate { return true diff --git a/pkg/yqlib/value_parser.go b/pkg/yqlib/value_parser.go new file mode 100644 index 00000000..d08da020 --- /dev/null +++ b/pkg/yqlib/value_parser.go @@ -0,0 +1,35 @@ +package yqlib + +import ( + "strconv" +) + +type ValueParser interface { + ParseValue(argument string) interface{} +} + +type valueParser struct{} + +func NewValueParser() ValueParser { + return &valueParser{} +} + +func (v *valueParser) ParseValue(argument string) interface{} { + var value, err interface{} + var inQuotes = len(argument) > 0 && argument[0] == '"' + if !inQuotes { + value, err = strconv.ParseFloat(argument, 64) + if err == nil { + return value + } + value, err = strconv.ParseBool(argument) + if err == nil { + return value + } + if argument == "[]" { + return make([]interface{}, 0) + } + return argument + } + return argument[1 : len(argument)-1] +} diff --git a/pkg/yqlib/value_parser_test.go b/pkg/yqlib/value_parser_test.go new file mode 100644 index 00000000..083fc3f5 --- /dev/null +++ b/pkg/yqlib/value_parser_test.go @@ -0,0 +1,25 @@ +package yqlib + +import ( + "testing" + + "github.com/mikefarah/yq/test" +) + +var parseValueTests = []struct { + argument string + expectedResult interface{} + testDescription string +}{ + {"true", true, "boolean"}, + {"\"true\"", "true", "boolean as string"}, + {"3.4", 3.4, "number"}, + {"\"3.4\"", "3.4", "number as string"}, + {"", "", "empty string"}, +} + +func TestParseValue(t *testing.T) { + for _, tt := range parseValueTests { + test.AssertResultWithContext(t, tt.expectedResult, NewValueParser().ParseValue(tt.argument), tt.testDescription) + } +} diff --git a/yq.go b/yq.go index 0d49f38b..f5a24397 100644 --- a/yq.go +++ b/yq.go @@ -34,6 +34,7 @@ var log = logging.MustGetLogger("yq") var lib = yqlib.NewYqLib(log) var jsonConverter = marshal.NewJsonConverter() var yamlConverter = marshal.NewYamlConverter() +var valueParser = yqlib.NewValueParser() func main() { cmd := newCommandCLI() @@ -557,31 +558,11 @@ func readWriteCommands(args []string, expectedArgs int, badArgsMessage string) ( return nil, errors.New(badArgsMessage) } else { writeCommands = make(yaml.MapSlice, 1) - writeCommands[0] = yaml.MapItem{Key: args[expectedArgs-2], Value: parseValue(args[expectedArgs-1])} + writeCommands[0] = yaml.MapItem{Key: args[expectedArgs-2], Value: valueParser.ParseValue(args[expectedArgs-1])} } return writeCommands, nil } -func parseValue(argument string) interface{} { - var value, err interface{} - var inQuotes = len(argument) > 0 && argument[0] == '"' - if !inQuotes { - value, err = strconv.ParseFloat(argument, 64) - if err == nil { - return value - } - value, err = strconv.ParseBool(argument) - if err == nil { - return value - } - if argument == "[]" { - return make([]interface{}, 0) - } - return argument - } - return argument[1 : len(argument)-1] -} - func toString(context interface{}) (string, error) { if outputToJSON { return jsonConverter.JsonToString(context) diff --git a/yq_test.go b/yq_test.go index 5eca98be..015fcace 100644 --- a/yq_test.go +++ b/yq_test.go @@ -9,24 +9,6 @@ import ( "github.com/mikefarah/yq/test" ) -var parseValueTests = []struct { - argument string - expectedResult interface{} - testDescription string -}{ - {"true", true, "boolean"}, - {"\"true\"", "true", "boolean as string"}, - {"3.4", 3.4, "number"}, - {"\"3.4\"", "3.4", "number as string"}, - {"", "", "empty string"}, -} - -func TestParseValue(t *testing.T) { - for _, tt := range parseValueTests { - test.AssertResultWithContext(t, tt.expectedResult, parseValue(tt.argument), tt.testDescription) - } -} - func TestMultilineString(t *testing.T) { testString := ` abcd