• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

lunarmodules / Penlight / 16883017568

11 Aug 2025 02:27PM UTC coverage: 87.973% (-0.9%) from 88.871%
16883017568

push

github

web-flow
Merge 43bd2455e into bd26cb9e4

23 of 24 new or added lines in 4 files covered. (95.83%)

54 existing lines in 4 files now uncovered.

5398 of 6136 relevant lines covered (87.97%)

41.26 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

39.36
/lua/pl/compat.lua
1
----------------
2
--- Lua 5.1/5.2/5.3 compatibility.
3
-- Injects `table.pack`, `table.unpack`, and `package.searchpath` in the global
4
-- environment, to make sure they are available for Lua 5.1 and LuaJIT.
5
--
6
-- All other functions are exported as usual in the returned module table.
7
--
8
-- NOTE: everything in this module is also available in `pl.utils`.
9
-- @module pl.compat
10
local compat = {}
44✔
11

12
--- boolean flag this is Lua 5.1 (or LuaJIT).
13
-- @field lua51
14
compat.lua51 = _VERSION == 'Lua 5.1'
44✔
15

16
--- boolean flag this is LuaJIT.
17
-- @field jit
18
compat.jit = (tostring(assert):match('builtin') ~= nil)
44✔
19

20
--- boolean flag this is LuaJIT with 5.2 compatibility compiled in.
21
-- @field jit52
22
if compat.jit then
44✔
23
    -- 'goto' is a keyword when 52 compatibility is enabled in LuaJit
UNCOV
24
    compat.jit52 = not loadstring("local goto = 1")
×
25
end
26

27
--- the directory separator character for the current platform.
28
-- @field dir_separator
29
compat.dir_separator = _G.package.config:sub(1,1)
44✔
30

31
--- boolean flag this is a Windows platform.
32
-- @field is_windows
33
compat.is_windows = compat.dir_separator == '\\'
44✔
34

35
--- execute a shell command, in a compatible and platform independent way.
36
-- This is a compatibility function that returns the same for Lua 5.1 and
37
-- Lua 5.2+.
38
--
39
-- NOTE: Windows systems can use signed 32bit integer exitcodes. Posix systems
40
-- only use exitcodes 0-255, anything else is undefined.
41
--
42
-- NOTE2: In Lua 5.2 and 5.3 a Windows exitcode of -1 would not properly be
43
-- returned, this function will return it properly for all versions.
44
-- @param cmd a shell command
45
-- @return true if successful
46
-- @return actual return code
47
function compat.execute(cmd)
44✔
48
    local res1,res2,res3 = os.execute(cmd)
39✔
49
    if res2 == "No error" and res3 == 0 and compat.is_windows then
39✔
50
      -- os.execute bug in Lua 5.2/5.3 not reporting -1 properly on Windows
51
      -- this was fixed in 5.4
52
      res3 = -1
×
53
    end
54
    if compat.lua51 and not compat.jit52 then
39✔
UNCOV
55
        if compat.is_windows then
×
56
            return res1==0,res1
×
57
        else
UNCOV
58
            res1 = res1 > 255 and res1 / 256 or res1
×
UNCOV
59
            return res1==0,res1
×
60
        end
61
    else
62
        if compat.is_windows then
39✔
63
            return res3==0,res3
×
64
        else
65
            return not not res1,res3
39✔
66
        end
67
    end
68
end
69

70
----------------
71
-- Load Lua code as a text or binary chunk (in a Lua 5.2 compatible way).
72
-- @param ld code string or loader
73
-- @param[opt] source name of chunk for errors
74
-- @param[opt] mode 'b', 't' or 'bt'
75
-- @param[opt] env environment to load the chunk in
76
-- @function compat.load
77

