Skip to content

System I/O

The sys namespace provides OS-level operations: file I/O, process execution, environment variables, signals, and terminal control.

// Write a file
sys.write("output.txt", "hello from praia")
// Read a file
let content = sys.read("output.txt")
print(content) // hello from praia
// Append to a file
sys.append("output.txt", "\nmore text")
sys.mkdir("my/nested/dir") // creates all parent dirs
print(sys.exists("output.txt")) // true
sys.remove("output.txt") // delete a file
sys.remove("my/nested/dir") // delete a directory (recursive)
sys.copy("src.txt", "dst.txt") // copy a file
sys.copy("srcdir", "dstdir") // copy a directory (recursive)
sys.move("old.txt", "new.txt") // move / rename
let files = sys.readDir("my/dir") // array of filenames in directory

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/sh
let r = sys.exec("ls -la")
print(r.stdout)
print(r.exitCode) // 0
// Array form -- no shell, safe from injection
let r2 = sys.exec(["git", "clone", "--quiet", url, dest])
print(r2.exitCode)
// Check for errors
let r3 = sys.exec("cat nonexistent.txt")
if (r3.exitCode != 0) {
print("Error:", r3.stderr)
}

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())
MethodDescription
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.pidThe child’s process ID
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.

Arguments after the script name are available in sys.args:

Terminal window
praia script.praia hello world
print(sys.args) // ["hello", "world"]

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) }
print(sys.env("HOME")) // "/Users/ada"
sys.setenv("MY_VAR", "hello")
print(sys.cwd()) // "/path/to/project"
print(sys.platform) // "darwin"
FunctionDescription
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"
sys.exit(0) // exit with code 0
sys.exit(1) // exit with code 1

Register callbacks for OS signals:

FunctionDescription
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 = true
sys.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.

sys.rawMode(true) // disable line buffering
let key = sys.readKey() // read a single keypress
sys.rawMode(false) // restore normal terminal
let size = sys.termSize()
print(size.rows, size.cols)
FunctionDescription
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).

FunctionDescription
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"