scansion/pretty.lua

Thu, 23 Mar 2023 15:12:30 +0000

author
Matthew Wild <mwild1@gmail.com>
date
Thu, 23 Mar 2023 15:12:30 +0000
changeset 174
662bd8c5ae28
parent 152
ba8219ac7484
child 178
e547ddf8b64d
permissions
-rw-r--r--

Serialize XML in a consistent order by default

This overrides all XML serialization to emit attributes in an ordered form, so
the XML will match across multiple runs. This can be useful for comparing
different runs, or even two stanzas printed in the same run (e.g. if there is
a mismatch).

112
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
1 require "verse"
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
2 local xml = require "scansion.xml";
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
3 local s_format, s_gsub = string.format, string.gsub;
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
4
174
662bd8c5ae28 Serialize XML in a consistent order by default
Matthew Wild <mwild1@gmail.com>
parents: 152
diff changeset
5 local unsorted_pairs = pairs;
662bd8c5ae28 Serialize XML in a consistent order by default
Matthew Wild <mwild1@gmail.com>
parents: 152
diff changeset
6 local sorted_pairs = require "util.iterators".sorted_pairs;
662bd8c5ae28 Serialize XML in a consistent order by default
Matthew Wild <mwild1@gmail.com>
parents: 152
diff changeset
7
112
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
8 local escape_table = { ["'"] = "&apos;", ["\""] = "&quot;", ["<"] = "&lt;", [">"] = "&gt;", ["&"] = "&amp;" };
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
9 local function xml_escape(str) return (s_gsub(str, "['&<>\"]", escape_table)); end
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
10
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
11 -- Dummy functions compatible with util.termcolours,
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
12 -- just in case we add colour in the future
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
13 local function getstyle() return "" end
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
14 local function getstring(style, text)
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
15 if not style then
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
16 text = style;
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
17 end
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
18 return text;
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
19 end
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
20
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
21 local default_config = {
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
22 indent = 2;
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
23 preserve_whitespace = false;
174
662bd8c5ae28 Serialize XML in a consistent order by default
Matthew Wild <mwild1@gmail.com>
parents: 152
diff changeset
24 sorted = true;
112
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
25 };
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
26
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
27 local function new(user_config)
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
28 local config = setmetatable({}, { __index = function (_, k) return user_config[k] or default_config[k]; end });
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
29 local style_attrk = getstyle("yellow");
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
30 local style_attrv = getstyle("red");
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
31 local style_tagname = getstyle("red");
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
32 local style_punc = getstyle("magenta");
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
33
174
662bd8c5ae28 Serialize XML in a consistent order by default
Matthew Wild <mwild1@gmail.com>
parents: 152
diff changeset
34 local pairs = user_config.sorted and sorted_pairs or unsorted_pairs;
662bd8c5ae28 Serialize XML in a consistent order by default
Matthew Wild <mwild1@gmail.com>
parents: 152
diff changeset
35
112
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
36 local attr_format = " "..getstring(style_attrk, "%s")..getstring(style_punc, "=")..getstring(style_attrv, "'%s'");
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
37 local open_tag_format = getstring(style_punc, "<")..getstring(style_tagname, "%s").."%s"..getstring(style_punc, ">");
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
38 local close_tag_format = getstring(style_punc, "</")..getstring(style_tagname, "%s")..getstring(style_punc, ">");
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
39 local tag_format = open_tag_format.."%s"..close_tag_format;
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
40 local short_close_tag_format = getstring(style_punc, "<")..getstring(style_tagname, "%s").."%s"..getstring(style_punc, "/>");
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
41 local function pretty_print(t, ind)
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
42 ind = ind or config.indent;
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
43 local children_text = "";
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
44 for i, child in ipairs(t) do
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
45 if type(child) == "string" then
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
46 if config.preserve_whitespace or child:match("%S") then
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
47 children_text = children_text .. "\n"..string.rep(" ", ind) .. xml_escape(child);
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
48 end
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
49 else
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
50 children_text = children_text .. "\n" .. pretty_print(child, ind+config.indent);
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
51 end
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
52 end
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
53
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
54 local attr_string = "";
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
55 if t.attr then
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
56 for k, v in pairs(t.attr) do
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
57 if type(k) == "string" then
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
58 attr_string = attr_string .. s_format(attr_format, k, tostring(v));
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
59 end
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
60 end
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
61 end
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
62
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
63 local use_tag_format = tag_format;
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
64 if #t == 0 then
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
65 use_tag_format = short_close_tag_format;
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
66 end
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
67 if children_text ~= "" then
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
68 children_text = children_text .. "\n" .. string.rep(" ", ind);
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
69 end
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
70
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
71 return string.rep(" ", ind)..s_format(use_tag_format, t.name, attr_string, children_text, t.name);
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
72 end
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
73
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
74 return function (s, ind)
152
ba8219ac7484 scansion.pretty: Just emit input on invalid XML
Matthew Wild <mwild1@gmail.com>
parents: 112
diff changeset
75 local doc = xml.parse(s);
ba8219ac7484 scansion.pretty: Just emit input on invalid XML
Matthew Wild <mwild1@gmail.com>
parents: 112
diff changeset
76 if not doc then
ba8219ac7484 scansion.pretty: Just emit input on invalid XML
Matthew Wild <mwild1@gmail.com>
parents: 112
diff changeset
77 return s; -- Not valid XML, don't prettify
ba8219ac7484 scansion.pretty: Just emit input on invalid XML
Matthew Wild <mwild1@gmail.com>
parents: 112
diff changeset
78 end
112
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
79 return pretty_print(doc, ind);
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
80 end
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
81 end
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
82
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
83 return {
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
84 new = new;
bbb49227c174 scansion.pretty: Utility lib for XML pretty-printing, borrowed from Prosody
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
85 }

mercurial