diff --git a/pkg/yqlib/doc/usage/lua.md b/pkg/yqlib/doc/usage/lua.md index 8a1df597..adb3d5f1 100644 --- a/pkg/yqlib/doc/usage/lua.md +++ b/pkg/yqlib/doc/usage/lua.md @@ -2,6 +2,7 @@ ## Basic example Given a sample.yml file of: ```yaml +--- hello: world ? look: non-string keys : True @@ -14,6 +15,15 @@ yq -o=lua '.' sample.yml ``` will output ```lua -return {["hello"]="world";[{["look"]="non-string keys";}]=true;["numbers"]={123,456,};}; +return { + ["hello"] = "world"; + [{ + ["look"] = "non-string keys"; + }] = true; + ["numbers"] = { + 123, + 456, + }; +}; ``` diff --git a/pkg/yqlib/encoder_lua.go b/pkg/yqlib/encoder_lua.go index fc1fe3c5..b5816b57 100644 --- a/pkg/yqlib/encoder_lua.go +++ b/pkg/yqlib/encoder_lua.go @@ -11,6 +11,8 @@ import ( type luaEncoder struct { docPrefix string docSuffix string + indent int + indentStr string unquoted bool escape *strings.Replacer } @@ -66,7 +68,7 @@ func NewLuaEncoder(prefs LuaPreferences) Encoder { "\\t", "\t", "\\\\", "\\", ) - return &luaEncoder{unescape.Replace(prefs.DocPrefix), unescape.Replace(prefs.DocSuffix), prefs.UnquotedKeys, escape} + return &luaEncoder{unescape.Replace(prefs.DocPrefix), unescape.Replace(prefs.DocSuffix), 0, "\t", prefs.UnquotedKeys, escape} } func (le *luaEncoder) PrintDocumentSeparator(writer io.Writer) error { @@ -81,12 +83,28 @@ func (le *luaEncoder) encodeString(writer io.Writer, node *yaml.Node) error { return writeString(writer, "\""+le.escape.Replace(node.Value)+"\"") } +func (le *luaEncoder) writeIndent(writer io.Writer) error { + if le.indentStr == "" { + return nil + } + err := writeString(writer, "\n") + if err != nil { + return err + } + return writeString(writer, strings.Repeat(le.indentStr, le.indent)) +} + func (le *luaEncoder) encodeArray(writer io.Writer, node *yaml.Node) error { err := writeString(writer, "{") if err != nil { return err } + le.indent++ for _, child := range node.Content { + err = le.writeIndent(writer) + if err != nil { + return err + } err := le.Encode(writer, child) if err != nil { return err @@ -96,6 +114,13 @@ func (le *luaEncoder) encodeArray(writer io.Writer, node *yaml.Node) error { return err } } + le.indent-- + if len(node.Content) != 0 { + err = le.writeIndent(writer) + if err != nil { + return err + } + } return writeString(writer, "}") } @@ -130,6 +155,7 @@ func (le *luaEncoder) encodeMap(writer io.Writer, node *yaml.Node) error { if err != nil { return err } + le.indent++ for i, child := range node.Content { if (i % 2) == 1 { // value @@ -141,27 +167,40 @@ func (le *luaEncoder) encodeMap(writer io.Writer, node *yaml.Node) error { if err != nil { return err } - } else if le.unquoted && child.Tag == "!!str" && !needsQuoting(child.Value) { - err = writeString(writer, child.Value+"=") - if err != nil { - return err - } } else { // key - err := writeString(writer, "[") + err = le.writeIndent(writer) if err != nil { return err } - err = le.encodeAny(writer, child) - if err != nil { - return err - } - err = writeString(writer, "]=") - if err != nil { - return err + if le.unquoted && child.Tag == "!!str" && !needsQuoting(child.Value) { + err = writeString(writer, child.Value+" = ") + if err != nil { + return err + } + } else { + err := writeString(writer, "[") + if err != nil { + return err + } + err = le.encodeAny(writer, child) + if err != nil { + return err + } + err = writeString(writer, "] = ") + if err != nil { + return err + } } } } + le.indent-- + if len(node.Content) != 0 { + err = le.writeIndent(writer) + if err != nil { + return err + } + } return writeString(writer, "}") } diff --git a/pkg/yqlib/lua_test.go b/pkg/yqlib/lua_test.go index de7e946f..df5b98ee 100644 --- a/pkg/yqlib/lua_test.go +++ b/pkg/yqlib/lua_test.go @@ -10,51 +10,66 @@ import ( var luaScenarios = []formatScenario{ { - description: "Basic example", - input: "hello: world\n? look: non-string keys\n: True\nnumbers: [123,456]\n", - expected: "return {[\"hello\"]=\"world\";[{[\"look\"]=\"non-string keys\";}]=true;[\"numbers\"]={123,456,};};\n", + description: "Basic example", + input: `--- +hello: world +? look: non-string keys +: True +numbers: [123,456] +`, + expected: `return { + ["hello"] = "world"; + [{ + ["look"] = "non-string keys"; + }] = true; + ["numbers"] = { + 123, + 456, + }; +}; +`, scenarioType: "encode", }, { skipDoc: true, description: "Sequence", input: "- a\n- b\n- c\n", - expected: "return {\"a\",\"b\",\"c\",};\n", + expected: "return {\n\t\"a\",\n\t\"b\",\n\t\"c\",\n};\n", scenarioType: "encode", }, { skipDoc: true, description: "Mapping", input: "a: b\nc:\n d: e\nf: 0\n", - expected: "return {[\"a\"]=\"b\";[\"c\"]={[\"d\"]=\"e\";};[\"f\"]=0;};\n", + expected: "return {\n\t[\"a\"] = \"b\";\n\t[\"c\"] = {\n\t\t[\"d\"] = \"e\";\n\t};\n\t[\"f\"] = 0;\n};\n", scenarioType: "encode", }, { skipDoc: true, description: "Scalar str", input: "str: |\n foo\n bar\n", - expected: "return {[\"str\"]=\"foo\\nbar\\n\";};\n", + expected: "return {\n\t[\"str\"] = \"foo\\nbar\\n\";\n};\n", scenarioType: "encode", }, { skipDoc: true, description: "Scalar null", input: "x: null\n", - expected: "return {[\"x\"]=nil;};\n", + expected: "return {\n\t[\"x\"] = nil;\n};\n", scenarioType: "encode", }, { skipDoc: true, description: "Scalar int", input: "- 1\n- 2\n- 0x10\n- 0o30\n- -999\n", - expected: "return {1,2,0x10,24,-999,};\n", + expected: "return {\n\t1,\n\t2,\n\t0x10,\n\t24,\n\t-999,\n};\n", scenarioType: "encode", }, { skipDoc: true, description: "Scalar float", input: "- 1.0\n- 3.14\n- 1e100\n- .Inf\n- .NAN\n", - expected: "return {1.0,3.14,1e100,(1/0),(0/0),};\n", + expected: "return {\n\t1.0,\n\t3.14,\n\t1e100,\n\t(1/0),\n\t(0/0),\n};\n", scenarioType: "encode", }, }