/
tpretty.lua
133 lines (119 loc) · 4.07 KB
/
tpretty.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
--------------------------------------------------------------------------------
--- Pretty visualization of non-recursive tables.
-- @module lua-nucleo.tpretty
-- This file is a part of lua-nucleo library
-- @copyright lua-nucleo authors (see file `COPYRIGHT` for the license)
--------------------------------------------------------------------------------
local pairs, ipairs, type, tostring = pairs, ipairs, type, tostring
local table_concat = table.concat
local string_match, string_format = string.match, string.format
local lua51_keywords = import 'lua-nucleo/language.lua' { 'lua51_keywords' }
local make_prettifier = import 'lua-nucleo/prettifier.lua' { 'make_prettifier' }
local is_table = import 'lua-nucleo/type.lua' { 'is_table' }
local tstr = import 'lua-nucleo/table.lua' { 'tstr' }
local arguments = import 'lua-nucleo/args.lua' { 'arguments' }
local number_to_string = import 'lua-nucleo/string.lua' { 'number_to_string' }
local tpretty
do
local add = ""
local function impl(t, cat, prettifier, visited)
local t_type = type(t)
if t_type == "table" then
if not visited[t] then
visited[t] = true
prettifier:table_start()
-- Serialize numeric indices
local next_i = 0
for i, v in ipairs(t) do
if i > 1 then -- TODO: Move condition out of the loop
prettifier:separator()
end
impl(v, cat, prettifier, visited)
next_i = i
end
local next_i = next_i + 1
-- Serialize hash part
-- Skipping comma only at first element if there is no numeric part.
local need_comma = (next_i > 1)
for k, v in pairs(t) do
local k_type = type(k)
if k_type == "string" then
if need_comma then
prettifier:separator()
end
need_comma = true
prettifier:key_start()
-- TODO: Need "%q" analogue, which would put quotes
-- only if string does not match regexp below
if not lua51_keywords[k] and string_match(k, "^[%a_][%a%d_]*$") then
cat(k)
else
cat(string_format("[%q]", k))
end
prettifier:value_start()
impl(v, cat, prettifier, visited)
prettifier:key_value_finish()
else
if
k_type ~= "number" or -- non-string non-number
k >= next_i or k < 1 or -- integer key in hash part of the table
k % 1 ~= 0 -- non-integer key
then
if need_comma then
prettifier:separator()
end
need_comma = true
prettifier:key_start()
cat("[")
impl(k, cat, prettifier, visited)
cat("]")
prettifier:value_start()
impl(v, cat, prettifier, visited)
prettifier:key_value_finish()
end
end
end
prettifier:table_finish()
visited[t] = nil
else
-- Note this loses information on recursive tables
cat('"table (recursive)"')
end
elseif t_type == "number" then
cat(number_to_string(t))
elseif t_type == "boolean" then
cat(tostring(t))
elseif t == nil then
cat("nil")
else
-- Note this converts non-serializable types to strings
cat(string_format("%q", tostring(t)))
end
end
tpretty = function(t, indent, cols)
indent = indent or " "
cols = cols or 80 --standard screen width
if not is_table(t) then
return tstr(t)
end
arguments(
-- all arguments should be listed, even though t is checked before
--"table", t
"string", indent,
"number", cols
)
local buf = {}
local sptable = {}
-- make_prettifier works with external buf, so special formatter cat
-- is used instead of make_concatter
local cat = function(v) buf[#buf + 1] = v end
local pr = make_prettifier(indent, buf, cols)
impl(t, cat, pr, {})
pr:finished()
return table_concat(buf)
end
end
return
{
tpretty = tpretty;
}