Lua runner with rich builtin stdlib ("lunascript")
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
luna/docs/os.md

105 lines
3.5 KiB

# `os`
Luna runs scripts in a sandbox, so the standard `os` table is trimmed to its
safe, time-related functions — `os.time`, `os.clock`, `os.date`,
`os.difftime` — while the parts that touch the system
(`os.execute`, `os.getenv`, `os.remove`, `os.exit`, …) are removed. To that
trimmed table Luna adds a high-resolution clock, an async sleep, and access to
the script's command-line arguments.
```lua
local t0 = os.microtime()
os.sleep(0.25)
print(string.format("waited %.3fs", os.microtime() - t0)) --> waited ~0.250s
```
## `os.microtime()`
Return the current time as a Unix timestamp in **seconds, as a float** with
sub-second precision — unlike `os.time`, which is whole seconds only. It is the
right tool for measuring elapsed time:
```lua
local start = os.microtime()
doSomeWork()
local elapsed = os.microtime() - start
log.info(string.format("took %.1f ms", elapsed * 1000))
```
It reads the system wall clock, so it tracks real time (and can jump if the clock
is adjusted); for interval timing the difference of two readings is what you
want.
## `os.args()`
Return the command-line arguments passed to the script, as an array (a fresh
table on every call, so it is safe to mutate). On the `luna` command line the
script's arguments are everything after the script path — even a token spelled
like a luna flag goes to the script there, so luna's own flags (`--sandbox` &
co.) must come before the path. A `--` between the path and the arguments is
accepted and skipped:
```sh
luna script.lua one two --three
luna --sandbox script.lua -- one two --three
```
```lua
-- script.lua
for i, arg in ipairs(os.args()) do
print(i, arg) --> 1 one / 2 two / 3 --three
end
```
An executable script with a `#!/usr/bin/env luna` shebang line receives its
arguments the same way, with no `--` needed:
```sh
./script.lua one two --three
```
In the REPL `os.args()` returns an empty table. Arguments are passed through
as raw byte strings, without UTF-8 conversion.
## `os.sleep(seconds)`
Pause for `seconds` (a float, so `os.sleep(0.1)` is 100 ms). This is an **async**
sleep: it suspends the script on the runtime instead of blocking the OS thread,
so concurrent work keeps running while it waits.
```lua
os.sleep(1) -- one second
os.sleep(0.05) -- 50 milliseconds
```
`seconds` must be a non-negative finite number.
Because the sleep suspends rather than blocks, sibling tasks started with
[`task.join`](concurrency.md) make progress during the wait — that is what lets
several sleeps (or requests, or queries) overlap:
```lua
-- finishes in ~0.3s, not 0.6s — the sleeps overlap
task.join(
function() os.sleep(0.3) end,
function() os.sleep(0.2) end,
function() os.sleep(0.1) end
)
```
One caveat applies to coroutines you drive yourself with `coroutine.wrap` /
`coroutine.resume`: there, `os.sleep` does not actually wait. See
[Self-driven coroutines](concurrency.md#self-driven-coroutines) for the full
explanation — the rule is to run anything that needs to sleep through
`task.join`.
## Notes
- **The sandbox keeps the time functions.** `os.time`, `os.clock`, `os.date`,
and `os.difftime` work as in stock Lua; functions that touch the system are
not present.
- **`microtime` for durations, `time` for timestamps.** Use `os.microtime` when
you need sub-second precision or are timing an interval; `os.time` when whole
seconds suffice.
- **`sleep` is cooperative.** It yields to the runtime, so it is cheap to sleep
inside concurrent tasks — see [Concurrency](concurrency.md).