78
---------------
79
-- Get environment of a function (in a Lua 5.1 compatible way).
80
-- Not 100% compatible, so with Lua 5.2 it may return nil for a function with no
81
-- global references!
82
-- Based on code by [Sergey Rozhenko](http://lua-users.org/lists/lua-l/2010-06/msg00313.html)
83
-- @param f a function or a call stack reference
84
-- @function compat.getfenv
85

86
---------------
87
-- Set environment of a function (in a Lua 5.1 compatible way).
88
-- @param f a function or a call stack reference
89
-- @param env a table that becomes the new environment of `f`
90
-- @function compat.setfenv
91

92
if compat.lua51 then -- define Lua 5.2 style load()
44✔
UNCOV
93
    if not compat.jit then -- but LuaJIT's load _is_ compatible
×
UNCOV
94
        local lua51_load = load
×
UNCOV
95
        function compat.load(str,src,mode,env)
×
96
            local chunk,err
UNCOV
97
            if type(str) == 'string' then
×
UNCOV
98
                if str:byte(1) == 27 and not (mode or 'bt'):find 'b' then
×
UNCOV
99
                    return nil,"attempt to load a binary chunk"
×
100
                end
UNCOV
101
                chunk,err = loadstring(str,src)
×
102
            else
UNCOV
103
                chunk,err = lua51_load(str,src)
×
104
            end
UNCOV
105
            if chunk and env then setfenv(chunk,env) end
×
UNCOV
106
            return chunk,err
×
107
        end
108
    else
UNCOV
109
        compat.load = load
×
110
    end
UNCOV
111
    compat.setfenv, compat.getfenv = setfenv, getfenv
×
112
else
113
    compat.load = load
44✔
114
    -- setfenv/getfenv replacements for Lua 5.2
115
    -- by Sergey Rozhenko
116
    -- http://lua-users.org/lists/lua-l/2010-06/msg00313.html
117
    -- Roberto Ierusalimschy notes that it is possible for getfenv to return nil
118
    -- in the case of a function with no globals:
119
    -- http://lua-users.org/lists/lua-l/2010-06/msg00315.html
120
    function compat.setfenv(f, t)
44✔
121
        f = (type(f) == 'function' and f or debug.getinfo(f + 1, 'f').func)
2✔
122
        local name
123
        local up = 0
2✔
124
        repeat
125
            up = up + 1
5✔
126
            name = debug.getupvalue(f, up)
5✔
127
        until name == '_ENV' or name == nil
5✔
128
        if name then
2✔
129
            debug.upvaluejoin(f, up, function() return name end, 1) -- use unique upvalue
2✔
130
            debug.setupvalue(f, up, t)
2✔
131
        end
132
        if f ~= 0 then return f end
2✔
133
    end
134

135
    function compat.getfenv(f)
44✔
136
        local f = f or 0
9✔
137
        f = (type(f) == 'function' and f or debug.getinfo(f + 1, 'f').func)
9✔
138
        local name, val
139
        local up = 0
9✔
140
        repeat
141
            up = up + 1
12✔
142
            name, val = debug.getupvalue(f, up)
12✔
143
        until name == '_ENV' or name == nil
12✔
144
        return val
9✔
145
    end
146
end
147

148

149
--- Global exported functions (for Lua 5.1 & LuaJIT)
150
-- @section lua52
151

152
--- pack an argument list into a table.
153
-- @param ... any arguments
154
-- @return a table with field n set to the length
155
-- @function table.pack
156
if not table.pack then
44✔
UNCOV
157
    function table.pack (...)       -- luacheck: ignore
×
UNCOV
158
        return {n=select('#',...); ...}
×
159
    end
160
end
161

162
--- unpack a table and return the elements.
163
--
164
-- NOTE: this version does NOT honor the n field, and hence it is not nil-safe.
165
-- See `utils.unpack` for a version that is nil-safe.
166
-- @param t table to unpack
167
-- @param[opt] i index from which to start unpacking, defaults to 1
168
-- @param[opt] j index of the last element to unpack, defaults to #t
169
-- @return multiple return values from the table
170
-- @function table.unpack
171
-- @see utils.unpack
172
if not table.unpack then
44✔
UNCOV
173
    table.unpack = unpack           -- luacheck: ignore
×
174
end
175

176
--- return the full path where a file name would be matched.
177
-- This function was introduced in Lua 5.2, so this compatibility version
178
-- will be injected in Lua 5.1 engines.
179
-- @string name file name, possibly dotted
180
-- @string path a path-template in the same form as package.path or package.cpath
181
-- @string[opt] sep template separate character to be replaced by path separator. Default: "."
182
-- @string[opt] rep the path separator to use, defaults to system separator. Default; "/" on Unixes, "\" on Windows.
183
-- @see path.package_path
184
-- @function package.searchpath
185
-- @return on success: path of the file
186
-- @return on failure: nil, error string listing paths tried
187
if not package.searchpath then
44✔
UNCOV
188
    function package.searchpath (name,path,sep,rep)    -- luacheck: ignore
×
UNCOV
189
        if type(name) ~= "string" then
×
190
            error(("bad argument #1 to 'searchpath' (string expected, got %s)"):format(type(path)), 2)
×
191
        end
UNCOV
192
        if type(path) ~= "string" then
×
193
            error(("bad argument #2 to 'searchpath' (string expected, got %s)"):format(type(path)), 2)
×
194
        end
UNCOV
195
        if sep ~= nil and type(sep) ~= "string" then
×
196
            error(("bad argument #3 to 'searchpath' (string expected, got %s)"):format(type(path)), 2)
×
197
        end
UNCOV
198
        if rep ~= nil and type(rep) ~= "string" then
×
199
            error(("bad argument #4 to 'searchpath' (string expected, got %s)"):format(type(path)), 2)
×
200
        end
UNCOV
201
        sep = sep or "."
×
UNCOV
202
        rep = rep or compat.dir_separator
×
203
        do
UNCOV
204
          local s, e = name:find(sep, nil, true)
×
UNCOV
205
          while s do
×
UNCOV
206
            name = name:sub(1, s-1) .. rep .. name:sub(e+1, -1)
×
UNCOV
207
            s, e = name:find(sep, s + #rep + 1, true)
×
208
          end
209
        end
UNCOV
210
        local tried = {}
×
UNCOV
211
        for m in path:gmatch('[^;]+') do
×
UNCOV
212
            local nm = m:gsub('?', name)
×
UNCOV
213
            tried[#tried+1] = nm
×
UNCOV
214
            local f = io.open(nm,'r')
×
UNCOV
215
            if f then f:close(); return nm end
×
216
        end
UNCOV
217
        return nil, "\tno file '" .. table.concat(tried, "'\n\tno file '") .. "'"
×
218
    end
219
end
220

221
--- Global exported functions (for Lua < 5.4)
222
-- @section lua54
223

224
--- raise a warning message.
225
-- This functions mimics the `warn` function added in Lua 5.4.
226
-- @function warn
227
-- @param ... any arguments
228
if not rawget(_G, "warn") then
44✔
UNCOV
229
    local enabled = false
×
230
    local function warn(arg1, ...)
UNCOV
231
        if type(arg1) == "string" and arg1:sub(1, 1) == "@" then
×
232
            -- control message
233
            if arg1 == "@on" then
×
234
                enabled = true
×
235
                return
×
236
            end
237
            if arg1 == "@off" then
×
238
                enabled = false
×
239
                return
×
240
            end
241
            return -- ignore unknown control messages
×
242
        end
UNCOV
243
        if enabled then
×
244
          io.stderr:write("Lua warning: ", arg1, ...)
×
245
          io.stderr:write("\n")
×
246
        end
247
    end
248
    -- use rawset to bypass OpenResty's protection of global scope
UNCOV
249
    rawset(_G, "warn", warn)
×
250
end
251

252
return compat
44✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc