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
|
local lpeg = require "lpeg"
local string = require "string"
local stringformat = string.format
local verboselvl = 0
local colorize = false
--- 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
}
|