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
|
local uv = require('luv')
local utils = {}
local usecolors
if uv.guess_handle(1) == "tty" then
utils.stdout = uv.new_tty(1, false)
usecolors = true
else
utils.stdout = uv.new_pipe(false)
uv.pipe_open(utils.stdout, 1)
usecolors = false
end
function utils.uvVersionGEQ(min_version)
if not min_version then return true end
local min_version_num = min_version
if type(min_version) == "string" then
local version_parts = {}
for part in min_version:gmatch("%d+") do
table.insert(version_parts, tonumber(part))
end
assert(#version_parts == 3, "malformed version string: " .. min_version)
min_version_num = version_parts[1]*0x10000 + version_parts[2]*0x100 + version_parts[3]
end
return uv.version() >= min_version_num
end
if _G.jit and _G.jit.os then
-- Luajit provides explicit platform detection
utils.isWindows = _G.jit.os == "Windows"
utils.isLinux = _G.jit.os == 'Linux'
else
-- Normal lua will only have \ for path separator on windows.
utils.isWindows = package.config:find("\\") and true or false
utils.isLinux = false
if not utils.isWindows then
-- Use os_uname if it's available, fallback to popen
if utils.uvVersionGEQ("1.25.0") then
local uname = uv.os_uname()
utils.isLinux = uname.sysname:lower() == 'linux'
else
local popen_handle = io.popen('uname -s')
if popen_handle then
local uname_os = assert(popen_handle:read('*a'))
popen_handle:close()
utils.isLinux = uname_os:lower() == 'linux'
end
end
end
end
local colors = {
black = "0;30",
red = "0;31",
green = "0;32",
yellow = "0;33",
blue = "0;34",
magenta = "0;35",
cyan = "0;36",
white = "0;37",
B = "1;",
Bblack = "1;30",
Bred = "1;31",
Bgreen = "1;32",
Byellow = "1;33",
Bblue = "1;34",
Bmagenta = "1;35",
Bcyan = "1;36",
Bwhite = "1;37"
}
function utils.color(color_name)
if usecolors then
return "\27[" .. (colors[color_name] or "0") .. "m"
else
return ""
end
end
function utils.colorize(color_name, string, reset_name)
return utils.color(color_name) .. tostring(string) .. utils.color(reset_name)
end
local backslash, null, newline, carriage, tab, quote, quote2, obracket, cbracket
function utils.loadColors(n)
if n ~= nil then usecolors = n end
backslash = utils.colorize("Bgreen", "\\\\", "green")
null = utils.colorize("Bgreen", "\\0", "green")
newline = utils.colorize("Bgreen", "\\n", "green")
carriage = utils.colorize("Bgreen", "\\r", "green")
tab = utils.colorize("Bgreen", "\\t", "green")
quote = utils.colorize("Bgreen", '"', "green")
quote2 = utils.colorize("Bgreen", '"')
obracket = utils.colorize("B", '[')
cbracket = utils.colorize("B", ']')
end
utils.loadColors()
function utils.dump(o, depth)
local t = type(o)
if t == 'string' then
return quote .. o:gsub("\\", backslash):gsub("%z", null):gsub("\n", newline):gsub("\r", carriage):gsub("\t", tab) .. quote2
end
if t == 'nil' then
return utils.colorize("Bblack", "nil")
end
if t == 'boolean' then
return utils.colorize("yellow", tostring(o))
end
if t == 'number' then
return utils.colorize("blue", tostring(o))
end
if t == 'userdata' then
return utils.colorize("magenta", tostring(o))
end
if t == 'thread' then
return utils.colorize("Bred", tostring(o))
end
if t == 'function' then
return utils.colorize("cyan", tostring(o))
end
if t == 'cdata' then
return utils.colorize("Bmagenta", tostring(o))
end
if t == 'table' then
if type(depth) == 'nil' then
depth = 0
end
if depth > 1 then
return utils.colorize("yellow", tostring(o))
end
local indent = (" "):rep(depth)
-- Check to see if this is an array
local is_array = true
local i = 1
for k,v in pairs(o) do
if not (k == i) then
is_array = false
end
i = i + 1
end
local first = true
local lines = {}
i = 1
local estimated = 0
for k,v in (is_array and ipairs or pairs)(o) do
local s
if is_array then
s = ""
else
if type(k) == "string" and k:find("^[%a_][%a%d_]*$") then
s = k .. ' = '
else
s = '[' .. utils.dump(k, 100) .. '] = '
end
end
s = s .. utils.dump(v, depth + 1)
lines[i] = s
estimated = estimated + #s
i = i + 1
end
if estimated > 200 then
return "{\n " .. indent .. table.concat(lines, ",\n " .. indent) .. "\n" .. indent .. "}"
else
return "{ " .. table.concat(lines, ", ") .. " }"
end
end
-- This doesn't happen right?
return tostring(o)
end
-- Print replacement that goes through libuv. This is useful on windows
-- to use libuv's code to translate ansi escape codes to windows API calls.
function print(...)
local n = select('#', ...)
local arguments = {...}
for i = 1, n do
arguments[i] = tostring(arguments[i])
end
uv.write(utils.stdout, table.concat(arguments, "\t") .. "\n")
end
-- A nice global data dumper
function utils.prettyPrint(...)
local n = select('#', ...)
local arguments = { ... }
for i = 1, n do
arguments[i] = utils.dump(arguments[i])
end
print(table.concat(arguments, "\t"))
end
return utils
|