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
|
local lpeg = require "lpeg"
local string = require "string"
local stringformat = string.format
local verboselvl = 0
local colorize = false
local table_mirrored = function (t, only)
local ret = { }
if t ~= nil then
for k, v in next, t do
ret [k] = v
if only == false then
ret [v] = k
end
end
end
return ret
end
local status do
local codes =
{ ok = 0
, error = -1
}
status = { codes = table_mirrored (codes) }
end
--- check if stderr is pipe; use color otherwise
local ok, unistd = pcall (require, "posix.unistd")
if ok then
local stderr_fd = unistd.STDERR_FILENO
colorize = unistd.isatty (unistd.STDERR_FILENO) == 1
end
local esc = '\27['
local colors =
{ black = esc .. "0;30m"
, red = esc .. "0;31m"
, green = esc .. "0;32m"
, yellow = esc .. "0;33m"
, blue = esc .. "0;34m"
, purple = esc .. "0;35m"
, cyan = esc .. "0;36m"
, white = esc .. "0;37m"
, reset = esc .. "m"
}
local mk_out = function (stream, threshold, newlinep, pfx, color)
if pfx == nil then
pfx = ""
else
if colorize and color ~= nil then
local col = colors [color]
if col ~= nil then
pfx = col .. pfx .. colors.reset end
end
pfx = "["..pfx.."] "
end
local out = io.stdout
if stream == "err" or stream == "stderr" then out = io.stderr end
return function (...)
if verboselvl >= threshold then
local ok, msg = pcall (stringformat, ...)
if ok then
out.write (out, pfx)
out.write (out, msg)
if newlinep == true then out:write "\n" end
---else silently ignore
end
end
end
end
local set_verbosity = function (n) verboselvl = n end
local trim_whitespace
local unescape_string
local internalize_value
do
local P = lpeg.P
local S = lpeg.S
local Cs = lpeg.Cs
local p_ws_char = S" \n\r\t\v"
local p_ws = p_ws_char^1
local p_ws_trailing = p_ws * P (-1)
local p_ws_drop = Cs ( (p_ws^-1 / "")
* (1 - p_ws_trailing)^0
* (p_ws^-1 * P (-1) / ""))
local p_escape_char = (P"\\n" / "\n")
+ (P"\\r" / "\r")
+ (P"\\t" / "\t")
+ (P"\\v" / "\v")
local p_unescape = Cs ((p_escape_char + 1)^0)
--[[--
rfc2445, sec. 4.1.2: Properties can have multiple values, separated by a
literal comma, thus text commas are escaped.
--]]--
local p_value_char = ( p_escape_char
+ P"\\," / ","
+ P"," / "\n")
local p_value = Cs ((p_value_char + 1)^0)
local lpegmatch = lpeg.match
trim_whitespace = function (s) return lpegmatch (p_ws_drop , s) end
unescape_string = function (s) return lpegmatch (p_unescape, s) end
internalize_value = function (s) return lpegmatch (p_value, s) end
end
return
{ println = mk_out ("stdout", 0, true)
, errorln = mk_out ("stderr", 0, true, "error", "red")
, noiseln = mk_out ("stderr", 1, true, "info" , "yellow")
, debugln = mk_out ("stderr", 2, true, "debug", "purple")
, set_verbosity = set_verbosity
, trim_whitespace = trim_whitespace
, unescape_string = unescape_string
, internalize_value = internalize_value
, status = status
}
|