diff options
author | Thijs Schreijer <thijs@thijsschreijer.nl> | 2025-03-01 19:17:17 +0100 |
---|---|---|
committer | Thijs Schreijer <thijs@thijsschreijer.nl> | 2025-03-02 19:40:15 +0100 |
commit | 2981db32130b30c9b12e7347bfdbe2e7584e9274 (patch) | |
tree | 9dc1330b743b9f4aed15d92c8036a5a41024fc87 /system | |
parent | bdd02cba9ffa1eee3684063b46091f2f868b32b8 (diff) | |
download | luasystem-2981db32130b30c9b12e7347bfdbe2e7584e9274.tar.gz luasystem-2981db32130b30c9b12e7347bfdbe2e7584e9274.tar.bz2 luasystem-2981db32130b30c9b12e7347bfdbe2e7584e9274.zip |
feat(readkey): allow a sleep function to be passed
There are cases where both a blocking and non-blocking sleep is
needed. In those cases just poatching system.sleep isn't good
enough. Hence now we can pass a sleep function.
Diffstat (limited to 'system')
-rw-r--r-- | system/init.lua | 21 |
1 files changed, 12 insertions, 9 deletions
diff --git a/system/init.lua b/system/init.lua index e99d0d4..a81978e 100644 --- a/system/init.lua +++ b/system/init.lua | |||
@@ -229,17 +229,18 @@ end | |||
229 | 229 | ||
230 | do | 230 | do |
231 | --- Reads a single byte from the console, with a timeout. | 231 | --- Reads a single byte from the console, with a timeout. |
232 | -- This function uses `system.sleep` to wait until either a byte is available or the timeout is reached. | 232 | -- This function uses `fsleep` to wait until either a byte is available or the timeout is reached. |
233 | -- The sleep period is exponentially backing off, starting at 0.0125 seconds, with a maximum of 0.2 seconds. | 233 | -- The sleep period is exponentially backing off, starting at 0.0125 seconds, with a maximum of 0.2 seconds. |
234 | -- It returns immediately if a byte is available or if `timeout` is less than or equal to `0`. | 234 | -- It returns immediately if a byte is available or if `timeout` is less than or equal to `0`. |
235 | -- | 235 | -- |
236 | -- Using `system.readansi` is preferred over this function. Since this function can leave stray/invalid | 236 | -- Using `system.readansi` is preferred over this function. Since this function can leave stray/invalid |
237 | -- byte-sequences in the input buffer, while `system.readansi` reads full ANSI and UTF8 sequences. | 237 | -- byte-sequences in the input buffer, while `system.readansi` reads full ANSI and UTF8 sequences. |
238 | -- @tparam number timeout the timeout in seconds. | 238 | -- @tparam number timeout the timeout in seconds. |
239 | -- @tparam[opt=system.sleep] function fsleep the function to call for sleeping. | ||
239 | -- @treturn[1] byte the byte value that was read. | 240 | -- @treturn[1] byte the byte value that was read. |
240 | -- @treturn[2] nil if no key was read | 241 | -- @treturn[2] nil if no key was read |
241 | -- @treturn[2] string error message; `"timeout"` if the timeout was reached. | 242 | -- @treturn[2] string error message; `"timeout"` if the timeout was reached. |
242 | function system.readkey(timeout) | 243 | function system.readkey(timeout, fsleep) |
243 | if type(timeout) ~= "number" then | 244 | if type(timeout) ~= "number" then |
244 | error("arg #1 to readkey, expected timeout in seconds, got " .. type(timeout), 2) | 245 | error("arg #1 to readkey, expected timeout in seconds, got " .. type(timeout), 2) |
245 | end | 246 | end |
@@ -247,7 +248,7 @@ do | |||
247 | local interval = 0.0125 | 248 | local interval = 0.0125 |
248 | local key = system._readkey() | 249 | local key = system._readkey() |
249 | while key == nil and timeout > 0 do | 250 | while key == nil and timeout > 0 do |
250 | system.sleep(math.min(interval, timeout)) | 251 | (fsleep or system.sleep)(math.min(interval, timeout)) |
251 | timeout = timeout - interval | 252 | timeout = timeout - interval |
252 | interval = math.min(0.2, interval * 2) | 253 | interval = math.min(0.2, interval * 2) |
253 | key = system._readkey() | 254 | key = system._readkey() |
@@ -270,20 +271,22 @@ do | |||
270 | 271 | ||
271 | --- Reads a single key, if it is the start of ansi escape sequence then it reads | 272 | --- Reads a single key, if it is the start of ansi escape sequence then it reads |
272 | -- the full sequence. The key can be a multi-byte string in case of multibyte UTF-8 character. | 273 | -- the full sequence. The key can be a multi-byte string in case of multibyte UTF-8 character. |
273 | -- This function uses `system.readkey`, and hence `system.sleep` to wait until either a key is | 274 | -- This function uses `system.readkey`, and hence `fsleep` to wait until either a key is |
274 | -- available or the timeout is reached. | 275 | -- available or the timeout is reached. |
275 | -- It returns immediately if a key is available or if `timeout` is less than or equal to `0`. | 276 | -- It returns immediately if a key is available or if `timeout` is less than or equal to `0`. |
276 | -- In case of an ANSI sequence, it will return the full sequence as a string. | 277 | -- In case of an ANSI sequence, it will return the full sequence as a string. |
277 | -- @tparam number timeout the timeout in seconds. | 278 | -- @tparam number timeout the timeout in seconds. |
279 | -- @tparam[opt=system.sleep] function fsleep the function to call for sleeping. | ||
278 | -- @treturn[1] string the character that was received (can be multi-byte), or a complete ANSI sequence | 280 | -- @treturn[1] string the character that was received (can be multi-byte), or a complete ANSI sequence |
279 | -- @treturn[1] string the type of input: `"char"` for a single key, `"ansi"` for an ANSI sequence | 281 | -- @treturn[1] string the type of input: `"char"` for a single key, `"ansi"` for an ANSI sequence |
280 | -- @treturn[2] nil in case of an error | 282 | -- @treturn[2] nil in case of an error |
281 | -- @treturn[2] string error message; `"timeout"` if the timeout was reached. | 283 | -- @treturn[2] string error message; `"timeout"` if the timeout was reached. |
282 | -- @treturn[2] string partial result in case of an error while reading a sequence, the sequence so far. | 284 | -- @treturn[2] string partial result in case of an error while reading a sequence, the sequence so far. |
283 | function system.readansi(timeout) | 285 | function system.readansi(timeout, fsleep) |
284 | if type(timeout) ~= "number" then | 286 | if type(timeout) ~= "number" then |
285 | error("arg #1 to readansi, expected timeout in seconds, got " .. type(timeout), 2) | 287 | error("arg #1 to readansi, expected timeout in seconds, got " .. type(timeout), 2) |
286 | end | 288 | end |
289 | fsleep = fsleep or system.sleep | ||
287 | 290 | ||
288 | local key | 291 | local key |
289 | 292 | ||
@@ -297,7 +300,7 @@ do | |||
297 | else | 300 | else |
298 | -- read a new key | 301 | -- read a new key |
299 | local err | 302 | local err |
300 | key, err = system.readkey(timeout) | 303 | key, err = system.readkey(timeout, fsleep) |
301 | if key == nil then -- timeout or error | 304 | if key == nil then -- timeout or error |
302 | return nil, err | 305 | return nil, err |
303 | end | 306 | end |
@@ -306,7 +309,7 @@ do | |||
306 | if key == 27 then | 309 | if key == 27 then |
307 | -- looks like an ansi escape sequence, immediately read next char | 310 | -- looks like an ansi escape sequence, immediately read next char |
308 | -- as an heuristic against manually typing escape sequences | 311 | -- as an heuristic against manually typing escape sequences |
309 | local key2 = system.readkey(0) | 312 | local key2 = system.readkey(0, fsleep) |
310 | if key2 ~= 91 and key2 ~= 79 then -- we expect either "[" or "O" for an ANSI sequence | 313 | if key2 ~= 91 and key2 ~= 79 then -- we expect either "[" or "O" for an ANSI sequence |
311 | -- not the expected [ or O character, so we return the key as is | 314 | -- not the expected [ or O character, so we return the key as is |
312 | -- and store the extra key read for the next call | 315 | -- and store the extra key read for the next call |
@@ -335,7 +338,7 @@ do | |||
335 | -- read remainder of UTF8 sequence | 338 | -- read remainder of UTF8 sequence |
336 | local timeout_end = system.gettime() + timeout | 339 | local timeout_end = system.gettime() + timeout |
337 | while true do | 340 | while true do |
338 | key, err = system.readkey(timeout_end - system.gettime()) | 341 | key, err = system.readkey(timeout_end - system.gettime(), fsleep) |
339 | if err then | 342 | if err then |
340 | break | 343 | break |
341 | end | 344 | end |
@@ -354,7 +357,7 @@ do | |||
354 | -- read remainder of ANSI sequence | 357 | -- read remainder of ANSI sequence |
355 | local timeout_end = system.gettime() + timeout | 358 | local timeout_end = system.gettime() + timeout |
356 | while true do | 359 | while true do |
357 | key, err = system.readkey(timeout_end - system.gettime()) | 360 | key, err = system.readkey(timeout_end - system.gettime(), fsleep) |
358 | if err then | 361 | if err then |
359 | break | 362 | break |
360 | end | 363 | end |