aboutsummaryrefslogtreecommitdiff
path: root/system
diff options
context:
space:
mode:
authorThijs Schreijer <thijs@thijsschreijer.nl>2025-03-01 19:17:17 +0100
committerThijs Schreijer <thijs@thijsschreijer.nl>2025-03-02 19:40:15 +0100
commit2981db32130b30c9b12e7347bfdbe2e7584e9274 (patch)
tree9dc1330b743b9f4aed15d92c8036a5a41024fc87 /system
parentbdd02cba9ffa1eee3684063b46091f2f868b32b8 (diff)
downloadluasystem-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.lua21
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
230do 230do
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