util.stanza: Add method returning stanza with added indentation
authorKim Alvefur <zash@zash.se>
Sun, 12 Apr 2020 17:03:05 +0200
changeset 10721 05e4645fc9b3
parent 10720 29575fe64860
child 10722 d229e4d31598
util.stanza: Add method returning stanza with added indentation Adds indentation and line breaks to stanzas, to make stanzas easier to read for humans.
spec/util_stanza_spec.lua
util/stanza.lua
--- a/spec/util_stanza_spec.lua	Sat Apr 11 19:31:15 2020 +0200
+++ b/spec/util_stanza_spec.lua	Sun Apr 12 17:03:05 2020 +0200
@@ -459,4 +459,12 @@
 			assert.equal("true", s2.attr["my-awesome-ns\1bar"]);
 		end);
 	end);
+
+	describe("indent", function ()
+		local s = st.stanza("foo"):text("\n"):tag("bar"):tag("baz"):up():text_tag("cow", "moo");
+		assert.equal("<foo>\n\t<bar>\n\t\t<baz/>\n\t\t<cow>moo</cow>\n\t</bar>\n</foo>", tostring(s:indent()));
+		assert.equal("<foo>\n  <bar>\n    <baz/>\n    <cow>moo</cow>\n  </bar>\n</foo>", tostring(s:indent(1, "  ")));
+		assert.equal("<foo>\n\t\t<bar>\n\t\t\t<baz/>\n\t\t\t<cow>moo</cow>\n\t\t</bar>\n\t</foo>", tostring(s:indent(2, "\t")));
+	end);
+
 end);
--- a/util/stanza.lua	Sat Apr 11 19:31:15 2020 +0200
+++ b/util/stanza.lua	Sun Apr 12 17:03:05 2020 +0200
@@ -511,6 +511,36 @@
 	stanza_mt.pretty_top_tag = stanza_mt.top_tag;
 end
 
+function stanza_mt.indent(t, level, indent)
+	if #t == 0 or (#t == 1 and type(t[1]) == "string") then
+		-- Empty nodes wouldn't have any indentation
+		-- Text-only nodes are preserved as to not alter the text content
+		-- Optimization: Skip clone of these since we don't alter them
+		return t;
+	end
+
+	indent = indent or "\t";
+	level = level or 1;
+	local tag = clone(t, true);
+
+	for child in t:children() do
+		if type(child) == "string" then
+			-- Already indented text would look weird but let's ignore that for now.
+			if child:find("%S") then
+				tag:text("\n" .. indent:rep(level));
+				tag:text(child);
+			end
+		elseif is_stanza(child) then
+			tag:text("\n" .. indent:rep(level));
+			tag:add_direct_child(child:indent(level+1, indent));
+		end
+	end
+	-- before the closing tag
+	tag:text("\n" .. indent:rep((level-1)));
+
+	return tag;
+end
+
 return {
 	stanza_mt = stanza_mt;
 	stanza = new_stanza;