Update.
This commit is contained in:
parent
957e3a4762
commit
2e425571ca
15
Makefile
Normal file
15
Makefile
Normal file
@ -0,0 +1,15 @@
|
||||
# retoor <retoor@molodetz.nl>
|
||||
|
||||
.PHONY: build tests clean debug
|
||||
|
||||
build:
|
||||
cd projects/make && $(MAKE) -f wren_cli.make -j $$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 4)
|
||||
|
||||
debug:
|
||||
cd projects/make && $(MAKE) -f wren_cli.make config=debug_64bit -j $$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 4)
|
||||
|
||||
tests: build
|
||||
python3 util/test.py
|
||||
|
||||
clean:
|
||||
cd projects/make && $(MAKE) -f wren_cli.make clean
|
||||
78
README.md
78
README.md
@ -1,59 +1,63 @@
|
||||
# Wren CLI
|
||||
# Wren-CLI
|
||||
|
||||
## The CLI project is a small and simple REPL and CLI tool for running Wren scripts.
|
||||
retoor <retoor@molodetz.nl>
|
||||
|
||||
It is backed by [libuv](http://libuv.org/) to implement IO functionality, and is a work in progress.
|
||||
A command-line interface and REPL for the [Wren](http://wren.io) programming language. Built on [libuv](http://libuv.org/) for asynchronous I/O with native support for HTTP/HTTPS, WebSockets, TLS, SQLite, JSON, regex, and more.
|
||||
|
||||
For documentation and usage, see http://wren.io/cli
|
||||
For more information about Wren, the language used by the CLI, see http://wren.io
|
||||
## Prerequisites
|
||||
|
||||
Like with Wren itself, we welcome [contributions][contribute].
|
||||
- C compiler (GCC or Clang)
|
||||
- Make
|
||||
- OpenSSL development libraries
|
||||
- Python 3 (for tests)
|
||||
|
||||
[contribute]: http://wren.io/contributing.html
|
||||
## Build
|
||||
|
||||
[](https://travis-ci.org/wren-lang/wren-cli)
|
||||
```bash
|
||||
git clone https://github.com/wren-lang/wren-cli.git
|
||||
cd wren-cli
|
||||
make build
|
||||
```
|
||||
|
||||
---
|
||||
Output binary: `bin/wren_cli`
|
||||
|
||||
## To build the Wren CLI
|
||||
### Platform-Specific Builds
|
||||
|
||||
### Windows
|
||||
| Platform | Command |
|
||||
|----------|---------|
|
||||
| Linux | `make build` |
|
||||
| macOS | `cd projects/make.mac && make` |
|
||||
| FreeBSD | `cd projects/make.bsd && gmake` |
|
||||
|
||||
The `projects/vs20xx` folders contain Visual Studio projects.
|
||||
## Test
|
||||
|
||||
### macOS
|
||||
```bash
|
||||
make tests
|
||||
```
|
||||
|
||||
The `projects/xcode` folder contains an Xcode project.
|
||||
Run a specific test suite:
|
||||
|
||||
The `projects/make.mac` folder also contains a `make` project.
|
||||
From that folder, run `make`.
|
||||
```bash
|
||||
python3 util/test.py json
|
||||
```
|
||||
|
||||
`cd projects/make.mac`
|
||||
`make`
|
||||
## Usage
|
||||
|
||||
### Linux
|
||||
```bash
|
||||
bin/wren_cli script.wren # Execute a script
|
||||
bin/wren_cli # Start the REPL
|
||||
```
|
||||
|
||||
The `projects/make` folder contains a `make` project.
|
||||
From that folder, run `make`.
|
||||
## Modules
|
||||
|
||||
`cd projects/make`
|
||||
`make`
|
||||
**Core**: io, os, scheduler, timer, net, repl
|
||||
|
||||
### FreeBSD
|
||||
**Extended**: json, env, math, base64, datetime, dns, signal, subprocess, crypto, regex, http, tls, sqlite, websocket, jinja, pathlib, tempfile, uuid
|
||||
|
||||
The `projects/make.bsd` folder contains a `make` project.
|
||||
From that folder, run `make`.
|
||||
## Documentation
|
||||
|
||||
`cd projects/make.bsd`
|
||||
`gmake`
|
||||
|
||||
## Alternative build options
|
||||
|
||||
The projects are generated by premake, found inside `projects/premake`.
|
||||
You can use premake5 (alpha 14 was used) to generate other projects.
|
||||
Generate other system's projects via the premake `--os` flag,
|
||||
i.e if on linux, `premake vs2019 --os=windows` is valid.
|
||||
|
||||
---
|
||||
See the `manual/` directory for the full reference including API docs, tutorials, and how-to guides.
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
|
||||
61
deps/wren/src/vm/wren_compiler.c
vendored
61
deps/wren/src/vm/wren_compiler.c
vendored
@ -108,6 +108,8 @@ typedef enum
|
||||
TOKEN_TRUE,
|
||||
TOKEN_VAR,
|
||||
TOKEN_WHILE,
|
||||
TOKEN_ASYNC,
|
||||
TOKEN_AWAIT,
|
||||
|
||||
TOKEN_FIELD,
|
||||
TOKEN_STATIC_FIELD,
|
||||
@ -619,6 +621,8 @@ static Keyword keywords[] =
|
||||
{"true", 4, TOKEN_TRUE},
|
||||
{"var", 3, TOKEN_VAR},
|
||||
{"while", 5, TOKEN_WHILE},
|
||||
{"async", 5, TOKEN_ASYNC},
|
||||
{"await", 5, TOKEN_AWAIT},
|
||||
{NULL, 0, TOKEN_EOF} // Sentinel to mark the end of the array.
|
||||
};
|
||||
|
||||
@ -1746,6 +1750,8 @@ static void expression(Compiler* compiler);
|
||||
static void statement(Compiler* compiler);
|
||||
static void definition(Compiler* compiler);
|
||||
static void parsePrecedence(Compiler* compiler, Precedence precedence);
|
||||
static void async_(Compiler* compiler, bool canAssign);
|
||||
static void await_(Compiler* compiler, bool canAssign);
|
||||
|
||||
// Replaces the placeholder argument for a previous CODE_JUMP or CODE_JUMP_IF
|
||||
// instruction with an offset that jumps to the current end of bytecode.
|
||||
@ -2499,6 +2505,59 @@ static void this_(Compiler* compiler, bool canAssign)
|
||||
loadThis(compiler);
|
||||
}
|
||||
|
||||
static int resolveScheduler(Compiler* compiler)
|
||||
{
|
||||
int symbol = wrenSymbolTableFind(
|
||||
&compiler->parser->module->variableNames,
|
||||
"Scheduler", 9);
|
||||
|
||||
if (symbol == -1)
|
||||
{
|
||||
symbol = wrenDeclareVariable(compiler->parser->vm,
|
||||
compiler->parser->module,
|
||||
"Scheduler", 9,
|
||||
compiler->parser->previous.line);
|
||||
if (symbol == -2)
|
||||
{
|
||||
error(compiler, "Too many module variables defined.");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return symbol;
|
||||
}
|
||||
|
||||
static void await_(Compiler* compiler, bool canAssign)
|
||||
{
|
||||
int schedulerSymbol = resolveScheduler(compiler);
|
||||
if (schedulerSymbol == -1) return;
|
||||
|
||||
emitShortArg(compiler, CODE_LOAD_MODULE_VAR, schedulerSymbol);
|
||||
|
||||
ignoreNewlines(compiler);
|
||||
expression(compiler);
|
||||
|
||||
callMethod(compiler, 1, "await_(_)", 9);
|
||||
}
|
||||
|
||||
static void async_(Compiler* compiler, bool canAssign)
|
||||
{
|
||||
int schedulerSymbol = resolveScheduler(compiler);
|
||||
if (schedulerSymbol == -1) return;
|
||||
|
||||
emitShortArg(compiler, CODE_LOAD_MODULE_VAR, schedulerSymbol);
|
||||
|
||||
consume(compiler, TOKEN_LEFT_BRACE, "Expect '{' after 'async'.");
|
||||
|
||||
Compiler fnCompiler;
|
||||
initCompiler(&fnCompiler, compiler->parser, compiler, false);
|
||||
fnCompiler.fn->arity = 0;
|
||||
|
||||
finishBody(&fnCompiler);
|
||||
endCompiler(&fnCompiler, "[async]", 7);
|
||||
|
||||
callMethod(compiler, 1, "async_(_)", 9);
|
||||
}
|
||||
|
||||
// Subscript or "array indexing" operator like `foo[bar]`.
|
||||
static void subscript(Compiler* compiler, bool canAssign)
|
||||
{
|
||||
@ -2799,6 +2858,8 @@ GrammarRule rules[] =
|
||||
/* TOKEN_TRUE */ PREFIX(boolean),
|
||||
/* TOKEN_VAR */ UNUSED,
|
||||
/* TOKEN_WHILE */ UNUSED,
|
||||
/* TOKEN_ASYNC */ PREFIX(async_),
|
||||
/* TOKEN_AWAIT */ PREFIX(await_),
|
||||
/* TOKEN_FIELD */ PREFIX(field),
|
||||
/* TOKEN_STATIC_FIELD */ PREFIX(staticField),
|
||||
/* TOKEN_NAME */ { name, NULL, namedSignature, PREC_NONE, NULL },
|
||||
|
||||
148
deps/wren/src/vm/wren_core.c
vendored
148
deps/wren/src/vm/wren_core.c
vendored
@ -2,6 +2,7 @@
|
||||
#include <errno.h>
|
||||
#include <float.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
@ -647,6 +648,7 @@ DEF_NUM_CONSTANT(smallest, DBL_MIN)
|
||||
|
||||
DEF_NUM_CONSTANT(maxSafeInteger, 9007199254740991.0)
|
||||
DEF_NUM_CONSTANT(minSafeInteger, -9007199254740991.0)
|
||||
DEF_NUM_CONSTANT(e, 2.71828182845904523536)
|
||||
|
||||
// Defines a primitive on Num that calls infix [op] and returns [type].
|
||||
#define DEF_NUM_INFIX(name, op, type) \
|
||||
@ -704,6 +706,10 @@ DEF_NUM_FN(tan, tan)
|
||||
DEF_NUM_FN(log, log)
|
||||
DEF_NUM_FN(log2, log2)
|
||||
DEF_NUM_FN(exp, exp)
|
||||
DEF_NUM_FN(log10, log10)
|
||||
DEF_NUM_FN(sinh, sinh)
|
||||
DEF_NUM_FN(cosh, cosh)
|
||||
DEF_NUM_FN(tanh, tanh)
|
||||
|
||||
DEF_PRIMITIVE(num_mod)
|
||||
{
|
||||
@ -843,6 +849,65 @@ DEF_PRIMITIVE(num_truncate)
|
||||
RETURN_NUM(integer);
|
||||
}
|
||||
|
||||
DEF_PRIMITIVE(num_toBase)
|
||||
{
|
||||
if (!validateInt(vm, args[1], "Radix")) return false;
|
||||
int radix = (int)AS_NUM(args[1]);
|
||||
if (radix < 2 || radix > 36)
|
||||
{
|
||||
RETURN_ERROR("Radix must be between 2 and 36.");
|
||||
}
|
||||
double raw = AS_NUM(args[0]);
|
||||
if (isnan(raw) || isinf(raw))
|
||||
{
|
||||
RETURN_ERROR("Cannot convert NaN or Infinity to a base string.");
|
||||
}
|
||||
int64_t value = (int64_t)trunc(raw);
|
||||
bool negative = value < 0;
|
||||
if (negative) value = -value;
|
||||
static const char lookup[] = "0123456789abcdefghijklmnopqrstuvwxyz";
|
||||
char buf[66];
|
||||
int len = 0;
|
||||
if (value == 0)
|
||||
{
|
||||
buf[len++] = '0';
|
||||
}
|
||||
else
|
||||
{
|
||||
while (value > 0)
|
||||
{
|
||||
buf[len++] = lookup[value % radix];
|
||||
value = value / radix;
|
||||
}
|
||||
}
|
||||
if (negative) buf[len++] = '-';
|
||||
for (int i = 0; i < len / 2; i++)
|
||||
{
|
||||
char tmp = buf[i];
|
||||
buf[i] = buf[len - 1 - i];
|
||||
buf[len - 1 - i] = tmp;
|
||||
}
|
||||
buf[len] = '\0';
|
||||
RETURN_VAL(wrenNewStringLength(vm, buf, len));
|
||||
}
|
||||
|
||||
DEF_PRIMITIVE(num_format)
|
||||
{
|
||||
if (!validateInt(vm, args[1], "Decimal places")) return false;
|
||||
int decimals = (int)AS_NUM(args[1]);
|
||||
if (decimals < 0 || decimals > 20)
|
||||
{
|
||||
RETURN_ERROR("Decimal places must be between 0 and 20.");
|
||||
}
|
||||
char buf[64];
|
||||
int len = snprintf(buf, sizeof(buf), "%.*f", decimals, AS_NUM(args[0]));
|
||||
if (len < 0 || len >= (int)sizeof(buf))
|
||||
{
|
||||
RETURN_ERROR("Formatting failed.");
|
||||
}
|
||||
RETURN_VAL(wrenNewStringLength(vm, buf, (size_t)len));
|
||||
}
|
||||
|
||||
DEF_PRIMITIVE(object_same)
|
||||
{
|
||||
RETURN_BOOL(wrenValuesEqual(args[1], args[2]));
|
||||
@ -1167,6 +1232,46 @@ DEF_PRIMITIVE(string_plus)
|
||||
RETURN_VAL(wrenStringFormat(vm, "@@", args[0], args[1]));
|
||||
}
|
||||
|
||||
DEF_PRIMITIVE(string_lt)
|
||||
{
|
||||
if (!validateString(vm, args[1], "Right operand")) return false;
|
||||
ObjString* left = AS_STRING(args[0]);
|
||||
ObjString* right = AS_STRING(args[1]);
|
||||
uint32_t minLen = left->length < right->length ? left->length : right->length;
|
||||
int cmp = memcmp(left->value, right->value, minLen);
|
||||
RETURN_BOOL(cmp < 0 || (cmp == 0 && left->length < right->length));
|
||||
}
|
||||
|
||||
DEF_PRIMITIVE(string_gt)
|
||||
{
|
||||
if (!validateString(vm, args[1], "Right operand")) return false;
|
||||
ObjString* left = AS_STRING(args[0]);
|
||||
ObjString* right = AS_STRING(args[1]);
|
||||
uint32_t minLen = left->length < right->length ? left->length : right->length;
|
||||
int cmp = memcmp(left->value, right->value, minLen);
|
||||
RETURN_BOOL(cmp > 0 || (cmp == 0 && left->length > right->length));
|
||||
}
|
||||
|
||||
DEF_PRIMITIVE(string_lte)
|
||||
{
|
||||
if (!validateString(vm, args[1], "Right operand")) return false;
|
||||
ObjString* left = AS_STRING(args[0]);
|
||||
ObjString* right = AS_STRING(args[1]);
|
||||
uint32_t minLen = left->length < right->length ? left->length : right->length;
|
||||
int cmp = memcmp(left->value, right->value, minLen);
|
||||
RETURN_BOOL(cmp < 0 || (cmp == 0 && left->length <= right->length));
|
||||
}
|
||||
|
||||
DEF_PRIMITIVE(string_gte)
|
||||
{
|
||||
if (!validateString(vm, args[1], "Right operand")) return false;
|
||||
ObjString* left = AS_STRING(args[0]);
|
||||
ObjString* right = AS_STRING(args[1]);
|
||||
uint32_t minLen = left->length < right->length ? left->length : right->length;
|
||||
int cmp = memcmp(left->value, right->value, minLen);
|
||||
RETURN_BOOL(cmp > 0 || (cmp == 0 && left->length >= right->length));
|
||||
}
|
||||
|
||||
DEF_PRIMITIVE(string_subscript)
|
||||
{
|
||||
ObjString* string = AS_STRING(args[0]);
|
||||
@ -1197,6 +1302,36 @@ DEF_PRIMITIVE(string_toString)
|
||||
RETURN_VAL(args[0]);
|
||||
}
|
||||
|
||||
DEF_PRIMITIVE(string_lower)
|
||||
{
|
||||
ObjString* str = AS_STRING(args[0]);
|
||||
char* buf = ALLOCATE_ARRAY(vm, char, str->length + 1);
|
||||
for (uint32_t i = 0; i < str->length; i++)
|
||||
{
|
||||
uint8_t c = (uint8_t)str->value[i];
|
||||
buf[i] = (c >= 'A' && c <= 'Z') ? (char)(c + 32) : (char)c;
|
||||
}
|
||||
buf[str->length] = '\0';
|
||||
Value result = wrenNewStringLength(vm, buf, str->length);
|
||||
DEALLOCATE(vm, buf);
|
||||
RETURN_VAL(result);
|
||||
}
|
||||
|
||||
DEF_PRIMITIVE(string_upper)
|
||||
{
|
||||
ObjString* str = AS_STRING(args[0]);
|
||||
char* buf = ALLOCATE_ARRAY(vm, char, str->length + 1);
|
||||
for (uint32_t i = 0; i < str->length; i++)
|
||||
{
|
||||
uint8_t c = (uint8_t)str->value[i];
|
||||
buf[i] = (c >= 'a' && c <= 'z') ? (char)(c - 32) : (char)c;
|
||||
}
|
||||
buf[str->length] = '\0';
|
||||
Value result = wrenNewStringLength(vm, buf, str->length);
|
||||
DEALLOCATE(vm, buf);
|
||||
RETURN_VAL(result);
|
||||
}
|
||||
|
||||
DEF_PRIMITIVE(system_clock)
|
||||
{
|
||||
RETURN_NUM((double)clock() / CLOCKS_PER_SEC);
|
||||
@ -1358,6 +1493,7 @@ void wrenInitializeCore(WrenVM* vm)
|
||||
PRIMITIVE(vm->numClass->obj.classObj, "smallest", num_smallest);
|
||||
PRIMITIVE(vm->numClass->obj.classObj, "maxSafeInteger", num_maxSafeInteger);
|
||||
PRIMITIVE(vm->numClass->obj.classObj, "minSafeInteger", num_minSafeInteger);
|
||||
PRIMITIVE(vm->numClass->obj.classObj, "e", num_e);
|
||||
PRIMITIVE(vm->numClass, "-(_)", num_minus);
|
||||
PRIMITIVE(vm->numClass, "+(_)", num_plus);
|
||||
PRIMITIVE(vm->numClass, "*(_)", num_multiply);
|
||||
@ -1403,6 +1539,12 @@ void wrenInitializeCore(WrenVM* vm)
|
||||
PRIMITIVE(vm->numClass, "sign", num_sign);
|
||||
PRIMITIVE(vm->numClass, "toString", num_toString);
|
||||
PRIMITIVE(vm->numClass, "truncate", num_truncate);
|
||||
PRIMITIVE(vm->numClass, "log10", num_log10);
|
||||
PRIMITIVE(vm->numClass, "sinh", num_sinh);
|
||||
PRIMITIVE(vm->numClass, "cosh", num_cosh);
|
||||
PRIMITIVE(vm->numClass, "tanh", num_tanh);
|
||||
PRIMITIVE(vm->numClass, "toBase(_)", num_toBase);
|
||||
PRIMITIVE(vm->numClass, "format(_)", num_format);
|
||||
|
||||
// These are defined just so that 0 and -0 are equal, which is specified by
|
||||
// IEEE 754 even though they have different bit representations.
|
||||
@ -1413,6 +1555,10 @@ void wrenInitializeCore(WrenVM* vm)
|
||||
PRIMITIVE(vm->stringClass->obj.classObj, "fromCodePoint(_)", string_fromCodePoint);
|
||||
PRIMITIVE(vm->stringClass->obj.classObj, "fromByte(_)", string_fromByte);
|
||||
PRIMITIVE(vm->stringClass, "+(_)", string_plus);
|
||||
PRIMITIVE(vm->stringClass, "<(_)", string_lt);
|
||||
PRIMITIVE(vm->stringClass, ">(_)", string_gt);
|
||||
PRIMITIVE(vm->stringClass, "<=(_)", string_lte);
|
||||
PRIMITIVE(vm->stringClass, ">=(_)", string_gte);
|
||||
PRIMITIVE(vm->stringClass, "[_]", string_subscript);
|
||||
PRIMITIVE(vm->stringClass, "byteAt_(_)", string_byteAt);
|
||||
PRIMITIVE(vm->stringClass, "byteCount_", string_byteCount);
|
||||
@ -1426,6 +1572,8 @@ void wrenInitializeCore(WrenVM* vm)
|
||||
PRIMITIVE(vm->stringClass, "iteratorValue(_)", string_iteratorValue);
|
||||
PRIMITIVE(vm->stringClass, "startsWith(_)", string_startsWith);
|
||||
PRIMITIVE(vm->stringClass, "toString", string_toString);
|
||||
PRIMITIVE(vm->stringClass, "lower_", string_lower);
|
||||
PRIMITIVE(vm->stringClass, "upper_", string_upper);
|
||||
|
||||
vm->listClass = AS_CLASS(wrenFindVariable(vm, coreModule, "List"));
|
||||
PRIMITIVE(vm->listClass->obj.classObj, "filled(_,_)", list_filled);
|
||||
|
||||
283
deps/wren/src/vm/wren_core.wren
vendored
283
deps/wren/src/vm/wren_core.wren
vendored
@ -2,7 +2,62 @@ class Bool {}
|
||||
class Fiber {}
|
||||
class Fn {}
|
||||
class Null {}
|
||||
class Num {}
|
||||
class Num {
|
||||
isZero { this == 0 }
|
||||
isPositive { this > 0 }
|
||||
isNegative { this < 0 }
|
||||
isFinite { !isInfinity && !isNan }
|
||||
isEven { isInteger && this % 2 == 0 }
|
||||
isOdd { isInteger && this % 2 != 0 }
|
||||
|
||||
isBetween(min, max) { this >= min && this <= max }
|
||||
|
||||
toDegrees { this * 180 / Num.pi }
|
||||
toRadians { this * Num.pi / 180 }
|
||||
|
||||
toChar { String.fromCodePoint(this) }
|
||||
toHex { toBase(16) }
|
||||
toBinary { toBase(2) }
|
||||
toOctal { toBase(8) }
|
||||
|
||||
gcd(other) {
|
||||
var a = this.abs
|
||||
var b = other.abs
|
||||
while (b != 0) {
|
||||
var t = b
|
||||
b = a % b
|
||||
a = t
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
lcm(other) {
|
||||
if (this == 0 && other == 0) return 0
|
||||
return (this * other).abs / gcd(other)
|
||||
}
|
||||
|
||||
digits {
|
||||
if (!isInteger) Fiber.abort("Value must be an integer.")
|
||||
var n = this.abs
|
||||
if (n == 0) {
|
||||
var z = List.new()
|
||||
z.add(0)
|
||||
return z
|
||||
}
|
||||
var result = List.new()
|
||||
while (n > 0) {
|
||||
result.add(n % 10)
|
||||
n = (n / 10).floor
|
||||
}
|
||||
var reversed = List.new()
|
||||
var i = result.count - 1
|
||||
while (i >= 0) {
|
||||
reversed.add(result[i])
|
||||
i = i - 1
|
||||
}
|
||||
return reversed
|
||||
}
|
||||
}
|
||||
|
||||
class Sequence {
|
||||
all(f) {
|
||||
@ -289,6 +344,230 @@ class String is Sequence {
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
lower { lower_ }
|
||||
upper { upper_ }
|
||||
|
||||
capitalize {
|
||||
if (isEmpty) return this
|
||||
return this[0].upper + this[1..-1].lower
|
||||
}
|
||||
|
||||
title {
|
||||
if (isEmpty) return this
|
||||
var result = ""
|
||||
var capitalizeNext = true
|
||||
for (c in this) {
|
||||
if (c == " " || c == "\t" || c == "\n" || c == "\r") {
|
||||
result = result + c
|
||||
capitalizeNext = true
|
||||
} else if (capitalizeNext) {
|
||||
result = result + c.upper
|
||||
capitalizeNext = false
|
||||
} else {
|
||||
result = result + c.lower
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
swapCase {
|
||||
var result = ""
|
||||
for (c in this) {
|
||||
var cp = c.codePoints.toList[0]
|
||||
if (cp >= 65 && cp <= 90) {
|
||||
result = result + c.lower
|
||||
} else if (cp >= 97 && cp <= 122) {
|
||||
result = result + c.upper
|
||||
} else {
|
||||
result = result + c
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
lastIndexOf(search) {
|
||||
var last = -1
|
||||
var index = 0
|
||||
var size = byteCount_
|
||||
var searchSize = search.byteCount_
|
||||
if (searchSize > size) return -1
|
||||
while (index <= size - searchSize) {
|
||||
var found = indexOf(search, index)
|
||||
if (found == -1) break
|
||||
last = found
|
||||
index = found + 1
|
||||
}
|
||||
return last
|
||||
}
|
||||
|
||||
lastIndexOf(search, start) {
|
||||
var last = -1
|
||||
var index = 0
|
||||
var searchSize = search.byteCount_
|
||||
if (searchSize > start + searchSize) return -1
|
||||
while (index <= start) {
|
||||
var found = indexOf(search, index)
|
||||
if (found == -1 || found > start) break
|
||||
last = found
|
||||
index = found + 1
|
||||
}
|
||||
return last
|
||||
}
|
||||
|
||||
isLower {
|
||||
if (isEmpty) return false
|
||||
var hasAlpha = false
|
||||
for (b in bytes) {
|
||||
if (b >= 65 && b <= 90) return false
|
||||
if (b >= 97 && b <= 122) hasAlpha = true
|
||||
}
|
||||
return hasAlpha
|
||||
}
|
||||
|
||||
isUpper {
|
||||
if (isEmpty) return false
|
||||
var hasAlpha = false
|
||||
for (b in bytes) {
|
||||
if (b >= 97 && b <= 122) return false
|
||||
if (b >= 65 && b <= 90) hasAlpha = true
|
||||
}
|
||||
return hasAlpha
|
||||
}
|
||||
|
||||
isDigit {
|
||||
if (isEmpty) return false
|
||||
for (b in bytes) {
|
||||
if (b < 48 || b > 57) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
isAlpha {
|
||||
if (isEmpty) return false
|
||||
for (b in bytes) {
|
||||
if (!((b >= 65 && b <= 90) || (b >= 97 && b <= 122))) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
isAlphaNumeric {
|
||||
if (isEmpty) return false
|
||||
for (b in bytes) {
|
||||
if (!((b >= 65 && b <= 90) || (b >= 97 && b <= 122) || (b >= 48 && b <= 57))) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
isSpace {
|
||||
if (isEmpty) return false
|
||||
for (b in bytes) {
|
||||
if (b != 32 && b != 9 && b != 10 && b != 13 && b != 12 && b != 11) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
isAscii {
|
||||
for (b in bytes) {
|
||||
if (b >= 128) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
reverse {
|
||||
var list = []
|
||||
for (c in this) {
|
||||
list.insert(0, c)
|
||||
}
|
||||
return list.join("")
|
||||
}
|
||||
|
||||
center(width) { center(width, " ") }
|
||||
|
||||
center(width, char) {
|
||||
if (!(width is Num) || !width.isInteger) {
|
||||
Fiber.abort("Width must be an integer.")
|
||||
}
|
||||
if (!(char is String) || char.isEmpty) {
|
||||
Fiber.abort("Fill character must be a non-empty string.")
|
||||
}
|
||||
var len = count
|
||||
if (len >= width) return this
|
||||
var total = width - len
|
||||
var left = (total / 2).floor
|
||||
var right = total - left
|
||||
return (char * (left + 1))[0...left] + this + (char * (right + 1))[0...right]
|
||||
}
|
||||
|
||||
lpad(width, char) {
|
||||
if (!(width is Num) || !width.isInteger) {
|
||||
Fiber.abort("Width must be an integer.")
|
||||
}
|
||||
if (!(char is String) || char.isEmpty) {
|
||||
Fiber.abort("Fill character must be a non-empty string.")
|
||||
}
|
||||
var len = count
|
||||
if (len >= width) return this
|
||||
var pad = width - len
|
||||
return (char * (pad + 1))[0...pad] + this
|
||||
}
|
||||
|
||||
rpad(width, char) {
|
||||
if (!(width is Num) || !width.isInteger) {
|
||||
Fiber.abort("Width must be an integer.")
|
||||
}
|
||||
if (!(char is String) || char.isEmpty) {
|
||||
Fiber.abort("Fill character must be a non-empty string.")
|
||||
}
|
||||
var len = count
|
||||
if (len >= width) return this
|
||||
var pad = width - len
|
||||
return this + (char * (pad + 1))[0...pad]
|
||||
}
|
||||
|
||||
zfill(width) {
|
||||
if (!(width is Num) || !width.isInteger) {
|
||||
Fiber.abort("Width must be an integer.")
|
||||
}
|
||||
var len = count
|
||||
if (len >= width) return this
|
||||
if (startsWith("-") || startsWith("+")) {
|
||||
return this[0] + ("0" * (width - len)) + this[1..-1]
|
||||
}
|
||||
return ("0" * (width - len)) + this
|
||||
}
|
||||
|
||||
removePrefix(prefix) {
|
||||
if (!(prefix is String)) {
|
||||
Fiber.abort("Prefix must be a string.")
|
||||
}
|
||||
if (startsWith(prefix)) return this[prefix.byteCount_..-1]
|
||||
return this
|
||||
}
|
||||
|
||||
removeSuffix(suffix) {
|
||||
if (!(suffix is String)) {
|
||||
Fiber.abort("Suffix must be a string.")
|
||||
}
|
||||
if (endsWith(suffix)) {
|
||||
var end = byteCount_ - suffix.byteCount_ - 1
|
||||
if (end < 0) return ""
|
||||
return this[0..end]
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
splitLines { replace("\r\n", "\n").replace("\r", "\n").split("\n") }
|
||||
|
||||
chars {
|
||||
var result = []
|
||||
for (c in this) {
|
||||
result.add(c)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
toNum { Num.fromString(this) }
|
||||
}
|
||||
|
||||
class StringByteSequence is Sequence {
|
||||
@ -480,4 +759,4 @@ class ClassAttributes {
|
||||
_methods = methods
|
||||
}
|
||||
toString { "attributes:%(_attributes) methods:%(_methods)" }
|
||||
}
|
||||
}
|
||||
|
||||
298
deps/wren/src/vm/wren_core.wren.inc
vendored
298
deps/wren/src/vm/wren_core.wren.inc
vendored
@ -1,10 +1,67 @@
|
||||
// Generated automatically from src/vm/wren_core.wren. Do not edit.
|
||||
// Please do not edit this file. It has been generated automatically
|
||||
// from `deps/wren/src/vm/wren_core.wren` using `util/wren_to_c_string.py`
|
||||
|
||||
static const char* coreModuleSource =
|
||||
"class Bool {}\n"
|
||||
"class Fiber {}\n"
|
||||
"class Fn {}\n"
|
||||
"class Null {}\n"
|
||||
"class Num {}\n"
|
||||
"class Num {\n"
|
||||
" isZero { this == 0 }\n"
|
||||
" isPositive { this > 0 }\n"
|
||||
" isNegative { this < 0 }\n"
|
||||
" isFinite { !isInfinity && !isNan }\n"
|
||||
" isEven { isInteger && this % 2 == 0 }\n"
|
||||
" isOdd { isInteger && this % 2 != 0 }\n"
|
||||
"\n"
|
||||
" isBetween(min, max) { this >= min && this <= max }\n"
|
||||
"\n"
|
||||
" toDegrees { this * 180 / Num.pi }\n"
|
||||
" toRadians { this * Num.pi / 180 }\n"
|
||||
"\n"
|
||||
" toChar { String.fromCodePoint(this) }\n"
|
||||
" toHex { toBase(16) }\n"
|
||||
" toBinary { toBase(2) }\n"
|
||||
" toOctal { toBase(8) }\n"
|
||||
"\n"
|
||||
" gcd(other) {\n"
|
||||
" var a = this.abs\n"
|
||||
" var b = other.abs\n"
|
||||
" while (b != 0) {\n"
|
||||
" var t = b\n"
|
||||
" b = a % b\n"
|
||||
" a = t\n"
|
||||
" }\n"
|
||||
" return a\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" lcm(other) {\n"
|
||||
" if (this == 0 && other == 0) return 0\n"
|
||||
" return (this * other).abs / gcd(other)\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" digits {\n"
|
||||
" if (!isInteger) Fiber.abort(\"Value must be an integer.\")\n"
|
||||
" var n = this.abs\n"
|
||||
" if (n == 0) {\n"
|
||||
" var z = List.new()\n"
|
||||
" z.add(0)\n"
|
||||
" return z\n"
|
||||
" }\n"
|
||||
" var result = List.new()\n"
|
||||
" while (n > 0) {\n"
|
||||
" result.add(n % 10)\n"
|
||||
" n = (n / 10).floor\n"
|
||||
" }\n"
|
||||
" var reversed = List.new()\n"
|
||||
" var i = result.count - 1\n"
|
||||
" while (i >= 0) {\n"
|
||||
" reversed.add(result[i])\n"
|
||||
" i = i - 1\n"
|
||||
" }\n"
|
||||
" return reversed\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"class Sequence {\n"
|
||||
" all(f) {\n"
|
||||
@ -238,11 +295,11 @@ static const char* coreModuleSource =
|
||||
" return result\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" trim() { trim_(\"\t\r\n \", true, true) }\n"
|
||||
" trim() { trim_(\"\\t\\r\\n \", true, true) }\n"
|
||||
" trim(chars) { trim_(chars, true, true) }\n"
|
||||
" trimEnd() { trim_(\"\t\r\n \", false, true) }\n"
|
||||
" trimEnd() { trim_(\"\\t\\r\\n \", false, true) }\n"
|
||||
" trimEnd(chars) { trim_(chars, false, true) }\n"
|
||||
" trimStart() { trim_(\"\t\r\n \", true, false) }\n"
|
||||
" trimStart() { trim_(\"\\t\\r\\n \", true, false) }\n"
|
||||
" trimStart(chars) { trim_(chars, true, false) }\n"
|
||||
"\n"
|
||||
" trim_(chars, trimStart, trimEnd) {\n"
|
||||
@ -291,6 +348,230 @@ static const char* coreModuleSource =
|
||||
" }\n"
|
||||
" return result\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" lower { lower_ }\n"
|
||||
" upper { upper_ }\n"
|
||||
"\n"
|
||||
" capitalize {\n"
|
||||
" if (isEmpty) return this\n"
|
||||
" return this[0].upper + this[1..-1].lower\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" title {\n"
|
||||
" if (isEmpty) return this\n"
|
||||
" var result = \"\"\n"
|
||||
" var capitalizeNext = true\n"
|
||||
" for (c in this) {\n"
|
||||
" if (c == \" \" || c == \"\\t\" || c == \"\\n\" || c == \"\\r\") {\n"
|
||||
" result = result + c\n"
|
||||
" capitalizeNext = true\n"
|
||||
" } else if (capitalizeNext) {\n"
|
||||
" result = result + c.upper\n"
|
||||
" capitalizeNext = false\n"
|
||||
" } else {\n"
|
||||
" result = result + c.lower\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" return result\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" swapCase {\n"
|
||||
" var result = \"\"\n"
|
||||
" for (c in this) {\n"
|
||||
" var cp = c.codePoints.toList[0]\n"
|
||||
" if (cp >= 65 && cp <= 90) {\n"
|
||||
" result = result + c.lower\n"
|
||||
" } else if (cp >= 97 && cp <= 122) {\n"
|
||||
" result = result + c.upper\n"
|
||||
" } else {\n"
|
||||
" result = result + c\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" return result\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" lastIndexOf(search) {\n"
|
||||
" var last = -1\n"
|
||||
" var index = 0\n"
|
||||
" var size = byteCount_\n"
|
||||
" var searchSize = search.byteCount_\n"
|
||||
" if (searchSize > size) return -1\n"
|
||||
" while (index <= size - searchSize) {\n"
|
||||
" var found = indexOf(search, index)\n"
|
||||
" if (found == -1) break\n"
|
||||
" last = found\n"
|
||||
" index = found + 1\n"
|
||||
" }\n"
|
||||
" return last\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" lastIndexOf(search, start) {\n"
|
||||
" var last = -1\n"
|
||||
" var index = 0\n"
|
||||
" var searchSize = search.byteCount_\n"
|
||||
" if (searchSize > start + searchSize) return -1\n"
|
||||
" while (index <= start) {\n"
|
||||
" var found = indexOf(search, index)\n"
|
||||
" if (found == -1 || found > start) break\n"
|
||||
" last = found\n"
|
||||
" index = found + 1\n"
|
||||
" }\n"
|
||||
" return last\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" isLower {\n"
|
||||
" if (isEmpty) return false\n"
|
||||
" var hasAlpha = false\n"
|
||||
" for (b in bytes) {\n"
|
||||
" if (b >= 65 && b <= 90) return false\n"
|
||||
" if (b >= 97 && b <= 122) hasAlpha = true\n"
|
||||
" }\n"
|
||||
" return hasAlpha\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" isUpper {\n"
|
||||
" if (isEmpty) return false\n"
|
||||
" var hasAlpha = false\n"
|
||||
" for (b in bytes) {\n"
|
||||
" if (b >= 97 && b <= 122) return false\n"
|
||||
" if (b >= 65 && b <= 90) hasAlpha = true\n"
|
||||
" }\n"
|
||||
" return hasAlpha\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" isDigit {\n"
|
||||
" if (isEmpty) return false\n"
|
||||
" for (b in bytes) {\n"
|
||||
" if (b < 48 || b > 57) return false\n"
|
||||
" }\n"
|
||||
" return true\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" isAlpha {\n"
|
||||
" if (isEmpty) return false\n"
|
||||
" for (b in bytes) {\n"
|
||||
" if (!((b >= 65 && b <= 90) || (b >= 97 && b <= 122))) return false\n"
|
||||
" }\n"
|
||||
" return true\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" isAlphaNumeric {\n"
|
||||
" if (isEmpty) return false\n"
|
||||
" for (b in bytes) {\n"
|
||||
" if (!((b >= 65 && b <= 90) || (b >= 97 && b <= 122) || (b >= 48 && b <= 57))) return false\n"
|
||||
" }\n"
|
||||
" return true\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" isSpace {\n"
|
||||
" if (isEmpty) return false\n"
|
||||
" for (b in bytes) {\n"
|
||||
" if (b != 32 && b != 9 && b != 10 && b != 13 && b != 12 && b != 11) return false\n"
|
||||
" }\n"
|
||||
" return true\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" isAscii {\n"
|
||||
" for (b in bytes) {\n"
|
||||
" if (b >= 128) return false\n"
|
||||
" }\n"
|
||||
" return true\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" reverse {\n"
|
||||
" var list = []\n"
|
||||
" for (c in this) {\n"
|
||||
" list.insert(0, c)\n"
|
||||
" }\n"
|
||||
" return list.join(\"\")\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" center(width) { center(width, \" \") }\n"
|
||||
"\n"
|
||||
" center(width, char) {\n"
|
||||
" if (!(width is Num) || !width.isInteger) {\n"
|
||||
" Fiber.abort(\"Width must be an integer.\")\n"
|
||||
" }\n"
|
||||
" if (!(char is String) || char.isEmpty) {\n"
|
||||
" Fiber.abort(\"Fill character must be a non-empty string.\")\n"
|
||||
" }\n"
|
||||
" var len = count\n"
|
||||
" if (len >= width) return this\n"
|
||||
" var total = width - len\n"
|
||||
" var left = (total / 2).floor\n"
|
||||
" var right = total - left\n"
|
||||
" return (char * (left + 1))[0...left] + this + (char * (right + 1))[0...right]\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" lpad(width, char) {\n"
|
||||
" if (!(width is Num) || !width.isInteger) {\n"
|
||||
" Fiber.abort(\"Width must be an integer.\")\n"
|
||||
" }\n"
|
||||
" if (!(char is String) || char.isEmpty) {\n"
|
||||
" Fiber.abort(\"Fill character must be a non-empty string.\")\n"
|
||||
" }\n"
|
||||
" var len = count\n"
|
||||
" if (len >= width) return this\n"
|
||||
" var pad = width - len\n"
|
||||
" return (char * (pad + 1))[0...pad] + this\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" rpad(width, char) {\n"
|
||||
" if (!(width is Num) || !width.isInteger) {\n"
|
||||
" Fiber.abort(\"Width must be an integer.\")\n"
|
||||
" }\n"
|
||||
" if (!(char is String) || char.isEmpty) {\n"
|
||||
" Fiber.abort(\"Fill character must be a non-empty string.\")\n"
|
||||
" }\n"
|
||||
" var len = count\n"
|
||||
" if (len >= width) return this\n"
|
||||
" var pad = width - len\n"
|
||||
" return this + (char * (pad + 1))[0...pad]\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" zfill(width) {\n"
|
||||
" if (!(width is Num) || !width.isInteger) {\n"
|
||||
" Fiber.abort(\"Width must be an integer.\")\n"
|
||||
" }\n"
|
||||
" var len = count\n"
|
||||
" if (len >= width) return this\n"
|
||||
" if (startsWith(\"-\") || startsWith(\"+\")) {\n"
|
||||
" return this[0] + (\"0\" * (width - len)) + this[1..-1]\n"
|
||||
" }\n"
|
||||
" return (\"0\" * (width - len)) + this\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" removePrefix(prefix) {\n"
|
||||
" if (!(prefix is String)) {\n"
|
||||
" Fiber.abort(\"Prefix must be a string.\")\n"
|
||||
" }\n"
|
||||
" if (startsWith(prefix)) return this[prefix.byteCount_..-1]\n"
|
||||
" return this\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" removeSuffix(suffix) {\n"
|
||||
" if (!(suffix is String)) {\n"
|
||||
" Fiber.abort(\"Suffix must be a string.\")\n"
|
||||
" }\n"
|
||||
" if (endsWith(suffix)) {\n"
|
||||
" var end = byteCount_ - suffix.byteCount_ - 1\n"
|
||||
" if (end < 0) return \"\"\n"
|
||||
" return this[0..end]\n"
|
||||
" }\n"
|
||||
" return this\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" splitLines { replace(\"\\r\\n\", \"\\n\").replace(\"\\r\", \"\\n\").split(\"\\n\") }\n"
|
||||
"\n"
|
||||
" chars {\n"
|
||||
" var result = []\n"
|
||||
" for (c in this) {\n"
|
||||
" result.add(c)\n"
|
||||
" }\n"
|
||||
" return result\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" toNum { Num.fromString(this) }\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"class StringByteSequence is Sequence {\n"
|
||||
@ -441,18 +722,18 @@ static const char* coreModuleSource =
|
||||
"\n"
|
||||
"class System {\n"
|
||||
" static print() {\n"
|
||||
" writeString_(\"\n\")\n"
|
||||
" writeString_(\"\\n\")\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" static print(obj) {\n"
|
||||
" writeObject_(obj)\n"
|
||||
" writeString_(\"\n\")\n"
|
||||
" writeString_(\"\\n\")\n"
|
||||
" return obj\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" static printAll(sequence) {\n"
|
||||
" for (object in sequence) writeObject_(object)\n"
|
||||
" writeString_(\"\n\")\n"
|
||||
" writeString_(\"\\n\")\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" static write(obj) {\n"
|
||||
@ -483,4 +764,3 @@ static const char* coreModuleSource =
|
||||
" }\n"
|
||||
" toString { \"attributes:%(_attributes) methods:%(_methods)\" }\n"
|
||||
"}\n";
|
||||
|
||||
|
||||
22
example/await_demo.wren
vendored
Normal file
22
example/await_demo.wren
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "scheduler" for Scheduler, Future
|
||||
import "timer" for Timer
|
||||
|
||||
System.print("=== Await Demo ===\n")
|
||||
|
||||
System.print("--- Basic Await ---")
|
||||
await Timer.sleep(1)
|
||||
System.print("Timer completed")
|
||||
|
||||
System.print("\n--- Concurrent Async ---")
|
||||
var task1 = async { Timer.sleep(1) }
|
||||
var task2 = async { Timer.sleep(1) }
|
||||
await task1
|
||||
await task2
|
||||
System.print("Both tasks completed concurrently")
|
||||
|
||||
System.print("\n--- Async With Result ---")
|
||||
var task = async { "computed value" }
|
||||
var result = await task
|
||||
System.print("Result: %(result)")
|
||||
67
example/jinja_markdown.wren
vendored
Normal file
67
example/jinja_markdown.wren
vendored
Normal file
@ -0,0 +1,67 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "jinja" for Environment, DictLoader
|
||||
|
||||
System.print("=" * 60)
|
||||
System.print("JINJA MARKDOWN - Markdown/HTML Conversion in Templates")
|
||||
System.print("=" * 60)
|
||||
|
||||
var templates = {
|
||||
"md_to_html": "{\% markdowntohtml \%}# {{ title }}
|
||||
|
||||
{{ description }}
|
||||
|
||||
- Item **one**
|
||||
- Item **two**
|
||||
- Item **three**
|
||||
{\% endmarkdowntohtml \%}",
|
||||
|
||||
"html_to_md": "{\% markdownfromhtml \%}<h1>{{ title }}</h1>
|
||||
<p>This is a <strong>paragraph</strong> with <em>formatting</em>.</p>
|
||||
<ul>
|
||||
<li>First</li>
|
||||
<li>Second</li>
|
||||
</ul>{\% endmarkdownfromhtml \%}",
|
||||
|
||||
"filter_md": "{{ content|markdown }}",
|
||||
|
||||
"filter_fromhtml": "{{ content|markdownfromhtml }}",
|
||||
|
||||
"mixed": "<div class=\"article\">
|
||||
{\% markdowntohtml \%}## {{ article.title }}
|
||||
|
||||
{{ article.body }}
|
||||
{\% endmarkdowntohtml \%}
|
||||
</div>"
|
||||
}
|
||||
|
||||
var env = Environment.new(DictLoader.new(templates))
|
||||
|
||||
System.print("\n--- Markdown to HTML (block tag) ---")
|
||||
System.print(env.getTemplate("md_to_html").render({
|
||||
"title": "Welcome",
|
||||
"description": "This is a *template* with markdown support."
|
||||
}))
|
||||
|
||||
System.print("\n--- HTML to Markdown (block tag) ---")
|
||||
System.print(env.getTemplate("html_to_md").render({
|
||||
"title": "Documentation"
|
||||
}))
|
||||
|
||||
System.print("\n--- Markdown filter ---")
|
||||
System.print(env.getTemplate("filter_md").render({
|
||||
"content": "**Bold** and *italic* text."
|
||||
}))
|
||||
|
||||
System.print("\n--- Markdown from HTML filter ---")
|
||||
System.print(env.getTemplate("filter_fromhtml").render({
|
||||
"content": "<h2>Section</h2><p>A paragraph.</p>"
|
||||
}))
|
||||
|
||||
System.print("\n--- Mixed HTML and Markdown ---")
|
||||
System.print(env.getTemplate("mixed").render({
|
||||
"article": {
|
||||
"title": "Getting Started",
|
||||
"body": "Read the **documentation** for details."
|
||||
}
|
||||
}))
|
||||
51
example/number_demo.wren
vendored
Normal file
51
example/number_demo.wren
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
System.print("=== Num Extensions Demo ===\n")
|
||||
|
||||
System.print("--- Constants ---")
|
||||
System.print("Num.pi: %(Num.pi)")
|
||||
System.print("Num.tau: %(Num.tau)")
|
||||
System.print("Num.e: %(Num.e)")
|
||||
|
||||
System.print("\n--- Query Methods ---")
|
||||
System.print("0.isZero: %(0.isZero)")
|
||||
System.print("5.isPositive: %(5.isPositive)")
|
||||
System.print("(-3).isNegative: %((-3).isNegative)")
|
||||
System.print("42.isFinite: %(42.isFinite)")
|
||||
System.print("(1/0).isFinite: %((1/0).isFinite)")
|
||||
System.print("4.isEven: %(4.isEven)")
|
||||
System.print("3.isOdd: %(3.isOdd)")
|
||||
System.print("5.isBetween(1, 10): %(5.isBetween(1, 10))")
|
||||
|
||||
System.print("\n--- Math Functions ---")
|
||||
System.print("100.log10: %(100.log10)")
|
||||
System.print("0.sinh: %(0.sinh)")
|
||||
System.print("0.cosh: %(0.cosh)")
|
||||
System.print("0.tanh: %(0.tanh)")
|
||||
|
||||
System.print("\n--- Angle Conversion ---")
|
||||
var pi = Num.pi
|
||||
System.print("pi.toDegrees: %(pi.toDegrees)")
|
||||
System.print("180.toRadians: %(180.toRadians)")
|
||||
|
||||
System.print("\n--- Base Conversion ---")
|
||||
System.print("255.toHex: %(255.toHex)")
|
||||
System.print("10.toBinary: %(10.toBinary)")
|
||||
System.print("8.toOctal: %(8.toOctal)")
|
||||
System.print("255.toBase(16): %(255.toBase(16))")
|
||||
System.print("100.toBase(36): %(100.toBase(36))")
|
||||
|
||||
System.print("\n--- Character Conversion ---")
|
||||
System.print("65.toChar: %(65.toChar)")
|
||||
System.print("97.toChar: %(97.toChar)")
|
||||
|
||||
System.print("\n--- Formatting ---")
|
||||
System.print("3.14159.format(2): %(3.14159.format(2))")
|
||||
System.print("42.format(3): %(42.format(3))")
|
||||
System.print("(-1.5).format(1): %((-1.5).format(1))")
|
||||
|
||||
System.print("\n--- Integer Operations ---")
|
||||
System.print("12.gcd(8): %(12.gcd(8))")
|
||||
System.print("4.lcm(6): %(4.lcm(6))")
|
||||
System.print("123.digits: %(123.digits)")
|
||||
System.print("0.digits: %(0.digits)")
|
||||
167
example/pathlib_demo.wren
vendored
Normal file
167
example/pathlib_demo.wren
vendored
Normal file
@ -0,0 +1,167 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "pathlib" for Path
|
||||
|
||||
System.print("=== Pathlib Module Demo ===\n")
|
||||
|
||||
System.print("--- Path Construction ---")
|
||||
var p = Path.new("/home/user/documents/report.tar.gz")
|
||||
System.print("Path: %(p)")
|
||||
System.print("Name: %(p.name)")
|
||||
System.print("Stem: %(p.stem)")
|
||||
System.print("Suffix: %(p.suffix)")
|
||||
System.print("Suffixes: %(p.suffixes)")
|
||||
System.print("Parts: %(p.parts)")
|
||||
|
||||
System.print("\n--- Parent Navigation ---")
|
||||
System.print("Parent: %(p.parent)")
|
||||
System.print("Parents:")
|
||||
for (ancestor in p.parents) {
|
||||
System.print(" %(ancestor)")
|
||||
}
|
||||
|
||||
System.print("\n--- Path Properties ---")
|
||||
System.print("Root: %(p.root)")
|
||||
System.print("Anchor: %(p.anchor)")
|
||||
System.print("Is absolute: %(p.isAbsolute)")
|
||||
var rel = Path.new("relative/path.txt")
|
||||
System.print("%(rel) is absolute: %(rel.isAbsolute)")
|
||||
|
||||
System.print("\n--- Join Operator (/) ---")
|
||||
var base = Path.new("/home/user")
|
||||
var config = base / ".config" / "myapp" / "settings.json"
|
||||
System.print("%(base) / .config / myapp / settings.json = %(config)")
|
||||
|
||||
System.print("\n--- joinpath ---")
|
||||
var multi = Path.new("/opt").joinpath(["local", "bin", "wren_cli"])
|
||||
System.print("Joined: %(multi)")
|
||||
|
||||
System.print("\n--- withName / withStem / withSuffix ---")
|
||||
var orig = Path.new("/data/archive.tar.gz")
|
||||
System.print("Original: %(orig)")
|
||||
System.print("withName(\"backup.zip\"): %(orig.withName("backup.zip"))")
|
||||
System.print("withStem(\"snapshot\"): %(orig.withStem("snapshot"))")
|
||||
System.print("withSuffix(\".bak\"): %(orig.withSuffix(".bak"))")
|
||||
|
||||
System.print("\n--- relativeTo ---")
|
||||
var full = Path.new("/home/user/projects/wren/src/main.c")
|
||||
var project = Path.new("/home/user/projects/wren")
|
||||
System.print("%(full) relative to %(project) = %(full.relativeTo(project))")
|
||||
|
||||
System.print("\n--- Glob Matching ---")
|
||||
var file = Path.new("/tmp/notes.txt")
|
||||
System.print("%(file.name) matches *.txt: %(file.match("*.txt"))")
|
||||
System.print("%(file.name) matches *.md: %(file.match("*.md"))")
|
||||
System.print("%(file.name) matches note?: %(file.match("note?"))")
|
||||
System.print("%(file.name) matches n*s.txt: %(file.match("n*s.txt"))")
|
||||
|
||||
System.print("\n--- Home and CWD ---")
|
||||
System.print("Home: %(Path.home)")
|
||||
System.print("CWD: %(Path.cwd)")
|
||||
|
||||
System.print("\n--- Expand User ---")
|
||||
var tilde = Path.new("~/.bashrc")
|
||||
System.print("%(tilde) -> %(tilde.expanduser())")
|
||||
|
||||
System.print("\n--- Equality ---")
|
||||
var a = Path.new("/tmp/test")
|
||||
var b = Path.new("/tmp/test")
|
||||
var c = Path.new("/tmp/other")
|
||||
System.print("%(a) == %(b): %(a == b)")
|
||||
System.print("%(a) == %(c): %(a == c)")
|
||||
System.print("%(a) != %(c): %(a != c)")
|
||||
|
||||
System.print("\n--- Filesystem Operations ---")
|
||||
var testDir = Path.new("/tmp/wren_pathlib_demo")
|
||||
if (testDir.exists()) testDir.rmtree()
|
||||
|
||||
testDir.mkdir(true)
|
||||
System.print("Created: %(testDir)")
|
||||
System.print("Exists: %(testDir.exists())")
|
||||
System.print("Is dir: %(testDir.isDir())")
|
||||
|
||||
var testFile = testDir / "hello.txt"
|
||||
testFile.writeText("Hello from pathlib!")
|
||||
System.print("Wrote: %(testFile)")
|
||||
System.print("Content: %(testFile.readText())")
|
||||
System.print("Is file: %(testFile.isFile())")
|
||||
|
||||
System.print("\n--- Stat ---")
|
||||
var s = testFile.stat()
|
||||
System.print("Size: %(s.size) bytes")
|
||||
|
||||
System.print("\n--- Touch ---")
|
||||
var marker = testDir / "marker"
|
||||
marker.touch()
|
||||
System.print("Touched: %(marker) (exists: %(marker.exists()))")
|
||||
|
||||
System.print("\n--- Copy ---")
|
||||
var copy = testDir / "hello_copy.txt"
|
||||
testFile.copyfile(copy)
|
||||
System.print("Copied to: %(copy)")
|
||||
System.print("Copy content: %(copy.readText())")
|
||||
|
||||
System.print("\n--- Rename ---")
|
||||
var renamed = testFile.rename(testDir / "greeting.txt")
|
||||
System.print("Renamed to: %(renamed)")
|
||||
System.print("Old exists: %(testFile.exists())")
|
||||
System.print("New content: %(renamed.readText())")
|
||||
|
||||
System.print("\n--- Resolve ---")
|
||||
var resolved = Path.new(".").resolve()
|
||||
System.print("Resolved '.': %(resolved)")
|
||||
|
||||
System.print("\n--- Same File ---")
|
||||
System.print("Same file: %(renamed.samefile(renamed))")
|
||||
|
||||
System.print("\n--- Owner and Group ---")
|
||||
System.print("Owner: %(renamed.owner())")
|
||||
System.print("Group: %(renamed.group())")
|
||||
|
||||
System.print("\n--- Mkdir with Parents ---")
|
||||
var deep = testDir / "a" / "b" / "c"
|
||||
deep.mkdir(true)
|
||||
System.print("Created: %(deep)")
|
||||
System.print("Exists: %(deep.exists())")
|
||||
|
||||
System.print("\n--- Iterdir ---")
|
||||
(testDir / "file1.txt").writeText("one")
|
||||
(testDir / "file2.txt").writeText("two")
|
||||
var entries = testDir.iterdir()
|
||||
System.print("Entries in %(testDir.name):")
|
||||
for (entry in entries) {
|
||||
var kind = entry.isDir() ? "dir" : "file"
|
||||
System.print(" %(entry.name) (%(kind))")
|
||||
}
|
||||
|
||||
System.print("\n--- Glob ---")
|
||||
var txtFiles = testDir.glob("*.txt")
|
||||
System.print("Text files in %(testDir.name):")
|
||||
for (f in txtFiles) {
|
||||
System.print(" %(f.name)")
|
||||
}
|
||||
|
||||
System.print("\n--- Recursive Glob ---")
|
||||
(testDir / "a" / "nested.txt").writeText("nested")
|
||||
(testDir / "a" / "b" / "deep.txt").writeText("deep")
|
||||
var allTxt = testDir.rglob("*.txt")
|
||||
System.print("All text files (recursive):")
|
||||
for (f in allTxt) {
|
||||
System.print(" %(f.relativeTo(testDir))")
|
||||
}
|
||||
|
||||
System.print("\n--- Walk ---")
|
||||
System.print("Directory tree:")
|
||||
for (entry in testDir.walk()) {
|
||||
var dir = entry[0]
|
||||
var dirs = entry[1]
|
||||
var files = entry[2]
|
||||
var indent = dir == testDir ? "" : " "
|
||||
System.print("%(indent)%(dir.relativeTo(testDir))/ (%(dirs.count) dirs, %(files.count) files)")
|
||||
}
|
||||
|
||||
System.print("\n--- Cleanup ---")
|
||||
testDir.rmtree()
|
||||
System.print("Cleaned up: %(testDir) (exists: %(testDir.exists()))")
|
||||
|
||||
System.print("\n=== Demo Complete ===")
|
||||
63
example/string_demo.wren
vendored
Normal file
63
example/string_demo.wren
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
System.print("=== String Methods Demo ===\n")
|
||||
|
||||
System.print("--- Case Conversion ---")
|
||||
var text = "Hello World"
|
||||
System.print("Original: %(text)")
|
||||
System.print("lower: %(text.lower)")
|
||||
System.print("upper: %(text.upper)")
|
||||
System.print("capitalize: %("hello world".capitalize)")
|
||||
System.print("title: %("hello world".title)")
|
||||
System.print("swapCase: %(text.swapCase)")
|
||||
|
||||
System.print("\n--- Character Testing ---")
|
||||
System.print("\"hello\".isLower: %("hello".isLower)")
|
||||
System.print("\"HELLO\".isUpper: %("HELLO".isUpper)")
|
||||
System.print("\"12345\".isDigit: %("12345".isDigit)")
|
||||
System.print("\"hello\".isAlpha: %("hello".isAlpha)")
|
||||
System.print("\"hello1\".isAlphaNumeric: %("hello1".isAlphaNumeric)")
|
||||
System.print("\" \".isSpace: %(" ".isSpace)")
|
||||
System.print("\"hello\".isAscii: %("hello".isAscii)")
|
||||
|
||||
System.print("\n--- Search ---")
|
||||
var sentence = "hello world hello"
|
||||
System.print("Text: %(sentence)")
|
||||
System.print("lastIndexOf(\"hello\"): %(sentence.lastIndexOf("hello"))")
|
||||
System.print("lastIndexOf(\"hello\", 11): %(sentence.lastIndexOf("hello", 11))")
|
||||
|
||||
System.print("\n--- Transformation ---")
|
||||
System.print("\"hello\".reverse: %("hello".reverse)")
|
||||
System.print("\"hi\".center(10, \"-\"): %("hi".center(10, "-"))")
|
||||
System.print("\"42\".lpad(5, \"0\"): %("42".lpad(5, "0"))")
|
||||
System.print("\"hi\".rpad(5, \".\"): %("hi".rpad(5, "."))")
|
||||
System.print("\"42\".zfill(5): %("42".zfill(5))")
|
||||
System.print("\"-42\".zfill(6): %("-42".zfill(6))")
|
||||
|
||||
System.print("\n--- Prefix/Suffix ---")
|
||||
System.print("removePrefix(\"Hello\"): %("HelloWorld".removePrefix("Hello"))")
|
||||
System.print("removeSuffix(\"World\"): %("HelloWorld".removeSuffix("World"))")
|
||||
|
||||
System.print("\n--- Comparison ---")
|
||||
System.print("\"apple\" < \"banana\": %("apple" < "banana")")
|
||||
System.print("\"banana\" > \"apple\": %("banana" > "apple")")
|
||||
System.print("\"abc\" <= \"abc\": %("abc" <= "abc")")
|
||||
System.print("\"abc\" >= \"abc\": %("abc" >= "abc")")
|
||||
System.print("\"abc\" < \"abcd\": %("abc" < "abcd")")
|
||||
System.print("\"abcd\" > \"abc\": %("abcd" > "abc")")
|
||||
System.print("\"Z\" < \"a\": %("Z" < "a")")
|
||||
|
||||
var fruits = ["cherry", "apple", "banana"]
|
||||
System.print("Sorted: %(fruits.sort {|a, b| a < b})")
|
||||
|
||||
System.print("\n--- Splitting ---")
|
||||
var lines = "line1\nline2\nline3".splitLines
|
||||
System.print("splitLines: %(lines)")
|
||||
|
||||
var chars = "abc".chars
|
||||
System.print("chars: %(chars)")
|
||||
|
||||
System.print("\n--- Conversion ---")
|
||||
System.print("\"42\".toNum: %("42".toNum)")
|
||||
System.print("\"3.14\".toNum: %("3.14".toNum)")
|
||||
System.print("\"abc\".toNum: %("abc".toNum)")
|
||||
60
example/tempfile_demo.wren
vendored
Normal file
60
example/tempfile_demo.wren
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "tempfile" for TempFile, NamedTemporaryFile, TemporaryDirectory
|
||||
import "pathlib" for Path
|
||||
|
||||
System.print("=== TempFile Module Demo ===\n")
|
||||
|
||||
System.print("--- Utility Functions ---")
|
||||
System.print("Temp directory: %(TempFile.gettempdir())")
|
||||
System.print("Temp prefix: %(TempFile.gettempprefix())")
|
||||
|
||||
System.print("\n--- mktemp (name only, no file created) ---")
|
||||
var name = TempFile.mktemp(".txt", "demo_")
|
||||
System.print("Generated name: %(name)")
|
||||
System.print("File exists: %(Path.new(name).exists())")
|
||||
|
||||
System.print("\n--- mkstemp (creates file atomically) ---")
|
||||
var path = TempFile.mkstemp(".dat", "demo_")
|
||||
System.print("Created file: %(path)")
|
||||
System.print("File exists: %(Path.new(path).exists())")
|
||||
Path.new(path).unlink()
|
||||
|
||||
System.print("\n--- mkdtemp (creates directory) ---")
|
||||
var dir = TempFile.mkdtemp("_work", "demo_")
|
||||
System.print("Created directory: %(dir)")
|
||||
System.print("Is directory: %(Path.new(dir).isDir())")
|
||||
Path.new(dir).rmdir()
|
||||
|
||||
System.print("\n--- NamedTemporaryFile ---")
|
||||
var tmp = NamedTemporaryFile.new(".txt", "demo_")
|
||||
System.print("Temp file: %(tmp.name)")
|
||||
tmp.write("Hello from tempfile module!")
|
||||
System.print("Content: %(tmp.read())")
|
||||
System.print("Auto-delete: %(tmp.delete)")
|
||||
tmp.close()
|
||||
System.print("Deleted after close: %(!(Path.new(tmp.name).exists()))")
|
||||
|
||||
System.print("\n--- NamedTemporaryFile.use (context manager) ---")
|
||||
NamedTemporaryFile.new(".log").use {|f|
|
||||
f.write("Log entry: operation completed")
|
||||
System.print("Inside use block: %(f.read())")
|
||||
}
|
||||
System.print("Automatically cleaned up after use block")
|
||||
|
||||
System.print("\n--- TemporaryDirectory ---")
|
||||
var tmpDir = TemporaryDirectory.new("_session", "demo_")
|
||||
System.print("Temp dir: %(tmpDir.name)")
|
||||
System.print("Is directory: %(tmpDir.path.isDir())")
|
||||
tmpDir.cleanup()
|
||||
System.print("Deleted after cleanup: %(!(Path.new(tmpDir.name).exists()))")
|
||||
|
||||
System.print("\n--- TemporaryDirectory.use (context manager) ---")
|
||||
TemporaryDirectory.new().use {|d|
|
||||
System.print("Working in: %(d.name)")
|
||||
Path.new(d.name + "/data.txt").writeText("temporary data")
|
||||
System.print("Created file inside temp dir")
|
||||
}
|
||||
System.print("Automatically cleaned up with all contents")
|
||||
|
||||
System.print("\n=== Done ===")
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="string.html">String</a></li>
|
||||
<li><a href="number.html">Num</a></li>
|
||||
<li><a href="http.html">http</a></li>
|
||||
<li><a href="websocket.html">websocket</a></li>
|
||||
<li><a href="tls.html">tls</a></li>
|
||||
@ -58,6 +60,7 @@
|
||||
<li><a href="datetime.html">datetime</a></li>
|
||||
<li><a href="timer.html">timer</a></li>
|
||||
<li><a href="io.html">io</a></li>
|
||||
<li><a href="pathlib.html">pathlib</a></li>
|
||||
<li><a href="scheduler.html">scheduler</a></li>
|
||||
<li><a href="math.html">math</a></li>
|
||||
<li><a href="uuid.html">uuid</a></li>
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="string.html">String</a></li>
|
||||
<li><a href="number.html">Num</a></li>
|
||||
<li><a href="http.html">http</a></li>
|
||||
<li><a href="websocket.html">websocket</a></li>
|
||||
<li><a href="tls.html">tls</a></li>
|
||||
@ -58,6 +60,7 @@
|
||||
<li><a href="datetime.html">datetime</a></li>
|
||||
<li><a href="timer.html">timer</a></li>
|
||||
<li><a href="io.html">io</a></li>
|
||||
<li><a href="pathlib.html">pathlib</a></li>
|
||||
<li><a href="scheduler.html">scheduler</a></li>
|
||||
<li><a href="math.html">math</a></li>
|
||||
</ul>
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="string.html">String</a></li>
|
||||
<li><a href="number.html">Num</a></li>
|
||||
<li><a href="http.html">http</a></li>
|
||||
<li><a href="websocket.html">websocket</a></li>
|
||||
<li><a href="tls.html">tls</a></li>
|
||||
@ -58,6 +60,7 @@
|
||||
<li><a href="datetime.html">datetime</a></li>
|
||||
<li><a href="timer.html">timer</a></li>
|
||||
<li><a href="io.html">io</a></li>
|
||||
<li><a href="pathlib.html">pathlib</a></li>
|
||||
<li><a href="scheduler.html">scheduler</a></li>
|
||||
<li><a href="math.html">math</a></li>
|
||||
</ul>
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="string.html">String</a></li>
|
||||
<li><a href="number.html">Num</a></li>
|
||||
<li><a href="http.html">http</a></li>
|
||||
<li><a href="websocket.html">websocket</a></li>
|
||||
<li><a href="tls.html">tls</a></li>
|
||||
@ -58,6 +60,7 @@
|
||||
<li><a href="datetime.html">datetime</a></li>
|
||||
<li><a href="timer.html">timer</a></li>
|
||||
<li><a href="io.html">io</a></li>
|
||||
<li><a href="pathlib.html">pathlib</a></li>
|
||||
<li><a href="scheduler.html">scheduler</a></li>
|
||||
<li><a href="math.html">math</a></li>
|
||||
<li><a href="uuid.html">uuid</a></li>
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="string.html">String</a></li>
|
||||
<li><a href="number.html">Num</a></li>
|
||||
<li><a href="http.html">http</a></li>
|
||||
<li><a href="websocket.html">websocket</a></li>
|
||||
<li><a href="tls.html">tls</a></li>
|
||||
@ -58,6 +60,7 @@
|
||||
<li><a href="datetime.html" class="active">datetime</a></li>
|
||||
<li><a href="timer.html">timer</a></li>
|
||||
<li><a href="io.html">io</a></li>
|
||||
<li><a href="pathlib.html">pathlib</a></li>
|
||||
<li><a href="scheduler.html">scheduler</a></li>
|
||||
<li><a href="math.html">math</a></li>
|
||||
</ul>
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="string.html">String</a></li>
|
||||
<li><a href="number.html">Num</a></li>
|
||||
<li><a href="http.html">http</a></li>
|
||||
<li><a href="websocket.html">websocket</a></li>
|
||||
<li><a href="tls.html">tls</a></li>
|
||||
@ -58,6 +60,7 @@
|
||||
<li><a href="datetime.html">datetime</a></li>
|
||||
<li><a href="timer.html">timer</a></li>
|
||||
<li><a href="io.html">io</a></li>
|
||||
<li><a href="pathlib.html">pathlib</a></li>
|
||||
<li><a href="scheduler.html">scheduler</a></li>
|
||||
<li><a href="math.html">math</a></li>
|
||||
</ul>
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="string.html">String</a></li>
|
||||
<li><a href="number.html">Num</a></li>
|
||||
<li><a href="http.html">http</a></li>
|
||||
<li><a href="websocket.html">websocket</a></li>
|
||||
<li><a href="tls.html">tls</a></li>
|
||||
@ -58,6 +60,7 @@
|
||||
<li><a href="datetime.html">datetime</a></li>
|
||||
<li><a href="timer.html">timer</a></li>
|
||||
<li><a href="io.html">io</a></li>
|
||||
<li><a href="pathlib.html">pathlib</a></li>
|
||||
<li><a href="scheduler.html">scheduler</a></li>
|
||||
<li><a href="math.html">math</a></li>
|
||||
</ul>
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="string.html">String</a></li>
|
||||
<li><a href="number.html">Num</a></li>
|
||||
<li><a href="http.html">http</a></li>
|
||||
<li><a href="websocket.html">websocket</a></li>
|
||||
<li><a href="tls.html">tls</a></li>
|
||||
@ -58,6 +60,7 @@
|
||||
<li><a href="datetime.html">datetime</a></li>
|
||||
<li><a href="timer.html">timer</a></li>
|
||||
<li><a href="io.html">io</a></li>
|
||||
<li><a href="pathlib.html">pathlib</a></li>
|
||||
<li><a href="scheduler.html">scheduler</a></li>
|
||||
<li><a href="math.html">math</a></li>
|
||||
<li><a href="uuid.html">uuid</a></li>
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="string.html">String</a></li>
|
||||
<li><a href="number.html">Num</a></li>
|
||||
<li><a href="http.html" class="active">http</a></li>
|
||||
<li><a href="websocket.html">websocket</a></li>
|
||||
<li><a href="tls.html">tls</a></li>
|
||||
@ -58,6 +60,7 @@
|
||||
<li><a href="datetime.html">datetime</a></li>
|
||||
<li><a href="timer.html">timer</a></li>
|
||||
<li><a href="io.html">io</a></li>
|
||||
<li><a href="pathlib.html">pathlib</a></li>
|
||||
<li><a href="scheduler.html">scheduler</a></li>
|
||||
<li><a href="math.html">math</a></li>
|
||||
</ul>
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="index.html" class="active">Overview</a></li>
|
||||
<li><a href="string.html">String</a></li>
|
||||
<li><a href="number.html">Num</a></li>
|
||||
<li><a href="http.html">http</a></li>
|
||||
<li><a href="websocket.html">websocket</a></li>
|
||||
<li><a href="tls.html">tls</a></li>
|
||||
@ -58,6 +60,7 @@
|
||||
<li><a href="datetime.html">datetime</a></li>
|
||||
<li><a href="timer.html">timer</a></li>
|
||||
<li><a href="io.html">io</a></li>
|
||||
<li><a href="pathlib.html">pathlib</a></li>
|
||||
<li><a href="scheduler.html">scheduler</a></li>
|
||||
<li><a href="math.html">math</a></li>
|
||||
<li><a href="uuid.html">uuid</a></li>
|
||||
@ -104,12 +107,26 @@
|
||||
<article>
|
||||
<h1>API Reference</h1>
|
||||
|
||||
<p>Wren-CLI provides 28 built-in modules covering networking, file I/O, data processing, system operations, and more. All modules are imported using the <code>import</code> statement.</p>
|
||||
<p>Wren-CLI provides 29 built-in modules covering networking, file I/O, data processing, system operations, and more. All modules are imported using the <code>import</code> statement.</p>
|
||||
|
||||
<pre><code>import "http" for Http
|
||||
import "json" for Json
|
||||
import "io" for File</code></pre>
|
||||
|
||||
<h2>Core Types</h2>
|
||||
<p>Extended methods on built-in types, available without imports.</p>
|
||||
|
||||
<div class="card-grid">
|
||||
<div class="card">
|
||||
<h3><a href="string.html">String</a></h3>
|
||||
<p>Case conversion, character testing, padding, splitting, reversing, and more on all strings.</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3><a href="number.html">Num</a></h3>
|
||||
<p>Query predicates, hyperbolic functions, base conversion, formatting, GCD/LCM, and more on all numbers.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2>Networking</h2>
|
||||
<p>Modules for HTTP, WebSocket, and low-level network operations.</p>
|
||||
|
||||
@ -198,6 +215,10 @@ import "io" for File</code></pre>
|
||||
<h3><a href="io.html">io</a></h3>
|
||||
<p>File and directory operations, stdin/stdout handling.</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h3><a href="pathlib.html">pathlib</a></h3>
|
||||
<p>Object-oriented filesystem paths with glob, walk, and tree operations.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2>Data & Time</h2>
|
||||
@ -345,6 +366,11 @@ import "io" for File</code></pre>
|
||||
<td>File, Directory, Stdin, Stdout</td>
|
||||
<td>File I/O</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="pathlib.html">pathlib</a></td>
|
||||
<td>Path, PurePath</td>
|
||||
<td>Filesystem paths</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="scheduler.html">scheduler</a></td>
|
||||
<td>Scheduler</td>
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="string.html">String</a></li>
|
||||
<li><a href="number.html">Num</a></li>
|
||||
<li><a href="http.html">http</a></li>
|
||||
<li><a href="websocket.html">websocket</a></li>
|
||||
<li><a href="tls.html">tls</a></li>
|
||||
@ -58,6 +60,7 @@
|
||||
<li><a href="datetime.html">datetime</a></li>
|
||||
<li><a href="timer.html">timer</a></li>
|
||||
<li><a href="io.html" class="active">io</a></li>
|
||||
<li><a href="pathlib.html">pathlib</a></li>
|
||||
<li><a href="scheduler.html">scheduler</a></li>
|
||||
<li><a href="math.html">math</a></li>
|
||||
</ul>
|
||||
@ -274,7 +277,7 @@ backup.call("important.txt")</code></pre>
|
||||
|
||||
<footer class="page-footer">
|
||||
<a href="timer.html" class="prev">timer</a>
|
||||
<a href="scheduler.html" class="next">scheduler</a>
|
||||
<a href="pathlib.html" class="next">pathlib</a>
|
||||
</footer>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="string.html">String</a></li>
|
||||
<li><a href="number.html">Num</a></li>
|
||||
<li><a href="http.html">http</a></li>
|
||||
<li><a href="websocket.html">websocket</a></li>
|
||||
<li><a href="tls.html">tls</a></li>
|
||||
@ -58,6 +60,7 @@
|
||||
<li><a href="datetime.html">datetime</a></li>
|
||||
<li><a href="timer.html">timer</a></li>
|
||||
<li><a href="io.html">io</a></li>
|
||||
<li><a href="pathlib.html">pathlib</a></li>
|
||||
<li><a href="scheduler.html">scheduler</a></li>
|
||||
<li><a href="math.html">math</a></li>
|
||||
</ul>
|
||||
@ -119,6 +122,7 @@
|
||||
<li><a href="#tests">Tests</a></li>
|
||||
<li><a href="#macros">Macros</a></li>
|
||||
<li><a href="#template-inheritance">Template Inheritance</a></li>
|
||||
<li><a href="#markdown-tags">Markdown Tags</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#filters-reference">Filters Reference</a></li>
|
||||
@ -357,6 +361,34 @@ var template = env.getTemplate("page.html") // Loads ./templates/page.html</cod
|
||||
This long text will be truncated to 50 characters...
|
||||
{% endfilter %}</code></pre>
|
||||
|
||||
<h3 id="markdown-tags">Markdown Tags</h3>
|
||||
|
||||
<p>Convert between Markdown and HTML within templates using block tags:</p>
|
||||
|
||||
<h4>markdowntohtml</h4>
|
||||
<p>Converts Markdown content to HTML:</p>
|
||||
<pre><code>{% markdowntohtml %}
|
||||
# Heading
|
||||
This is **bold** text.
|
||||
{% endmarkdowntohtml %}</code></pre>
|
||||
|
||||
<p>Variables are resolved before conversion:</p>
|
||||
<pre><code>{% markdowntohtml %}
|
||||
# {{ title }}
|
||||
{{ description }}
|
||||
{% endmarkdowntohtml %}</code></pre>
|
||||
|
||||
<h4>markdownfromhtml</h4>
|
||||
<p>Converts HTML content back to Markdown:</p>
|
||||
<pre><code>{% markdownfromhtml %}
|
||||
<h1>Heading</h1>
|
||||
<p>This is <strong>bold</strong> text.</p>
|
||||
{% endmarkdownfromhtml %}</code></pre>
|
||||
|
||||
<p>Corresponding filters are also available for inline use:</p>
|
||||
<pre><code>{{ markdown_text|markdown }}
|
||||
{{ html_content|markdownfromhtml }}</code></pre>
|
||||
|
||||
<h3 id="comments">Comments</h3>
|
||||
|
||||
<p>Comments are not included in the output:</p>
|
||||
@ -527,6 +559,16 @@ var template = env.getTemplate("page.html") // Loads ./templates/page.html</cod
|
||||
<td>URL-encode string</td>
|
||||
<td><code>{{ "hello world"|urlencode }}</code> → hello+world</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>markdown</code></td>
|
||||
<td>Convert Markdown to HTML</td>
|
||||
<td><code>{{ md_text|markdown }}</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>markdownfromhtml</code></td>
|
||||
<td>Convert HTML to Markdown</td>
|
||||
<td><code>{{ html_content|markdownfromhtml }}</code></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3>List/Collection Filters</h3>
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="string.html">String</a></li>
|
||||
<li><a href="number.html">Num</a></li>
|
||||
<li><a href="http.html">http</a></li>
|
||||
<li><a href="websocket.html">websocket</a></li>
|
||||
<li><a href="tls.html">tls</a></li>
|
||||
@ -58,6 +60,7 @@
|
||||
<li><a href="datetime.html">datetime</a></li>
|
||||
<li><a href="timer.html">timer</a></li>
|
||||
<li><a href="io.html">io</a></li>
|
||||
<li><a href="pathlib.html">pathlib</a></li>
|
||||
<li><a href="scheduler.html">scheduler</a></li>
|
||||
<li><a href="math.html">math</a></li>
|
||||
</ul>
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="string.html">String</a></li>
|
||||
<li><a href="number.html">Num</a></li>
|
||||
<li><a href="http.html">http</a></li>
|
||||
<li><a href="websocket.html">websocket</a></li>
|
||||
<li><a href="tls.html">tls</a></li>
|
||||
@ -58,6 +60,7 @@
|
||||
<li><a href="datetime.html">datetime</a></li>
|
||||
<li><a href="timer.html">timer</a></li>
|
||||
<li><a href="io.html">io</a></li>
|
||||
<li><a href="pathlib.html">pathlib</a></li>
|
||||
<li><a href="scheduler.html">scheduler</a></li>
|
||||
<li><a href="math.html">math</a></li>
|
||||
<li><a href="uuid.html">uuid</a></li>
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="string.html">String</a></li>
|
||||
<li><a href="number.html">Num</a></li>
|
||||
<li><a href="http.html">http</a></li>
|
||||
<li><a href="websocket.html">websocket</a></li>
|
||||
<li><a href="tls.html">tls</a></li>
|
||||
@ -58,6 +60,7 @@
|
||||
<li><a href="datetime.html">datetime</a></li>
|
||||
<li><a href="timer.html">timer</a></li>
|
||||
<li><a href="io.html">io</a></li>
|
||||
<li><a href="pathlib.html">pathlib</a></li>
|
||||
<li><a href="scheduler.html">scheduler</a></li>
|
||||
<li><a href="math.html" class="active">math</a></li>
|
||||
</ul>
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="string.html">String</a></li>
|
||||
<li><a href="number.html">Num</a></li>
|
||||
<li><a href="http.html">http</a></li>
|
||||
<li><a href="websocket.html">websocket</a></li>
|
||||
<li><a href="tls.html">tls</a></li>
|
||||
@ -58,6 +60,7 @@
|
||||
<li><a href="datetime.html">datetime</a></li>
|
||||
<li><a href="timer.html">timer</a></li>
|
||||
<li><a href="io.html">io</a></li>
|
||||
<li><a href="pathlib.html">pathlib</a></li>
|
||||
<li><a href="scheduler.html">scheduler</a></li>
|
||||
<li><a href="math.html">math</a></li>
|
||||
</ul>
|
||||
|
||||
493
manual/api/number.html
Normal file
493
manual/api/number.html
Normal file
@ -0,0 +1,493 @@
|
||||
<!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>Num - 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="index.html">Overview</a></li>
|
||||
<li><a href="string.html">String</a></li>
|
||||
<li><a href="number.html" class="active">Num</a></li>
|
||||
<li><a href="http.html">http</a></li>
|
||||
<li><a href="websocket.html">websocket</a></li>
|
||||
<li><a href="tls.html">tls</a></li>
|
||||
<li><a href="net.html">net</a></li>
|
||||
<li><a href="dns.html">dns</a></li>
|
||||
<li><a href="json.html">json</a></li>
|
||||
<li><a href="base64.html">base64</a></li>
|
||||
<li><a href="regex.html">regex</a></li>
|
||||
<li><a href="jinja.html">jinja</a></li>
|
||||
<li><a href="crypto.html">crypto</a></li>
|
||||
<li><a href="os.html">os</a></li>
|
||||
<li><a href="env.html">env</a></li>
|
||||
<li><a href="signal.html">signal</a></li>
|
||||
<li><a href="subprocess.html">subprocess</a></li>
|
||||
<li><a href="sqlite.html">sqlite</a></li>
|
||||
<li><a href="datetime.html">datetime</a></li>
|
||||
<li><a href="timer.html">timer</a></li>
|
||||
<li><a href="io.html">io</a></li>
|
||||
<li><a href="pathlib.html">pathlib</a></li>
|
||||
<li><a href="scheduler.html">scheduler</a></li>
|
||||
<li><a href="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>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<span class="section-title">How-To Guides</span>
|
||||
<ul>
|
||||
<li><a href="../howto/index.html">How-To List</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">API Reference</a>
|
||||
<span class="separator">/</span>
|
||||
<span>Num</span>
|
||||
</nav>
|
||||
|
||||
<article>
|
||||
<h1>Num</h1>
|
||||
|
||||
<p>The <code>Num</code> class is the core numeric type in Wren. All numbers are double-precision floating point. The class provides arithmetic, trigonometric, bitwise, rounding, query, conversion, and formatting methods.</p>
|
||||
|
||||
<h2>Static Constants</h2>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">Num.pi</span> → <span class="type">Num</span>
|
||||
</div>
|
||||
<p>The ratio of a circle's circumference to its diameter (3.14159...).</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">Num.tau</span> → <span class="type">Num</span>
|
||||
</div>
|
||||
<p>Two times pi (6.28318...).</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">Num.e</span> → <span class="type">Num</span>
|
||||
</div>
|
||||
<p>Euler's number (2.71828...).</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">Num.infinity</span> → <span class="type">Num</span>
|
||||
</div>
|
||||
<p>Positive infinity.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">Num.nan</span> → <span class="type">Num</span>
|
||||
</div>
|
||||
<p>Not-a-number value.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">Num.largest</span> → <span class="type">Num</span>
|
||||
</div>
|
||||
<p>The largest representable double value.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">Num.smallest</span> → <span class="type">Num</span>
|
||||
</div>
|
||||
<p>The smallest positive representable double value.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">Num.maxSafeInteger</span> → <span class="type">Num</span>
|
||||
</div>
|
||||
<p>The largest integer representable without loss of precision (9007199254740991).</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">Num.minSafeInteger</span> → <span class="type">Num</span>
|
||||
</div>
|
||||
<p>The smallest integer representable without loss of precision (-9007199254740991).</p>
|
||||
|
||||
<h3>Static Methods</h3>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">Num.fromString</span>(<span class="param">string</span>) → <span class="type">Num|null</span>
|
||||
</div>
|
||||
<p>Parses a string as a number. Returns <code>null</code> if the string is not a valid number.</p>
|
||||
<pre><code>Num.fromString("42") // 42
|
||||
Num.fromString("3.14") // 3.14
|
||||
Num.fromString("nope") // null</code></pre>
|
||||
|
||||
<h2>Query Methods</h2>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">isInteger</span> → <span class="type">Bool</span>
|
||||
</div>
|
||||
<p>Whether the number is an integer (has no fractional part).</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">isNan</span> → <span class="type">Bool</span>
|
||||
</div>
|
||||
<p>Whether the number is NaN.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">isInfinity</span> → <span class="type">Bool</span>
|
||||
</div>
|
||||
<p>Whether the number is positive or negative infinity.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">isFinite</span> → <span class="type">Bool</span>
|
||||
</div>
|
||||
<p>Whether the number is finite (not infinity and not NaN).</p>
|
||||
<pre><code>42.isFinite // true
|
||||
(1/0).isFinite // false
|
||||
(0/0).isFinite // false</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">isZero</span> → <span class="type">Bool</span>
|
||||
</div>
|
||||
<p>Whether the number equals zero.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">isPositive</span> → <span class="type">Bool</span>
|
||||
</div>
|
||||
<p>Whether the number is strictly greater than zero.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">isNegative</span> → <span class="type">Bool</span>
|
||||
</div>
|
||||
<p>Whether the number is strictly less than zero.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">isEven</span> → <span class="type">Bool</span>
|
||||
</div>
|
||||
<p>Whether the number is an even integer.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">isOdd</span> → <span class="type">Bool</span>
|
||||
</div>
|
||||
<p>Whether the number is an odd integer.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">isBetween</span>(<span class="param">min</span>, <span class="param">max</span>) → <span class="type">Bool</span>
|
||||
</div>
|
||||
<p>Whether the number is within the inclusive range [min, max].</p>
|
||||
<pre><code>5.isBetween(1, 10) // true
|
||||
0.isBetween(1, 10) // false
|
||||
10.isBetween(1, 10) // true</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">sign</span> → <span class="type">Num</span>
|
||||
</div>
|
||||
<p>Returns 1 for positive, -1 for negative, or 0 for zero.</p>
|
||||
|
||||
<h2>Arithmetic</h2>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">abs</span> → <span class="type">Num</span>
|
||||
</div>
|
||||
<p>Absolute value.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">min</span>(<span class="param">other</span>) → <span class="type">Num</span>
|
||||
</div>
|
||||
<p>Returns the smaller of this number and <code>other</code>.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">max</span>(<span class="param">other</span>) → <span class="type">Num</span>
|
||||
</div>
|
||||
<p>Returns the larger of this number and <code>other</code>.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">clamp</span>(<span class="param">min</span>, <span class="param">max</span>) → <span class="type">Num</span>
|
||||
</div>
|
||||
<p>Constrains this number to the range [min, max].</p>
|
||||
<pre><code>15.clamp(0, 10) // 10
|
||||
5.clamp(0, 10) // 5
|
||||
(-3).clamp(0, 10) // 0</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">pow</span>(<span class="param">exponent</span>) → <span class="type">Num</span>
|
||||
</div>
|
||||
<p>Raises this number to the given power.</p>
|
||||
|
||||
<h2>Rounding</h2>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">ceil</span> → <span class="type">Num</span>
|
||||
</div>
|
||||
<p>Rounds up to the nearest integer.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">floor</span> → <span class="type">Num</span>
|
||||
</div>
|
||||
<p>Rounds down to the nearest integer.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">round</span> → <span class="type">Num</span>
|
||||
</div>
|
||||
<p>Rounds to the nearest integer.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">truncate</span> → <span class="type">Num</span>
|
||||
</div>
|
||||
<p>Removes the fractional part, rounding toward zero.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">fraction</span> → <span class="type">Num</span>
|
||||
</div>
|
||||
<p>Returns the fractional part of the number.</p>
|
||||
|
||||
<h2>Roots & Exponents</h2>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">sqrt</span> → <span class="type">Num</span>
|
||||
</div>
|
||||
<p>Square root.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">cbrt</span> → <span class="type">Num</span>
|
||||
</div>
|
||||
<p>Cube root.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">exp</span> → <span class="type">Num</span>
|
||||
</div>
|
||||
<p>Returns e raised to this power.</p>
|
||||
|
||||
<h2>Logarithms</h2>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">log</span> → <span class="type">Num</span>
|
||||
</div>
|
||||
<p>Natural logarithm (base e).</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">log2</span> → <span class="type">Num</span>
|
||||
</div>
|
||||
<p>Base-2 logarithm.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">log10</span> → <span class="type">Num</span>
|
||||
</div>
|
||||
<p>Base-10 logarithm.</p>
|
||||
<pre><code>100.log10 // 2
|
||||
1000.log10 // 3
|
||||
1.log10 // 0</code></pre>
|
||||
|
||||
<h2>Trigonometry</h2>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">sin</span> → <span class="type">Num</span>
|
||||
</div>
|
||||
<p>Sine (argument in radians).</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">cos</span> → <span class="type">Num</span>
|
||||
</div>
|
||||
<p>Cosine (argument in radians).</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">tan</span> → <span class="type">Num</span>
|
||||
</div>
|
||||
<p>Tangent (argument in radians).</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">asin</span> → <span class="type">Num</span>
|
||||
</div>
|
||||
<p>Arc sine, returns radians.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">acos</span> → <span class="type">Num</span>
|
||||
</div>
|
||||
<p>Arc cosine, returns radians.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">atan</span> → <span class="type">Num</span>
|
||||
</div>
|
||||
<p>Arc tangent, returns radians.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">atan</span>(<span class="param">x</span>) → <span class="type">Num</span>
|
||||
</div>
|
||||
<p>Two-argument arc tangent (atan2). Returns the angle between the positive x-axis and the point (x, this).</p>
|
||||
|
||||
<h3>Hyperbolic Functions</h3>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">sinh</span> → <span class="type">Num</span>
|
||||
</div>
|
||||
<p>Hyperbolic sine.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">cosh</span> → <span class="type">Num</span>
|
||||
</div>
|
||||
<p>Hyperbolic cosine.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">tanh</span> → <span class="type">Num</span>
|
||||
</div>
|
||||
<p>Hyperbolic tangent.</p>
|
||||
<pre><code>0.sinh // 0
|
||||
0.cosh // 1
|
||||
0.tanh // 0</code></pre>
|
||||
|
||||
<h2>Angle Conversion</h2>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">toDegrees</span> → <span class="type">Num</span>
|
||||
</div>
|
||||
<p>Converts radians to degrees.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">toRadians</span> → <span class="type">Num</span>
|
||||
</div>
|
||||
<p>Converts degrees to radians.</p>
|
||||
<pre><code>Num.pi.toDegrees // 180
|
||||
180.toRadians // 3.14159...</code></pre>
|
||||
|
||||
<h2>Conversion</h2>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">toString</span> → <span class="type">String</span>
|
||||
</div>
|
||||
<p>Converts the number to its string representation.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">toChar</span> → <span class="type">String</span>
|
||||
</div>
|
||||
<p>Returns the Unicode character for this code point.</p>
|
||||
<pre><code>65.toChar // "A"
|
||||
97.toChar // "a"</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">toBase</span>(<span class="param">radix</span>) → <span class="type">String</span>
|
||||
</div>
|
||||
<p>Converts the integer part to a string in the given base (2-36).</p>
|
||||
<pre><code>255.toBase(16) // "ff"
|
||||
255.toBase(2) // "11111111"
|
||||
255.toBase(8) // "377"</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">toHex</span> → <span class="type">String</span>
|
||||
</div>
|
||||
<p>Shorthand for <code>toBase(16)</code>.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">toBinary</span> → <span class="type">String</span>
|
||||
</div>
|
||||
<p>Shorthand for <code>toBase(2)</code>.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">toOctal</span> → <span class="type">String</span>
|
||||
</div>
|
||||
<p>Shorthand for <code>toBase(8)</code>.</p>
|
||||
|
||||
<h2>Formatting</h2>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">format</span>(<span class="param">decimals</span>) → <span class="type">String</span>
|
||||
</div>
|
||||
<p>Formats the number with a fixed number of decimal places (0-20).</p>
|
||||
<pre><code>3.14159.format(2) // "3.14"
|
||||
42.format(3) // "42.000"
|
||||
(-1.5).format(1) // "-1.5"</code></pre>
|
||||
|
||||
<h2>Integer Operations</h2>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">gcd</span>(<span class="param">other</span>) → <span class="type">Num</span>
|
||||
</div>
|
||||
<p>Greatest common divisor using the Euclidean algorithm. Operates on absolute values.</p>
|
||||
<pre><code>12.gcd(8) // 4
|
||||
54.gcd(24) // 6
|
||||
7.gcd(13) // 1</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">lcm</span>(<span class="param">other</span>) → <span class="type">Num</span>
|
||||
</div>
|
||||
<p>Least common multiple.</p>
|
||||
<pre><code>4.lcm(6) // 12
|
||||
3.lcm(5) // 15</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">digits</span> → <span class="type">List</span>
|
||||
</div>
|
||||
<p>Returns a list of the individual digits of the integer's absolute value. Aborts if the number is not an integer.</p>
|
||||
<pre><code>123.digits // [1, 2, 3]
|
||||
0.digits // [0]
|
||||
(-456).digits // [4, 5, 6]</code></pre>
|
||||
|
||||
<h2>Bitwise Operations</h2>
|
||||
|
||||
<p>Bitwise operators work on 32-bit unsigned integers.</p>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>Operator</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
<tr><td><code>&(other)</code></td><td>Bitwise AND</td></tr>
|
||||
<tr><td><code>|(other)</code></td><td>Bitwise OR</td></tr>
|
||||
<tr><td><code>^(other)</code></td><td>Bitwise XOR</td></tr>
|
||||
<tr><td><code><<(other)</code></td><td>Left shift</td></tr>
|
||||
<tr><td><code>>>(other)</code></td><td>Right shift</td></tr>
|
||||
<tr><td><code>~</code></td><td>Bitwise NOT</td></tr>
|
||||
</table>
|
||||
|
||||
<h2>Ranges</h2>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">..</span>(<span class="param">to</span>) → <span class="type">Range</span>
|
||||
</div>
|
||||
<p>Creates an inclusive range from this number to <code>to</code>.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">...</span>(<span class="param">to</span>) → <span class="type">Range</span>
|
||||
</div>
|
||||
<p>Creates an exclusive range from this number to <code>to</code> (excludes the end).</p>
|
||||
<pre><code>for (i in 1..5) System.print(i) // 1 2 3 4 5
|
||||
for (i in 1...5) System.print(i) // 1 2 3 4</code></pre>
|
||||
</article>
|
||||
|
||||
<footer class="page-footer">
|
||||
<a href="string.html" class="prev">String</a>
|
||||
<a href="http.html" class="next">http</a>
|
||||
</footer>
|
||||
</main>
|
||||
</div>
|
||||
<script src="../js/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="string.html">String</a></li>
|
||||
<li><a href="number.html">Num</a></li>
|
||||
<li><a href="http.html">http</a></li>
|
||||
<li><a href="websocket.html">websocket</a></li>
|
||||
<li><a href="tls.html">tls</a></li>
|
||||
@ -58,6 +60,7 @@
|
||||
<li><a href="datetime.html">datetime</a></li>
|
||||
<li><a href="timer.html">timer</a></li>
|
||||
<li><a href="io.html">io</a></li>
|
||||
<li><a href="pathlib.html">pathlib</a></li>
|
||||
<li><a href="scheduler.html">scheduler</a></li>
|
||||
<li><a href="math.html">math</a></li>
|
||||
</ul>
|
||||
|
||||
659
manual/api/pathlib.html
Normal file
659
manual/api/pathlib.html
Normal file
@ -0,0 +1,659 @@
|
||||
<!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>pathlib - 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="index.html">Overview</a></li>
|
||||
<li><a href="string.html">String</a></li>
|
||||
<li><a href="number.html">Num</a></li>
|
||||
<li><a href="http.html">http</a></li>
|
||||
<li><a href="websocket.html">websocket</a></li>
|
||||
<li><a href="tls.html">tls</a></li>
|
||||
<li><a href="net.html">net</a></li>
|
||||
<li><a href="dns.html">dns</a></li>
|
||||
<li><a href="json.html">json</a></li>
|
||||
<li><a href="base64.html">base64</a></li>
|
||||
<li><a href="regex.html">regex</a></li>
|
||||
<li><a href="jinja.html">jinja</a></li>
|
||||
<li><a href="crypto.html">crypto</a></li>
|
||||
<li><a href="os.html">os</a></li>
|
||||
<li><a href="env.html">env</a></li>
|
||||
<li><a href="signal.html">signal</a></li>
|
||||
<li><a href="subprocess.html">subprocess</a></li>
|
||||
<li><a href="sqlite.html">sqlite</a></li>
|
||||
<li><a href="datetime.html">datetime</a></li>
|
||||
<li><a href="timer.html">timer</a></li>
|
||||
<li><a href="io.html">io</a></li>
|
||||
<li><a href="pathlib.html" class="active">pathlib</a></li>
|
||||
<li><a href="scheduler.html">scheduler</a></li>
|
||||
<li><a href="math.html">math</a></li>
|
||||
<li><a href="uuid.html">uuid</a></li>
|
||||
<li><a href="html.html">html</a></li>
|
||||
<li><a href="argparse.html">argparse</a></li>
|
||||
<li><a href="wdantic.html">wdantic</a></li>
|
||||
<li><a href="dataset.html">dataset</a></li>
|
||||
<li><a href="markdown.html">markdown</a></li>
|
||||
<li><a href="web.html">web</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">Templates</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="../howto/index.html">How-To List</a></li>
|
||||
<li><a href="../howto/http-requests.html">HTTP Requests</a></li>
|
||||
<li><a href="../howto/json-parsing.html">JSON Parsing</a></li>
|
||||
<li><a href="../howto/regex-patterns.html">Regex Patterns</a></li>
|
||||
<li><a href="../howto/file-operations.html">File Operations</a></li>
|
||||
<li><a href="../howto/async-operations.html">Async Operations</a></li>
|
||||
<li><a href="../howto/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">API Reference</a>
|
||||
<span class="separator">/</span>
|
||||
<span>pathlib</span>
|
||||
</nav>
|
||||
|
||||
<article>
|
||||
<h1>pathlib</h1>
|
||||
|
||||
<p>The <code>pathlib</code> module provides object-oriented filesystem path operations. Inspired by Python's <code>pathlib</code>, it offers immutable <code>Path</code> objects that combine path manipulation with filesystem I/O in a single interface.</p>
|
||||
|
||||
<pre><code>import "pathlib" for Path</code></pre>
|
||||
|
||||
<div class="toc">
|
||||
<h4>On This Page</h4>
|
||||
<ul>
|
||||
<li><a href="#purepath-class">PurePath Class</a></li>
|
||||
<li><a href="#path-class">Path Class</a></li>
|
||||
<li><a href="#path-properties">Path Properties</a></li>
|
||||
<li><a href="#path-manipulation">Path Manipulation</a></li>
|
||||
<li><a href="#filesystem-operations">Filesystem Operations</a></li>
|
||||
<li><a href="#directory-operations">Directory Operations</a></li>
|
||||
<li><a href="#symlink-operations">Symlink Operations</a></li>
|
||||
<li><a href="#examples">Examples</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<h2 id="purepath-class">PurePath Class</h2>
|
||||
|
||||
<div class="class-header">
|
||||
<h3>PurePath</h3>
|
||||
<p>String-only path operations without filesystem access. Base class for <code>Path</code>.</p>
|
||||
</div>
|
||||
|
||||
<h3>Constructor</h3>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">PurePath.new</span>(<span class="param">path</span>) → <span class="type">PurePath</span>
|
||||
</div>
|
||||
<p>Creates a new PurePath from a string or another PurePath.</p>
|
||||
<pre><code>var p = PurePath.new("/home/user/file.txt")</code></pre>
|
||||
|
||||
<h3>Properties</h3>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">parts</span> → <span class="type">List</span>
|
||||
</div>
|
||||
<p>The individual components of the path.</p>
|
||||
<pre><code>var p = Path.new("/home/user/file.txt")
|
||||
System.print(p.parts) // [/, home, user, file.txt]</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">name</span> → <span class="type">String</span>
|
||||
</div>
|
||||
<p>The final component of the path (filename with extension).</p>
|
||||
<pre><code>var p = Path.new("/home/user/file.tar.gz")
|
||||
System.print(p.name) // file.tar.gz</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">stem</span> → <span class="type">String</span>
|
||||
</div>
|
||||
<p>The filename without the last extension.</p>
|
||||
<pre><code>var p = Path.new("/home/user/file.tar.gz")
|
||||
System.print(p.stem) // file.tar</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">suffix</span> → <span class="type">String</span>
|
||||
</div>
|
||||
<p>The last file extension, including the leading dot.</p>
|
||||
<pre><code>var p = Path.new("/home/user/file.tar.gz")
|
||||
System.print(p.suffix) // .gz</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">suffixes</span> → <span class="type">List</span>
|
||||
</div>
|
||||
<p>All file extensions as a list.</p>
|
||||
<pre><code>var p = Path.new("/home/user/file.tar.gz")
|
||||
System.print(p.suffixes) // [.tar, .gz]</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">parent</span> → <span class="type">Path</span>
|
||||
</div>
|
||||
<p>The logical parent of the path.</p>
|
||||
<pre><code>var p = Path.new("/home/user/file.txt")
|
||||
System.print(p.parent) // /home/user</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">parents</span> → <span class="type">List</span>
|
||||
</div>
|
||||
<p>A list of all ancestor paths, from immediate parent to root.</p>
|
||||
<pre><code>var p = Path.new("/home/user/docs/file.txt")
|
||||
for (ancestor in p.parents) {
|
||||
System.print(ancestor)
|
||||
}
|
||||
// /home/user/docs
|
||||
// /home/user
|
||||
// /home
|
||||
// /</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">drive</span> → <span class="type">String</span>
|
||||
</div>
|
||||
<p>The drive letter (Windows only). Returns empty string on POSIX.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">root</span> → <span class="type">String</span>
|
||||
</div>
|
||||
<p>The root of the path. Returns <code>"/"</code> for absolute paths, empty string for relative.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">anchor</span> → <span class="type">String</span>
|
||||
</div>
|
||||
<p>The concatenation of drive and root.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">isAbsolute</span> → <span class="type">Bool</span>
|
||||
</div>
|
||||
<p>True if the path is absolute (has a root).</p>
|
||||
<pre><code>System.print(Path.new("/etc/hosts").isAbsolute) // true
|
||||
System.print(Path.new("relative/path").isAbsolute) // false</code></pre>
|
||||
|
||||
<h2 id="path-manipulation">Path Manipulation</h2>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">path</span> / <span class="param">other</span> → <span class="type">Path</span>
|
||||
</div>
|
||||
<p>Joins two paths using the <code>/</code> operator. If <code>other</code> is absolute, it replaces the current path.</p>
|
||||
<pre><code>var base = Path.new("/home/user")
|
||||
var full = base / "documents" / "file.txt"
|
||||
System.print(full) // /home/user/documents/file.txt</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">joinpath</span>(<span class="param">other</span>) → <span class="type">Path</span>
|
||||
</div>
|
||||
<p>Joins paths. Accepts a string, Path, or List of components.</p>
|
||||
<pre><code>var p = Path.new("/home").joinpath("user").joinpath("file.txt")
|
||||
System.print(p) // /home/user/file.txt
|
||||
|
||||
var q = Path.new("/home").joinpath(["user", "docs", "file.txt"])
|
||||
System.print(q) // /home/user/docs/file.txt</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">withName</span>(<span class="param">newName</span>) → <span class="type">Path</span>
|
||||
</div>
|
||||
<p>Returns a new path with the filename replaced.</p>
|
||||
<pre><code>var p = Path.new("/home/user/old.txt")
|
||||
System.print(p.withName("new.txt")) // /home/user/new.txt</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">withStem</span>(<span class="param">newStem</span>) → <span class="type">Path</span>
|
||||
</div>
|
||||
<p>Returns a new path with the stem replaced, keeping the extension.</p>
|
||||
<pre><code>var p = Path.new("/data/archive.tar.gz")
|
||||
System.print(p.withStem("backup")) // /data/backup.gz</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">withSuffix</span>(<span class="param">newSuffix</span>) → <span class="type">Path</span>
|
||||
</div>
|
||||
<p>Returns a new path with the extension replaced.</p>
|
||||
<pre><code>var p = Path.new("/data/file.txt")
|
||||
System.print(p.withSuffix(".md")) // /data/file.md</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">relativeTo</span>(<span class="param">base</span>) → <span class="type">Path</span>
|
||||
</div>
|
||||
<p>Returns a relative path from <code>base</code> to this path. Aborts if the path is not relative to <code>base</code>.</p>
|
||||
<pre><code>var p = Path.new("/home/user/docs/file.txt")
|
||||
System.print(p.relativeTo("/home/user")) // docs/file.txt</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">match</span>(<span class="param">pattern</span>) → <span class="type">Bool</span>
|
||||
</div>
|
||||
<p>Matches the filename against a glob pattern. Supports <code>*</code> and <code>?</code> wildcards.</p>
|
||||
<pre><code>var p = Path.new("/home/user/notes.txt")
|
||||
System.print(p.match("*.txt")) // true
|
||||
System.print(p.match("*.md")) // false</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">asPosix</span> → <span class="type">String</span>
|
||||
</div>
|
||||
<p>Returns the path string with forward slashes (converts backslashes on Windows).</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">expanduser</span>() → <span class="type">Path</span>
|
||||
</div>
|
||||
<p>Expands a leading <code>~</code> to the user's home directory.</p>
|
||||
<pre><code>var p = Path.new("~/.config/app")
|
||||
System.print(p.expanduser()) // /home/alice/.config/app</code></pre>
|
||||
|
||||
<h3>Operators</h3>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">==</span>(<span class="param">other</span>) → <span class="type">Bool</span>
|
||||
</div>
|
||||
<p>Compares two paths for equality by their string representation.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">!=</span>(<span class="param">other</span>) → <span class="type">Bool</span>
|
||||
</div>
|
||||
<p>Compares two paths for inequality.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">toString</span> → <span class="type">String</span>
|
||||
</div>
|
||||
<p>Returns the path as a string.</p>
|
||||
|
||||
<h2 id="path-class">Path Class</h2>
|
||||
|
||||
<div class="class-header">
|
||||
<h3>Path</h3>
|
||||
<p>Extends PurePath with filesystem operations. This is the primary class for working with paths.</p>
|
||||
</div>
|
||||
|
||||
<h3>Constructor</h3>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">Path.new</span>(<span class="param">path</span>) → <span class="type">Path</span>
|
||||
</div>
|
||||
<p>Creates a new Path from a string or another Path.</p>
|
||||
<pre><code>var p = Path.new("/home/user/file.txt")</code></pre>
|
||||
|
||||
<h3>Class Properties</h3>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">Path.cwd</span> → <span class="type">Path</span>
|
||||
</div>
|
||||
<p>The current working directory as a Path.</p>
|
||||
<pre><code>System.print(Path.cwd) // /home/user/projects</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">Path.home</span> → <span class="type">Path</span>
|
||||
</div>
|
||||
<p>The current user's home directory as a Path.</p>
|
||||
<pre><code>System.print(Path.home) // /home/alice</code></pre>
|
||||
|
||||
<h2 id="filesystem-operations">Filesystem Operations</h2>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">exists</span>() → <span class="type">Bool</span>
|
||||
</div>
|
||||
<p>Returns true if the path points to an existing file or directory.</p>
|
||||
<pre><code>if (Path.new("/etc/hosts").exists()) {
|
||||
System.print("File exists")
|
||||
}</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">isFile</span>() → <span class="type">Bool</span>
|
||||
</div>
|
||||
<p>Returns true if the path points to a regular file.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">isDir</span>() → <span class="type">Bool</span>
|
||||
</div>
|
||||
<p>Returns true if the path points to a directory.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">isSymlink</span>() → <span class="type">Bool</span>
|
||||
</div>
|
||||
<p>Returns true if the path is a symbolic link.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">stat</span>() → <span class="type">Stat</span>
|
||||
</div>
|
||||
<p>Returns a Stat object with file metadata (size, mode, timestamps).</p>
|
||||
<pre><code>var s = Path.new("/etc/hosts").stat()
|
||||
System.print(s.size) // 234</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">lstat</span>() → <span class="type">Stat</span>
|
||||
</div>
|
||||
<p>Like <code>stat()</code> but does not follow symbolic links.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">readText</span>() → <span class="type">String</span>
|
||||
</div>
|
||||
<p>Reads the entire file contents as a string.</p>
|
||||
<pre><code>var content = Path.new("config.json").readText()
|
||||
System.print(content)</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">readBytes</span>() → <span class="type">String</span>
|
||||
</div>
|
||||
<p>Reads the entire file contents as bytes.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">writeText</span>(<span class="param">content</span>)
|
||||
</div>
|
||||
<p>Writes a string to the file, creating or overwriting it.</p>
|
||||
<pre><code>Path.new("output.txt").writeText("Hello, World!")</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">writeBytes</span>(<span class="param">content</span>)
|
||||
</div>
|
||||
<p>Writes bytes to the file, creating or overwriting it.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">touch</span>()
|
||||
</div>
|
||||
<p>Creates an empty file if it does not exist, or updates its modification time if it does.</p>
|
||||
<pre><code>Path.new("marker.txt").touch()</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">unlink</span>()
|
||||
</div>
|
||||
<p>Deletes the file.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">rename</span>(<span class="param">target</span>) → <span class="type">Path</span>
|
||||
</div>
|
||||
<p>Moves or renames the file to <code>target</code>. Returns the new Path.</p>
|
||||
<pre><code>var old = Path.new("draft.txt")
|
||||
var published = old.rename("article.txt")
|
||||
System.print(published) // article.txt</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">replace</span>(<span class="param">target</span>) → <span class="type">Path</span>
|
||||
</div>
|
||||
<p>Alias for <code>rename()</code>. Replaces the target if it exists.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">copyfile</span>(<span class="param">dest</span>)
|
||||
</div>
|
||||
<p>Copies this file to <code>dest</code>.</p>
|
||||
<pre><code>Path.new("original.txt").copyfile("backup.txt")</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">chmod</span>(<span class="param">mode</span>)
|
||||
</div>
|
||||
<p>Changes the file permissions. Mode is an octal number.</p>
|
||||
<pre><code>Path.new("script.sh").chmod(0x1ed) // 0755 in octal</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">resolve</span>() → <span class="type">Path</span>
|
||||
</div>
|
||||
<p>Returns the absolute real path, resolving any symlinks.</p>
|
||||
<pre><code>var real = Path.new("./relative/../file.txt").resolve()
|
||||
System.print(real) // /home/user/file.txt</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">samefile</span>(<span class="param">other</span>) → <span class="type">Bool</span>
|
||||
</div>
|
||||
<p>Returns true if this path and <code>other</code> refer to the same file (compares inodes).</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">owner</span>() → <span class="type">String</span>
|
||||
</div>
|
||||
<p>Returns the username of the file owner (POSIX only).</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">group</span>() → <span class="type">String</span>
|
||||
</div>
|
||||
<p>Returns the group name of the file (POSIX only).</p>
|
||||
|
||||
<h2 id="directory-operations">Directory Operations</h2>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">mkdir</span>()
|
||||
</div>
|
||||
<p>Creates the directory.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">mkdir</span>(<span class="param">parents</span>)
|
||||
</div>
|
||||
<p>Creates the directory. If <code>parents</code> is true, creates all intermediate directories.</p>
|
||||
<pre><code>Path.new("/tmp/a/b/c").mkdir(true)</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">rmdir</span>()
|
||||
</div>
|
||||
<p>Removes an empty directory.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">rmtree</span>()
|
||||
</div>
|
||||
<p>Recursively deletes the directory and all its contents.</p>
|
||||
<pre><code>Path.new("/tmp/build_output").rmtree()</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">iterdir</span>() → <span class="type">List</span>
|
||||
</div>
|
||||
<p>Returns a list of Path objects for each entry in the directory.</p>
|
||||
<pre><code>for (entry in Path.new(".").iterdir()) {
|
||||
System.print(entry.name)
|
||||
}</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">glob</span>(<span class="param">pattern</span>) → <span class="type">List</span>
|
||||
</div>
|
||||
<p>Returns paths matching the glob pattern in this directory. Supports <code>*</code> and <code>?</code> wildcards.</p>
|
||||
<pre><code>var txtFiles = Path.new(".").glob("*.txt")
|
||||
for (f in txtFiles) {
|
||||
System.print(f.name)
|
||||
}</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">rglob</span>(<span class="param">pattern</span>) → <span class="type">List</span>
|
||||
</div>
|
||||
<p>Recursively matches files in this directory and all subdirectories.</p>
|
||||
<pre><code>var allWren = Path.cwd.rglob("*.wren")
|
||||
System.print("Found %(allWren.count) Wren files")</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">walk</span>() → <span class="type">List</span>
|
||||
</div>
|
||||
<p>Recursively walks the directory tree top-down. Returns a list of <code>[dirPath, dirNames, fileNames]</code> tuples.</p>
|
||||
<pre><code>for (entry in Path.new("src").walk()) {
|
||||
var dir = entry[0]
|
||||
var dirs = entry[1]
|
||||
var files = entry[2]
|
||||
for (f in files) {
|
||||
System.print(dir / f)
|
||||
}
|
||||
}</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">walk</span>(<span class="param">topDown</span>) → <span class="type">List</span>
|
||||
</div>
|
||||
<p>Walks the directory tree. If <code>topDown</code> is false, visits child directories before parents.</p>
|
||||
|
||||
<h2 id="symlink-operations">Symlink Operations</h2>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">symlinkTo</span>(<span class="param">target</span>)
|
||||
</div>
|
||||
<p>Creates a symbolic link at this path pointing to <code>target</code>.</p>
|
||||
<pre><code>Path.new("/tmp/link").symlinkTo("/etc/hosts")</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">hardlinkTo</span>(<span class="param">target</span>)
|
||||
</div>
|
||||
<p>Creates a hard link at this path pointing to <code>target</code>.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">readlink</span>() → <span class="type">String</span>
|
||||
</div>
|
||||
<p>Returns the target of the symbolic link.</p>
|
||||
|
||||
<h2 id="examples">Examples</h2>
|
||||
|
||||
<h3>Configuration File Management</h3>
|
||||
<pre><code>import "pathlib" for Path
|
||||
import "json" for Json
|
||||
|
||||
var configDir = Path.home / ".config" / "myapp"
|
||||
if (!configDir.exists()) {
|
||||
configDir.mkdir(true)
|
||||
}
|
||||
|
||||
var configFile = configDir / "settings.json"
|
||||
if (!configFile.exists()) {
|
||||
configFile.writeText(Json.stringify({
|
||||
"theme": "dark",
|
||||
"language": "en"
|
||||
}, 2))
|
||||
}
|
||||
|
||||
var settings = Json.parse(configFile.readText())
|
||||
System.print("Theme: %(settings["theme"])")</code></pre>
|
||||
|
||||
<h3>Batch File Processing</h3>
|
||||
<pre><code>import "pathlib" for Path
|
||||
|
||||
var dataDir = Path.new("./data")
|
||||
for (file in dataDir.glob("*.csv")) {
|
||||
var size = file.stat().size
|
||||
System.print("%(file.name): %(size) bytes")
|
||||
}
|
||||
|
||||
var total = 0
|
||||
for (wren in Path.cwd.rglob("*.wren")) {
|
||||
total = total + 1
|
||||
}
|
||||
System.print("Found %(total) Wren source files")</code></pre>
|
||||
|
||||
<h3>Directory Tree Traversal</h3>
|
||||
<pre><code>import "pathlib" for Path
|
||||
|
||||
var src = Path.new("src")
|
||||
for (entry in src.walk()) {
|
||||
var dir = entry[0]
|
||||
var files = entry[2]
|
||||
if (files.count > 0) {
|
||||
System.print("%(dir.relativeTo(src)):")
|
||||
for (f in files) {
|
||||
System.print(" %(f)")
|
||||
}
|
||||
}
|
||||
}</code></pre>
|
||||
|
||||
<h3>Path Manipulation</h3>
|
||||
<pre><code>import "pathlib" for Path
|
||||
|
||||
var p = Path.new("/home/user/documents/report.tar.gz")
|
||||
|
||||
System.print(p.name) // report.tar.gz
|
||||
System.print(p.stem) // report.tar
|
||||
System.print(p.suffix) // .gz
|
||||
System.print(p.suffixes) // [.tar, .gz]
|
||||
System.print(p.parent) // /home/user/documents
|
||||
|
||||
var backup = p.withSuffix(".bak")
|
||||
System.print(backup) // /home/user/documents/report.tar.bak
|
||||
|
||||
var renamed = p.withName("summary.pdf")
|
||||
System.print(renamed) // /home/user/documents/summary.pdf</code></pre>
|
||||
|
||||
<h3>Temporary File Cleanup</h3>
|
||||
<pre><code>import "pathlib" for Path
|
||||
|
||||
var tmpDir = Path.new("/tmp/build_artifacts")
|
||||
if (tmpDir.exists()) {
|
||||
tmpDir.rmtree()
|
||||
}
|
||||
|
||||
tmpDir.mkdir(true)
|
||||
(tmpDir / "output.o").touch()
|
||||
(tmpDir / "output.bin").touch()
|
||||
|
||||
var count = tmpDir.iterdir().count
|
||||
System.print("%(count) files in build directory")
|
||||
|
||||
tmpDir.rmtree()</code></pre>
|
||||
|
||||
<h3>Home Directory Expansion</h3>
|
||||
<pre><code>import "pathlib" for Path
|
||||
|
||||
var shortcuts = [
|
||||
Path.new("~/.bashrc"),
|
||||
Path.new("~/.config"),
|
||||
Path.new("~/Documents")
|
||||
]
|
||||
|
||||
for (p in shortcuts) {
|
||||
var expanded = p.expanduser()
|
||||
System.print("%(p) -> %(expanded) (exists: %(expanded.exists()))")
|
||||
}</code></pre>
|
||||
|
||||
<div class="admonition note">
|
||||
<div class="admonition-title">Note</div>
|
||||
<p>Path objects are immutable. Methods like <code>withName()</code>, <code>withSuffix()</code>, and <code>joinpath()</code> return new Path objects rather than modifying the original.</p>
|
||||
</div>
|
||||
|
||||
<div class="admonition tip">
|
||||
<div class="admonition-title">Tip</div>
|
||||
<p>Use the <code>/</code> operator for readable path construction: <code>Path.home / ".config" / "myapp" / "settings.json"</code> reads naturally and handles separator insertion automatically.</p>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<footer class="page-footer">
|
||||
<a href="io.html" class="prev">io</a>
|
||||
<a href="scheduler.html" class="next">scheduler</a>
|
||||
</footer>
|
||||
</main>
|
||||
</div>
|
||||
<script src="../js/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="string.html">String</a></li>
|
||||
<li><a href="number.html">Num</a></li>
|
||||
<li><a href="http.html">http</a></li>
|
||||
<li><a href="websocket.html">websocket</a></li>
|
||||
<li><a href="tls.html">tls</a></li>
|
||||
@ -58,6 +60,7 @@
|
||||
<li><a href="datetime.html">datetime</a></li>
|
||||
<li><a href="timer.html">timer</a></li>
|
||||
<li><a href="io.html">io</a></li>
|
||||
<li><a href="pathlib.html">pathlib</a></li>
|
||||
<li><a href="scheduler.html">scheduler</a></li>
|
||||
<li><a href="math.html">math</a></li>
|
||||
</ul>
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="string.html">String</a></li>
|
||||
<li><a href="number.html">Num</a></li>
|
||||
<li><a href="http.html">http</a></li>
|
||||
<li><a href="websocket.html">websocket</a></li>
|
||||
<li><a href="tls.html">tls</a></li>
|
||||
@ -58,6 +60,7 @@
|
||||
<li><a href="datetime.html">datetime</a></li>
|
||||
<li><a href="timer.html">timer</a></li>
|
||||
<li><a href="io.html">io</a></li>
|
||||
<li><a href="pathlib.html">pathlib</a></li>
|
||||
<li><a href="scheduler.html" class="active">scheduler</a></li>
|
||||
<li><a href="math.html">math</a></li>
|
||||
</ul>
|
||||
@ -183,7 +186,7 @@ for (f in fibers) f.call()
|
||||
</article>
|
||||
|
||||
<footer class="page-footer">
|
||||
<a href="io.html" class="prev">io</a>
|
||||
<a href="pathlib.html" class="prev">pathlib</a>
|
||||
<a href="math.html" class="next">math</a>
|
||||
</footer>
|
||||
</main>
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="string.html">String</a></li>
|
||||
<li><a href="number.html">Num</a></li>
|
||||
<li><a href="http.html">http</a></li>
|
||||
<li><a href="websocket.html">websocket</a></li>
|
||||
<li><a href="tls.html">tls</a></li>
|
||||
@ -58,6 +60,7 @@
|
||||
<li><a href="datetime.html">datetime</a></li>
|
||||
<li><a href="timer.html">timer</a></li>
|
||||
<li><a href="io.html">io</a></li>
|
||||
<li><a href="pathlib.html">pathlib</a></li>
|
||||
<li><a href="scheduler.html">scheduler</a></li>
|
||||
<li><a href="math.html">math</a></li>
|
||||
</ul>
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="string.html">String</a></li>
|
||||
<li><a href="number.html">Num</a></li>
|
||||
<li><a href="http.html">http</a></li>
|
||||
<li><a href="websocket.html">websocket</a></li>
|
||||
<li><a href="tls.html">tls</a></li>
|
||||
@ -58,6 +60,7 @@
|
||||
<li><a href="datetime.html">datetime</a></li>
|
||||
<li><a href="timer.html">timer</a></li>
|
||||
<li><a href="io.html">io</a></li>
|
||||
<li><a href="pathlib.html">pathlib</a></li>
|
||||
<li><a href="scheduler.html">scheduler</a></li>
|
||||
<li><a href="math.html">math</a></li>
|
||||
</ul>
|
||||
|
||||
454
manual/api/string.html
Normal file
454
manual/api/string.html
Normal file
@ -0,0 +1,454 @@
|
||||
<!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>String - 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="index.html">Overview</a></li>
|
||||
<li><a href="string.html" class="active">String</a></li>
|
||||
<li><a href="http.html">http</a></li>
|
||||
<li><a href="websocket.html">websocket</a></li>
|
||||
<li><a href="tls.html">tls</a></li>
|
||||
<li><a href="net.html">net</a></li>
|
||||
<li><a href="dns.html">dns</a></li>
|
||||
<li><a href="json.html">json</a></li>
|
||||
<li><a href="base64.html">base64</a></li>
|
||||
<li><a href="regex.html">regex</a></li>
|
||||
<li><a href="jinja.html">jinja</a></li>
|
||||
<li><a href="crypto.html">crypto</a></li>
|
||||
<li><a href="os.html">os</a></li>
|
||||
<li><a href="env.html">env</a></li>
|
||||
<li><a href="signal.html">signal</a></li>
|
||||
<li><a href="subprocess.html">subprocess</a></li>
|
||||
<li><a href="sqlite.html">sqlite</a></li>
|
||||
<li><a href="datetime.html">datetime</a></li>
|
||||
<li><a href="timer.html">timer</a></li>
|
||||
<li><a href="io.html">io</a></li>
|
||||
<li><a href="pathlib.html">pathlib</a></li>
|
||||
<li><a href="scheduler.html">scheduler</a></li>
|
||||
<li><a href="math.html">math</a></li>
|
||||
<li><a href="uuid.html">uuid</a></li>
|
||||
<li><a href="html.html">html</a></li>
|
||||
<li><a href="argparse.html">argparse</a></li>
|
||||
<li><a href="wdantic.html">wdantic</a></li>
|
||||
<li><a href="dataset.html">dataset</a></li>
|
||||
<li><a href="markdown.html">markdown</a></li>
|
||||
<li><a href="web.html">web</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">Templates</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="../howto/index.html">How-To List</a></li>
|
||||
<li><a href="../howto/http-requests.html">HTTP Requests</a></li>
|
||||
<li><a href="../howto/json-parsing.html">JSON Parsing</a></li>
|
||||
<li><a href="../howto/regex-patterns.html">Regex Patterns</a></li>
|
||||
<li><a href="../howto/file-operations.html">File Operations</a></li>
|
||||
<li><a href="../howto/async-operations.html">Async Operations</a></li>
|
||||
<li><a href="../howto/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">API Reference</a>
|
||||
<span class="separator">/</span>
|
||||
<span>String</span>
|
||||
</nav>
|
||||
|
||||
<article>
|
||||
<h1>String</h1>
|
||||
|
||||
<p>The <code>String</code> class is a core type available globally without imports. Strings in Wren are immutable sequences of bytes, typically representing UTF-8 encoded text. All methods return new strings rather than modifying the original.</p>
|
||||
|
||||
<pre><code>var s = "Hello World"
|
||||
System.print(s.lower) // hello world
|
||||
System.print(s.upper) // HELLO WORLD
|
||||
System.print(s.title) // Hello World
|
||||
System.print(s.reverse) // dlroW olleH</code></pre>
|
||||
|
||||
<h2>Case Conversion</h2>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">lower</span> → <span class="type">String</span>
|
||||
</div>
|
||||
<p>Returns the string with all ASCII uppercase characters converted to lowercase.</p>
|
||||
<pre><code>"Hello World".lower // "hello world"
|
||||
"ABC 123".lower // "abc 123"</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">upper</span> → <span class="type">String</span>
|
||||
</div>
|
||||
<p>Returns the string with all ASCII lowercase characters converted to uppercase.</p>
|
||||
<pre><code>"Hello World".upper // "HELLO WORLD"
|
||||
"abc 123".upper // "ABC 123"</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">capitalize</span> → <span class="type">String</span>
|
||||
</div>
|
||||
<p>Returns the string with the first character uppercased and the rest lowercased.</p>
|
||||
<pre><code>"hello world".capitalize // "Hello world"
|
||||
"HELLO".capitalize // "Hello"</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">title</span> → <span class="type">String</span>
|
||||
</div>
|
||||
<p>Returns the string with the first character of each word capitalized and the rest lowercased. Words are separated by whitespace.</p>
|
||||
<pre><code>"hello world".title // "Hello World"
|
||||
"HELLO WORLD".title // "Hello World"</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">swapCase</span> → <span class="type">String</span>
|
||||
</div>
|
||||
<p>Returns the string with uppercase characters converted to lowercase and vice versa.</p>
|
||||
<pre><code>"Hello World".swapCase // "hELLO wORLD"</code></pre>
|
||||
|
||||
<h2>Character Testing</h2>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">isLower</span> → <span class="type">Bool</span>
|
||||
</div>
|
||||
<p>Returns <code>true</code> if the string contains at least one alphabetic character and all alphabetic characters are lowercase.</p>
|
||||
<pre><code>"hello".isLower // true
|
||||
"hello1".isLower // true
|
||||
"Hello".isLower // false
|
||||
"123".isLower // false</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">isUpper</span> → <span class="type">Bool</span>
|
||||
</div>
|
||||
<p>Returns <code>true</code> if the string contains at least one alphabetic character and all alphabetic characters are uppercase.</p>
|
||||
<pre><code>"HELLO".isUpper // true
|
||||
"HELLO1".isUpper // true
|
||||
"Hello".isUpper // false</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">isDigit</span> → <span class="type">Bool</span>
|
||||
</div>
|
||||
<p>Returns <code>true</code> if the string is non-empty and all bytes are ASCII digits (0-9).</p>
|
||||
<pre><code>"12345".isDigit // true
|
||||
"123a5".isDigit // false
|
||||
"".isDigit // false</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">isAlpha</span> → <span class="type">Bool</span>
|
||||
</div>
|
||||
<p>Returns <code>true</code> if the string is non-empty and all bytes are ASCII letters (a-z, A-Z).</p>
|
||||
<pre><code>"hello".isAlpha // true
|
||||
"hello1".isAlpha // false</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">isAlphaNumeric</span> → <span class="type">Bool</span>
|
||||
</div>
|
||||
<p>Returns <code>true</code> if the string is non-empty and all bytes are ASCII letters or digits.</p>
|
||||
<pre><code>"hello123".isAlphaNumeric // true
|
||||
"hello!".isAlphaNumeric // false</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">isSpace</span> → <span class="type">Bool</span>
|
||||
</div>
|
||||
<p>Returns <code>true</code> if the string is non-empty and all bytes are ASCII whitespace (space, tab, newline, carriage return, form feed, vertical tab).</p>
|
||||
<pre><code>" ".isSpace // true
|
||||
" \t\n".isSpace // true
|
||||
"hello".isSpace // false</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">isAscii</span> → <span class="type">Bool</span>
|
||||
</div>
|
||||
<p>Returns <code>true</code> if all bytes in the string are less than 128. Returns <code>true</code> for empty strings.</p>
|
||||
<pre><code>"hello".isAscii // true
|
||||
"".isAscii // true</code></pre>
|
||||
|
||||
<h2>Search</h2>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">lastIndexOf</span>(<span class="param">search</span>) → <span class="type">Num</span>
|
||||
</div>
|
||||
<p>Returns the byte index of the last occurrence of <code>search</code> in the string, or <code>-1</code> if not found.</p>
|
||||
<ul class="param-list">
|
||||
<li><span class="param-name">search</span> <span class="param-type">(String)</span> - The substring to search for</li>
|
||||
<li><span class="returns">Returns:</span> Byte index or -1</li>
|
||||
</ul>
|
||||
<pre><code>"hello world hello".lastIndexOf("hello") // 12
|
||||
"hello".lastIndexOf("x") // -1</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">lastIndexOf</span>(<span class="param">search</span>, <span class="param">start</span>) → <span class="type">Num</span>
|
||||
</div>
|
||||
<p>Returns the byte index of the last occurrence of <code>search</code> at or before <code>start</code>, or <code>-1</code> if not found.</p>
|
||||
<ul class="param-list">
|
||||
<li><span class="param-name">search</span> <span class="param-type">(String)</span> - The substring to search for</li>
|
||||
<li><span class="param-name">start</span> <span class="param-type">(Num)</span> - Maximum byte index to search from</li>
|
||||
<li><span class="returns">Returns:</span> Byte index or -1</li>
|
||||
</ul>
|
||||
<pre><code>"hello world hello".lastIndexOf("hello", 11) // 0
|
||||
"hello world hello".lastIndexOf("hello", 12) // 12</code></pre>
|
||||
|
||||
<h2>Transformation</h2>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">reverse</span> → <span class="type">String</span>
|
||||
</div>
|
||||
<p>Returns the string with characters in reverse order. Code point aware for UTF-8 strings.</p>
|
||||
<pre><code>"hello".reverse // "olleh"
|
||||
"abcde".reverse // "edcba"</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">center</span>(<span class="param">width</span>) → <span class="type">String</span>
|
||||
</div>
|
||||
<p>Centers the string in a field of <code>width</code> characters, padded with spaces.</p>
|
||||
<pre><code>"hi".center(10) // " hi "</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">center</span>(<span class="param">width</span>, <span class="param">char</span>) → <span class="type">String</span>
|
||||
</div>
|
||||
<p>Centers the string in a field of <code>width</code> characters, padded with the given fill character.</p>
|
||||
<pre><code>"hi".center(10, "-") // "----hi----"</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">lpad</span>(<span class="param">width</span>, <span class="param">char</span>) → <span class="type">String</span>
|
||||
</div>
|
||||
<p>Left-pads the string to <code>width</code> characters using the given fill character.</p>
|
||||
<pre><code>"42".lpad(5, "0") // "00042"</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">rpad</span>(<span class="param">width</span>, <span class="param">char</span>) → <span class="type">String</span>
|
||||
</div>
|
||||
<p>Right-pads the string to <code>width</code> characters using the given fill character.</p>
|
||||
<pre><code>"hi".rpad(5, ".") // "hi..."</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">zfill</span>(<span class="param">width</span>) → <span class="type">String</span>
|
||||
</div>
|
||||
<p>Pads the string with leading zeros to <code>width</code> characters. Preserves a leading <code>-</code> or <code>+</code> sign.</p>
|
||||
<pre><code>"42".zfill(5) // "00042"
|
||||
"-42".zfill(6) // "-00042"
|
||||
"+42".zfill(6) // "+00042"</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">removePrefix</span>(<span class="param">prefix</span>) → <span class="type">String</span>
|
||||
</div>
|
||||
<p>If the string starts with <code>prefix</code>, returns the string with the prefix removed. Otherwise returns the original string.</p>
|
||||
<pre><code>"HelloWorld".removePrefix("Hello") // "World"
|
||||
"HelloWorld".removePrefix("World") // "HelloWorld"</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">removeSuffix</span>(<span class="param">suffix</span>) → <span class="type">String</span>
|
||||
</div>
|
||||
<p>If the string ends with <code>suffix</code>, returns the string with the suffix removed. Otherwise returns the original string.</p>
|
||||
<pre><code>"HelloWorld".removeSuffix("World") // "Hello"
|
||||
"HelloWorld".removeSuffix("Hello") // "HelloWorld"</code></pre>
|
||||
|
||||
<h2>Splitting & Conversion</h2>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">splitLines</span> → <span class="type">List</span>
|
||||
</div>
|
||||
<p>Splits the string by line endings (<code>\n</code>, <code>\r\n</code>, <code>\r</code>) and returns a list of strings.</p>
|
||||
<pre><code>"line1\nline2\nline3".splitLines // ["line1", "line2", "line3"]
|
||||
"a\r\nb\r\nc".splitLines // ["a", "b", "c"]</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">chars</span> → <span class="type">List</span>
|
||||
</div>
|
||||
<p>Returns a list of individual characters (code points) in the string.</p>
|
||||
<pre><code>"abc".chars // ["a", "b", "c"]
|
||||
"".chars // []</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">toNum</span> → <span class="type">Num</span> | <span class="type">Null</span>
|
||||
</div>
|
||||
<p>Parses the string as a number. Returns <code>null</code> if the string cannot be parsed.</p>
|
||||
<pre><code>"42".toNum // 42
|
||||
"3.14".toNum // 3.14
|
||||
"-7".toNum // -7
|
||||
"abc".toNum // null</code></pre>
|
||||
|
||||
<h2>Comparison</h2>
|
||||
|
||||
<p>Strings support lexicographic comparison using the standard comparison operators. Comparison is byte-by-byte using the raw byte values, which produces correct results for ASCII and UTF-8 encoded text.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name"><</span>(<span class="param">other</span>) → <span class="type">Bool</span>
|
||||
</div>
|
||||
<p>Returns <code>true</code> if this string is lexicographically less than <code>other</code>.</p>
|
||||
<ul class="param-list">
|
||||
<li><span class="param-name">other</span> <span class="param-type">(String)</span> - The string to compare against</li>
|
||||
</ul>
|
||||
<pre><code>"apple" < "banana" // true
|
||||
"abc" < "abd" // true
|
||||
"abc" < "abcd" // true (prefix is less than longer string)</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">></span>(<span class="param">other</span>) → <span class="type">Bool</span>
|
||||
</div>
|
||||
<p>Returns <code>true</code> if this string is lexicographically greater than <code>other</code>.</p>
|
||||
<ul class="param-list">
|
||||
<li><span class="param-name">other</span> <span class="param-type">(String)</span> - The string to compare against</li>
|
||||
</ul>
|
||||
<pre><code>"banana" > "apple" // true
|
||||
"abd" > "abc" // true
|
||||
"abcd" > "abc" // true</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name"><=</span>(<span class="param">other</span>) → <span class="type">Bool</span>
|
||||
</div>
|
||||
<p>Returns <code>true</code> if this string is lexicographically less than or equal to <code>other</code>.</p>
|
||||
<ul class="param-list">
|
||||
<li><span class="param-name">other</span> <span class="param-type">(String)</span> - The string to compare against</li>
|
||||
</ul>
|
||||
<pre><code>"abc" <= "abc" // true
|
||||
"abc" <= "abd" // true
|
||||
"abd" <= "abc" // false</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">>=</span>(<span class="param">other</span>) → <span class="type">Bool</span>
|
||||
</div>
|
||||
<p>Returns <code>true</code> if this string is lexicographically greater than or equal to <code>other</code>.</p>
|
||||
<ul class="param-list">
|
||||
<li><span class="param-name">other</span> <span class="param-type">(String)</span> - The string to compare against</li>
|
||||
</ul>
|
||||
<pre><code>"abc" >= "abc" // true
|
||||
"abd" >= "abc" // true
|
||||
"abc" >= "abd" // false</code></pre>
|
||||
|
||||
<div class="admonition tip">
|
||||
<div class="admonition-title">Tip</div>
|
||||
<p>String comparison is byte-based, so uppercase letters sort before lowercase letters in ASCII order (e.g., <code>"Z" < "a"</code> is <code>true</code>). If you need case-insensitive comparison, convert both strings to the same case first using <code>lower</code> or <code>upper</code>.</p>
|
||||
</div>
|
||||
|
||||
<h2>Existing Methods</h2>
|
||||
|
||||
<p>The following methods are also available on all strings as part of the core VM.</p>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<th>Method</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>contains(s)</code></td>
|
||||
<td>Returns true if the string contains <code>s</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>startsWith(s)</code></td>
|
||||
<td>Returns true if the string starts with <code>s</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>endsWith(s)</code></td>
|
||||
<td>Returns true if the string ends with <code>s</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>indexOf(s)</code></td>
|
||||
<td>Returns the byte index of <code>s</code>, or -1</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>indexOf(s, start)</code></td>
|
||||
<td>Returns the byte index of <code>s</code> starting from <code>start</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>split(delim)</code></td>
|
||||
<td>Splits by delimiter, returns a list</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>replace(from, to)</code></td>
|
||||
<td>Replaces all occurrences of <code>from</code> with <code>to</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>trim()</code></td>
|
||||
<td>Removes leading and trailing whitespace</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>trimStart()</code></td>
|
||||
<td>Removes leading whitespace</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>trimEnd()</code></td>
|
||||
<td>Removes trailing whitespace</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>bytes</code></td>
|
||||
<td>Returns a sequence of byte values</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>codePoints</code></td>
|
||||
<td>Returns a sequence of code point values</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>count</code></td>
|
||||
<td>Number of code points in the string</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>isEmpty</code></td>
|
||||
<td>Returns true if the string has no characters</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>*(n)</code></td>
|
||||
<td>Repeats the string <code>n</code> times</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div class="admonition note">
|
||||
<div class="admonition-title">Note</div>
|
||||
<p>String is a core type available globally. No <code>import</code> statement is needed. All string methods operate on ASCII characters. Multi-byte UTF-8 characters are preserved but case conversion applies only to ASCII letters (a-z, A-Z).</p>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<footer class="page-footer">
|
||||
<a href="index.html" class="prev">Overview</a>
|
||||
<a href="http.html" class="next">http</a>
|
||||
</footer>
|
||||
</main>
|
||||
</div>
|
||||
<script src="../js/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="string.html">String</a></li>
|
||||
<li><a href="number.html">Num</a></li>
|
||||
<li><a href="http.html">http</a></li>
|
||||
<li><a href="websocket.html">websocket</a></li>
|
||||
<li><a href="tls.html">tls</a></li>
|
||||
@ -58,6 +60,7 @@
|
||||
<li><a href="datetime.html">datetime</a></li>
|
||||
<li><a href="timer.html">timer</a></li>
|
||||
<li><a href="io.html">io</a></li>
|
||||
<li><a href="pathlib.html">pathlib</a></li>
|
||||
<li><a href="scheduler.html">scheduler</a></li>
|
||||
<li><a href="math.html">math</a></li>
|
||||
</ul>
|
||||
|
||||
370
manual/api/tempfile.html
Normal file
370
manual/api/tempfile.html
Normal file
@ -0,0 +1,370 @@
|
||||
<!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>tempfile - 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="index.html">Overview</a></li>
|
||||
<li><a href="string.html">String</a></li>
|
||||
<li><a href="number.html">Num</a></li>
|
||||
<li><a href="http.html">http</a></li>
|
||||
<li><a href="websocket.html">websocket</a></li>
|
||||
<li><a href="tls.html">tls</a></li>
|
||||
<li><a href="net.html">net</a></li>
|
||||
<li><a href="dns.html">dns</a></li>
|
||||
<li><a href="json.html">json</a></li>
|
||||
<li><a href="base64.html">base64</a></li>
|
||||
<li><a href="regex.html">regex</a></li>
|
||||
<li><a href="jinja.html">jinja</a></li>
|
||||
<li><a href="crypto.html">crypto</a></li>
|
||||
<li><a href="os.html">os</a></li>
|
||||
<li><a href="env.html">env</a></li>
|
||||
<li><a href="signal.html">signal</a></li>
|
||||
<li><a href="subprocess.html">subprocess</a></li>
|
||||
<li><a href="sqlite.html">sqlite</a></li>
|
||||
<li><a href="datetime.html">datetime</a></li>
|
||||
<li><a href="timer.html">timer</a></li>
|
||||
<li><a href="io.html">io</a></li>
|
||||
<li><a href="pathlib.html">pathlib</a></li>
|
||||
<li><a href="tempfile.html" class="active">tempfile</a></li>
|
||||
<li><a href="scheduler.html">scheduler</a></li>
|
||||
<li><a href="math.html">math</a></li>
|
||||
<li><a href="uuid.html">uuid</a></li>
|
||||
<li><a href="html.html">html</a></li>
|
||||
<li><a href="argparse.html">argparse</a></li>
|
||||
<li><a href="wdantic.html">wdantic</a></li>
|
||||
<li><a href="dataset.html">dataset</a></li>
|
||||
<li><a href="markdown.html">markdown</a></li>
|
||||
<li><a href="web.html">web</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<span class="section-title">Tutorials</span>
|
||||
<ul>
|
||||
<li><a href="../tutorials/index.html">Tutorial List</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section">
|
||||
<span class="section-title">How-To Guides</span>
|
||||
<ul>
|
||||
<li><a href="../howto/index.html">How-To List</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">API Reference</a>
|
||||
<span class="separator">/</span>
|
||||
<span>tempfile</span>
|
||||
</nav>
|
||||
|
||||
<article>
|
||||
<h1>tempfile</h1>
|
||||
|
||||
<p>The <code>tempfile</code> module provides utilities for creating temporary files and directories. It mirrors Python's <code>tempfile</code> API with three classes: <code>TempFile</code> for low-level operations, <code>NamedTemporaryFile</code> for temporary files with automatic cleanup, and <code>TemporaryDirectory</code> for temporary directories with recursive cleanup.</p>
|
||||
|
||||
<pre><code>import "tempfile" for TempFile, NamedTemporaryFile, TemporaryDirectory</code></pre>
|
||||
|
||||
<h2>TempFile Class</h2>
|
||||
|
||||
<div class="class-header">
|
||||
<h3>TempFile</h3>
|
||||
<p>Low-level temporary file and directory utilities</p>
|
||||
</div>
|
||||
|
||||
<h3>Static Properties</h3>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">TempFile.tempdir</span> → <span class="type">String|Null</span>
|
||||
</div>
|
||||
<p>Gets or sets a global override for the temporary directory. When set, <code>gettempdir()</code> returns this value instead of checking environment variables.</p>
|
||||
<pre><code>TempFile.tempdir = "/my/custom/tmp"
|
||||
System.print(TempFile.gettempdir()) // /my/custom/tmp
|
||||
TempFile.tempdir = null // Reset to default</code></pre>
|
||||
|
||||
<h3>Static Methods</h3>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">TempFile.gettempdir</span>() → <span class="type">String</span>
|
||||
</div>
|
||||
<p>Returns the resolved temporary directory path. Checks in order: the <code>tempdir</code> override, then <code>TMPDIR</code>, <code>TEMP</code>, <code>TMP</code> environment variables, and falls back to <code>/tmp</code> on POSIX or <code>C:\Temp</code> on Windows.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">TempFile.gettempprefix</span>() → <span class="type">String</span>
|
||||
</div>
|
||||
<p>Returns the default prefix for temporary file names: <code>"tmp"</code>.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">TempFile.mktemp</span>() → <span class="type">String</span><br>
|
||||
<span class="method-name">TempFile.mktemp</span>(<span class="param">suffix</span>) → <span class="type">String</span><br>
|
||||
<span class="method-name">TempFile.mktemp</span>(<span class="param">suffix</span>, <span class="param">prefix</span>) → <span class="type">String</span><br>
|
||||
<span class="method-name">TempFile.mktemp</span>(<span class="param">suffix</span>, <span class="param">prefix</span>, <span class="param">dir</span>) → <span class="type">String</span>
|
||||
</div>
|
||||
<p>Generates a unique temporary file path without creating any file. The generated name consists of the prefix, 8 random hexadecimal characters, and the suffix.</p>
|
||||
<ul class="param-list">
|
||||
<li><span class="param-name">suffix</span> <span class="param-type">(String)</span> - Suffix for the filename (default: <code>""</code>)</li>
|
||||
<li><span class="param-name">prefix</span> <span class="param-type">(String)</span> - Prefix for the filename (default: <code>"tmp"</code>)</li>
|
||||
<li><span class="param-name">dir</span> <span class="param-type">(String)</span> - Directory for the path (default: <code>gettempdir()</code>)</li>
|
||||
<li><span class="returns">Returns:</span> A file path string (file is not created)</li>
|
||||
</ul>
|
||||
<pre><code>var name = TempFile.mktemp(".txt", "data_")
|
||||
System.print(name) // e.g., /tmp/data_a1b2c3d4.txt</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">TempFile.mkstemp</span>() → <span class="type">String</span><br>
|
||||
<span class="method-name">TempFile.mkstemp</span>(<span class="param">suffix</span>) → <span class="type">String</span><br>
|
||||
<span class="method-name">TempFile.mkstemp</span>(<span class="param">suffix</span>, <span class="param">prefix</span>) → <span class="type">String</span><br>
|
||||
<span class="method-name">TempFile.mkstemp</span>(<span class="param">suffix</span>, <span class="param">prefix</span>, <span class="param">dir</span>) → <span class="type">String</span>
|
||||
</div>
|
||||
<p>Creates a temporary file atomically using exclusive creation flags (<code>O_EXCL</code>), preventing race conditions. Retries up to 100 times on name collisions.</p>
|
||||
<ul class="param-list">
|
||||
<li><span class="param-name">suffix</span> <span class="param-type">(String)</span> - Suffix for the filename (default: <code>""</code>)</li>
|
||||
<li><span class="param-name">prefix</span> <span class="param-type">(String)</span> - Prefix for the filename (default: <code>"tmp"</code>)</li>
|
||||
<li><span class="param-name">dir</span> <span class="param-type">(String)</span> - Directory for the file (default: <code>gettempdir()</code>)</li>
|
||||
<li><span class="returns">Returns:</span> The path of the newly created file</li>
|
||||
</ul>
|
||||
<pre><code>import "io" for File
|
||||
|
||||
var path = TempFile.mkstemp(".dat", "work_")
|
||||
System.print(path) // e.g., /tmp/work_e5f6a7b8.dat
|
||||
File.delete(path) // Caller must clean up</code></pre>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">TempFile.mkdtemp</span>() → <span class="type">String</span><br>
|
||||
<span class="method-name">TempFile.mkdtemp</span>(<span class="param">suffix</span>) → <span class="type">String</span><br>
|
||||
<span class="method-name">TempFile.mkdtemp</span>(<span class="param">suffix</span>, <span class="param">prefix</span>) → <span class="type">String</span><br>
|
||||
<span class="method-name">TempFile.mkdtemp</span>(<span class="param">suffix</span>, <span class="param">prefix</span>, <span class="param">dir</span>) → <span class="type">String</span>
|
||||
</div>
|
||||
<p>Creates a temporary directory. Retries up to 100 times on name collisions.</p>
|
||||
<ul class="param-list">
|
||||
<li><span class="param-name">suffix</span> <span class="param-type">(String)</span> - Suffix for the directory name (default: <code>""</code>)</li>
|
||||
<li><span class="param-name">prefix</span> <span class="param-type">(String)</span> - Prefix for the directory name (default: <code>"tmp"</code>)</li>
|
||||
<li><span class="param-name">dir</span> <span class="param-type">(String)</span> - Parent directory (default: <code>gettempdir()</code>)</li>
|
||||
<li><span class="returns">Returns:</span> The path of the newly created directory</li>
|
||||
</ul>
|
||||
<pre><code>import "io" for Directory
|
||||
|
||||
var dir = TempFile.mkdtemp("_work")
|
||||
System.print(dir) // e.g., /tmp/tmp9c0d1e2f_work
|
||||
Directory.delete(dir) // Caller must clean up</code></pre>
|
||||
|
||||
<h2>NamedTemporaryFile Class</h2>
|
||||
|
||||
<div class="class-header">
|
||||
<h3>NamedTemporaryFile</h3>
|
||||
<p>A temporary file with a visible name that is optionally deleted on close</p>
|
||||
</div>
|
||||
|
||||
<h3>Constructors</h3>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">NamedTemporaryFile.new</span>() → <span class="type">NamedTemporaryFile</span><br>
|
||||
<span class="method-name">NamedTemporaryFile.new</span>(<span class="param">suffix</span>) → <span class="type">NamedTemporaryFile</span><br>
|
||||
<span class="method-name">NamedTemporaryFile.new</span>(<span class="param">suffix</span>, <span class="param">prefix</span>) → <span class="type">NamedTemporaryFile</span><br>
|
||||
<span class="method-name">NamedTemporaryFile.new</span>(<span class="param">suffix</span>, <span class="param">prefix</span>, <span class="param">dir</span>) → <span class="type">NamedTemporaryFile</span><br>
|
||||
<span class="method-name">NamedTemporaryFile.new</span>(<span class="param">suffix</span>, <span class="param">prefix</span>, <span class="param">dir</span>, <span class="param">delete</span>) → <span class="type">NamedTemporaryFile</span>
|
||||
</div>
|
||||
<ul class="param-list">
|
||||
<li><span class="param-name">suffix</span> <span class="param-type">(String)</span> - Suffix for the filename (default: <code>""</code>)</li>
|
||||
<li><span class="param-name">prefix</span> <span class="param-type">(String)</span> - Prefix for the filename (default: <code>"tmp"</code>)</li>
|
||||
<li><span class="param-name">dir</span> <span class="param-type">(String|Null)</span> - Directory for the file (default: <code>null</code>, uses <code>TempFile.gettempdir()</code>)</li>
|
||||
<li><span class="param-name">delete</span> <span class="param-type">(Bool)</span> - Whether to delete the file on close (default: <code>true</code>)</li>
|
||||
</ul>
|
||||
|
||||
<h3>Properties</h3>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">.name</span> → <span class="type">String</span>
|
||||
</div>
|
||||
<p>The full path of the temporary file.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">.path</span> → <span class="type">Path</span>
|
||||
</div>
|
||||
<p>A <code>Path</code> object for the temporary file.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">.delete</span> → <span class="type">Bool</span>
|
||||
</div>
|
||||
<p>Whether the file will be deleted on close. Can be set.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">.closed</span> → <span class="type">Bool</span>
|
||||
</div>
|
||||
<p>Whether the file has been closed.</p>
|
||||
|
||||
<h3>Methods</h3>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">.write</span>(<span class="param">content</span>)
|
||||
</div>
|
||||
<p>Writes string content to the file, replacing any existing content.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">.read</span>() → <span class="type">String</span>
|
||||
</div>
|
||||
<p>Reads and returns the file content as a string.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">.close</span>()
|
||||
</div>
|
||||
<p>Closes the file. If <code>delete</code> is <code>true</code>, the file is deleted from disk.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">.use</span>(<span class="param">fn</span>) → <span class="type">*</span>
|
||||
</div>
|
||||
<p>Executes <code>fn</code> with the file as argument and guarantees cleanup afterwards, even if an error occurs. Equivalent to Python's <code>with</code> statement.</p>
|
||||
<pre><code>NamedTemporaryFile.new(".txt").use {|f|
|
||||
f.write("temporary data")
|
||||
System.print(f.read())
|
||||
}
|
||||
// File is automatically deleted here</code></pre>
|
||||
|
||||
<h2>TemporaryDirectory Class</h2>
|
||||
|
||||
<div class="class-header">
|
||||
<h3>TemporaryDirectory</h3>
|
||||
<p>A temporary directory with recursive cleanup support</p>
|
||||
</div>
|
||||
|
||||
<h3>Constructors</h3>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">TemporaryDirectory.new</span>() → <span class="type">TemporaryDirectory</span><br>
|
||||
<span class="method-name">TemporaryDirectory.new</span>(<span class="param">suffix</span>) → <span class="type">TemporaryDirectory</span><br>
|
||||
<span class="method-name">TemporaryDirectory.new</span>(<span class="param">suffix</span>, <span class="param">prefix</span>) → <span class="type">TemporaryDirectory</span><br>
|
||||
<span class="method-name">TemporaryDirectory.new</span>(<span class="param">suffix</span>, <span class="param">prefix</span>, <span class="param">dir</span>) → <span class="type">TemporaryDirectory</span><br>
|
||||
<span class="method-name">TemporaryDirectory.new</span>(<span class="param">suffix</span>, <span class="param">prefix</span>, <span class="param">dir</span>, <span class="param">delete</span>) → <span class="type">TemporaryDirectory</span>
|
||||
</div>
|
||||
<ul class="param-list">
|
||||
<li><span class="param-name">suffix</span> <span class="param-type">(String)</span> - Suffix for the directory name (default: <code>""</code>)</li>
|
||||
<li><span class="param-name">prefix</span> <span class="param-type">(String)</span> - Prefix for the directory name (default: <code>"tmp"</code>)</li>
|
||||
<li><span class="param-name">dir</span> <span class="param-type">(String|Null)</span> - Parent directory (default: <code>null</code>, uses <code>TempFile.gettempdir()</code>)</li>
|
||||
<li><span class="param-name">delete</span> <span class="param-type">(Bool)</span> - Whether to delete the directory on cleanup (default: <code>true</code>)</li>
|
||||
</ul>
|
||||
|
||||
<h3>Properties</h3>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">.name</span> → <span class="type">String</span>
|
||||
</div>
|
||||
<p>The full path of the temporary directory.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">.path</span> → <span class="type">Path</span>
|
||||
</div>
|
||||
<p>A <code>Path</code> object for the temporary directory.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">.delete</span> → <span class="type">Bool</span>
|
||||
</div>
|
||||
<p>Whether the directory will be deleted on cleanup. Can be set.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">.closed</span> → <span class="type">Bool</span>
|
||||
</div>
|
||||
<p>Whether the directory has been cleaned up.</p>
|
||||
|
||||
<h3>Methods</h3>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">.cleanup</span>()
|
||||
</div>
|
||||
<p>Removes the directory and all its contents recursively (using <code>Path.rmtree()</code>). If <code>delete</code> is <code>false</code>, the directory is not removed.</p>
|
||||
|
||||
<div class="method-signature">
|
||||
<span class="method-name">.use</span>(<span class="param">fn</span>) → <span class="type">*</span>
|
||||
</div>
|
||||
<p>Executes <code>fn</code> with the directory as argument and guarantees cleanup afterwards, even if an error occurs.</p>
|
||||
<pre><code>TemporaryDirectory.new().use {|d|
|
||||
var path = d.name + "/data.txt"
|
||||
// Create files, do work...
|
||||
}
|
||||
// Directory and all contents automatically removed</code></pre>
|
||||
|
||||
<h2>Examples</h2>
|
||||
|
||||
<h3>Processing Files Safely</h3>
|
||||
<pre><code>import "tempfile" for NamedTemporaryFile
|
||||
import "pathlib" for Path
|
||||
|
||||
NamedTemporaryFile.new(".csv", "report_").use {|tmp|
|
||||
tmp.write("name,value\nalice,42\nbob,17")
|
||||
var data = tmp.read()
|
||||
System.print("Processing %(tmp.name)")
|
||||
System.print(data)
|
||||
}</code></pre>
|
||||
|
||||
<h3>Working Directory for Build Output</h3>
|
||||
<pre><code>import "tempfile" for TemporaryDirectory
|
||||
import "pathlib" for Path
|
||||
|
||||
TemporaryDirectory.new("_build").use {|build|
|
||||
var src = Path.new(build.name) / "output.txt"
|
||||
src.writeText("Build artifact")
|
||||
System.print("Build dir: %(build.name)")
|
||||
}
|
||||
// Build directory cleaned up automatically</code></pre>
|
||||
|
||||
<h3>Persistent Temporary Files</h3>
|
||||
<pre><code>import "tempfile" for NamedTemporaryFile
|
||||
|
||||
var tmp = NamedTemporaryFile.new(".log", "app_", null, false)
|
||||
tmp.write("Application started")
|
||||
tmp.close()
|
||||
// File persists at tmp.name after close
|
||||
System.print("Log file: %(tmp.name)")</code></pre>
|
||||
|
||||
<div class="admonition note">
|
||||
<div class="admonition-title">Note</div>
|
||||
<p>File creation via <code>mkstemp</code> uses exclusive creation flags (<code>O_EXCL</code>) for atomic file creation, preventing race conditions between checking for existence and creating the file. Random suffixes are generated using <code>Crypto.randomBytes</code> for cryptographic quality randomness.</p>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<footer class="page-footer">
|
||||
<a href="pathlib.html" class="prev">pathlib</a>
|
||||
<a href="scheduler.html" class="next">scheduler</a>
|
||||
</footer>
|
||||
</main>
|
||||
</div>
|
||||
<script src="../js/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="string.html">String</a></li>
|
||||
<li><a href="number.html">Num</a></li>
|
||||
<li><a href="http.html">http</a></li>
|
||||
<li><a href="websocket.html">websocket</a></li>
|
||||
<li><a href="tls.html">tls</a></li>
|
||||
@ -58,6 +60,7 @@
|
||||
<li><a href="datetime.html">datetime</a></li>
|
||||
<li><a href="timer.html" class="active">timer</a></li>
|
||||
<li><a href="io.html">io</a></li>
|
||||
<li><a href="pathlib.html">pathlib</a></li>
|
||||
<li><a href="scheduler.html">scheduler</a></li>
|
||||
<li><a href="math.html">math</a></li>
|
||||
</ul>
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="string.html">String</a></li>
|
||||
<li><a href="number.html">Num</a></li>
|
||||
<li><a href="http.html">http</a></li>
|
||||
<li><a href="websocket.html">websocket</a></li>
|
||||
<li><a href="tls.html" class="active">tls</a></li>
|
||||
@ -58,6 +60,7 @@
|
||||
<li><a href="datetime.html">datetime</a></li>
|
||||
<li><a href="timer.html">timer</a></li>
|
||||
<li><a href="io.html">io</a></li>
|
||||
<li><a href="pathlib.html">pathlib</a></li>
|
||||
<li><a href="scheduler.html">scheduler</a></li>
|
||||
<li><a href="math.html">math</a></li>
|
||||
</ul>
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="string.html">String</a></li>
|
||||
<li><a href="number.html">Num</a></li>
|
||||
<li><a href="http.html">http</a></li>
|
||||
<li><a href="websocket.html">websocket</a></li>
|
||||
<li><a href="tls.html">tls</a></li>
|
||||
@ -58,6 +60,7 @@
|
||||
<li><a href="datetime.html">datetime</a></li>
|
||||
<li><a href="timer.html">timer</a></li>
|
||||
<li><a href="io.html">io</a></li>
|
||||
<li><a href="pathlib.html">pathlib</a></li>
|
||||
<li><a href="scheduler.html">scheduler</a></li>
|
||||
<li><a href="math.html">math</a></li>
|
||||
<li><a href="uuid.html" class="active">uuid</a></li>
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="string.html">String</a></li>
|
||||
<li><a href="number.html">Num</a></li>
|
||||
<li><a href="http.html">http</a></li>
|
||||
<li><a href="websocket.html">websocket</a></li>
|
||||
<li><a href="tls.html">tls</a></li>
|
||||
@ -58,6 +60,7 @@
|
||||
<li><a href="datetime.html">datetime</a></li>
|
||||
<li><a href="timer.html">timer</a></li>
|
||||
<li><a href="io.html">io</a></li>
|
||||
<li><a href="pathlib.html">pathlib</a></li>
|
||||
<li><a href="scheduler.html">scheduler</a></li>
|
||||
<li><a href="math.html">math</a></li>
|
||||
<li><a href="uuid.html">uuid</a></li>
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="string.html">String</a></li>
|
||||
<li><a href="number.html">Num</a></li>
|
||||
<li><a href="http.html">http</a></li>
|
||||
<li><a href="websocket.html">websocket</a></li>
|
||||
<li><a href="tls.html">tls</a></li>
|
||||
@ -58,6 +60,7 @@
|
||||
<li><a href="datetime.html">datetime</a></li>
|
||||
<li><a href="timer.html">timer</a></li>
|
||||
<li><a href="io.html">io</a></li>
|
||||
<li><a href="pathlib.html">pathlib</a></li>
|
||||
<li><a href="scheduler.html">scheduler</a></li>
|
||||
<li><a href="math.html">math</a></li>
|
||||
<li><a href="uuid.html">uuid</a></li>
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="index.html">Overview</a></li>
|
||||
<li><a href="string.html">String</a></li>
|
||||
<li><a href="number.html">Num</a></li>
|
||||
<li><a href="http.html">http</a></li>
|
||||
<li><a href="websocket.html" class="active">websocket</a></li>
|
||||
<li><a href="tls.html">tls</a></li>
|
||||
@ -58,6 +60,7 @@
|
||||
<li><a href="datetime.html">datetime</a></li>
|
||||
<li><a href="timer.html">timer</a></li>
|
||||
<li><a href="io.html">io</a></li>
|
||||
<li><a href="pathlib.html">pathlib</a></li>
|
||||
<li><a href="scheduler.html">scheduler</a></li>
|
||||
<li><a href="math.html">math</a></li>
|
||||
</ul>
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="../api/index.html">Overview</a></li>
|
||||
<li><a href="../api/string.html">String</a></li>
|
||||
<li><a href="../api/number.html">Num</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>
|
||||
@ -58,6 +60,7 @@
|
||||
<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/pathlib.html">pathlib</a></li>
|
||||
<li><a href="../api/scheduler.html">scheduler</a></li>
|
||||
<li><a href="../api/math.html">math</a></li>
|
||||
</ul>
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="../api/index.html">Overview</a></li>
|
||||
<li><a href="../api/string.html">String</a></li>
|
||||
<li><a href="../api/number.html">Num</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>
|
||||
@ -58,6 +60,7 @@
|
||||
<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/pathlib.html">pathlib</a></li>
|
||||
<li><a href="../api/scheduler.html">scheduler</a></li>
|
||||
<li><a href="../api/math.html">math</a></li>
|
||||
</ul>
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="../api/index.html">Overview</a></li>
|
||||
<li><a href="../api/string.html">String</a></li>
|
||||
<li><a href="../api/number.html">Num</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>
|
||||
@ -58,6 +60,7 @@
|
||||
<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/pathlib.html">pathlib</a></li>
|
||||
<li><a href="../api/scheduler.html">scheduler</a></li>
|
||||
<li><a href="../api/math.html">math</a></li>
|
||||
</ul>
|
||||
@ -139,7 +142,7 @@ sudo apt-get install build-essential libssl-dev git python3</code></pre>
|
||||
<h3>Build</h3>
|
||||
<pre><code>git clone https://github.com/wren-lang/wren-cli.git
|
||||
cd wren-cli
|
||||
cd projects/make && make</code></pre>
|
||||
make build</code></pre>
|
||||
|
||||
<p>The binary will be created at <code>bin/wren_cli</code>.</p>
|
||||
|
||||
@ -221,7 +224,7 @@ cd projects/make.bsd && gmake</code></pre>
|
||||
<pre><code>bin/wren_cli --version</code></pre>
|
||||
|
||||
<p>Run the test suite:</p>
|
||||
<pre><code>python3 util/test.py</code></pre>
|
||||
<pre><code>make tests</code></pre>
|
||||
|
||||
<p>Start the REPL:</p>
|
||||
<pre><code>bin/wren_cli</code></pre>
|
||||
@ -242,7 +245,7 @@ cd projects/make.bsd && gmake</code></pre>
|
||||
<h3>Build Errors</h3>
|
||||
<p>Try cleaning and rebuilding:</p>
|
||||
<pre><code>make clean
|
||||
make</code></pre>
|
||||
make build</code></pre>
|
||||
|
||||
<h3>Test Failures</h3>
|
||||
<p>Run a specific test module to isolate issues:</p>
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="../api/index.html">Overview</a></li>
|
||||
<li><a href="../api/string.html">String</a></li>
|
||||
<li><a href="../api/number.html">Num</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>
|
||||
@ -58,6 +60,7 @@
|
||||
<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/pathlib.html">pathlib</a></li>
|
||||
<li><a href="../api/scheduler.html">scheduler</a></li>
|
||||
<li><a href="../api/math.html">math</a></li>
|
||||
</ul>
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="../api/index.html">Overview</a></li>
|
||||
<li><a href="../api/string.html">String</a></li>
|
||||
<li><a href="../api/number.html">Num</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>
|
||||
@ -58,6 +60,7 @@
|
||||
<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/pathlib.html">pathlib</a></li>
|
||||
<li><a href="../api/scheduler.html">scheduler</a></li>
|
||||
<li><a href="../api/math.html">math</a></li>
|
||||
</ul>
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="../api/index.html">Overview</a></li>
|
||||
<li><a href="../api/string.html">String</a></li>
|
||||
<li><a href="../api/number.html">Num</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>
|
||||
@ -58,6 +60,7 @@
|
||||
<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/pathlib.html">pathlib</a></li>
|
||||
<li><a href="../api/scheduler.html">scheduler</a></li>
|
||||
<li><a href="../api/math.html">math</a></li>
|
||||
</ul>
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="../api/index.html">Overview</a></li>
|
||||
<li><a href="../api/string.html">String</a></li>
|
||||
<li><a href="../api/number.html">Num</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>
|
||||
@ -58,6 +60,7 @@
|
||||
<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/pathlib.html">pathlib</a></li>
|
||||
<li><a href="../api/scheduler.html">scheduler</a></li>
|
||||
<li><a href="../api/math.html">math</a></li>
|
||||
</ul>
|
||||
@ -391,7 +394,7 @@ 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>
|
||||
<p>For full API documentation, see the <a href="../api/io.html">IO module reference</a>. For object-oriented path manipulation with glob, walk, and tree operations, see the <a href="../api/pathlib.html">pathlib module reference</a>.</p>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="../api/index.html">Overview</a></li>
|
||||
<li><a href="../api/string.html">String</a></li>
|
||||
<li><a href="../api/number.html">Num</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>
|
||||
@ -58,6 +60,7 @@
|
||||
<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/pathlib.html">pathlib</a></li>
|
||||
<li><a href="../api/scheduler.html">scheduler</a></li>
|
||||
<li><a href="../api/math.html">math</a></li>
|
||||
</ul>
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="../api/index.html">Overview</a></li>
|
||||
<li><a href="../api/string.html">String</a></li>
|
||||
<li><a href="../api/number.html">Num</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>
|
||||
@ -58,6 +60,7 @@
|
||||
<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/pathlib.html">pathlib</a></li>
|
||||
<li><a href="../api/scheduler.html">scheduler</a></li>
|
||||
<li><a href="../api/math.html">math</a></li>
|
||||
</ul>
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="../api/index.html">Overview</a></li>
|
||||
<li><a href="../api/string.html">String</a></li>
|
||||
<li><a href="../api/number.html">Num</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>
|
||||
@ -58,6 +60,7 @@
|
||||
<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/pathlib.html">pathlib</a></li>
|
||||
<li><a href="../api/scheduler.html">scheduler</a></li>
|
||||
<li><a href="../api/math.html">math</a></li>
|
||||
</ul>
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="../api/index.html">Overview</a></li>
|
||||
<li><a href="../api/string.html">String</a></li>
|
||||
<li><a href="../api/number.html">Num</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>
|
||||
@ -58,6 +60,7 @@
|
||||
<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/pathlib.html">pathlib</a></li>
|
||||
<li><a href="../api/scheduler.html">scheduler</a></li>
|
||||
<li><a href="../api/math.html">math</a></li>
|
||||
</ul>
|
||||
|
||||
@ -58,6 +58,7 @@
|
||||
<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/pathlib.html">pathlib</a></li>
|
||||
<li><a href="api/scheduler.html">scheduler</a></li>
|
||||
<li><a href="api/math.html">math</a></li>
|
||||
</ul>
|
||||
@ -148,6 +149,7 @@
|
||||
<a href="api/signal.html" class="module-card">signal</a>
|
||||
<a href="api/subprocess.html" class="module-card">subprocess</a>
|
||||
<a href="api/io.html" class="module-card">io</a>
|
||||
<a href="api/pathlib.html" class="module-card">pathlib</a>
|
||||
</div>
|
||||
|
||||
<h3>Data & Time</h3>
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="../api/index.html">Overview</a></li>
|
||||
<li><a href="../api/string.html">String</a></li>
|
||||
<li><a href="../api/number.html">Num</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>
|
||||
@ -58,6 +60,7 @@
|
||||
<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/pathlib.html">pathlib</a></li>
|
||||
<li><a href="../api/scheduler.html">scheduler</a></li>
|
||||
<li><a href="../api/math.html">math</a></li>
|
||||
</ul>
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="../api/index.html">Overview</a></li>
|
||||
<li><a href="../api/string.html">String</a></li>
|
||||
<li><a href="../api/number.html">Num</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>
|
||||
@ -58,6 +60,7 @@
|
||||
<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/pathlib.html">pathlib</a></li>
|
||||
<li><a href="../api/scheduler.html">scheduler</a></li>
|
||||
<li><a href="../api/math.html">math</a></li>
|
||||
</ul>
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="../api/index.html">Overview</a></li>
|
||||
<li><a href="../api/string.html">String</a></li>
|
||||
<li><a href="../api/number.html">Num</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>
|
||||
@ -58,6 +60,7 @@
|
||||
<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/pathlib.html">pathlib</a></li>
|
||||
<li><a href="../api/scheduler.html">scheduler</a></li>
|
||||
<li><a href="../api/math.html">math</a></li>
|
||||
</ul>
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="../api/index.html">Overview</a></li>
|
||||
<li><a href="../api/string.html">String</a></li>
|
||||
<li><a href="../api/number.html">Num</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>
|
||||
@ -58,6 +60,7 @@
|
||||
<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/pathlib.html">pathlib</a></li>
|
||||
<li><a href="../api/scheduler.html">scheduler</a></li>
|
||||
<li><a href="../api/math.html">math</a></li>
|
||||
</ul>
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="../api/index.html">Overview</a></li>
|
||||
<li><a href="../api/string.html">String</a></li>
|
||||
<li><a href="../api/number.html">Num</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>
|
||||
@ -58,6 +60,7 @@
|
||||
<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/pathlib.html">pathlib</a></li>
|
||||
<li><a href="../api/scheduler.html">scheduler</a></li>
|
||||
<li><a href="../api/math.html">math</a></li>
|
||||
</ul>
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="../api/index.html">Overview</a></li>
|
||||
<li><a href="../api/string.html">String</a></li>
|
||||
<li><a href="../api/number.html">Num</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>
|
||||
@ -58,6 +60,7 @@
|
||||
<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/pathlib.html">pathlib</a></li>
|
||||
<li><a href="../api/scheduler.html">scheduler</a></li>
|
||||
<li><a href="../api/math.html">math</a></li>
|
||||
</ul>
|
||||
@ -215,6 +218,11 @@ System.print(data["name"])</code></pre>
|
||||
<td>File I/O</td>
|
||||
<td>File, Directory, Stdin</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="../api/pathlib.html">pathlib</a></td>
|
||||
<td>Filesystem paths</td>
|
||||
<td>Path, PurePath</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="../api/scheduler.html">scheduler</a></td>
|
||||
<td>Async scheduling</td>
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="../api/index.html">Overview</a></li>
|
||||
<li><a href="../api/string.html">String</a></li>
|
||||
<li><a href="../api/number.html">Num</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>
|
||||
@ -58,6 +60,7 @@
|
||||
<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/pathlib.html">pathlib</a></li>
|
||||
<li><a href="../api/scheduler.html">scheduler</a></li>
|
||||
<li><a href="../api/math.html">math</a></li>
|
||||
</ul>
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="../api/index.html">Overview</a></li>
|
||||
<li><a href="../api/string.html">String</a></li>
|
||||
<li><a href="../api/number.html">Num</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>
|
||||
@ -58,6 +60,7 @@
|
||||
<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/pathlib.html">pathlib</a></li>
|
||||
<li><a href="../api/scheduler.html">scheduler</a></li>
|
||||
<li><a href="../api/math.html">math</a></li>
|
||||
</ul>
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="../api/index.html">Overview</a></li>
|
||||
<li><a href="../api/string.html">String</a></li>
|
||||
<li><a href="../api/number.html">Num</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>
|
||||
@ -58,6 +60,7 @@
|
||||
<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/pathlib.html">pathlib</a></li>
|
||||
<li><a href="../api/scheduler.html">scheduler</a></li>
|
||||
<li><a href="../api/math.html">math</a></li>
|
||||
</ul>
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="../api/index.html">Overview</a></li>
|
||||
<li><a href="../api/string.html">String</a></li>
|
||||
<li><a href="../api/number.html">Num</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>
|
||||
@ -58,6 +60,7 @@
|
||||
<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/pathlib.html">pathlib</a></li>
|
||||
<li><a href="../api/scheduler.html">scheduler</a></li>
|
||||
<li><a href="../api/math.html">math</a></li>
|
||||
</ul>
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="../api/index.html">Overview</a></li>
|
||||
<li><a href="../api/string.html">String</a></li>
|
||||
<li><a href="../api/number.html">Num</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>
|
||||
@ -58,6 +60,7 @@
|
||||
<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/pathlib.html">pathlib</a></li>
|
||||
<li><a href="../api/scheduler.html">scheduler</a></li>
|
||||
<li><a href="../api/math.html">math</a></li>
|
||||
</ul>
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
<span class="section-title">API Reference</span>
|
||||
<ul>
|
||||
<li><a href="../api/index.html">Overview</a></li>
|
||||
<li><a href="../api/string.html">String</a></li>
|
||||
<li><a href="../api/number.html">Num</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>
|
||||
@ -58,6 +60,7 @@
|
||||
<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/pathlib.html">pathlib</a></li>
|
||||
<li><a href="../api/scheduler.html">scheduler</a></li>
|
||||
<li><a href="../api/math.html">math</a></li>
|
||||
</ul>
|
||||
|
||||
20
recursion_error.wren
vendored
Normal file
20
recursion_error.wren
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
import "io" for File, Directory
|
||||
|
||||
|
||||
var listWrenFiles
|
||||
|
||||
listWrenFiles = Fn.new { |path|
|
||||
var items = Directory.list(path)
|
||||
|
||||
for (item in items) {
|
||||
var fullPath = "%(path)/%(item)"
|
||||
|
||||
if (Directory.exists(fullPath)) {
|
||||
listWrenFiles.call(fullPath)
|
||||
} else if (item.endsWith(".wren")) {
|
||||
System.print(fullPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
listWrenFiles.call(".")
|
||||
@ -28,6 +28,7 @@
|
||||
#include "signal.wren.inc"
|
||||
#include "sqlite.wren.inc"
|
||||
#include "subprocess.wren.inc"
|
||||
#include "tempfile.wren.inc"
|
||||
#include "timer.wren.inc"
|
||||
#include "tls.wren.inc"
|
||||
#include "uuid.wren.inc"
|
||||
@ -504,6 +505,8 @@ static ModuleRegistry modules[] =
|
||||
STATIC_METHOD("run_(_,_)", subprocessRun)
|
||||
END_CLASS
|
||||
END_MODULE
|
||||
MODULE(tempfile)
|
||||
END_MODULE
|
||||
MODULE(timer)
|
||||
CLASS(Timer)
|
||||
STATIC_METHOD("startTimer_(_,_)", timerStartTimer)
|
||||
|
||||
@ -156,7 +156,7 @@ void directoryCreate(WrenVM* vm)
|
||||
{
|
||||
const char* path = wrenGetSlotString(vm, 1);
|
||||
uv_fs_t* request = createRequest(wrenGetSlotHandle(vm, 2));
|
||||
uv_fs_mkdir(getLoop(), request, path, 0, fileDirectoryCallback);
|
||||
uv_fs_mkdir(getLoop(), request, path, 0777, fileDirectoryCallback);
|
||||
}
|
||||
|
||||
void directoryDelete(WrenVM* vm)
|
||||
|
||||
81
src/module/jinja.wren
vendored
81
src/module/jinja.wren
vendored
@ -1,6 +1,7 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "io" for File
|
||||
import "markdown" for Markdown
|
||||
|
||||
class Token {
|
||||
static TEXT { "TEXT" }
|
||||
@ -745,6 +746,34 @@ class FilterBlockNode is Node {
|
||||
}
|
||||
}
|
||||
|
||||
class MarkdownToHtmlNode is Node {
|
||||
construct new(body) {
|
||||
_body = body
|
||||
}
|
||||
|
||||
render(ctx) {
|
||||
var content = ""
|
||||
for (node in _body) {
|
||||
content = content + node.render(ctx)
|
||||
}
|
||||
return Markdown.toHtml(content)
|
||||
}
|
||||
}
|
||||
|
||||
class MarkdownFromHtmlNode is Node {
|
||||
construct new(body) {
|
||||
_body = body
|
||||
}
|
||||
|
||||
render(ctx) {
|
||||
var content = ""
|
||||
for (node in _body) {
|
||||
content = content + node.render(ctx)
|
||||
}
|
||||
return Markdown.fromHtml(content)
|
||||
}
|
||||
}
|
||||
|
||||
class Expression {
|
||||
evaluate(ctx) { null }
|
||||
}
|
||||
@ -1172,6 +1201,8 @@ class Filters {
|
||||
if (name == "indent") return indent(value, args.count > 0 ? args[0] : 4, args.count > 1 ? args[1] : false)
|
||||
if (name == "tojson") return tojson(value)
|
||||
if (name == "debug") return debug(value)
|
||||
if (name == "markdown") return SafeString.new(Markdown.toHtml(value.toString))
|
||||
if (name == "markdownfromhtml") return Markdown.fromHtml(value.toString)
|
||||
Fiber.abort(TemplateError.new("Unknown filter: %(name)", 0, 0).toString)
|
||||
}
|
||||
|
||||
@ -1801,6 +1832,8 @@ class Parser {
|
||||
if (tagName == "macro") return parseMacro_()
|
||||
if (tagName == "raw") return parseRaw_()
|
||||
if (tagName == "filter") return parseFilterBlock_()
|
||||
if (tagName == "markdowntohtml") return parseMarkdownToHtml_()
|
||||
if (tagName == "markdownfromhtml") return parseMarkdownFromHtml_()
|
||||
|
||||
Fiber.abort(TemplateError.new("Unknown block tag: %(tagName)", nameToken.line, nameToken.col).toString)
|
||||
}
|
||||
@ -2180,6 +2213,54 @@ class Parser {
|
||||
Fiber.abort(TemplateError.new("Unclosed filter tag", 0, 0).toString)
|
||||
}
|
||||
|
||||
parseMarkdownToHtml_() {
|
||||
consumeBlockEnd_()
|
||||
var body = []
|
||||
while (!isAtEnd_()) {
|
||||
var token = peek_()
|
||||
if (token.type == Token.BLOCK_START || token.type == Token.BLOCK_START_TRIM) {
|
||||
advance_()
|
||||
var nextName = peek_()
|
||||
if (nextName.type == Token.NAME && nextName.value == "endmarkdowntohtml") {
|
||||
advance_()
|
||||
consumeBlockEnd_()
|
||||
return MarkdownToHtmlNode.new(body)
|
||||
}
|
||||
_pos = _pos - 1
|
||||
var innerNode = parseInnerNode_()
|
||||
if (innerNode != null) body.add(innerNode)
|
||||
} else {
|
||||
var innerNode = parseInnerNode_()
|
||||
if (innerNode != null) body.add(innerNode)
|
||||
}
|
||||
}
|
||||
Fiber.abort(TemplateError.new("Unclosed markdowntohtml tag", 0, 0).toString)
|
||||
}
|
||||
|
||||
parseMarkdownFromHtml_() {
|
||||
consumeBlockEnd_()
|
||||
var body = []
|
||||
while (!isAtEnd_()) {
|
||||
var token = peek_()
|
||||
if (token.type == Token.BLOCK_START || token.type == Token.BLOCK_START_TRIM) {
|
||||
advance_()
|
||||
var nextName = peek_()
|
||||
if (nextName.type == Token.NAME && nextName.value == "endmarkdownfromhtml") {
|
||||
advance_()
|
||||
consumeBlockEnd_()
|
||||
return MarkdownFromHtmlNode.new(body)
|
||||
}
|
||||
_pos = _pos - 1
|
||||
var innerNode = parseInnerNode_()
|
||||
if (innerNode != null) body.add(innerNode)
|
||||
} else {
|
||||
var innerNode = parseInnerNode_()
|
||||
if (innerNode != null) body.add(innerNode)
|
||||
}
|
||||
}
|
||||
Fiber.abort(TemplateError.new("Unclosed markdownfromhtml tag", 0, 0).toString)
|
||||
}
|
||||
|
||||
parseInnerNode_() {
|
||||
var token = peek_()
|
||||
|
||||
|
||||
@ -5,6 +5,7 @@ static const char* jinjaModuleSource =
|
||||
"// retoor <retoor@molodetz.nl>\n"
|
||||
"\n"
|
||||
"import \"io\" for File\n"
|
||||
"import \"markdown\" for Markdown\n"
|
||||
"\n"
|
||||
"class Token {\n"
|
||||
" static TEXT { \"TEXT\" }\n"
|
||||
@ -749,6 +750,34 @@ static const char* jinjaModuleSource =
|
||||
" }\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"class MarkdownToHtmlNode is Node {\n"
|
||||
" construct new(body) {\n"
|
||||
" _body = body\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" render(ctx) {\n"
|
||||
" var content = \"\"\n"
|
||||
" for (node in _body) {\n"
|
||||
" content = content + node.render(ctx)\n"
|
||||
" }\n"
|
||||
" return Markdown.toHtml(content)\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"class MarkdownFromHtmlNode is Node {\n"
|
||||
" construct new(body) {\n"
|
||||
" _body = body\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" render(ctx) {\n"
|
||||
" var content = \"\"\n"
|
||||
" for (node in _body) {\n"
|
||||
" content = content + node.render(ctx)\n"
|
||||
" }\n"
|
||||
" return Markdown.fromHtml(content)\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"class Expression {\n"
|
||||
" evaluate(ctx) { null }\n"
|
||||
"}\n"
|
||||
@ -1176,6 +1205,8 @@ static const char* jinjaModuleSource =
|
||||
" if (name == \"indent\") return indent(value, args.count > 0 ? args[0] : 4, args.count > 1 ? args[1] : false)\n"
|
||||
" if (name == \"tojson\") return tojson(value)\n"
|
||||
" if (name == \"debug\") return debug(value)\n"
|
||||
" if (name == \"markdown\") return SafeString.new(Markdown.toHtml(value.toString))\n"
|
||||
" if (name == \"markdownfromhtml\") return Markdown.fromHtml(value.toString)\n"
|
||||
" Fiber.abort(TemplateError.new(\"Unknown filter: %(name)\", 0, 0).toString)\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
@ -1805,6 +1836,8 @@ static const char* jinjaModuleSource =
|
||||
" if (tagName == \"macro\") return parseMacro_()\n"
|
||||
" if (tagName == \"raw\") return parseRaw_()\n"
|
||||
" if (tagName == \"filter\") return parseFilterBlock_()\n"
|
||||
" if (tagName == \"markdowntohtml\") return parseMarkdownToHtml_()\n"
|
||||
" if (tagName == \"markdownfromhtml\") return parseMarkdownFromHtml_()\n"
|
||||
"\n"
|
||||
" Fiber.abort(TemplateError.new(\"Unknown block tag: %(tagName)\", nameToken.line, nameToken.col).toString)\n"
|
||||
" }\n"
|
||||
@ -2184,6 +2217,54 @@ static const char* jinjaModuleSource =
|
||||
" Fiber.abort(TemplateError.new(\"Unclosed filter tag\", 0, 0).toString)\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" parseMarkdownToHtml_() {\n"
|
||||
" consumeBlockEnd_()\n"
|
||||
" var body = []\n"
|
||||
" while (!isAtEnd_()) {\n"
|
||||
" var token = peek_()\n"
|
||||
" if (token.type == Token.BLOCK_START || token.type == Token.BLOCK_START_TRIM) {\n"
|
||||
" advance_()\n"
|
||||
" var nextName = peek_()\n"
|
||||
" if (nextName.type == Token.NAME && nextName.value == \"endmarkdowntohtml\") {\n"
|
||||
" advance_()\n"
|
||||
" consumeBlockEnd_()\n"
|
||||
" return MarkdownToHtmlNode.new(body)\n"
|
||||
" }\n"
|
||||
" _pos = _pos - 1\n"
|
||||
" var innerNode = parseInnerNode_()\n"
|
||||
" if (innerNode != null) body.add(innerNode)\n"
|
||||
" } else {\n"
|
||||
" var innerNode = parseInnerNode_()\n"
|
||||
" if (innerNode != null) body.add(innerNode)\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" Fiber.abort(TemplateError.new(\"Unclosed markdowntohtml tag\", 0, 0).toString)\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" parseMarkdownFromHtml_() {\n"
|
||||
" consumeBlockEnd_()\n"
|
||||
" var body = []\n"
|
||||
" while (!isAtEnd_()) {\n"
|
||||
" var token = peek_()\n"
|
||||
" if (token.type == Token.BLOCK_START || token.type == Token.BLOCK_START_TRIM) {\n"
|
||||
" advance_()\n"
|
||||
" var nextName = peek_()\n"
|
||||
" if (nextName.type == Token.NAME && nextName.value == \"endmarkdownfromhtml\") {\n"
|
||||
" advance_()\n"
|
||||
" consumeBlockEnd_()\n"
|
||||
" return MarkdownFromHtmlNode.new(body)\n"
|
||||
" }\n"
|
||||
" _pos = _pos - 1\n"
|
||||
" var innerNode = parseInnerNode_()\n"
|
||||
" if (innerNode != null) body.add(innerNode)\n"
|
||||
" } else {\n"
|
||||
" var innerNode = parseInnerNode_()\n"
|
||||
" if (innerNode != null) body.add(innerNode)\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" Fiber.abort(TemplateError.new(\"Unclosed markdownfromhtml tag\", 0, 0).toString)\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" parseInnerNode_() {\n"
|
||||
" var token = peek_()\n"
|
||||
"\n"
|
||||
|
||||
@ -205,10 +205,14 @@ static void allocCallback(uv_handle_t* handle, size_t suggestedSize, uv_buf_t* b
|
||||
|
||||
static void readCallback(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf)
|
||||
{
|
||||
if (nread == 0) {
|
||||
free(buf->base);
|
||||
return;
|
||||
}
|
||||
|
||||
SocketData* data = (SocketData*)stream->data;
|
||||
WrenHandle* fiber = data->fiber;
|
||||
|
||||
// Stop reading immediately. We only want one chunk.
|
||||
uv_read_stop(stream);
|
||||
data->fiber = NULL;
|
||||
|
||||
|
||||
53
src/module/scheduler.wren
vendored
53
src/module/scheduler.wren
vendored
@ -8,15 +8,28 @@ class Scheduler {
|
||||
})
|
||||
}
|
||||
|
||||
// Called by native code.
|
||||
static resume_(fiber) { fiber.transfer() }
|
||||
static resume_(fiber, arg) { fiber.transfer(arg) }
|
||||
static resumeError_(fiber, error) { fiber.transferError(error) }
|
||||
|
||||
// wait for a method to finish that has a callback on the C side
|
||||
static await_(fn) {
|
||||
fn.call()
|
||||
return Scheduler.runNextScheduled_()
|
||||
static await_(arg) {
|
||||
if (arg is Fn) {
|
||||
arg.call()
|
||||
return Scheduler.runNextScheduled_()
|
||||
}
|
||||
if (arg is Future) return arg.await_()
|
||||
return arg
|
||||
}
|
||||
|
||||
static async_(fn) {
|
||||
return Future.new(fn)
|
||||
}
|
||||
|
||||
static scheduleTransfer_(fiber, value) {
|
||||
if (__scheduled == null) __scheduled = []
|
||||
__scheduled.add(Fiber.new {
|
||||
fiber.transfer(value)
|
||||
})
|
||||
}
|
||||
|
||||
static runNextScheduled_() {
|
||||
@ -30,4 +43,34 @@ class Scheduler {
|
||||
foreign static captureMethods_()
|
||||
}
|
||||
|
||||
class Future {
|
||||
construct new(fn) {
|
||||
_resolved = false
|
||||
_result = null
|
||||
_waiters = []
|
||||
var self = this
|
||||
Scheduler.add {
|
||||
self.resolve_(fn.call())
|
||||
}
|
||||
}
|
||||
|
||||
resolve_(value) {
|
||||
_resolved = true
|
||||
_result = value
|
||||
for (w in _waiters) {
|
||||
Scheduler.scheduleTransfer_(w, value)
|
||||
}
|
||||
_waiters = []
|
||||
}
|
||||
|
||||
await_() {
|
||||
if (_resolved) return _result
|
||||
_waiters.add(Fiber.current)
|
||||
return Scheduler.runNextScheduled_()
|
||||
}
|
||||
|
||||
isDone { _resolved }
|
||||
result { _result }
|
||||
}
|
||||
|
||||
Scheduler.captureMethods_()
|
||||
|
||||
@ -12,15 +12,28 @@ static const char* schedulerModuleSource =
|
||||
" })\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" // Called by native code.\n"
|
||||
" static resume_(fiber) { fiber.transfer() }\n"
|
||||
" static resume_(fiber, arg) { fiber.transfer(arg) }\n"
|
||||
" static resumeError_(fiber, error) { fiber.transferError(error) }\n"
|
||||
"\n"
|
||||
" // wait for a method to finish that has a callback on the C side\n"
|
||||
" static await_(fn) {\n"
|
||||
" fn.call()\n"
|
||||
" return Scheduler.runNextScheduled_()\n"
|
||||
" static await_(arg) {\n"
|
||||
" if (arg is Fn) {\n"
|
||||
" arg.call()\n"
|
||||
" return Scheduler.runNextScheduled_()\n"
|
||||
" }\n"
|
||||
" if (arg is Future) return arg.await_()\n"
|
||||
" return arg\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" static async_(fn) {\n"
|
||||
" return Future.new(fn)\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" static scheduleTransfer_(fiber, value) {\n"
|
||||
" if (__scheduled == null) __scheduled = []\n"
|
||||
" __scheduled.add(Fiber.new {\n"
|
||||
" fiber.transfer(value)\n"
|
||||
" })\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" static runNextScheduled_() {\n"
|
||||
@ -34,4 +47,34 @@ static const char* schedulerModuleSource =
|
||||
" foreign static captureMethods_()\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"class Future {\n"
|
||||
" construct new(fn) {\n"
|
||||
" _resolved = false\n"
|
||||
" _result = null\n"
|
||||
" _waiters = []\n"
|
||||
" var self = this\n"
|
||||
" Scheduler.add {\n"
|
||||
" self.resolve_(fn.call())\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" resolve_(value) {\n"
|
||||
" _resolved = true\n"
|
||||
" _result = value\n"
|
||||
" for (w in _waiters) {\n"
|
||||
" Scheduler.scheduleTransfer_(w, value)\n"
|
||||
" }\n"
|
||||
" _waiters = []\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" await_() {\n"
|
||||
" if (_resolved) return _result\n"
|
||||
" _waiters.add(Fiber.current)\n"
|
||||
" return Scheduler.runNextScheduled_()\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" isDone { _resolved }\n"
|
||||
" result { _result }\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"Scheduler.captureMethods_()\n";
|
||||
|
||||
173
src/module/tempfile.wren
vendored
Normal file
173
src/module/tempfile.wren
vendored
Normal file
@ -0,0 +1,173 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "io" for Directory, File, FileFlags
|
||||
import "os" for Platform
|
||||
import "env" for Environment
|
||||
import "crypto" for Crypto
|
||||
import "strutil" for Str
|
||||
import "bytes" for Bytes
|
||||
import "pathlib" for Path
|
||||
|
||||
class TempFile {
|
||||
static tempdir { __tempdir }
|
||||
static tempdir=(value) { __tempdir = value }
|
||||
|
||||
static gettempdir() {
|
||||
if (__tempdir != null) return __tempdir
|
||||
var candidates = ["TMPDIR", "TEMP", "TMP"]
|
||||
for (name in candidates) {
|
||||
var value = Environment.get(name)
|
||||
if (value != null && value.count > 0) return value
|
||||
}
|
||||
if (Platform.isPosix) return "/tmp"
|
||||
return "C:\\Temp"
|
||||
}
|
||||
|
||||
static gettempprefix() { "tmp" }
|
||||
|
||||
static randomSuffix_() {
|
||||
var bytes = Crypto.randomBytes(4)
|
||||
return Str.hexEncode(Bytes.fromList(bytes))
|
||||
}
|
||||
|
||||
static mktemp() { mktemp("", gettempprefix(), gettempdir()) }
|
||||
static mktemp(suffix) { mktemp(suffix, gettempprefix(), gettempdir()) }
|
||||
static mktemp(suffix, prefix) { mktemp(suffix, prefix, gettempdir()) }
|
||||
|
||||
static mktemp(suffix, prefix, dir) {
|
||||
var name = prefix + randomSuffix_() + suffix
|
||||
return dir + "/" + name
|
||||
}
|
||||
|
||||
static mkstemp() { mkstemp("", gettempprefix(), gettempdir()) }
|
||||
static mkstemp(suffix) { mkstemp(suffix, gettempprefix(), gettempdir()) }
|
||||
static mkstemp(suffix, prefix) { mkstemp(suffix, prefix, gettempdir()) }
|
||||
|
||||
static mkstemp(suffix, prefix, dir) {
|
||||
var flags = FileFlags.writeOnly | FileFlags.create | FileFlags.exclusive
|
||||
for (i in 0...100) {
|
||||
var name = prefix + randomSuffix_() + suffix
|
||||
var path = dir + "/" + name
|
||||
var file
|
||||
var error
|
||||
var fiber = Fiber.new {
|
||||
file = File.openWithFlags(path, flags)
|
||||
}
|
||||
fiber.try()
|
||||
if (fiber.error == null && file != null) {
|
||||
file.close()
|
||||
return path
|
||||
}
|
||||
}
|
||||
Fiber.abort("Failed to create temporary file after 100 attempts.")
|
||||
}
|
||||
|
||||
static mkdtemp() { mkdtemp("", gettempprefix(), gettempdir()) }
|
||||
static mkdtemp(suffix) { mkdtemp(suffix, gettempprefix(), gettempdir()) }
|
||||
static mkdtemp(suffix, prefix) { mkdtemp(suffix, prefix, gettempdir()) }
|
||||
|
||||
static mkdtemp(suffix, prefix, dir) {
|
||||
for (i in 0...100) {
|
||||
var name = prefix + randomSuffix_() + suffix
|
||||
var path = dir + "/" + name
|
||||
var p = Path.new(path)
|
||||
if (!p.exists()) {
|
||||
Directory.create(path)
|
||||
return path
|
||||
}
|
||||
}
|
||||
Fiber.abort("Failed to create temporary directory after 100 attempts.")
|
||||
}
|
||||
}
|
||||
|
||||
class NamedTemporaryFile {
|
||||
construct new() { init_("", TempFile.gettempprefix(), TempFile.gettempdir(), true) }
|
||||
construct new(suffix) { init_(suffix, TempFile.gettempprefix(), TempFile.gettempdir(), true) }
|
||||
construct new(suffix, prefix) { init_(suffix, prefix, TempFile.gettempdir(), true) }
|
||||
construct new(suffix, prefix, dir) { init_(suffix, prefix, dir, true) }
|
||||
construct new(suffix, prefix, dir, delete) { init_(suffix, prefix, dir, delete) }
|
||||
|
||||
init_(suffix, prefix, dir, delete) {
|
||||
var d = dir != null ? dir : TempFile.gettempdir()
|
||||
_name = TempFile.mkstemp(suffix, prefix, d)
|
||||
_delete = delete
|
||||
_closed = false
|
||||
}
|
||||
|
||||
name { _name }
|
||||
path { Path.new(_name) }
|
||||
delete { _delete }
|
||||
delete=(value) { _delete = value }
|
||||
closed { _closed }
|
||||
|
||||
write(content) {
|
||||
if (_closed) Fiber.abort("File is closed.")
|
||||
File.openWithFlags(_name, FileFlags.writeOnly | FileFlags.create) {|f|
|
||||
f.writeBytes(content, 0)
|
||||
}
|
||||
}
|
||||
|
||||
read() {
|
||||
if (_closed) Fiber.abort("File is closed.")
|
||||
return File.read(_name)
|
||||
}
|
||||
|
||||
close() {
|
||||
if (_closed) return
|
||||
_closed = true
|
||||
if (_delete) {
|
||||
var fiber = Fiber.new { File.delete(_name) }
|
||||
fiber.try()
|
||||
}
|
||||
}
|
||||
|
||||
use(fn) {
|
||||
var fiber = Fiber.new { fn.call(this) }
|
||||
var result = fiber.try()
|
||||
close()
|
||||
if (fiber.error != null) Fiber.abort(fiber.error)
|
||||
return result
|
||||
}
|
||||
|
||||
toString { "NamedTemporaryFile(%(name))" }
|
||||
}
|
||||
|
||||
class TemporaryDirectory {
|
||||
construct new() { init_("", TempFile.gettempprefix(), TempFile.gettempdir(), true) }
|
||||
construct new(suffix) { init_(suffix, TempFile.gettempprefix(), TempFile.gettempdir(), true) }
|
||||
construct new(suffix, prefix) { init_(suffix, prefix, TempFile.gettempdir(), true) }
|
||||
construct new(suffix, prefix, dir) { init_(suffix, prefix, dir, true) }
|
||||
construct new(suffix, prefix, dir, delete) { init_(suffix, prefix, dir, delete) }
|
||||
|
||||
init_(suffix, prefix, dir, delete) {
|
||||
var d = dir != null ? dir : TempFile.gettempdir()
|
||||
_name = TempFile.mkdtemp(suffix, prefix, d)
|
||||
_delete = delete
|
||||
_closed = false
|
||||
}
|
||||
|
||||
name { _name }
|
||||
path { Path.new(_name) }
|
||||
delete { _delete }
|
||||
delete=(value) { _delete = value }
|
||||
closed { _closed }
|
||||
|
||||
cleanup() {
|
||||
if (_closed) return
|
||||
_closed = true
|
||||
if (_delete) {
|
||||
var fiber = Fiber.new { Path.new(_name).rmtree() }
|
||||
fiber.try()
|
||||
}
|
||||
}
|
||||
|
||||
use(fn) {
|
||||
var fiber = Fiber.new { fn.call(this) }
|
||||
var result = fiber.try()
|
||||
cleanup()
|
||||
if (fiber.error != null) Fiber.abort(fiber.error)
|
||||
return result
|
||||
}
|
||||
|
||||
toString { "TemporaryDirectory(%(name))" }
|
||||
}
|
||||
177
src/module/tempfile.wren.inc
Normal file
177
src/module/tempfile.wren.inc
Normal file
@ -0,0 +1,177 @@
|
||||
// Please do not edit this file. It has been generated automatically
|
||||
// from `src/module/tempfile.wren` using `util/wren_to_c_string.py`
|
||||
|
||||
static const char* tempfileModuleSource =
|
||||
"// retoor <retoor@molodetz.nl>\n"
|
||||
"\n"
|
||||
"import \"io\" for Directory, File, FileFlags\n"
|
||||
"import \"os\" for Platform\n"
|
||||
"import \"env\" for Environment\n"
|
||||
"import \"crypto\" for Crypto\n"
|
||||
"import \"strutil\" for Str\n"
|
||||
"import \"bytes\" for Bytes\n"
|
||||
"import \"pathlib\" for Path\n"
|
||||
"\n"
|
||||
"class TempFile {\n"
|
||||
" static tempdir { __tempdir }\n"
|
||||
" static tempdir=(value) { __tempdir = value }\n"
|
||||
"\n"
|
||||
" static gettempdir() {\n"
|
||||
" if (__tempdir != null) return __tempdir\n"
|
||||
" var candidates = [\"TMPDIR\", \"TEMP\", \"TMP\"]\n"
|
||||
" for (name in candidates) {\n"
|
||||
" var value = Environment.get(name)\n"
|
||||
" if (value != null && value.count > 0) return value\n"
|
||||
" }\n"
|
||||
" if (Platform.isPosix) return \"/tmp\"\n"
|
||||
" return \"C:\\\\Temp\"\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" static gettempprefix() { \"tmp\" }\n"
|
||||
"\n"
|
||||
" static randomSuffix_() {\n"
|
||||
" var bytes = Crypto.randomBytes(4)\n"
|
||||
" return Str.hexEncode(Bytes.fromList(bytes))\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" static mktemp() { mktemp(\"\", gettempprefix(), gettempdir()) }\n"
|
||||
" static mktemp(suffix) { mktemp(suffix, gettempprefix(), gettempdir()) }\n"
|
||||
" static mktemp(suffix, prefix) { mktemp(suffix, prefix, gettempdir()) }\n"
|
||||
"\n"
|
||||
" static mktemp(suffix, prefix, dir) {\n"
|
||||
" var name = prefix + randomSuffix_() + suffix\n"
|
||||
" return dir + \"/\" + name\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" static mkstemp() { mkstemp(\"\", gettempprefix(), gettempdir()) }\n"
|
||||
" static mkstemp(suffix) { mkstemp(suffix, gettempprefix(), gettempdir()) }\n"
|
||||
" static mkstemp(suffix, prefix) { mkstemp(suffix, prefix, gettempdir()) }\n"
|
||||
"\n"
|
||||
" static mkstemp(suffix, prefix, dir) {\n"
|
||||
" var flags = FileFlags.writeOnly | FileFlags.create | FileFlags.exclusive\n"
|
||||
" for (i in 0...100) {\n"
|
||||
" var name = prefix + randomSuffix_() + suffix\n"
|
||||
" var path = dir + \"/\" + name\n"
|
||||
" var file\n"
|
||||
" var error\n"
|
||||
" var fiber = Fiber.new {\n"
|
||||
" file = File.openWithFlags(path, flags)\n"
|
||||
" }\n"
|
||||
" fiber.try()\n"
|
||||
" if (fiber.error == null && file != null) {\n"
|
||||
" file.close()\n"
|
||||
" return path\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" Fiber.abort(\"Failed to create temporary file after 100 attempts.\")\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" static mkdtemp() { mkdtemp(\"\", gettempprefix(), gettempdir()) }\n"
|
||||
" static mkdtemp(suffix) { mkdtemp(suffix, gettempprefix(), gettempdir()) }\n"
|
||||
" static mkdtemp(suffix, prefix) { mkdtemp(suffix, prefix, gettempdir()) }\n"
|
||||
"\n"
|
||||
" static mkdtemp(suffix, prefix, dir) {\n"
|
||||
" for (i in 0...100) {\n"
|
||||
" var name = prefix + randomSuffix_() + suffix\n"
|
||||
" var path = dir + \"/\" + name\n"
|
||||
" var p = Path.new(path)\n"
|
||||
" if (!p.exists()) {\n"
|
||||
" Directory.create(path)\n"
|
||||
" return path\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" Fiber.abort(\"Failed to create temporary directory after 100 attempts.\")\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"class NamedTemporaryFile {\n"
|
||||
" construct new() { init_(\"\", TempFile.gettempprefix(), TempFile.gettempdir(), true) }\n"
|
||||
" construct new(suffix) { init_(suffix, TempFile.gettempprefix(), TempFile.gettempdir(), true) }\n"
|
||||
" construct new(suffix, prefix) { init_(suffix, prefix, TempFile.gettempdir(), true) }\n"
|
||||
" construct new(suffix, prefix, dir) { init_(suffix, prefix, dir, true) }\n"
|
||||
" construct new(suffix, prefix, dir, delete) { init_(suffix, prefix, dir, delete) }\n"
|
||||
"\n"
|
||||
" init_(suffix, prefix, dir, delete) {\n"
|
||||
" var d = dir != null ? dir : TempFile.gettempdir()\n"
|
||||
" _name = TempFile.mkstemp(suffix, prefix, d)\n"
|
||||
" _delete = delete\n"
|
||||
" _closed = false\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" name { _name }\n"
|
||||
" path { Path.new(_name) }\n"
|
||||
" delete { _delete }\n"
|
||||
" delete=(value) { _delete = value }\n"
|
||||
" closed { _closed }\n"
|
||||
"\n"
|
||||
" write(content) {\n"
|
||||
" if (_closed) Fiber.abort(\"File is closed.\")\n"
|
||||
" File.openWithFlags(_name, FileFlags.writeOnly | FileFlags.create) {|f|\n"
|
||||
" f.writeBytes(content, 0)\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" read() {\n"
|
||||
" if (_closed) Fiber.abort(\"File is closed.\")\n"
|
||||
" return File.read(_name)\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" close() {\n"
|
||||
" if (_closed) return\n"
|
||||
" _closed = true\n"
|
||||
" if (_delete) {\n"
|
||||
" var fiber = Fiber.new { File.delete(_name) }\n"
|
||||
" fiber.try()\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" use(fn) {\n"
|
||||
" var fiber = Fiber.new { fn.call(this) }\n"
|
||||
" var result = fiber.try()\n"
|
||||
" close()\n"
|
||||
" if (fiber.error != null) Fiber.abort(fiber.error)\n"
|
||||
" return result\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" toString { \"NamedTemporaryFile(%(name))\" }\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"class TemporaryDirectory {\n"
|
||||
" construct new() { init_(\"\", TempFile.gettempprefix(), TempFile.gettempdir(), true) }\n"
|
||||
" construct new(suffix) { init_(suffix, TempFile.gettempprefix(), TempFile.gettempdir(), true) }\n"
|
||||
" construct new(suffix, prefix) { init_(suffix, prefix, TempFile.gettempdir(), true) }\n"
|
||||
" construct new(suffix, prefix, dir) { init_(suffix, prefix, dir, true) }\n"
|
||||
" construct new(suffix, prefix, dir, delete) { init_(suffix, prefix, dir, delete) }\n"
|
||||
"\n"
|
||||
" init_(suffix, prefix, dir, delete) {\n"
|
||||
" var d = dir != null ? dir : TempFile.gettempdir()\n"
|
||||
" _name = TempFile.mkdtemp(suffix, prefix, d)\n"
|
||||
" _delete = delete\n"
|
||||
" _closed = false\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" name { _name }\n"
|
||||
" path { Path.new(_name) }\n"
|
||||
" delete { _delete }\n"
|
||||
" delete=(value) { _delete = value }\n"
|
||||
" closed { _closed }\n"
|
||||
"\n"
|
||||
" cleanup() {\n"
|
||||
" if (_closed) return\n"
|
||||
" _closed = true\n"
|
||||
" if (_delete) {\n"
|
||||
" var fiber = Fiber.new { Path.new(_name).rmtree() }\n"
|
||||
" fiber.try()\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" use(fn) {\n"
|
||||
" var fiber = Fiber.new { fn.call(this) }\n"
|
||||
" var result = fiber.try()\n"
|
||||
" cleanup()\n"
|
||||
" if (fiber.error != null) Fiber.abort(fiber.error)\n"
|
||||
" return result\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" toString { \"TemporaryDirectory(%(name))\" }\n"
|
||||
"}\n";
|
||||
15
test/argparse/choices.wren
vendored
Normal file
15
test/argparse/choices.wren
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "argparse" for ArgumentParser
|
||||
|
||||
var parser = ArgumentParser.new()
|
||||
parser.addArgument("-l", {"long": "--level", "choices": ["debug", "info", "warn", "error"]})
|
||||
|
||||
var args = parser.parseArgs(["-l", "info"])
|
||||
System.print(args["level"]) // expect: info
|
||||
|
||||
var args2 = parser.parseArgs(["--level", "error"])
|
||||
System.print(args2["level"]) // expect: error
|
||||
|
||||
var args3 = parser.parseArgs(["--level", "debug"])
|
||||
System.print(args3["level"]) // expect: debug
|
||||
8
test/argparse/error_invalid_choice.wren
vendored
Normal file
8
test/argparse/error_invalid_choice.wren
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "argparse" for ArgumentParser
|
||||
|
||||
var parser = ArgumentParser.new()
|
||||
parser.addArgument("-l", {"choices": ["debug", "info", "warn", "error"]})
|
||||
|
||||
var args = parser.parseArgs(["-l", "trace"]) // expect runtime error: Invalid choice 'trace' for -l
|
||||
8
test/argparse/error_missing_option.wren
vendored
Normal file
8
test/argparse/error_missing_option.wren
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "argparse" for ArgumentParser
|
||||
|
||||
var parser = ArgumentParser.new()
|
||||
parser.addArgument("-o", {"required": true})
|
||||
|
||||
var args = parser.parseArgs([]) // expect runtime error: Missing required option: -o
|
||||
8
test/argparse/error_missing_required.wren
vendored
Normal file
8
test/argparse/error_missing_required.wren
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "argparse" for ArgumentParser
|
||||
|
||||
var parser = ArgumentParser.new()
|
||||
parser.addArgument("filename")
|
||||
|
||||
var args = parser.parseArgs([]) // expect runtime error: Missing required argument: filename
|
||||
8
test/argparse/error_nargs_plus.wren
vendored
Normal file
8
test/argparse/error_nargs_plus.wren
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "argparse" for ArgumentParser
|
||||
|
||||
var parser = ArgumentParser.new()
|
||||
parser.addArgument("-f", {"nargs": "+"})
|
||||
|
||||
var args = parser.parseArgs(["-f"]) // expect runtime error: Option -f requires at least one value
|
||||
7
test/argparse/error_unexpected_arg.wren
vendored
Normal file
7
test/argparse/error_unexpected_arg.wren
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "argparse" for ArgumentParser
|
||||
|
||||
var parser = ArgumentParser.new()
|
||||
|
||||
var args = parser.parseArgs(["extra"]) // expect runtime error: Unexpected argument: extra
|
||||
7
test/argparse/error_unknown_option.wren
vendored
Normal file
7
test/argparse/error_unknown_option.wren
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "argparse" for ArgumentParser
|
||||
|
||||
var parser = ArgumentParser.new()
|
||||
|
||||
var args = parser.parseArgs(["--unknown"]) // expect runtime error: Unknown option: --unknown
|
||||
21
test/argparse/help.wren
vendored
Normal file
21
test/argparse/help.wren
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "argparse" for ArgumentParser
|
||||
|
||||
var parser = ArgumentParser.new("A test program")
|
||||
parser.prog = "myapp"
|
||||
parser.addArgument("input", {"help": "Input file path"})
|
||||
parser.addArgument("-o", {"long": "--output", "help": "Output file path"})
|
||||
parser.addArgument("-v", {"long": "--verbose", "action": "storeTrue", "help": "Enable verbose mode"})
|
||||
|
||||
parser.printHelp()
|
||||
// expect: usage: myapp [options] input
|
||||
// expect:
|
||||
// expect: A test program
|
||||
// expect:
|
||||
// expect: positional arguments:
|
||||
// expect: input Input file path
|
||||
// expect:
|
||||
// expect: optional arguments:
|
||||
// expect: -o, --output Output file path
|
||||
// expect: -v, --verbose Enable verbose mode
|
||||
21
test/argparse/mixed.wren
vendored
Normal file
21
test/argparse/mixed.wren
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "argparse" for ArgumentParser
|
||||
|
||||
var parser = ArgumentParser.new()
|
||||
parser.addArgument("input")
|
||||
parser.addArgument("-o", {"long": "--output", "default": "out.txt"})
|
||||
parser.addArgument("-v", {"action": "storeTrue"})
|
||||
parser.addArgument("-n", {"type": "int", "default": 1})
|
||||
|
||||
var args = parser.parseArgs(["data.csv", "-o", "result.json", "-v", "-n", "10"])
|
||||
System.print(args["input"]) // expect: data.csv
|
||||
System.print(args["output"]) // expect: result.json
|
||||
System.print(args["v"]) // expect: true
|
||||
System.print(args["n"]) // expect: 10
|
||||
|
||||
var args2 = parser.parseArgs(["data.csv"])
|
||||
System.print(args2["input"]) // expect: data.csv
|
||||
System.print(args2["output"]) // expect: out.txt
|
||||
System.print(args2["v"]) // expect: false
|
||||
System.print(args2["n"]) // expect: 1
|
||||
16
test/argparse/nargs_num.wren
vendored
Normal file
16
test/argparse/nargs_num.wren
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "argparse" for ArgumentParser
|
||||
|
||||
var parser = ArgumentParser.new()
|
||||
parser.addArgument("-p", {"long": "--point", "nargs": 2, "type": "int"})
|
||||
|
||||
var args = parser.parseArgs(["-p", "10", "20"])
|
||||
System.print(args["point"].count) // expect: 2
|
||||
System.print(args["point"][0]) // expect: 10
|
||||
System.print(args["point"][1]) // expect: 20
|
||||
|
||||
var args2 = parser.parseArgs(["--point", "5", "15"])
|
||||
System.print(args2["point"].count) // expect: 2
|
||||
System.print(args2["point"][0]) // expect: 5
|
||||
System.print(args2["point"][1]) // expect: 15
|
||||
15
test/argparse/nargs_plus.wren
vendored
Normal file
15
test/argparse/nargs_plus.wren
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "argparse" for ArgumentParser
|
||||
|
||||
var parser = ArgumentParser.new()
|
||||
parser.addArgument("-f", {"long": "--files", "nargs": "+"})
|
||||
|
||||
var args = parser.parseArgs(["-f", "a.txt", "b.txt"])
|
||||
System.print(args["files"].count) // expect: 2
|
||||
System.print(args["files"][0]) // expect: a.txt
|
||||
System.print(args["files"][1]) // expect: b.txt
|
||||
|
||||
var args2 = parser.parseArgs(["--files", "single.txt"])
|
||||
System.print(args2["files"].count) // expect: 1
|
||||
System.print(args2["files"][0]) // expect: single.txt
|
||||
20
test/argparse/nargs_positional.wren
vendored
Normal file
20
test/argparse/nargs_positional.wren
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "argparse" for ArgumentParser
|
||||
|
||||
var parser = ArgumentParser.new()
|
||||
parser.addArgument("files", {"nargs": "*", "required": false})
|
||||
|
||||
var args = parser.parseArgs(["a.txt", "b.txt", "c.txt"])
|
||||
System.print(args["files"].count) // expect: 3
|
||||
System.print(args["files"][0]) // expect: a.txt
|
||||
System.print(args["files"][1]) // expect: b.txt
|
||||
System.print(args["files"][2]) // expect: c.txt
|
||||
|
||||
var parser2 = ArgumentParser.new()
|
||||
parser2.addArgument("files", {"nargs": "+"})
|
||||
|
||||
var args2 = parser2.parseArgs(["x.txt", "y.txt"])
|
||||
System.print(args2["files"].count) // expect: 2
|
||||
System.print(args2["files"][0]) // expect: x.txt
|
||||
System.print(args2["files"][1]) // expect: y.txt
|
||||
15
test/argparse/nargs_star.wren
vendored
Normal file
15
test/argparse/nargs_star.wren
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "argparse" for ArgumentParser
|
||||
|
||||
var parser = ArgumentParser.new()
|
||||
parser.addArgument("-f", {"long": "--files", "nargs": "*"})
|
||||
|
||||
var args = parser.parseArgs(["-f", "a.txt", "b.txt", "c.txt"])
|
||||
System.print(args["files"].count) // expect: 3
|
||||
System.print(args["files"][0]) // expect: a.txt
|
||||
System.print(args["files"][1]) // expect: b.txt
|
||||
System.print(args["files"][2]) // expect: c.txt
|
||||
|
||||
var args2 = parser.parseArgs(["--files"])
|
||||
System.print(args2["files"].count) // expect: 0
|
||||
8
test/await/async_already_resolved.wren
vendored
Normal file
8
test/await/async_already_resolved.wren
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
import "scheduler" for Scheduler, Future
|
||||
import "timer" for Timer
|
||||
|
||||
var task = async { "ready" }
|
||||
|
||||
await Timer.sleep(10)
|
||||
System.print(task.isDone) // expect: true
|
||||
System.print(await task) // expect: ready
|
||||
7
test/await/async_basic.wren
vendored
Normal file
7
test/await/async_basic.wren
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
import "scheduler" for Scheduler, Future
|
||||
import "timer" for Timer
|
||||
|
||||
var task = async { 42 }
|
||||
|
||||
var result = await task
|
||||
System.print(result) // expect: 42
|
||||
18
test/await/async_concurrent.wren
vendored
Normal file
18
test/await/async_concurrent.wren
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
import "scheduler" for Scheduler, Future
|
||||
import "timer" for Timer
|
||||
|
||||
var order = []
|
||||
|
||||
var task1 = async {
|
||||
await Timer.sleep(2)
|
||||
order.add("task1")
|
||||
}
|
||||
|
||||
var task2 = async {
|
||||
await Timer.sleep(1)
|
||||
order.add("task2")
|
||||
}
|
||||
|
||||
await task1
|
||||
await task2
|
||||
System.print(order) // expect: [task2, task1]
|
||||
5
test/await/basic.wren
vendored
Normal file
5
test/await/basic.wren
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
import "scheduler" for Scheduler
|
||||
import "timer" for Timer
|
||||
|
||||
await Timer.sleep(1)
|
||||
System.print("done") // expect: done
|
||||
11
test/await/in_method.wren
vendored
Normal file
11
test/await/in_method.wren
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
import "scheduler" for Scheduler
|
||||
import "timer" for Timer
|
||||
|
||||
class Helper {
|
||||
static run() {
|
||||
await Timer.sleep(1)
|
||||
return "completed"
|
||||
}
|
||||
}
|
||||
|
||||
System.print(Helper.run()) // expect: completed
|
||||
6
test/await/return_value.wren
vendored
Normal file
6
test/await/return_value.wren
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
import "scheduler" for Scheduler
|
||||
import "timer" for Timer
|
||||
|
||||
var result = await Timer.sleep(1)
|
||||
System.print(result == null) // expect: true
|
||||
System.print("done") // expect: done
|
||||
51
test/core/string/comparison.wren
vendored
Normal file
51
test/core/string/comparison.wren
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
System.print("apple" < "banana") // expect: true
|
||||
System.print("banana" > "apple") // expect: true
|
||||
System.print("abc" <= "abc") // expect: true
|
||||
System.print("abc" >= "abc") // expect: true
|
||||
|
||||
System.print("abc" < "abd") // expect: true
|
||||
System.print("abd" > "abc") // expect: true
|
||||
System.print("abd" < "abc") // expect: false
|
||||
System.print("abc" > "abd") // expect: false
|
||||
|
||||
System.print("abc" < "abcd") // expect: true
|
||||
System.print("abcd" > "abc") // expect: true
|
||||
System.print("abcd" < "abc") // expect: false
|
||||
System.print("abc" > "abcd") // expect: false
|
||||
|
||||
System.print("a" <= "b") // expect: true
|
||||
System.print("b" >= "a") // expect: true
|
||||
System.print("b" <= "a") // expect: false
|
||||
System.print("a" >= "b") // expect: false
|
||||
|
||||
System.print("b" < "a") // expect: false
|
||||
System.print("a" > "b") // expect: false
|
||||
|
||||
System.print("" < "a") // expect: true
|
||||
System.print("a" > "") // expect: true
|
||||
System.print("" <= "") // expect: true
|
||||
System.print("" >= "") // expect: true
|
||||
System.print("" < "") // expect: false
|
||||
System.print("" > "") // expect: false
|
||||
|
||||
System.print("a" < "a") // expect: false
|
||||
System.print("a" > "a") // expect: false
|
||||
System.print("a" <= "a") // expect: true
|
||||
System.print("a" >= "a") // expect: true
|
||||
|
||||
System.print("A" < "a") // expect: true
|
||||
System.print("a" > "A") // expect: true
|
||||
System.print("Z" < "a") // expect: true
|
||||
System.print("a" > "Z") // expect: true
|
||||
|
||||
System.print("abc" < "abc") // expect: false
|
||||
System.print("abc" > "abc") // expect: false
|
||||
System.print("abc" <= "abc") // expect: true
|
||||
System.print("abc" >= "abc") // expect: true
|
||||
|
||||
System.print("xyz" < "xya") // expect: false
|
||||
System.print("xyz" > "xya") // expect: true
|
||||
System.print("xyz" <= "xya") // expect: false
|
||||
System.print("xyz" >= "xya") // expect: true
|
||||
21
test/jinja/markdown_tags.wren
vendored
Normal file
21
test/jinja/markdown_tags.wren
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
import "jinja" for Environment, DictLoader
|
||||
|
||||
var env = Environment.new(DictLoader.new({
|
||||
"md_heading": "{\% markdowntohtml \%}# Hello{\% endmarkdowntohtml \%}",
|
||||
"md_bold": "{\% markdowntohtml \%}**bold**{\% endmarkdowntohtml \%}",
|
||||
"md_var": "{\% markdowntohtml \%}# {{ title }}{\% endmarkdowntohtml \%}",
|
||||
"html_to_md": "{\% markdownfromhtml \%}<h1>Hello</h1>{\% endmarkdownfromhtml \%}",
|
||||
"html_to_md_bold": "{\% markdownfromhtml \%}<p><strong>bold</strong></p>{\% endmarkdownfromhtml \%}",
|
||||
"filter_md": "{{ text|markdown }}",
|
||||
"filter_fromhtml": "{{ html|markdownfromhtml }}"
|
||||
}))
|
||||
|
||||
System.print(env.getTemplate("md_heading").render({})) // expect: <h1>Hello</h1>
|
||||
System.print(env.getTemplate("md_bold").render({})) // expect: <p><strong>bold</strong></p>
|
||||
System.print(env.getTemplate("md_var").render({"title": "World"})) // expect: <h1>World</h1>
|
||||
System.print(env.getTemplate("html_to_md").render({})) // expect: # Hello
|
||||
System.print(env.getTemplate("html_to_md_bold").render({})) // expect: **bold**
|
||||
System.print(env.getTemplate("filter_md").render({"text": "**strong**"})) // expect: <p><strong>strong</strong></p>
|
||||
System.print(env.getTemplate("filter_fromhtml").render({"html": "<h1>Title</h1>"})) // expect: # Title
|
||||
6
test/number/angle.wren
vendored
Normal file
6
test/number/angle.wren
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
// retoor <retoor@molodetz.nl>
|
||||
|
||||
System.print(Num.pi.toDegrees) // expect: 180
|
||||
System.print(180.toRadians == Num.pi) // expect: true
|
||||
System.print(0.toDegrees) // expect: 0
|
||||
System.print(0.toRadians) // expect: 0
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user