System I/O
The sys namespace provides OS-level operations: file I/O, process execution, environment variables, signals, and terminal control.
File I/O
Section titled “File I/O”// Write a filesys.write("output.txt", "hello from praia")
// Read a filelet content = sys.read("output.txt")print(content) // hello from praia
// Append to a filesys.append("output.txt", "\nmore text")File system
Section titled “File system”sys.mkdir("my/nested/dir") // creates all parent dirsprint(sys.exists("output.txt")) // truesys.remove("output.txt") // delete a filesys.remove("my/nested/dir") // delete a directory (recursive)sys.copy("src.txt", "dst.txt") // copy a filesys.copy("srcdir", "dstdir") // copy a directory (recursive)sys.move("old.txt", "new.txt") // move / renamelet files = sys.readDir("my/dir") // array of filenames in directoryRunning commands
Section titled “Running commands”sys.exec(cmd) (also sys.run(cmd)) runs a command and returns {stdout, stderr, exitCode}. Pass a string for shell execution, or an array for safe argument passing:
// String form -- runs through /bin/shlet r = sys.exec("ls -la")print(r.stdout)print(r.exitCode) // 0
// Array form -- no shell, safe from injectionlet r2 = sys.exec(["git", "clone", "--quiet", url, dest])print(r2.exitCode)
// Check for errorslet r3 = sys.exec("cat nonexistent.txt")if (r3.exitCode != 0) { print("Error:", r3.stderr)}Process spawning
Section titled “Process spawning”sys.spawn(cmd) launches a child process with piped stdin/stdout/stderr:
let proc = sys.spawn("cat -n")proc.write("hello\n")proc.write("world\n")proc.closeStdin()print(proc.read())print("exit:", proc.wait())Process handle methods
Section titled “Process handle methods”| Method | Description |
|---|---|
proc.write(data) | Write to the child’s stdin |
proc.closeStdin() | Close stdin (signals EOF) |
proc.read() | Read all of stdout (blocks until EOF) |
proc.readErr() | Read all of stderr |
proc.readLine() | Read one line from stdout (nil on EOF) |
proc.wait() | Wait for exit, returns exit code |
proc.kill(signal?) | Send a signal (default SIGTERM) |
proc.pid | The child’s process ID |
Line-by-line reading
Section titled “Line-by-line reading”let proc = sys.spawn("grep -i error")proc.write("INFO all good\n")proc.write("ERROR disk full\n")proc.write("ERROR timeout\n")proc.closeStdin()
let line = proc.readLine()while (line != nil) { print("match:", line) line = proc.readLine()}proc.wait()Use sys.exec for fire-and-forget commands. Use sys.spawn when you need to pipe input, read output line-by-line, or interact with a long-running process.
Command-line arguments
Section titled “Command-line arguments”Arguments after the script name are available in sys.args:
praia script.praia hello worldprint(sys.args) // ["hello", "world"]Reading from stdin
Section titled “Reading from stdin”sys.input(prompt?) reads one line from standard input. Returns nil on EOF (Ctrl-D).
let name = sys.input("What's your name? ")if (name == nil) { sys.exit(0) }Environment variables
Section titled “Environment variables”print(sys.env("HOME")) // "/Users/ada"sys.setenv("MY_VAR", "hello")print(sys.cwd()) // "/path/to/project"print(sys.platform) // "darwin"| Function | Description |
|---|---|
sys.env(name) | Read environment variable (nil if not set) |
sys.setenv(name, value) | Set an environment variable |
sys.cwd() | Current working directory |
sys.uid() | Effective user ID |
sys.isRoot() | true if running as root (uid 0) |
sys.platform | "darwin", "linux", or "windows" |
Exiting
Section titled “Exiting”sys.exit(0) // exit with code 0sys.exit(1) // exit with code 1Signal handling
Section titled “Signal handling”Register callbacks for OS signals:
| Function | Description |
|---|---|
sys.onSignal(name, fn) | Register a handler. Pass nil to restore default. |
sys.checkSignals() | Process pending signals. Returns true if any fired. |
sys.signal(name) | Send a signal to the current process. |
Supported: SIGINT, SIGTERM, SIGHUP, SIGUSR1, SIGUSR2 (short names like INT also work).
let running = truesys.onSignal("SIGINT", lam{ sig in print("shutting down...") running = false})
while (running) { // ... do work ... sys.checkSignals()}print("cleanup done")Call sys.checkSignals() in long-running loops so callbacks get a chance to run.
Terminal I/O
Section titled “Terminal I/O”sys.rawMode(true) // disable line bufferinglet key = sys.readKey() // read a single keypresssys.rawMode(false) // restore normal terminal
let size = sys.termSize()print(size.rows, size.cols)| Function | Description |
|---|---|
sys.rawMode(bool) | Enable/disable raw terminal mode |
sys.readKey() | Read a single keypress (handles escape sequences) |
sys.termSize() | Returns {rows, cols} |
sys.stdout(str) | Write to stdout without trailing newline |
Arrow keys return escape sequences: "\x1b[A" (up), "\x1b[B" (down), "\x1b[C" (right), "\x1b[D" (left).
Path utilities
Section titled “Path utilities”| Function | Description |
|---|---|
path.join(parts...) | Join path segments |
path.dirname(p) | Parent directory |
path.basename(p) | Filename component |
path.ext(p) | File extension (including dot) |
path.resolve(p) | Absolute path |
path.join("src", "main.cpp") // "src/main.cpp"path.dirname("/usr/local/bin/p") // "/usr/local/bin"path.basename("/usr/local/bin/p") // "p"path.ext("script.praia") // ".praia"