about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2024-12-14 21:23:09 +0100
committerbptato <nincsnevem662@gmail.com>2024-12-14 21:25:19 +0100
commitc1fcfaaeff72aeebf47a25822f0135fbbde07ef8 (patch)
tree7ed17d4951cd82c4b0775f54f973ca8aa1fcf6fc
parent0b3e3ed7c789a6b258d7241c95f79c2113814e14 (diff)
downloadchawan-c1fcfaaeff72aeebf47a25822f0135fbbde07ef8.tar.gz
client: document readFile, writeFile; add getenv, setenv
Both are quite useful.

readFile and writeFile got a small makeover in error handling; in
particular, readFile now returns null instead of the empty string when
the file is missing and writeFile throws a TypeError on I/O errors.
-rw-r--r--doc/api.md30
-rw-r--r--src/local/client.nim39
2 files changed, 62 insertions, 7 deletions
diff --git a/doc/api.md b/doc/api.md
index 08e9f234..fae58e51 100644
--- a/doc/api.md
+++ b/doc/api.md
@@ -72,6 +72,36 @@ Note: this suspends the entire process group.</td>
 </tr>
 
 <tr>
+<td>`readFile(path)`</td>
+<td>Read a file at `path`.<br>
+Returns the file's content as a string, or null if the file does not
+exist.
+</td>
+</tr>
+
+<tr>
+<td>`writeFile(path, content)`</td>
+<td>Write `content` to the file at `path`.<br>
+Throws a TypeError if this failed for whatever reason.
+</td>
+</tr>
+
+<tr>
+<td>`getenv(name, fallback = null)`</td>
+<td>Get an environment variable by `name`.<br>
+Returns `fallback` if the variable does not exist.
+</td>
+</tr>
+
+<tr>
+<td>`setenv(name, value)`</td>
+<td>Set an environment variable by `name`.<br>
+Throws a type error if the operation failed (e.g. because the variable's
+size exceeded an OS-specified limit.)
+</td>
+</tr>
+
+<tr>
 <td>`pager`</td>
 <td>The pager object. Implements `Pager`, as described below.</td>
 </tr>
diff --git a/src/local/client.nim b/src/local/client.nim
index f9b10096..e072ea92 100644
--- a/src/local/client.nim
+++ b/src/local/client.nim
@@ -78,16 +78,41 @@ proc readBlob(client: Client; path: string): WebFile {.jsfunc.} =
   let name = path.afterLast('/')
   return newWebFile(name, ps.fd)
 
-#TODO this is dumb
-proc readFile(client: Client; path: string): string {.jsfunc.} =
+proc readFile(ctx: JSContext; client: Client; path: string): JSValue
+    {.jsfunc.} =
   try:
-    return readFile(path)
+    return ctx.toJS(readFile(path))
   except IOError:
-    discard
+    return JS_NULL
 
-#TODO ditto
-proc writeFile(client: Client; path, content: string) {.jsfunc.} =
-  writeFile(path, content)
+proc writeFile(ctx: JSContext; client: Client; path, content: string): JSValue
+    {.jsfunc.} =
+  try:
+    writeFile(path, content)
+  except IOError:
+    return JS_ThrowTypeError(ctx, "Could not write to file %s", cstring(path))
+  return JS_UNDEFINED
+
+proc getenv(ctx: JSContext; client: Client; s: string;
+    fallback = JS_NULL): JSValue {.jsfunc.} =
+  if not existsEnv(s):
+    return fallback
+  return ctx.toJS(getEnv(s))
+
+proc setenv(ctx: JSContext; client: Client; s: string; val: JSValue): JSValue
+    {.jsfunc.} =
+  try:
+    if JS_IsNull(val):
+      delEnv(s)
+    else:
+      var vals: string
+      if (let res = ctx.fromJS(val, vals); res.isSome):
+        putEnv(s, vals)
+      else:
+        return JS_EXCEPTION
+  except OSError:
+    return JS_ThrowTypeError(ctx, "Failed to set environment variable")
+  return JS_UNDEFINED
 
 proc nimGCStats(client: Client): string {.jsfunc.} =
   return GC_getStatistics()