feat: add example scripts for argparse, bytes, dataset, html, markdown, uuid, wdantic, and web chat modules

Add comprehensive demo scripts showcasing the usage of multiple Wren modules including argument parsing, byte manipulation, in-memory dataset operations, HTML encoding/slugification, markdown-to-HTML conversion, UUID generation/validation, schema validation with wdantic, and a full web chat application with REST endpoints.
This commit is contained in:
2026-01-24 22:40:22 +00:00
parent 0a65272f80
commit 5a4054ec66
105 changed files with 23275 additions and 94 deletions
+421
View File
@@ -0,0 +1,421 @@
<!DOCTYPE html>
<!-- retoor <retoor@molodetz.nl> -->
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Async Programming - Wren-CLI Manual</title>
<link rel="stylesheet" href="../css/style.css">
</head>
<body>
<button class="mobile-menu-toggle">Menu</button>
<div class="container">
<aside class="sidebar">
<div class="sidebar-header">
<h1><a href="../index.html">Wren-CLI</a></h1>
<div class="version">v0.4.0</div>
</div>
<nav class="sidebar-nav">
<div class="section">
<span class="section-title">Getting Started</span>
<ul>
<li><a href="../getting-started/index.html">Overview</a></li>
<li><a href="../getting-started/installation.html">Installation</a></li>
<li><a href="../getting-started/first-script.html">First Script</a></li>
<li><a href="../getting-started/repl.html">Using the REPL</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">Language</span>
<ul>
<li><a href="../language/index.html">Syntax Overview</a></li>
<li><a href="../language/classes.html">Classes</a></li>
<li><a href="../language/methods.html">Methods</a></li>
<li><a href="../language/control-flow.html">Control Flow</a></li>
<li><a href="../language/fibers.html">Fibers</a></li>
<li><a href="../language/modules.html">Modules</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">API Reference</span>
<ul>
<li><a href="../api/index.html">Overview</a></li>
<li><a href="../api/http.html">http</a></li>
<li><a href="../api/websocket.html">websocket</a></li>
<li><a href="../api/tls.html">tls</a></li>
<li><a href="../api/net.html">net</a></li>
<li><a href="../api/dns.html">dns</a></li>
<li><a href="../api/json.html">json</a></li>
<li><a href="../api/base64.html">base64</a></li>
<li><a href="../api/regex.html">regex</a></li>
<li><a href="../api/jinja.html">jinja</a></li>
<li><a href="../api/crypto.html">crypto</a></li>
<li><a href="../api/os.html">os</a></li>
<li><a href="../api/env.html">env</a></li>
<li><a href="../api/signal.html">signal</a></li>
<li><a href="../api/subprocess.html">subprocess</a></li>
<li><a href="../api/sqlite.html">sqlite</a></li>
<li><a href="../api/datetime.html">datetime</a></li>
<li><a href="../api/timer.html">timer</a></li>
<li><a href="../api/io.html">io</a></li>
<li><a href="../api/scheduler.html">scheduler</a></li>
<li><a href="../api/math.html">math</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">Tutorials</span>
<ul>
<li><a href="../tutorials/index.html">Tutorial List</a></li>
<li><a href="../tutorials/http-client.html">HTTP Client</a></li>
<li><a href="../tutorials/websocket-chat.html">WebSocket Chat</a></li>
<li><a href="../tutorials/database-app.html">Database App</a></li>
<li><a href="../tutorials/template-rendering.html">Template Rendering</a></li>
<li><a href="../tutorials/cli-tool.html">CLI Tool</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">How-To Guides</span>
<ul>
<li><a href="index.html">How-To List</a></li>
<li><a href="http-requests.html">HTTP Requests</a></li>
<li><a href="json-parsing.html">JSON Parsing</a></li>
<li><a href="regex-patterns.html">Regex Patterns</a></li>
<li><a href="file-operations.html">File Operations</a></li>
<li><a href="async-operations.html" class="active">Async Operations</a></li>
<li><a href="error-handling.html">Error Handling</a></li>
</ul>
</div>
</nav>
</aside>
<main class="content">
<nav class="breadcrumb">
<a href="../index.html">Home</a>
<span class="separator">/</span>
<a href="index.html">How-To Guides</a>
<span class="separator">/</span>
<span>Async Operations</span>
</nav>
<article>
<h1>Async Programming</h1>
<p>Wren-CLI uses fibers for concurrent operations. Understanding fibers is key to writing efficient async code.</p>
<h2>Create a Fiber</h2>
<pre><code>var fiber = Fiber.new {
System.print("Hello from fiber!")
}
fiber.call()</code></pre>
<h2>Fibers with Return Values</h2>
<pre><code>var fiber = Fiber.new {
return 42
}
var result = fiber.call()
System.print("Result: %(result)") // 42</code></pre>
<h2>Sleep/Delay</h2>
<pre><code>import "timer" for Timer
System.print("Starting...")
Timer.sleep(1000) // Wait 1 second
System.print("Done!")</code></pre>
<h2>Sequential HTTP Requests</h2>
<pre><code>import "http" for Http
var r1 = Http.get("https://api.example.com/1")
var r2 = Http.get("https://api.example.com/2")
var r3 = Http.get("https://api.example.com/3")
System.print(r1.json)
System.print(r2.json)
System.print(r3.json)</code></pre>
<h2>Parallel HTTP Requests</h2>
<pre><code>import "http" for Http
var urls = [
"https://api.example.com/1",
"https://api.example.com/2",
"https://api.example.com/3"
]
var fibers = []
for (url in urls) {
fibers.add(Fiber.new { Http.get(url) })
}
for (fiber in fibers) {
fiber.call()
}
for (fiber in fibers) {
System.print(fiber.value)
}</code></pre>
<h2>Run Task in Background</h2>
<pre><code>import "timer" for Timer
var backgroundTask = Fiber.new {
for (i in 1..5) {
System.print("Background: %(i)")
Timer.sleep(500)
}
}
backgroundTask.call()
System.print("Main thread continues...")
Timer.sleep(3000)</code></pre>
<h2>Wait for Multiple Operations</h2>
<pre><code>import "http" for Http
var fetchAll = Fn.new { |urls|
var results = []
var fibers = []
for (url in urls) {
fibers.add(Fiber.new { Http.get(url) })
}
for (fiber in fibers) {
fiber.call()
}
for (fiber in fibers) {
results.add(fiber.value)
}
return results
}
var responses = fetchAll.call([
"https://api.example.com/a",
"https://api.example.com/b"
])
for (r in responses) {
System.print(r.statusCode)
}</code></pre>
<h2>Timeout Pattern</h2>
<pre><code>import "timer" for Timer
import "datetime" for DateTime
var withTimeout = Fn.new { |operation, timeoutMs|
var start = DateTime.now()
var result = null
var done = false
var workFiber = Fiber.new {
result = operation.call()
done = true
}
workFiber.call()
while (!done) {
var elapsed = (DateTime.now() - start).milliseconds
if (elapsed >= timeoutMs) {
Fiber.abort("Operation timed out")
}
Timer.sleep(10)
}
return result
}
var result = withTimeout.call(Fn.new {
Timer.sleep(500)
return "completed"
}, 1000)
System.print(result)</code></pre>
<h2>Polling Loop</h2>
<pre><code>import "timer" for Timer
import "http" for Http
var pollUntilReady = Fn.new { |url, maxAttempts|
var attempts = 0
while (attempts < maxAttempts) {
attempts = attempts + 1
System.print("Attempt %(attempts)...")
var response = Http.get(url)
if (response.json["ready"]) {
return response.json
}
Timer.sleep(2000)
}
return null
}
var result = pollUntilReady.call("https://api.example.com/status", 10)
if (result) {
System.print("Ready: %(result)")
} else {
System.print("Timed out waiting for ready state")
}</code></pre>
<h2>Rate Limiting</h2>
<pre><code>import "timer" for Timer
import "http" for Http
var rateLimitedFetch = Fn.new { |urls, delayMs|
var results = []
for (url in urls) {
var response = Http.get(url)
results.add(response)
Timer.sleep(delayMs)
}
return results
}
var responses = rateLimitedFetch.call([
"https://api.example.com/1",
"https://api.example.com/2",
"https://api.example.com/3"
], 1000)
for (r in responses) {
System.print(r.statusCode)
}</code></pre>
<h2>Producer/Consumer Pattern</h2>
<pre><code>import "timer" for Timer
var queue = []
var running = true
var producer = Fiber.new {
for (i in 1..10) {
queue.add(i)
System.print("Produced: %(i)")
Timer.sleep(200)
}
running = false
}
var consumer = Fiber.new {
while (running || queue.count > 0) {
if (queue.count > 0) {
var item = queue.removeAt(0)
System.print("Consumed: %(item)")
}
Timer.sleep(100)
}
}
producer.call()
consumer.call()
System.print("Done!")</code></pre>
<h2>Retry with Exponential Backoff</h2>
<pre><code>import "timer" for Timer
import "http" for Http
var retryWithBackoff = Fn.new { |operation, maxRetries|
var attempt = 0
var delay = 1000
while (attempt < maxRetries) {
var fiber = Fiber.new { operation.call() }
var result = fiber.try()
if (!fiber.error) {
return result
}
attempt = attempt + 1
System.print("Attempt %(attempt) failed, retrying in %(delay)ms...")
Timer.sleep(delay)
delay = delay * 2
}
Fiber.abort("All %(maxRetries) attempts failed")
}
var response = retryWithBackoff.call(Fn.new {
return Http.get("https://api.example.com/data")
}, 3)
System.print(response.json)</code></pre>
<h2>Concurrent WebSocket Handling</h2>
<pre><code>import "websocket" for WebSocket, WebSocketMessage
import "timer" for Timer
var ws = WebSocket.connect("ws://localhost:8080")
var receiver = Fiber.new {
while (true) {
var message = ws.receive()
if (message == null) break
if (message.opcode == WebSocketMessage.TEXT) {
System.print("Received: %(message.payload)")
}
}
}
var sender = Fiber.new {
for (i in 1..5) {
ws.send("Message %(i)")
Timer.sleep(1000)
}
ws.close()
}
receiver.call()
sender.call()</code></pre>
<h2>Graceful Shutdown</h2>
<pre><code>import "signal" for Signal
import "timer" for Timer
var running = true
Signal.handle("SIGINT", Fn.new {
System.print("\nShutting down gracefully...")
running = false
})
System.print("Press Ctrl+C to stop")
while (running) {
System.print("Working...")
Timer.sleep(1000)
}
System.print("Cleanup complete, exiting.")</code></pre>
<div class="admonition note">
<div class="admonition-title">Note</div>
<p>Wren fibers are cooperative, not preemptive. A fiber runs until it explicitly yields, calls an async operation, or completes. Long-running computations should periodically yield to allow other fibers to run.</p>
</div>
<div class="admonition tip">
<div class="admonition-title">See Also</div>
<p>For more on fibers, see the <a href="../language/fibers.html">Fibers language guide</a> and the <a href="../api/scheduler.html">Scheduler module reference</a>.</p>
</div>
</article>
<footer class="page-footer">
<a href="file-operations.html" class="prev">File Operations</a>
<a href="error-handling.html" class="next">Error Handling</a>
</footer>
</main>
</div>
<script src="../js/main.js"></script>
</body>
</html>
+478
View File
@@ -0,0 +1,478 @@
<!DOCTYPE html>
<!-- retoor <retoor@molodetz.nl> -->
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Error Handling - Wren-CLI Manual</title>
<link rel="stylesheet" href="../css/style.css">
</head>
<body>
<button class="mobile-menu-toggle">Menu</button>
<div class="container">
<aside class="sidebar">
<div class="sidebar-header">
<h1><a href="../index.html">Wren-CLI</a></h1>
<div class="version">v0.4.0</div>
</div>
<nav class="sidebar-nav">
<div class="section">
<span class="section-title">Getting Started</span>
<ul>
<li><a href="../getting-started/index.html">Overview</a></li>
<li><a href="../getting-started/installation.html">Installation</a></li>
<li><a href="../getting-started/first-script.html">First Script</a></li>
<li><a href="../getting-started/repl.html">Using the REPL</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">Language</span>
<ul>
<li><a href="../language/index.html">Syntax Overview</a></li>
<li><a href="../language/classes.html">Classes</a></li>
<li><a href="../language/methods.html">Methods</a></li>
<li><a href="../language/control-flow.html">Control Flow</a></li>
<li><a href="../language/fibers.html">Fibers</a></li>
<li><a href="../language/modules.html">Modules</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">API Reference</span>
<ul>
<li><a href="../api/index.html">Overview</a></li>
<li><a href="../api/http.html">http</a></li>
<li><a href="../api/websocket.html">websocket</a></li>
<li><a href="../api/tls.html">tls</a></li>
<li><a href="../api/net.html">net</a></li>
<li><a href="../api/dns.html">dns</a></li>
<li><a href="../api/json.html">json</a></li>
<li><a href="../api/base64.html">base64</a></li>
<li><a href="../api/regex.html">regex</a></li>
<li><a href="../api/jinja.html">jinja</a></li>
<li><a href="../api/crypto.html">crypto</a></li>
<li><a href="../api/os.html">os</a></li>
<li><a href="../api/env.html">env</a></li>
<li><a href="../api/signal.html">signal</a></li>
<li><a href="../api/subprocess.html">subprocess</a></li>
<li><a href="../api/sqlite.html">sqlite</a></li>
<li><a href="../api/datetime.html">datetime</a></li>
<li><a href="../api/timer.html">timer</a></li>
<li><a href="../api/io.html">io</a></li>
<li><a href="../api/scheduler.html">scheduler</a></li>
<li><a href="../api/math.html">math</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">Tutorials</span>
<ul>
<li><a href="../tutorials/index.html">Tutorial List</a></li>
<li><a href="../tutorials/http-client.html">HTTP Client</a></li>
<li><a href="../tutorials/websocket-chat.html">WebSocket Chat</a></li>
<li><a href="../tutorials/database-app.html">Database App</a></li>
<li><a href="../tutorials/template-rendering.html">Template Rendering</a></li>
<li><a href="../tutorials/cli-tool.html">CLI Tool</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">How-To Guides</span>
<ul>
<li><a href="index.html">How-To List</a></li>
<li><a href="http-requests.html">HTTP Requests</a></li>
<li><a href="json-parsing.html">JSON Parsing</a></li>
<li><a href="regex-patterns.html">Regex Patterns</a></li>
<li><a href="file-operations.html">File Operations</a></li>
<li><a href="async-operations.html">Async Operations</a></li>
<li><a href="error-handling.html" class="active">Error Handling</a></li>
</ul>
</div>
</nav>
</aside>
<main class="content">
<nav class="breadcrumb">
<a href="../index.html">Home</a>
<span class="separator">/</span>
<a href="index.html">How-To Guides</a>
<span class="separator">/</span>
<span>Error Handling</span>
</nav>
<article>
<h1>Error Handling</h1>
<p>Wren uses fibers for error handling. The <code>fiber.try()</code> method catches errors without crashing your program.</p>
<h2>Basic Try/Catch Pattern</h2>
<pre><code>var fiber = Fiber.new {
Fiber.abort("Something went wrong!")
}
var result = fiber.try()
if (fiber.error) {
System.print("Error: %(fiber.error)")
} else {
System.print("Result: %(result)")
}</code></pre>
<h2>Throw an Error</h2>
<pre><code>Fiber.abort("This is an error message")</code></pre>
<h2>Catch Specific Error Types</h2>
<pre><code>var fiber = Fiber.new {
var x = null
return x.count // Error: null has no method 'count'
}
var result = fiber.try()
if (fiber.error) {
if (fiber.error.contains("null")) {
System.print("Null reference error")
} else {
System.print("Other error: %(fiber.error)")
}
}</code></pre>
<h2>Safe File Read</h2>
<pre><code>import "io" for File
var safeRead = Fn.new { |path|
var fiber = Fiber.new { File.read(path) }
var content = fiber.try()
if (fiber.error) {
return null
}
return content
}
var content = safeRead.call("config.txt")
if (content) {
System.print(content)
} else {
System.print("Could not read file")
}</code></pre>
<h2>Safe JSON Parse</h2>
<pre><code>import "json" for Json
var safeParse = Fn.new { |jsonStr|
var fiber = Fiber.new { Json.parse(jsonStr) }
var data = fiber.try()
if (fiber.error) {
System.print("Invalid JSON: %(fiber.error)")
return null
}
return data
}
var data = safeParse.call('{"valid": true}') // Works
var bad = safeParse.call('not json') // Returns null</code></pre>
<h2>Safe HTTP Request</h2>
<pre><code>import "http" for Http
var safeFetch = Fn.new { |url|
var fiber = Fiber.new { Http.get(url) }
var response = fiber.try()
if (fiber.error) {
return {"error": fiber.error, "ok": false}
}
if (response.statusCode >= 400) {
return {"error": "HTTP %(response.statusCode)", "ok": false}
}
return {"data": response.json, "ok": true}
}
var result = safeFetch.call("https://api.example.com/data")
if (result["ok"]) {
System.print(result["data"])
} else {
System.print("Error: %(result["error"])")
}</code></pre>
<h2>Input Validation</h2>
<pre><code>var validateEmail = Fn.new { |email|
if (email == null) {
Fiber.abort("Email is required")
}
if (!email.contains("@")) {
Fiber.abort("Invalid email format")
}
return true
}
var validate = Fn.new { |email|
var fiber = Fiber.new { validateEmail.call(email) }
fiber.try()
return fiber.error
}
System.print(validate.call(null)) // Email is required
System.print(validate.call("invalid")) // Invalid email format
System.print(validate.call("a@b.com")) // null (no error)</code></pre>
<h2>Result Type Pattern</h2>
<pre><code>class Result {
construct ok(value) {
_value = value
_error = null
}
construct error(message) {
_value = null
_error = message
}
isOk { _error == null }
isError { _error != null }
value { _value }
error { _error }
unwrap {
if (isError) Fiber.abort(_error)
return _value
}
unwrapOr(default) { isOk ? _value : default }
}
var divide = Fn.new { |a, b|
if (b == 0) {
return Result.error("Division by zero")
}
return Result.ok(a / b)
}
var result = divide.call(10, 2)
if (result.isOk) {
System.print("Result: %(result.value)")
}
var bad = divide.call(10, 0)
if (bad.isError) {
System.print("Error: %(bad.error)")
}
System.print(divide.call(10, 5).unwrapOr(0)) // 2
System.print(divide.call(10, 0).unwrapOr(0)) // 0</code></pre>
<h2>Assert Function</h2>
<pre><code>var assert = Fn.new { |condition, message|
if (!condition) {
Fiber.abort("Assertion failed: %(message)")
}
}
var processUser = Fn.new { |user|
assert.call(user != null, "User is required")
assert.call(user["name"] != null, "User name is required")
assert.call(user["age"] >= 0, "Age must be non-negative")
System.print("Processing %(user["name"])...")
}</code></pre>
<h2>Multiple Error Sources</h2>
<pre><code>import "http" for Http
import "json" for Json
var fetchAndParse = Fn.new { |url|
var httpFiber = Fiber.new { Http.get(url) }
var response = httpFiber.try()
if (httpFiber.error) {
return {"error": "Network error: %(httpFiber.error)"}
}
if (response.statusCode != 200) {
return {"error": "HTTP error: %(response.statusCode)"}
}
var jsonFiber = Fiber.new { Json.parse(response.body) }
var data = jsonFiber.try()
if (jsonFiber.error) {
return {"error": "Parse error: %(jsonFiber.error)"}
}
return {"data": data}
}
var result = fetchAndParse.call("https://api.example.com/data")
if (result.containsKey("error")) {
System.print(result["error"])
} else {
System.print(result["data"])
}</code></pre>
<h2>Error Logging</h2>
<pre><code>import "datetime" for DateTime
import "io" for File
class Logger {
construct new(logFile) {
_logFile = logFile
}
log(level, message) {
var timestamp = DateTime.now().toString
var entry = "[%(timestamp)] [%(level)] %(message)\n"
var existing = ""
var fiber = Fiber.new { File.read(_logFile) }
existing = fiber.try() || ""
File.write(_logFile, existing + entry)
if (level == "ERROR") {
System.print("ERROR: %(message)")
}
}
error(message) { log("ERROR", message) }
warn(message) { log("WARN", message) }
info(message) { log("INFO", message) }
}
var logger = Logger.new("app.log")
var safeDivide = Fn.new { |a, b|
if (b == 0) {
logger.error("Division by zero: %(a) / %(b)")
return null
}
return a / b
}
var result = safeDivide.call(10, 0)</code></pre>
<h2>Cleanup with Finally Pattern</h2>
<pre><code>import "sqlite" for Sqlite
var withDatabase = Fn.new { |dbPath, operation|
var db = Sqlite.open(dbPath)
var result = null
var error = null
var fiber = Fiber.new { operation.call(db) }
result = fiber.try()
error = fiber.error
db.close()
if (error) {
Fiber.abort(error)
}
return result
}
var users = withDatabase.call("app.db", Fn.new { |db|
return db.execute("SELECT * FROM users")
})
System.print(users)</code></pre>
<h2>Custom Error Class</h2>
<pre><code>class AppError {
construct new(code, message) {
_code = code
_message = message
}
code { _code }
message { _message }
toString { "[%(code)] %(message)" }
static notFound(resource) {
return AppError.new("NOT_FOUND", "%(resource) not found")
}
static validation(field, reason) {
return AppError.new("VALIDATION", "%(field): %(reason)")
}
static unauthorized() {
return AppError.new("UNAUTHORIZED", "Authentication required")
}
}
var findUser = Fn.new { |id|
if (id == null) {
Fiber.abort(AppError.validation("id", "is required").toString)
}
var user = null
if (user == null) {
Fiber.abort(AppError.notFound("User %(id)").toString)
}
return user
}
var fiber = Fiber.new { findUser.call(null) }
fiber.try()
System.print(fiber.error) // [VALIDATION] id: is required</code></pre>
<h2>Retry on Error</h2>
<pre><code>import "timer" for Timer
var retry = Fn.new { |operation, maxAttempts, delayMs|
var lastError = null
for (i in 1..maxAttempts) {
var fiber = Fiber.new { operation.call() }
var result = fiber.try()
if (!fiber.error) {
return result
}
lastError = fiber.error
System.print("Attempt %(i) failed: %(lastError)")
if (i < maxAttempts) {
Timer.sleep(delayMs)
}
}
Fiber.abort("All %(maxAttempts) attempts failed. Last error: %(lastError)")
}
var result = retry.call(Fn.new {
return "success"
}, 3, 1000)</code></pre>
<div class="admonition tip">
<div class="admonition-title">Best Practices</div>
<ul>
<li>Always wrap external calls (HTTP, file I/O) in fibers</li>
<li>Provide meaningful error messages</li>
<li>Log errors for debugging</li>
<li>Fail fast on programming errors, recover from user errors</li>
<li>Clean up resources (close files, connections) even on error</li>
</ul>
</div>
<div class="admonition note">
<div class="admonition-title">See Also</div>
<p>For more on fibers, see the <a href="../language/fibers.html">Fibers language guide</a>.</p>
</div>
</article>
<footer class="page-footer">
<a href="async-operations.html" class="prev">Async Operations</a>
<a href="../index.html" class="next">Home</a>
</footer>
</main>
</div>
<script src="../js/main.js"></script>
</body>
</html>
+406
View File
@@ -0,0 +1,406 @@
<!DOCTYPE html>
<!-- retoor <retoor@molodetz.nl> -->
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>File Operations - Wren-CLI Manual</title>
<link rel="stylesheet" href="../css/style.css">
</head>
<body>
<button class="mobile-menu-toggle">Menu</button>
<div class="container">
<aside class="sidebar">
<div class="sidebar-header">
<h1><a href="../index.html">Wren-CLI</a></h1>
<div class="version">v0.4.0</div>
</div>
<nav class="sidebar-nav">
<div class="section">
<span class="section-title">Getting Started</span>
<ul>
<li><a href="../getting-started/index.html">Overview</a></li>
<li><a href="../getting-started/installation.html">Installation</a></li>
<li><a href="../getting-started/first-script.html">First Script</a></li>
<li><a href="../getting-started/repl.html">Using the REPL</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">Language</span>
<ul>
<li><a href="../language/index.html">Syntax Overview</a></li>
<li><a href="../language/classes.html">Classes</a></li>
<li><a href="../language/methods.html">Methods</a></li>
<li><a href="../language/control-flow.html">Control Flow</a></li>
<li><a href="../language/fibers.html">Fibers</a></li>
<li><a href="../language/modules.html">Modules</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">API Reference</span>
<ul>
<li><a href="../api/index.html">Overview</a></li>
<li><a href="../api/http.html">http</a></li>
<li><a href="../api/websocket.html">websocket</a></li>
<li><a href="../api/tls.html">tls</a></li>
<li><a href="../api/net.html">net</a></li>
<li><a href="../api/dns.html">dns</a></li>
<li><a href="../api/json.html">json</a></li>
<li><a href="../api/base64.html">base64</a></li>
<li><a href="../api/regex.html">regex</a></li>
<li><a href="../api/jinja.html">jinja</a></li>
<li><a href="../api/crypto.html">crypto</a></li>
<li><a href="../api/os.html">os</a></li>
<li><a href="../api/env.html">env</a></li>
<li><a href="../api/signal.html">signal</a></li>
<li><a href="../api/subprocess.html">subprocess</a></li>
<li><a href="../api/sqlite.html">sqlite</a></li>
<li><a href="../api/datetime.html">datetime</a></li>
<li><a href="../api/timer.html">timer</a></li>
<li><a href="../api/io.html">io</a></li>
<li><a href="../api/scheduler.html">scheduler</a></li>
<li><a href="../api/math.html">math</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">Tutorials</span>
<ul>
<li><a href="../tutorials/index.html">Tutorial List</a></li>
<li><a href="../tutorials/http-client.html">HTTP Client</a></li>
<li><a href="../tutorials/websocket-chat.html">WebSocket Chat</a></li>
<li><a href="../tutorials/database-app.html">Database App</a></li>
<li><a href="../tutorials/template-rendering.html">Template Rendering</a></li>
<li><a href="../tutorials/cli-tool.html">CLI Tool</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">How-To Guides</span>
<ul>
<li><a href="index.html">How-To List</a></li>
<li><a href="http-requests.html">HTTP Requests</a></li>
<li><a href="json-parsing.html">JSON Parsing</a></li>
<li><a href="regex-patterns.html">Regex Patterns</a></li>
<li><a href="file-operations.html" class="active">File Operations</a></li>
<li><a href="async-operations.html">Async Operations</a></li>
<li><a href="error-handling.html">Error Handling</a></li>
</ul>
</div>
</nav>
</aside>
<main class="content">
<nav class="breadcrumb">
<a href="../index.html">Home</a>
<span class="separator">/</span>
<a href="index.html">How-To Guides</a>
<span class="separator">/</span>
<span>File Operations</span>
</nav>
<article>
<h1>File Operations</h1>
<h2>Read Entire File</h2>
<pre><code>import "io" for File
var content = File.read("document.txt")
System.print(content)</code></pre>
<h2>Write to File</h2>
<pre><code>import "io" for File
File.write("output.txt", "Hello, World!")
System.print("File written!")</code></pre>
<h2>Append to File</h2>
<pre><code>import "io" for File
var existing = File.exists("log.txt") ? File.read("log.txt") : ""
File.write("log.txt", existing + "New line\n")</code></pre>
<h2>Check if File Exists</h2>
<pre><code>import "io" for File
if (File.exists("config.txt")) {
System.print("Config found")
var content = File.read("config.txt")
} else {
System.print("Config not found, using defaults")
}</code></pre>
<h2>Get File Size</h2>
<pre><code>import "io" for File
var size = File.size("data.bin")
System.print("File size: %(size) bytes")</code></pre>
<h2>Copy File</h2>
<pre><code>import "io" for File
File.copy("source.txt", "destination.txt")
System.print("File copied!")</code></pre>
<h2>Rename/Move File</h2>
<pre><code>import "io" for File
File.rename("old_name.txt", "new_name.txt")
System.print("File renamed!")
File.rename("file.txt", "subdir/file.txt")
System.print("File moved!")</code></pre>
<h2>Delete File</h2>
<pre><code>import "io" for File
if (File.exists("temp.txt")) {
File.delete("temp.txt")
System.print("File deleted!")
}</code></pre>
<h2>List Directory Contents</h2>
<pre><code>import "io" for Directory
var files = Directory.list(".")
for (file in files) {
System.print(file)
}</code></pre>
<h2>Check if Directory Exists</h2>
<pre><code>import "io" for Directory
if (Directory.exists("data")) {
System.print("Directory found")
} else {
System.print("Directory not found")
}</code></pre>
<h2>Create Directory</h2>
<pre><code>import "io" for Directory
if (!Directory.exists("output")) {
Directory.create("output")
System.print("Directory created!")
}</code></pre>
<h2>Delete Empty Directory</h2>
<pre><code>import "io" for Directory
Directory.delete("empty_folder")
System.print("Directory deleted!")</code></pre>
<h2>Read File Line by Line</h2>
<pre><code>import "io" for File
var content = File.read("data.txt")
var lines = content.split("\n")
for (line in lines) {
if (line.count > 0) {
System.print(line)
}
}</code></pre>
<h2>Process Files in Directory</h2>
<pre><code>import "io" for File, Directory
var files = Directory.list("./data")
for (filename in files) {
if (filename.endsWith(".txt")) {
var path = "./data/%(filename)"
var content = File.read(path)
System.print("%(filename): %(content.count) chars")
}
}</code></pre>
<h2>Recursive Directory Listing</h2>
<pre><code>import "io" for File, Directory
var listRecursive = Fn.new { |path, indent|
var items = Directory.list(path)
for (item in items) {
var fullPath = "%(path)/%(item)"
System.print("%(indent)%(item)")
if (Directory.exists(fullPath)) {
listRecursive.call(fullPath, indent + " ")
}
}
}
listRecursive.call(".", "")</code></pre>
<h2>Find Files by Extension</h2>
<pre><code>import "io" for File, Directory
var findByExtension = Fn.new { |path, ext|
var results = []
var items = Directory.list(path)
for (item in items) {
var fullPath = "%(path)/%(item)"
if (Directory.exists(fullPath)) {
var subResults = findByExtension.call(fullPath, ext)
for (r in subResults) results.add(r)
} else if (item.endsWith(ext)) {
results.add(fullPath)
}
}
return results
}
var wrenFiles = findByExtension.call(".", ".wren")
for (file in wrenFiles) {
System.print(file)
}</code></pre>
<h2>Read JSON Configuration</h2>
<pre><code>import "io" for File
import "json" for Json
var loadConfig = Fn.new { |path, defaults|
if (!File.exists(path)) {
return defaults
}
var content = File.read(path)
var config = Json.parse(content)
for (key in defaults.keys) {
if (!config.containsKey(key)) {
config[key] = defaults[key]
}
}
return config
}
var config = loadConfig.call("config.json", {
"port": 8080,
"debug": false
})
System.print("Port: %(config["port"])")</code></pre>
<h2>Save JSON Configuration</h2>
<pre><code>import "io" for File
import "json" for Json
var config = {
"database": "app.db",
"port": 8080,
"debug": true
}
File.write("config.json", Json.stringify(config, 2))
System.print("Configuration saved!")</code></pre>
<h2>Create Backup Copy</h2>
<pre><code>import "io" for File
import "datetime" for DateTime
var backup = Fn.new { |path|
if (!File.exists(path)) {
System.print("File not found: %(path)")
return null
}
var timestamp = DateTime.now().format("\%Y\%m\%d_\%H\%M\%S")
var backupPath = "%(path).%(timestamp).bak"
File.copy(path, backupPath)
System.print("Backup created: %(backupPath)")
return backupPath
}
backup.call("important.txt")</code></pre>
<h2>Read User Input</h2>
<pre><code>import "io" for Stdin
System.write("Enter your name: ")
var name = Stdin.readLine()
System.print("Hello, %(name)!")</code></pre>
<h2>Interactive Menu</h2>
<pre><code>import "io" for Stdin
System.print("Select an option:")
System.print("1. Option A")
System.print("2. Option B")
System.print("3. Exit")
System.write("Choice: ")
var choice = Stdin.readLine()
if (choice == "1") {
System.print("You selected Option A")
} else if (choice == "2") {
System.print("You selected Option B")
} else if (choice == "3") {
System.print("Goodbye!")
}</code></pre>
<h2>Safe File Operations with Error Handling</h2>
<pre><code>import "io" for File
var safeRead = Fn.new { |path|
var fiber = Fiber.new { File.read(path) }
var result = fiber.try()
if (fiber.error) {
System.print("Error reading %(path): %(fiber.error)")
return null
}
return result
}
var content = safeRead.call("maybe_exists.txt")
if (content) {
System.print("Content: %(content)")
}</code></pre>
<h2>Calculate Directory Size</h2>
<pre><code>import "io" for File, Directory
var dirSize = Fn.new { |path|
var total = 0
var items = Directory.list(path)
for (item in items) {
var fullPath = "%(path)/%(item)"
if (Directory.exists(fullPath)) {
total = total + dirSize.call(fullPath)
} else if (File.exists(fullPath)) {
total = total + File.size(fullPath)
}
}
return total
}
var size = dirSize.call(".")
System.print("Total size: %(size) bytes")</code></pre>
<div class="admonition tip">
<div class="admonition-title">See Also</div>
<p>For full API documentation, see the <a href="../api/io.html">IO module reference</a>.</p>
</div>
</article>
<footer class="page-footer">
<a href="regex-patterns.html" class="prev">Regex Patterns</a>
<a href="async-operations.html" class="next">Async Operations</a>
</footer>
</main>
</div>
<script src="../js/main.js"></script>
</body>
</html>
+334
View File
@@ -0,0 +1,334 @@
<!DOCTYPE html>
<!-- retoor <retoor@molodetz.nl> -->
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Making HTTP Requests - Wren-CLI Manual</title>
<link rel="stylesheet" href="../css/style.css">
</head>
<body>
<button class="mobile-menu-toggle">Menu</button>
<div class="container">
<aside class="sidebar">
<div class="sidebar-header">
<h1><a href="../index.html">Wren-CLI</a></h1>
<div class="version">v0.4.0</div>
</div>
<nav class="sidebar-nav">
<div class="section">
<span class="section-title">Getting Started</span>
<ul>
<li><a href="../getting-started/index.html">Overview</a></li>
<li><a href="../getting-started/installation.html">Installation</a></li>
<li><a href="../getting-started/first-script.html">First Script</a></li>
<li><a href="../getting-started/repl.html">Using the REPL</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">Language</span>
<ul>
<li><a href="../language/index.html">Syntax Overview</a></li>
<li><a href="../language/classes.html">Classes</a></li>
<li><a href="../language/methods.html">Methods</a></li>
<li><a href="../language/control-flow.html">Control Flow</a></li>
<li><a href="../language/fibers.html">Fibers</a></li>
<li><a href="../language/modules.html">Modules</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">API Reference</span>
<ul>
<li><a href="../api/index.html">Overview</a></li>
<li><a href="../api/http.html">http</a></li>
<li><a href="../api/websocket.html">websocket</a></li>
<li><a href="../api/tls.html">tls</a></li>
<li><a href="../api/net.html">net</a></li>
<li><a href="../api/dns.html">dns</a></li>
<li><a href="../api/json.html">json</a></li>
<li><a href="../api/base64.html">base64</a></li>
<li><a href="../api/regex.html">regex</a></li>
<li><a href="../api/jinja.html">jinja</a></li>
<li><a href="../api/crypto.html">crypto</a></li>
<li><a href="../api/os.html">os</a></li>
<li><a href="../api/env.html">env</a></li>
<li><a href="../api/signal.html">signal</a></li>
<li><a href="../api/subprocess.html">subprocess</a></li>
<li><a href="../api/sqlite.html">sqlite</a></li>
<li><a href="../api/datetime.html">datetime</a></li>
<li><a href="../api/timer.html">timer</a></li>
<li><a href="../api/io.html">io</a></li>
<li><a href="../api/scheduler.html">scheduler</a></li>
<li><a href="../api/math.html">math</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">Tutorials</span>
<ul>
<li><a href="../tutorials/index.html">Tutorial List</a></li>
<li><a href="../tutorials/http-client.html">HTTP Client</a></li>
<li><a href="../tutorials/websocket-chat.html">WebSocket Chat</a></li>
<li><a href="../tutorials/database-app.html">Database App</a></li>
<li><a href="../tutorials/template-rendering.html">Template Rendering</a></li>
<li><a href="../tutorials/cli-tool.html">CLI Tool</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">How-To Guides</span>
<ul>
<li><a href="index.html">How-To List</a></li>
<li><a href="http-requests.html" class="active">HTTP Requests</a></li>
<li><a href="json-parsing.html">JSON Parsing</a></li>
<li><a href="regex-patterns.html">Regex Patterns</a></li>
<li><a href="file-operations.html">File Operations</a></li>
<li><a href="async-operations.html">Async Operations</a></li>
<li><a href="error-handling.html">Error Handling</a></li>
</ul>
</div>
</nav>
</aside>
<main class="content">
<nav class="breadcrumb">
<a href="../index.html">Home</a>
<span class="separator">/</span>
<a href="index.html">How-To Guides</a>
<span class="separator">/</span>
<span>HTTP Requests</span>
</nav>
<article>
<h1>Making HTTP Requests</h1>
<h2>Basic GET Request</h2>
<pre><code>import "http" for Http
var response = Http.get("https://api.example.com/data")
System.print(response.body)</code></pre>
<h2>GET Request with JSON Response</h2>
<pre><code>import "http" for Http
var response = Http.get("https://jsonplaceholder.typicode.com/posts/1")
var data = response.json
System.print("Title: %(data["title"])")</code></pre>
<h2>GET Request with Headers</h2>
<pre><code>import "http" for Http
var response = Http.get("https://api.example.com/data", {
"Accept": "application/json",
"User-Agent": "Wren-CLI/1.0"
})
System.print(response.body)</code></pre>
<h2>POST Request with JSON Body</h2>
<pre><code>import "http" for Http
import "json" for Json
var data = {
"name": "John Doe",
"email": "john@example.com"
}
var response = Http.post(
"https://api.example.com/users",
Json.stringify(data),
{"Content-Type": "application/json"}
)
System.print("Status: %(response.statusCode)")
System.print("Created: %(response.json)")</code></pre>
<h2>PUT Request</h2>
<pre><code>import "http" for Http
import "json" for Json
var data = {
"id": 1,
"name": "Jane Doe",
"email": "jane@example.com"
}
var response = Http.put(
"https://api.example.com/users/1",
Json.stringify(data),
{"Content-Type": "application/json"}
)
System.print("Updated: %(response.statusCode == 200)")</code></pre>
<h2>DELETE Request</h2>
<pre><code>import "http" for Http
var response = Http.delete("https://api.example.com/users/1")
System.print("Deleted: %(response.statusCode == 204)")</code></pre>
<h2>PATCH Request</h2>
<pre><code>import "http" for Http
import "json" for Json
var response = Http.patch(
"https://api.example.com/users/1",
Json.stringify({"email": "newemail@example.com"}),
{"Content-Type": "application/json"}
)
System.print("Patched: %(response.statusCode)")</code></pre>
<h2>Bearer Token Authentication</h2>
<pre><code>import "http" for Http
var token = "your-api-token"
var response = Http.get("https://api.example.com/protected", {
"Authorization": "Bearer %(token)"
})
System.print(response.json)</code></pre>
<h2>Basic Authentication</h2>
<pre><code>import "http" for Http
import "base64" for Base64
var username = "user"
var password = "pass"
var credentials = Base64.encode("%(username):%(password)")
var response = Http.get("https://api.example.com/protected", {
"Authorization": "Basic %(credentials)"
})
System.print(response.body)</code></pre>
<h2>API Key Authentication</h2>
<pre><code>import "http" for Http
var response = Http.get("https://api.example.com/data", {
"X-API-Key": "your-api-key"
})
System.print(response.body)</code></pre>
<h2>Check Response Status</h2>
<pre><code>import "http" for Http
var response = Http.get("https://api.example.com/data")
if (response.statusCode == 200) {
System.print("Success: %(response.json)")
} else if (response.statusCode == 404) {
System.print("Not found")
} else if (response.statusCode >= 500) {
System.print("Server error: %(response.statusCode)")
} else {
System.print("Error: %(response.statusCode)")
}</code></pre>
<h2>Access Response Headers</h2>
<pre><code>import "http" for Http
var response = Http.get("https://api.example.com/data")
System.print("Content-Type: %(response.headers["content-type"])")
System.print("All headers: %(response.headers)")</code></pre>
<h2>URL Query Parameters</h2>
<pre><code>import "http" for Http
var response = Http.get("https://api.example.com/search?q=wren&limit=10")
System.print(response.json)</code></pre>
<h2>Form URL Encoded POST</h2>
<pre><code>import "http" for Http
var body = "username=john&password=secret"
var response = Http.post(
"https://api.example.com/login",
body,
{"Content-Type": "application/x-www-form-urlencoded"}
)
System.print(response.json)</code></pre>
<h2>Download File</h2>
<pre><code>import "http" for Http
import "io" for File
var response = Http.get("https://example.com/file.txt")
if (response.statusCode == 200) {
File.write("downloaded.txt", response.body)
System.print("File downloaded!")
}</code></pre>
<h2>HTTPS Request</h2>
<pre><code>import "http" for Http
var response = Http.get("https://secure.example.com/api")
System.print(response.body)</code></pre>
<h2>Error Handling</h2>
<pre><code>import "http" for Http
var fiber = Fiber.new {
return Http.get("https://api.example.com/data")
}
var response = fiber.try()
if (fiber.error) {
System.print("Request failed: %(fiber.error)")
} else if (response.statusCode >= 400) {
System.print("HTTP error: %(response.statusCode)")
} else {
System.print("Success: %(response.json)")
}</code></pre>
<h2>Retry on Failure</h2>
<pre><code>import "http" for Http
import "timer" for Timer
var fetchWithRetry = Fn.new { |url, maxRetries|
var attempt = 0
while (attempt < maxRetries) {
var fiber = Fiber.new { Http.get(url) }
var response = fiber.try()
if (!fiber.error && response.statusCode == 200) {
return response
}
attempt = attempt + 1
if (attempt < maxRetries) {
Timer.sleep(1000 * attempt)
}
}
return null
}
var response = fetchWithRetry.call("https://api.example.com/data", 3)
if (response) {
System.print(response.json)
} else {
System.print("Failed after 3 retries")
}</code></pre>
<div class="admonition tip">
<div class="admonition-title">See Also</div>
<p>For a complete API client example, see the <a href="../tutorials/http-client.html">HTTP Client Tutorial</a>. For full API documentation, see the <a href="../api/http.html">HTTP module reference</a>.</p>
</div>
</article>
<footer class="page-footer">
<a href="index.html" class="prev">How-To List</a>
<a href="json-parsing.html" class="next">JSON Parsing</a>
</footer>
</main>
</div>
<script src="../js/main.js"></script>
</body>
</html>
+208
View File
@@ -0,0 +1,208 @@
<!DOCTYPE html>
<!-- retoor <retoor@molodetz.nl> -->
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>How-To Guides - Wren-CLI Manual</title>
<link rel="stylesheet" href="../css/style.css">
</head>
<body>
<button class="mobile-menu-toggle">Menu</button>
<div class="container">
<aside class="sidebar">
<div class="sidebar-header">
<h1><a href="../index.html">Wren-CLI</a></h1>
<div class="version">v0.4.0</div>
</div>
<nav class="sidebar-nav">
<div class="section">
<span class="section-title">Getting Started</span>
<ul>
<li><a href="../getting-started/index.html">Overview</a></li>
<li><a href="../getting-started/installation.html">Installation</a></li>
<li><a href="../getting-started/first-script.html">First Script</a></li>
<li><a href="../getting-started/repl.html">Using the REPL</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">Language</span>
<ul>
<li><a href="../language/index.html">Syntax Overview</a></li>
<li><a href="../language/classes.html">Classes</a></li>
<li><a href="../language/methods.html">Methods</a></li>
<li><a href="../language/control-flow.html">Control Flow</a></li>
<li><a href="../language/fibers.html">Fibers</a></li>
<li><a href="../language/modules.html">Modules</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">API Reference</span>
<ul>
<li><a href="../api/index.html">Overview</a></li>
<li><a href="../api/http.html">http</a></li>
<li><a href="../api/websocket.html">websocket</a></li>
<li><a href="../api/tls.html">tls</a></li>
<li><a href="../api/net.html">net</a></li>
<li><a href="../api/dns.html">dns</a></li>
<li><a href="../api/json.html">json</a></li>
<li><a href="../api/base64.html">base64</a></li>
<li><a href="../api/regex.html">regex</a></li>
<li><a href="../api/jinja.html">jinja</a></li>
<li><a href="../api/crypto.html">crypto</a></li>
<li><a href="../api/os.html">os</a></li>
<li><a href="../api/env.html">env</a></li>
<li><a href="../api/signal.html">signal</a></li>
<li><a href="../api/subprocess.html">subprocess</a></li>
<li><a href="../api/sqlite.html">sqlite</a></li>
<li><a href="../api/datetime.html">datetime</a></li>
<li><a href="../api/timer.html">timer</a></li>
<li><a href="../api/io.html">io</a></li>
<li><a href="../api/scheduler.html">scheduler</a></li>
<li><a href="../api/math.html">math</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">Tutorials</span>
<ul>
<li><a href="../tutorials/index.html">Tutorial List</a></li>
<li><a href="../tutorials/http-client.html">HTTP Client</a></li>
<li><a href="../tutorials/websocket-chat.html">WebSocket Chat</a></li>
<li><a href="../tutorials/database-app.html">Database App</a></li>
<li><a href="../tutorials/template-rendering.html">Template Rendering</a></li>
<li><a href="../tutorials/cli-tool.html">CLI Tool</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">How-To Guides</span>
<ul>
<li><a href="index.html" class="active">How-To List</a></li>
<li><a href="http-requests.html">HTTP Requests</a></li>
<li><a href="json-parsing.html">JSON Parsing</a></li>
<li><a href="regex-patterns.html">Regex Patterns</a></li>
<li><a href="file-operations.html">File Operations</a></li>
<li><a href="async-operations.html">Async Operations</a></li>
<li><a href="error-handling.html">Error Handling</a></li>
</ul>
</div>
</nav>
</aside>
<main class="content">
<nav class="breadcrumb">
<a href="../index.html">Home</a>
<span class="separator">/</span>
<span>How-To Guides</span>
</nav>
<article>
<h1>How-To Guides</h1>
<p>Quick, focused guides that show you how to accomplish specific tasks. Each guide provides working code examples you can copy and adapt for your projects.</p>
<div class="card-grid">
<div class="card">
<h3><a href="http-requests.html">Making HTTP Requests</a></h3>
<p>GET, POST, PUT, DELETE requests with headers, authentication, and error handling.</p>
<div class="card-meta">
<span class="tag">http</span>
</div>
</div>
<div class="card">
<h3><a href="json-parsing.html">Working with JSON</a></h3>
<p>Parse JSON strings, access nested data, create JSON output, and handle errors.</p>
<div class="card-meta">
<span class="tag">json</span>
</div>
</div>
<div class="card">
<h3><a href="regex-patterns.html">Using Regular Expressions</a></h3>
<p>Match, search, replace, and split text with regex patterns.</p>
<div class="card-meta">
<span class="tag">regex</span>
</div>
</div>
<div class="card">
<h3><a href="file-operations.html">File Operations</a></h3>
<p>Read, write, copy, and delete files. Work with directories and paths.</p>
<div class="card-meta">
<span class="tag">io</span>
</div>
</div>
<div class="card">
<h3><a href="async-operations.html">Async Programming</a></h3>
<p>Use fibers for concurrent operations, parallel requests, and timeouts.</p>
<div class="card-meta">
<span class="tag">fibers</span>
<span class="tag">scheduler</span>
</div>
</div>
<div class="card">
<h3><a href="error-handling.html">Error Handling</a></h3>
<p>Catch errors with fibers, validate input, and handle edge cases gracefully.</p>
<div class="card-meta">
<span class="tag">fibers</span>
</div>
</div>
</div>
<h2>How-To vs Tutorials</h2>
<p><strong>Tutorials</strong> are learning-oriented. They walk you through building complete applications step by step, introducing concepts gradually.</p>
<p><strong>How-To Guides</strong> are goal-oriented. They assume you know the basics and need to accomplish a specific task quickly. Each guide focuses on one topic with copy-paste examples.</p>
<h2>Quick Reference</h2>
<table>
<tr>
<th>Task</th>
<th>Guide</th>
<th>Key Functions</th>
</tr>
<tr>
<td>Fetch data from API</td>
<td><a href="http-requests.html">HTTP Requests</a></td>
<td><code>Http.get()</code>, <code>response.json</code></td>
</tr>
<tr>
<td>Parse JSON string</td>
<td><a href="json-parsing.html">JSON Parsing</a></td>
<td><code>Json.parse()</code></td>
</tr>
<tr>
<td>Validate email format</td>
<td><a href="regex-patterns.html">Regex Patterns</a></td>
<td><code>Regex.new().test()</code></td>
</tr>
<tr>
<td>Read file contents</td>
<td><a href="file-operations.html">File Operations</a></td>
<td><code>File.read()</code></td>
</tr>
<tr>
<td>Run tasks in parallel</td>
<td><a href="async-operations.html">Async Operations</a></td>
<td><code>Fiber.new { }</code></td>
</tr>
<tr>
<td>Handle runtime errors</td>
<td><a href="error-handling.html">Error Handling</a></td>
<td><code>fiber.try()</code></td>
</tr>
</table>
</article>
<footer class="page-footer">
<a href="../tutorials/cli-tool.html" class="prev">CLI Tool</a>
<a href="http-requests.html" class="next">HTTP Requests</a>
</footer>
</main>
</div>
<script src="../js/main.js"></script>
</body>
</html>
+343
View File
@@ -0,0 +1,343 @@
<!DOCTYPE html>
<!-- retoor <retoor@molodetz.nl> -->
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Working with JSON - Wren-CLI Manual</title>
<link rel="stylesheet" href="../css/style.css">
</head>
<body>
<button class="mobile-menu-toggle">Menu</button>
<div class="container">
<aside class="sidebar">
<div class="sidebar-header">
<h1><a href="../index.html">Wren-CLI</a></h1>
<div class="version">v0.4.0</div>
</div>
<nav class="sidebar-nav">
<div class="section">
<span class="section-title">Getting Started</span>
<ul>
<li><a href="../getting-started/index.html">Overview</a></li>
<li><a href="../getting-started/installation.html">Installation</a></li>
<li><a href="../getting-started/first-script.html">First Script</a></li>
<li><a href="../getting-started/repl.html">Using the REPL</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">Language</span>
<ul>
<li><a href="../language/index.html">Syntax Overview</a></li>
<li><a href="../language/classes.html">Classes</a></li>
<li><a href="../language/methods.html">Methods</a></li>
<li><a href="../language/control-flow.html">Control Flow</a></li>
<li><a href="../language/fibers.html">Fibers</a></li>
<li><a href="../language/modules.html">Modules</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">API Reference</span>
<ul>
<li><a href="../api/index.html">Overview</a></li>
<li><a href="../api/http.html">http</a></li>
<li><a href="../api/websocket.html">websocket</a></li>
<li><a href="../api/tls.html">tls</a></li>
<li><a href="../api/net.html">net</a></li>
<li><a href="../api/dns.html">dns</a></li>
<li><a href="../api/json.html">json</a></li>
<li><a href="../api/base64.html">base64</a></li>
<li><a href="../api/regex.html">regex</a></li>
<li><a href="../api/jinja.html">jinja</a></li>
<li><a href="../api/crypto.html">crypto</a></li>
<li><a href="../api/os.html">os</a></li>
<li><a href="../api/env.html">env</a></li>
<li><a href="../api/signal.html">signal</a></li>
<li><a href="../api/subprocess.html">subprocess</a></li>
<li><a href="../api/sqlite.html">sqlite</a></li>
<li><a href="../api/datetime.html">datetime</a></li>
<li><a href="../api/timer.html">timer</a></li>
<li><a href="../api/io.html">io</a></li>
<li><a href="../api/scheduler.html">scheduler</a></li>
<li><a href="../api/math.html">math</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">Tutorials</span>
<ul>
<li><a href="../tutorials/index.html">Tutorial List</a></li>
<li><a href="../tutorials/http-client.html">HTTP Client</a></li>
<li><a href="../tutorials/websocket-chat.html">WebSocket Chat</a></li>
<li><a href="../tutorials/database-app.html">Database App</a></li>
<li><a href="../tutorials/template-rendering.html">Template Rendering</a></li>
<li><a href="../tutorials/cli-tool.html">CLI Tool</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">How-To Guides</span>
<ul>
<li><a href="index.html">How-To List</a></li>
<li><a href="http-requests.html">HTTP Requests</a></li>
<li><a href="json-parsing.html" class="active">JSON Parsing</a></li>
<li><a href="regex-patterns.html">Regex Patterns</a></li>
<li><a href="file-operations.html">File Operations</a></li>
<li><a href="async-operations.html">Async Operations</a></li>
<li><a href="error-handling.html">Error Handling</a></li>
</ul>
</div>
</nav>
</aside>
<main class="content">
<nav class="breadcrumb">
<a href="../index.html">Home</a>
<span class="separator">/</span>
<a href="index.html">How-To Guides</a>
<span class="separator">/</span>
<span>JSON Parsing</span>
</nav>
<article>
<h1>Working with JSON</h1>
<h2>Parse JSON String</h2>
<pre><code>import "json" for Json
var jsonStr = '{"name": "Alice", "age": 30}'
var data = Json.parse(jsonStr)
System.print(data["name"]) // Alice
System.print(data["age"]) // 30</code></pre>
<h2>Parse JSON Array</h2>
<pre><code>import "json" for Json
var jsonStr = '[1, 2, 3, "four", true, null]'
var items = Json.parse(jsonStr)
for (item in items) {
System.print(item)
}</code></pre>
<h2>Access Nested Objects</h2>
<pre><code>import "json" for Json
var jsonStr = '{"user": {"name": "Bob", "address": {"city": "NYC"}}}'
var data = Json.parse(jsonStr)
System.print(data["user"]["name"]) // Bob
System.print(data["user"]["address"]["city"]) // NYC</code></pre>
<h2>Convert Wren Object to JSON</h2>
<pre><code>import "json" for Json
var data = {
"name": "Charlie",
"age": 25,
"active": true
}
var jsonStr = Json.stringify(data)
System.print(jsonStr) // {"name":"Charlie","age":25,"active":true}</code></pre>
<h2>Pretty Print JSON</h2>
<pre><code>import "json" for Json
var data = {
"users": [
{"name": "Alice", "age": 30},
{"name": "Bob", "age": 25}
]
}
var pretty = Json.stringify(data, 2)
System.print(pretty)</code></pre>
<p>Output:</p>
<pre><code>{
"users": [
{
"name": "Alice",
"age": 30
},
{
"name": "Bob",
"age": 25
}
]
}</code></pre>
<h2>Check if Key Exists</h2>
<pre><code>import "json" for Json
var data = Json.parse('{"name": "Alice"}')
if (data.containsKey("name")) {
System.print("Name: %(data["name"])")
}
if (!data.containsKey("age")) {
System.print("Age not specified")
}</code></pre>
<h2>Provide Default Values</h2>
<pre><code>import "json" for Json
var data = Json.parse('{"name": "Alice"}')
var name = data["name"]
var age = data.containsKey("age") ? data["age"] : 0
var city = data.containsKey("city") ? data["city"] : "Unknown"
System.print("%(name), %(age), %(city)")</code></pre>
<h2>Iterate Over Object Keys</h2>
<pre><code>import "json" for Json
var data = Json.parse('{"a": 1, "b": 2, "c": 3}')
for (key in data.keys) {
System.print("%(key): %(data[key])")
}</code></pre>
<h2>Iterate Over Array</h2>
<pre><code>import "json" for Json
var users = Json.parse('[{"name": "Alice"}, {"name": "Bob"}]')
for (i in 0...users.count) {
System.print("%(i + 1). %(users[i]["name"])")
}</code></pre>
<h2>Modify JSON Data</h2>
<pre><code>import "json" for Json
var data = Json.parse('{"name": "Alice", "age": 30}')
data["age"] = 31
data["email"] = "alice@example.com"
data.remove("name")
System.print(Json.stringify(data))</code></pre>
<h2>Parse JSON from File</h2>
<pre><code>import "json" for Json
import "io" for File
var content = File.read("config.json")
var config = Json.parse(content)
System.print(config["setting"])</code></pre>
<h2>Write JSON to File</h2>
<pre><code>import "json" for Json
import "io" for File
var data = {
"database": "myapp.db",
"port": 8080,
"debug": true
}
File.write("config.json", Json.stringify(data, 2))</code></pre>
<h2>Handle Parse Errors</h2>
<pre><code>import "json" for Json
var jsonStr = "invalid json {"
var fiber = Fiber.new { Json.parse(jsonStr) }
var result = fiber.try()
if (fiber.error) {
System.print("Parse error: %(fiber.error)")
} else {
System.print(result)
}</code></pre>
<h2>Work with Null Values</h2>
<pre><code>import "json" for Json
var data = Json.parse('{"name": "Alice", "address": null}')
if (data["address"] == null) {
System.print("No address provided")
}
var output = {"value": null}
System.print(Json.stringify(output)) // {"value":null}</code></pre>
<h2>Build JSON Array Dynamically</h2>
<pre><code>import "json" for Json
var users = []
users.add({"name": "Alice", "role": "admin"})
users.add({"name": "Bob", "role": "user"})
users.add({"name": "Charlie", "role": "user"})
System.print(Json.stringify(users, 2))</code></pre>
<h2>Filter JSON Array</h2>
<pre><code>import "json" for Json
var users = Json.parse('[
{"name": "Alice", "age": 30},
{"name": "Bob", "age": 17},
{"name": "Charlie", "age": 25}
]')
var adults = []
for (user in users) {
if (user["age"] >= 18) {
adults.add(user)
}
}
System.print("Adults: %(Json.stringify(adults))")</code></pre>
<h2>Transform JSON Data</h2>
<pre><code>import "json" for Json
var users = Json.parse('[
{"firstName": "Alice", "lastName": "Smith"},
{"firstName": "Bob", "lastName": "Jones"}
]')
var names = []
for (user in users) {
names.add("%(user["firstName"]) %(user["lastName"])")
}
System.print(names.join(", "))</code></pre>
<h2>Merge JSON Objects</h2>
<pre><code>import "json" for Json
var defaults = {"theme": "light", "language": "en", "timeout": 30}
var userPrefs = {"theme": "dark"}
var config = {}
for (key in defaults.keys) {
config[key] = defaults[key]
}
for (key in userPrefs.keys) {
config[key] = userPrefs[key]
}
System.print(Json.stringify(config, 2))</code></pre>
<div class="admonition tip">
<div class="admonition-title">See Also</div>
<p>For full API documentation, see the <a href="../api/json.html">JSON module reference</a>.</p>
</div>
</article>
<footer class="page-footer">
<a href="http-requests.html" class="prev">HTTP Requests</a>
<a href="regex-patterns.html" class="next">Regex Patterns</a>
</footer>
</main>
</div>
<script src="../js/main.js"></script>
</body>
</html>
+337
View File
@@ -0,0 +1,337 @@
<!DOCTYPE html>
<!-- retoor <retoor@molodetz.nl> -->
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Using Regular Expressions - Wren-CLI Manual</title>
<link rel="stylesheet" href="../css/style.css">
</head>
<body>
<button class="mobile-menu-toggle">Menu</button>
<div class="container">
<aside class="sidebar">
<div class="sidebar-header">
<h1><a href="../index.html">Wren-CLI</a></h1>
<div class="version">v0.4.0</div>
</div>
<nav class="sidebar-nav">
<div class="section">
<span class="section-title">Getting Started</span>
<ul>
<li><a href="../getting-started/index.html">Overview</a></li>
<li><a href="../getting-started/installation.html">Installation</a></li>
<li><a href="../getting-started/first-script.html">First Script</a></li>
<li><a href="../getting-started/repl.html">Using the REPL</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">Language</span>
<ul>
<li><a href="../language/index.html">Syntax Overview</a></li>
<li><a href="../language/classes.html">Classes</a></li>
<li><a href="../language/methods.html">Methods</a></li>
<li><a href="../language/control-flow.html">Control Flow</a></li>
<li><a href="../language/fibers.html">Fibers</a></li>
<li><a href="../language/modules.html">Modules</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">API Reference</span>
<ul>
<li><a href="../api/index.html">Overview</a></li>
<li><a href="../api/http.html">http</a></li>
<li><a href="../api/websocket.html">websocket</a></li>
<li><a href="../api/tls.html">tls</a></li>
<li><a href="../api/net.html">net</a></li>
<li><a href="../api/dns.html">dns</a></li>
<li><a href="../api/json.html">json</a></li>
<li><a href="../api/base64.html">base64</a></li>
<li><a href="../api/regex.html">regex</a></li>
<li><a href="../api/jinja.html">jinja</a></li>
<li><a href="../api/crypto.html">crypto</a></li>
<li><a href="../api/os.html">os</a></li>
<li><a href="../api/env.html">env</a></li>
<li><a href="../api/signal.html">signal</a></li>
<li><a href="../api/subprocess.html">subprocess</a></li>
<li><a href="../api/sqlite.html">sqlite</a></li>
<li><a href="../api/datetime.html">datetime</a></li>
<li><a href="../api/timer.html">timer</a></li>
<li><a href="../api/io.html">io</a></li>
<li><a href="../api/scheduler.html">scheduler</a></li>
<li><a href="../api/math.html">math</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">Tutorials</span>
<ul>
<li><a href="../tutorials/index.html">Tutorial List</a></li>
<li><a href="../tutorials/http-client.html">HTTP Client</a></li>
<li><a href="../tutorials/websocket-chat.html">WebSocket Chat</a></li>
<li><a href="../tutorials/database-app.html">Database App</a></li>
<li><a href="../tutorials/template-rendering.html">Template Rendering</a></li>
<li><a href="../tutorials/cli-tool.html">CLI Tool</a></li>
</ul>
</div>
<div class="section">
<span class="section-title">How-To Guides</span>
<ul>
<li><a href="index.html">How-To List</a></li>
<li><a href="http-requests.html">HTTP Requests</a></li>
<li><a href="json-parsing.html">JSON Parsing</a></li>
<li><a href="regex-patterns.html" class="active">Regex Patterns</a></li>
<li><a href="file-operations.html">File Operations</a></li>
<li><a href="async-operations.html">Async Operations</a></li>
<li><a href="error-handling.html">Error Handling</a></li>
</ul>
</div>
</nav>
</aside>
<main class="content">
<nav class="breadcrumb">
<a href="../index.html">Home</a>
<span class="separator">/</span>
<a href="index.html">How-To Guides</a>
<span class="separator">/</span>
<span>Regex Patterns</span>
</nav>
<article>
<h1>Using Regular Expressions</h1>
<h2>Test if String Matches Pattern</h2>
<pre><code>import "regex" for Regex
var pattern = Regex.new("^hello")
System.print(pattern.test("hello world")) // true
System.print(pattern.test("say hello")) // false</code></pre>
<h2>Find First Match</h2>
<pre><code>import "regex" for Regex
var pattern = Regex.new("\\d+")
var match = pattern.match("Order 12345 shipped")
if (match) {
System.print(match.text) // 12345
System.print(match.start) // 6
System.print(match.end) // 11
}</code></pre>
<h2>Find All Matches</h2>
<pre><code>import "regex" for Regex
var pattern = Regex.new("\\d+")
var matches = pattern.matchAll("Items: 10, 20, 30")
for (match in matches) {
System.print(match.text)
}
// 10
// 20
// 30</code></pre>
<h2>Capture Groups</h2>
<pre><code>import "regex" for Regex
var pattern = Regex.new("(\\w+)@(\\w+\\.\\w+)")
var match = pattern.match("Contact: alice@example.com")
if (match) {
System.print(match.group(0)) // alice@example.com
System.print(match.group(1)) // alice
System.print(match.group(2)) // example.com
}</code></pre>
<h2>Replace Matches</h2>
<pre><code>import "regex" for Regex
var pattern = Regex.new("\\bcat\\b")
var result = pattern.replace("The cat sat on the cat mat", "dog")
System.print(result) // The dog sat on the dog mat</code></pre>
<h2>Replace with Callback</h2>
<pre><code>import "regex" for Regex
var pattern = Regex.new("\\d+")
var result = pattern.replace("a1b2c3", Fn.new { |match|
return "[%(match.text)]"
})
System.print(result) // a[1]b[2]c[3]</code></pre>
<h2>Split String</h2>
<pre><code>import "regex" for Regex
var pattern = Regex.new("[,;\\s]+")
var parts = pattern.split("apple, banana; cherry date")
for (part in parts) {
System.print(part)
}
// apple
// banana
// cherry
// date</code></pre>
<h2>Case Insensitive Matching</h2>
<pre><code>import "regex" for Regex
var pattern = Regex.new("hello", "i")
System.print(pattern.test("Hello World")) // true
System.print(pattern.test("HELLO")) // true</code></pre>
<h2>Multiline Matching</h2>
<pre><code>import "regex" for Regex
var text = "Line 1\nLine 2\nLine 3"
var pattern = Regex.new("^Line", "m")
var matches = pattern.matchAll(text)
System.print(matches.count) // 3</code></pre>
<h2>Common Patterns</h2>
<h3>Validate Email</h3>
<pre><code>import "regex" for Regex
var emailPattern = Regex.new("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$")
System.print(emailPattern.test("user@example.com")) // true
System.print(emailPattern.test("invalid-email")) // false</code></pre>
<h3>Validate URL</h3>
<pre><code>import "regex" for Regex
var urlPattern = Regex.new("^https?://[a-zA-Z0-9.-]+(/.*)?$")
System.print(urlPattern.test("https://example.com")) // true
System.print(urlPattern.test("http://example.com/path")) // true
System.print(urlPattern.test("ftp://invalid")) // false</code></pre>
<h3>Validate Phone Number</h3>
<pre><code>import "regex" for Regex
var phonePattern = Regex.new("^\\+?\\d{1,3}[-.\\s]?\\(?\\d{3}\\)?[-.\\s]?\\d{3}[-.\\s]?\\d{4}$")
System.print(phonePattern.test("+1-555-123-4567")) // true
System.print(phonePattern.test("(555) 123-4567")) // true</code></pre>
<h3>Extract Numbers</h3>
<pre><code>import "regex" for Regex
var numberPattern = Regex.new("-?\\d+\\.?\\d*")
var text = "Temperature: -5.5 to 32.0 degrees"
var matches = numberPattern.matchAll(text)
for (match in matches) {
System.print(match.text)
}
// -5.5
// 32.0</code></pre>
<h3>Extract Hashtags</h3>
<pre><code>import "regex" for Regex
var hashtagPattern = Regex.new("#\\w+")
var text = "Check out #wren and #programming!"
var matches = hashtagPattern.matchAll(text)
for (match in matches) {
System.print(match.text)
}
// #wren
// #programming</code></pre>
<h3>Remove HTML Tags</h3>
<pre><code>import "regex" for Regex
var tagPattern = Regex.new("<[^>]+>")
var html = "<p>Hello <b>World</b>!</p>"
var text = tagPattern.replace(html, "")
System.print(text) // Hello World!</code></pre>
<h3>Validate Password Strength</h3>
<pre><code>import "regex" for Regex
var hasUpper = Regex.new("[A-Z]")
var hasLower = Regex.new("[a-z]")
var hasDigit = Regex.new("\\d")
var hasSpecial = Regex.new("[!@#$%^&*]")
var minLength = 8
var validatePassword = Fn.new { |password|
if (password.count < minLength) return false
if (!hasUpper.test(password)) return false
if (!hasLower.test(password)) return false
if (!hasDigit.test(password)) return false
if (!hasSpecial.test(password)) return false
return true
}
System.print(validatePassword.call("Weak")) // false
System.print(validatePassword.call("Strong@Pass1")) // true</code></pre>
<h3>Parse Log Lines</h3>
<pre><code>import "regex" for Regex
var logPattern = Regex.new("\\[(\\d{4}-\\d{2}-\\d{2})\\]\\s+(\\w+):\\s+(.+)")
var line = "[2024-01-15] ERROR: Connection failed"
var match = logPattern.match(line)
if (match) {
System.print("Date: %(match.group(1))") // 2024-01-15
System.print("Level: %(match.group(2))") // ERROR
System.print("Message: %(match.group(3))") // Connection failed
}</code></pre>
<h3>Validate IP Address</h3>
<pre><code>import "regex" for Regex
var ipPattern = Regex.new("^((25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(25[0-5]|2[0-4]\\d|[01]?\\d\\d?)$")
System.print(ipPattern.test("192.168.1.1")) // true
System.print(ipPattern.test("256.1.1.1")) // false
System.print(ipPattern.test("10.0.0.255")) // true</code></pre>
<h2>Pattern Syntax Quick Reference</h2>
<table>
<tr><th>Pattern</th><th>Description</th></tr>
<tr><td><code>.</code></td><td>Any character except newline</td></tr>
<tr><td><code>\\d</code></td><td>Digit (0-9)</td></tr>
<tr><td><code>\\w</code></td><td>Word character (a-z, A-Z, 0-9, _)</td></tr>
<tr><td><code>\\s</code></td><td>Whitespace</td></tr>
<tr><td><code>^</code></td><td>Start of string/line</td></tr>
<tr><td><code>$</code></td><td>End of string/line</td></tr>
<tr><td><code>*</code></td><td>Zero or more</td></tr>
<tr><td><code>+</code></td><td>One or more</td></tr>
<tr><td><code>?</code></td><td>Zero or one</td></tr>
<tr><td><code>{n,m}</code></td><td>Between n and m times</td></tr>
<tr><td><code>[abc]</code></td><td>Character class</td></tr>
<tr><td><code>[^abc]</code></td><td>Negated character class</td></tr>
<tr><td><code>(group)</code></td><td>Capture group</td></tr>
<tr><td><code>a|b</code></td><td>Alternation (a or b)</td></tr>
<tr><td><code>\\b</code></td><td>Word boundary</td></tr>
</table>
<div class="admonition tip">
<div class="admonition-title">See Also</div>
<p>For full API documentation, see the <a href="../api/regex.html">Regex module reference</a>.</p>
</div>
</article>
<footer class="page-footer">
<a href="json-parsing.html" class="prev">JSON Parsing</a>
<a href="file-operations.html" class="next">File Operations</a>
</footer>
</main>
</div>
<script src="../js/main.js"></script>
</body>
</html>