feat: add File and Process effects for real I/O
Adds two essential effects that enable Lux to interact with the system:
File effect:
- read(path) - Read file contents as string
- write(path, content) - Write string to file
- append(path, content) - Append to file
- exists(path) - Check if file/directory exists
- delete(path) - Delete a file
- readDir(path) - List directory contents
- isDir(path) - Check if path is directory
- mkdir(path) - Create directory (including parents)
Process effect:
- exec(cmd) - Run shell command, return stdout
- execStatus(cmd) - Run command, return exit code
- env(name) - Get environment variable (returns Option)
- args() - Get command line arguments
- exit(code) - Exit program with code
- cwd() - Get current working directory
- setCwd(path) - Change working directory
Also fixes formatter bug with empty handler blocks in `run ... with {}`.
These effects make Lux capable of writing real CLI tools and scripts.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
50
examples/file_io.lux
Normal file
50
examples/file_io.lux
Normal file
@@ -0,0 +1,50 @@
|
||||
// File I/O example - demonstrates the File effect
|
||||
//
|
||||
// This script reads a file, counts lines/words, and writes a report
|
||||
|
||||
fn countLines(content: String): Int = {
|
||||
let lines = String.split(content, "\n")
|
||||
List.length(lines)
|
||||
}
|
||||
|
||||
fn countWords(content: String): Int = {
|
||||
let words = String.split(content, " ")
|
||||
List.length(List.filter(words, fn(w: String): Bool => String.length(w) > 0))
|
||||
}
|
||||
|
||||
fn analyzeFile(path: String): Unit with {File, Console} = {
|
||||
Console.print("Analyzing file: " + path)
|
||||
|
||||
if File.exists(path) then {
|
||||
let content = File.read(path)
|
||||
let lines = countLines(content)
|
||||
let words = countWords(content)
|
||||
let chars = String.length(content)
|
||||
|
||||
Console.print(" Lines: " + toString(lines))
|
||||
Console.print(" Words: " + toString(words))
|
||||
Console.print(" Chars: " + toString(chars))
|
||||
} else {
|
||||
Console.print(" Error: File not found!")
|
||||
}
|
||||
}
|
||||
|
||||
fn main(): Unit with {File, Console} = {
|
||||
Console.print("=== Lux File Analyzer ===")
|
||||
Console.print("")
|
||||
|
||||
// Analyze this file itself
|
||||
analyzeFile("examples/file_io.lux")
|
||||
Console.print("")
|
||||
|
||||
// Analyze hello.lux
|
||||
analyzeFile("examples/hello.lux")
|
||||
Console.print("")
|
||||
|
||||
// Write a report
|
||||
let report = "File analysis complete.\nAnalyzed 2 files."
|
||||
File.write("/tmp/lux_report.txt", report)
|
||||
Console.print("Report written to /tmp/lux_report.txt")
|
||||
}
|
||||
|
||||
let result = run main() with {}
|
||||
58
examples/shell.lux
Normal file
58
examples/shell.lux
Normal file
@@ -0,0 +1,58 @@
|
||||
// Shell/Process example - demonstrates the Process effect
|
||||
//
|
||||
// This script runs shell commands and uses environment variables
|
||||
|
||||
fn main(): Unit with {Process, Console} = {
|
||||
Console.print("=== Lux Shell Example ===")
|
||||
Console.print("")
|
||||
|
||||
// Get current working directory
|
||||
let cwd = Process.cwd()
|
||||
Console.print("Current directory: " + cwd)
|
||||
Console.print("")
|
||||
|
||||
// Get environment variables
|
||||
Console.print("Environment variables:")
|
||||
match Process.env("USER") {
|
||||
Some(user) => Console.print(" USER: " + user),
|
||||
None => Console.print(" USER: (not set)")
|
||||
}
|
||||
match Process.env("HOME") {
|
||||
Some(home) => Console.print(" HOME: " + home),
|
||||
None => Console.print(" HOME: (not set)")
|
||||
}
|
||||
match Process.env("SHELL") {
|
||||
Some(shell) => Console.print(" SHELL: " + shell),
|
||||
None => Console.print(" SHELL: (not set)")
|
||||
}
|
||||
Console.print("")
|
||||
|
||||
// Run shell commands
|
||||
Console.print("Running shell commands:")
|
||||
|
||||
let date = Process.exec("date")
|
||||
Console.print(" date: " + String.trim(date))
|
||||
|
||||
let kernel = Process.exec("uname -r")
|
||||
Console.print(" kernel: " + String.trim(kernel))
|
||||
|
||||
let files = Process.exec("ls examples/*.lux | wc -l")
|
||||
Console.print(" .lux files in examples/: " + String.trim(files))
|
||||
Console.print("")
|
||||
|
||||
// Command line arguments
|
||||
Console.print("Command line arguments:")
|
||||
let args = Process.args()
|
||||
let argCount = List.length(args)
|
||||
if argCount == 0 then {
|
||||
Console.print(" (no arguments)")
|
||||
} else {
|
||||
Console.print(" Count: " + toString(argCount))
|
||||
match List.head(args) {
|
||||
Some(first) => Console.print(" First: " + first),
|
||||
None => Console.print(" First: (empty)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let result = run main() with {}
|
||||
Reference in New Issue
Block a user