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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
|
--!A cross-platform build utility based on Lua
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
-- Copyright (C) 2015-present, Xmake Open Source Community.
--
-- @author OpportunityLiu
-- @file todisplay.lua
--
-- define module
local todisplay = todisplay or {}
-- load modules
local colors = require("base/colors")
local math = require("base/math")
function todisplay._reset()
local reset = todisplay._RESET
if not reset then
reset = colors.translate("${reset}")
todisplay._RESET = reset
end
return reset
end
-- format string with theme colors
function todisplay._format(fmtkey, fmtdefault, ...)
local theme = colors.theme()
if theme then
return colors.translate(string.format(theme:get(fmtkey), ...), { patch_reset = false, ignore_unknown = true })
else
return string.format(fmtdefault, ...)
end
end
-- translate string with theme formats
function todisplay._translate(str)
local theme = colors.theme()
if theme then
return colors.translate(str, { patch_reset = false, ignore_unknown = true })
else
return colors.ignore(str)
end
end
-- print keyword
function todisplay._print_keyword(keyword)
return todisplay._translate("${reset}${color.dump.keyword}") .. tostring(keyword) .. todisplay._reset()
end
-- print string
function todisplay._print_string(str, as_key)
local quote = (not as_key) or (not str:match("^[a-zA-Z_][a-zA-Z0-9_]*$"))
if quote then
return todisplay._translate([[${reset}${color.dump.string_quote}"${reset}${color.dump.string}]])
.. str
.. todisplay._translate([[${reset}${color.dump.string_quote}"${reset}]])
else
return todisplay._translate("${reset}${color.dump.string}") .. str .. todisplay._reset()
end
end
-- print number
function todisplay._print_number(num)
return todisplay._translate("${reset}${color.dump.number}") .. tostring(num) .. todisplay._reset()
end
-- print function
function todisplay._print_function(func)
local funcinfo = debug.getinfo(func)
local srcinfo = funcinfo.short_src
if funcinfo.linedefined >= 0 then
srcinfo = srcinfo .. ":" .. funcinfo.linedefined
end
local funcname = funcinfo.name and (funcinfo.name .. " ") or ""
return todisplay._translate("${reset}${color.dump.function}function ${bright}")
.. funcname
.. todisplay._translate("${reset}${dim}")
.. srcinfo .. todisplay._reset()
end
function todisplay._get_tostr_method(value)
local metatable = debug.getmetatable(value)
if metatable then
local __todisplay = rawget(metatable, "__todisplay")
local __tostring = rawget(metatable, "__tostring")
return __todisplay, __tostring
end
return nil, nil
end
-- print value with default format
function todisplay._print_default_scalar(value, style, formatkey)
local __todisplay, __tostring = todisplay._get_tostr_method(value)
if __todisplay then
local ok, str = pcall(__todisplay, value)
if ok then
value = todisplay._translate(str)
-- disable format
formatkey = nil
end
elseif __tostring then
local ok, str = pcall(__tostring, value)
if ok then
value = str
end
end
if formatkey then
value = todisplay._format(formatkey, "%s", value)
end
local reset = todisplay._reset()
return reset .. todisplay._translate(style) .. value .. reset
end
-- print udata value with scalar format
function todisplay._print_udata_scalar(value)
return todisplay._print_default_scalar(value, "${color.dump.udata}", "text.dump.udata_format")
end
-- print table value with scalar format
function todisplay._print_table_scalar(value, expand)
if debug.getmetatable(value) or not expand then
return todisplay._print_default_scalar(value, "${color.dump.table}", "text.dump.table_format")
end
local pvalues = {}
local has_string_key = false
local as, ae = math.huge, -math.huge
local k, v
for i = 1, 10 do
k, v = next(value, k)
if k == nil then break end
if type(k) == "string" then
pvalues[k] = todisplay._print_scalar(v, false)
has_string_key = true
elseif type(k) == "number" and math.isint(k) then
pvalues[k] = todisplay._print_scalar(v, false)
as = math.min(k, as)
ae = math.max(k, ae)
else
-- no common table or array
return todisplay._print_default_scalar(value, "${color.dump.table}", "text.dump.table_format")
end
end
if k ~= nil then
-- to large
return todisplay._print_default_scalar(value, "${color.dump.table}", "text.dump.table_format")
end
local results = {}
local is_arr = as >= 1 and ae <= 20
if is_arr then
local nilstr
for i = 1, ae do
local pv = pvalues[i]
if pv == nil then
if not nilstr then
nilstr = todisplay._print_keyword("nil")
end
pv = nilstr
end
results[i] = pv
end
end
if has_string_key then
for pk, pv in pairs(pvalues) do
if type(pk) == "string" then
local pkstr = todisplay._print_string(pk, true)
table.insert(results, pkstr .. " = " .. pv)
elseif not is_arr then
local pkstr = todisplay._print_number(pk)
table.insert(results, pkstr .. " = " .. pv)
end
end
end
if #results == 0 then
return todisplay._translate("${reset}${color.dump.table}") .. "{ }" .. todisplay._reset()
end
return todisplay._translate("${reset}${color.dump.table}") .. "{ " .. table.concat(results, ", ") .." }" .. todisplay._reset()
end
-- print scalar value
function todisplay._print_scalar(value, expand)
if type(value) == "nil" or type(value) == "boolean" then
return todisplay._print_keyword(value)
elseif type(value) == "number" then
return todisplay._print_number(value)
elseif type(value) == "string" then
return todisplay._print_string(value)
elseif type(value) == "function" then
return todisplay._print_function(value)
elseif type(value) == "userdata" then
return todisplay._print_udata_scalar(value)
elseif type(value) == "table" then
return todisplay._print_table_scalar(value, expand)
else
return todisplay._print_default_scalar(value, "${color.dump.default}", "text.dump.default_format")
end
end
function todisplay.print(value)
return todisplay._print_scalar(value, true)
end
setmetatable(todisplay, {
__call = function (_, ...)
return todisplay.print(...)
end
})
return todisplay
|