papagaio 0.37.3 → 0.39.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +63 -25
- package/dist/wasm/papagaio.js +0 -2
- package/dist/wasm/papagaio_wasm.js +0 -0
- package/package.json +1 -2
package/README.md
CHANGED
|
@@ -178,6 +178,14 @@ The **`$from`** operator allows you to capture processed content and assign it t
|
|
|
178
178
|
2. **Immediate Registration**: The variable is registered as an exact-match rule as soon as it is parsed. This allows for **chained assignments**.
|
|
179
179
|
3. **Output Suppression**: The entire `$from` directive is removed from the output text.
|
|
180
180
|
|
|
181
|
+
### Lexical Scopes and Sandboxing
|
|
182
|
+
|
|
183
|
+
Every block operator or preprocessing field evaluated dynamically (such as inside `$from`, `$then`, `$else`, `$while`, `$repeat`, and `$until`) is executed in its own **local nested scope**.
|
|
184
|
+
|
|
185
|
+
- **Sandboxing**: Any variable declared inside a local scope (e.g. `$B$from{local_val}` inside `$A$from{...}`) that does *not* exist in a parent scope is treated as a local variable. It will be completely destroyed and freed when the block finishes evaluating (sandboxed).
|
|
186
|
+
- **Shadowing & Upward Updates**: If a variable updated inside a local scope already exists in a parent/ancestor scope, Papagaio avoids shadowing it. Instead, it propagates the update upwards, modifying the existing variable in the parent scope.
|
|
187
|
+
- **Recursive Nesting**: Local scopes can be nested arbitrarily. Each child scope has full read/write access to variables in parent scopes, but parent or sibling scopes do not have access to variables declared exclusively in child scopes.
|
|
188
|
+
|
|
181
189
|
### Examples
|
|
182
190
|
|
|
183
191
|
#### Chained Assignments
|
|
@@ -218,25 +226,29 @@ Any variable can be treated as a list by accessing it through the `$list` modifi
|
|
|
218
226
|
### Syntax
|
|
219
227
|
|
|
220
228
|
```
|
|
221
|
-
$VARNAME$list
|
|
229
|
+
$VARNAME$list{separator}$OPERATION{...arguments}
|
|
222
230
|
```
|
|
223
231
|
|
|
224
232
|
### Operations
|
|
225
233
|
|
|
226
234
|
| Operation | Signature | Emits | Mutates |
|
|
227
235
|
|---|---|---|---|
|
|
228
|
-
| `get` | `$V$list
|
|
229
|
-
| `set` | `$V$list
|
|
230
|
-
| `push` | `$V$list
|
|
231
|
-
| `pop` | `$V$list
|
|
232
|
-
| `shift` | `$V$list
|
|
233
|
-
| `unshift` | `$V$list
|
|
234
|
-
| `insert` | `$V$list
|
|
235
|
-
| `remove` | `$V$list
|
|
236
|
-
| `swap` | `$V$list
|
|
237
|
-
| `reverse` | `$V$list
|
|
238
|
-
| `count` | `$V$list
|
|
239
|
-
| `join` | `$V$list
|
|
236
|
+
| `get` | `$V$list{sep}$get{idx}` | Element at index | No |
|
|
237
|
+
| `set` | `$V$list{sep}$set{idx}{content}` | Nothing | Yes |
|
|
238
|
+
| `push` | `$V$list{sep}$push{content}` | Nothing | Yes |
|
|
239
|
+
| `pop` | `$V$list{sep}$pop` | Last element | Yes |
|
|
240
|
+
| `shift` | `$V$list{sep}$shift` | First element | Yes |
|
|
241
|
+
| `unshift` | `$V$list{sep}$unshift{content}` | Nothing | Yes |
|
|
242
|
+
| `insert` | `$V$list{sep}$insert{idx}{content}` | Nothing | Yes |
|
|
243
|
+
| `remove` | `$V$list{sep}$remove{idx}` | Nothing | Yes |
|
|
244
|
+
| `swap` | `$V$list{sep}$swap{idx_a}{idx_b}` | Nothing | Yes |
|
|
245
|
+
| `reverse` | `$V$list{sep}$reverse` | Nothing | Yes |
|
|
246
|
+
| `count` | `$V$list{sep}$count` | Number of elements | No |
|
|
247
|
+
| `join` | `$V$list{sep_orig}$join{sep_new}` | List with new separator | No |
|
|
248
|
+
| `slice` | `$V$list{sep}$slice{start}{end}` | Sub-list from start to end | No |
|
|
249
|
+
| `find` | `$V$list{sep}$find{pat}` | First **whole element** matching `pat` | No |
|
|
250
|
+
| `contains` | `$V$list{sep}$contains{pat}` | Index of `pat` **within** matching element | No |
|
|
251
|
+
| `replace` | `$V$list{sep}$replace{pat}{rep}` | First match found; updates the **whole element** | Yes |
|
|
240
252
|
|
|
241
253
|
**Index rules**: zero-based; negative indices count from the end (`-1` = last); out-of-range access emits `""` silently.
|
|
242
254
|
|
|
@@ -245,39 +257,42 @@ $VARNAME$list$OPERATION{separator}{...arguments}
|
|
|
245
257
|
```text
|
|
246
258
|
$FRUITS$from{apple,banana,orange}
|
|
247
259
|
|
|
248
|
-
$FRUITS$list
|
|
249
|
-
$FRUITS$list
|
|
250
|
-
$FRUITS$list
|
|
260
|
+
$FRUITS$list{,}$get{0} → apple
|
|
261
|
+
$FRUITS$list{,}$get{-1} → orange
|
|
262
|
+
$FRUITS$list{,}$count → 3
|
|
251
263
|
```
|
|
252
264
|
|
|
253
265
|
```text
|
|
254
266
|
$L$from{a,b,c}
|
|
255
|
-
$L$list
|
|
256
|
-
$L$list
|
|
267
|
+
$L$list{,}$push{d}
|
|
268
|
+
$L$list{,}$set{1}{B}
|
|
257
269
|
$L → a,B,c,d
|
|
258
270
|
```
|
|
259
271
|
|
|
260
272
|
```text
|
|
261
273
|
$STACK$from{x,y,z}
|
|
262
|
-
Popped: $STACK$list
|
|
274
|
+
Popped: $STACK$list{,}$pop
|
|
263
275
|
Rest: $STACK → Popped: z / Rest: x,y
|
|
264
276
|
```
|
|
265
277
|
|
|
266
278
|
```text
|
|
267
279
|
$CSV$from{one,two,three}
|
|
268
|
-
$CSV$list
|
|
280
|
+
$CSV$list{,}$join{ | } → one | two | three
|
|
269
281
|
```
|
|
270
282
|
|
|
271
283
|
```text
|
|
272
284
|
$PATH$from{/usr/local/bin}
|
|
273
|
-
$PATH$list
|
|
285
|
+
$PATH$list{/}$get{-1} → bin
|
|
274
286
|
```
|
|
275
287
|
|
|
276
288
|
```text
|
|
277
289
|
/* Dynamic separator from variable */
|
|
278
290
|
$SEP$from{,}
|
|
279
291
|
$L$from{x,y,z}
|
|
280
|
-
$L$list
|
|
292
|
+
$L$list{$SEP}$get{2} → z
|
|
293
|
+
|
|
294
|
+
$L$from{a,b,c,d,e}
|
|
295
|
+
$L$list{,}$slice{1}{4} → b,c,d
|
|
281
296
|
```
|
|
282
297
|
|
|
283
298
|
---
|
|
@@ -290,6 +305,10 @@ Papagaio provides operators for conditional logic and value chaining. These are
|
|
|
290
305
|
|
|
291
306
|
```
|
|
292
307
|
$VAL$compare{target}
|
|
308
|
+
$VAL$find{pattern}
|
|
309
|
+
$VAL$contains{pattern}
|
|
310
|
+
$VAL$replace{pattern}{replacement}
|
|
311
|
+
$VAL$slice{start}{end}
|
|
293
312
|
$VAL$then{content}
|
|
294
313
|
$VAL$else{content}
|
|
295
314
|
```
|
|
@@ -297,8 +316,12 @@ $VAL$else{content}
|
|
|
297
316
|
| Operator | Behavior |
|
|
298
317
|
|---|---|
|
|
299
318
|
| **`compare`** | If `$VAL` matches `target`, emits `$VAL`. Otherwise, emits `""`. |
|
|
300
|
-
| **`
|
|
301
|
-
| **`
|
|
319
|
+
| **`find`** | Performs a non-anchored search for `pattern` in `$VAL`. Emits the matched substring. |
|
|
320
|
+
| **`contains`** | Performs a non-anchored search. Emits the character index of the first match (or `""`). |
|
|
321
|
+
| **`replace`** | Replaces the first match of `pattern` with `replacement`. Emits the OLD match. |
|
|
322
|
+
| **`slice`** | Returns a substring from `start` to `end`. Supports negative indices. |
|
|
323
|
+
| **`then`** | If `$VAL` is **not empty**, processes and emits `content`. Otherwise, emits `""`. |
|
|
324
|
+
| **`else`** | If `$VAL` **is empty**, processes and emits `content`. Otherwise, passes `$VAL` through. |
|
|
302
325
|
| **`repeat`** | `$repeat{N}{code}` | Executes `code` N times. Emits nothing; used for side effects. |
|
|
303
326
|
| **`while`** | `$while{pat}{code}` | Executes `code` while its result matches `pat`. Emits the last successful result. |
|
|
304
327
|
| **`until`** | `$until{pat}{code}` | Executes `code` until its result matches `pat`. Emits the match that caused the break. |
|
|
@@ -320,6 +343,21 @@ $A$compare{world}$then{Matched!} → (empty)
|
|
|
320
343
|
$A$from{abc}
|
|
321
344
|
$A$compare{abc}$then{YES}$else{NO} → YES
|
|
322
345
|
$A$compare{xyz}$then{YES}$else{NO} → NO
|
|
346
|
+
|
|
347
|
+
#### Search and Extract:
|
|
348
|
+
```text
|
|
349
|
+
$A$from{user_id: 12345}
|
|
350
|
+
$A$find{$d+}$ → 12345
|
|
351
|
+
$A$contains{id} → 5
|
|
352
|
+
$A$replace{$d+}{HIDDEN} $A → 12345 user_id: HIDDEN
|
|
353
|
+
|
|
354
|
+
#### Slicing:
|
|
355
|
+
```text
|
|
356
|
+
$A$from{hello world}
|
|
357
|
+
$A$slice{0}{5} → hello
|
|
358
|
+
$A$slice{-5} → world
|
|
359
|
+
```
|
|
360
|
+
```
|
|
323
361
|
```
|
|
324
362
|
|
|
325
363
|
### Standalone and Braced Usage
|
|
@@ -330,7 +368,7 @@ $A$compare{xyz}$then{YES}$else{NO} → NO
|
|
|
330
368
|
#### Example:
|
|
331
369
|
```text
|
|
332
370
|
$L$from{a,b,c}
|
|
333
|
-
$R$from{$L$list
|
|
371
|
+
$R$from{$L$list{,}$get{0}}
|
|
334
372
|
$R$compare{a}$then{Is A}$else{Not A} → Is A
|
|
335
373
|
```
|
|
336
374
|
|
package/dist/wasm/papagaio.js
CHANGED
|
@@ -20,8 +20,6 @@ class Papagaio {
|
|
|
20
20
|
|
|
21
21
|
registerCommand(name, handler) {
|
|
22
22
|
// Note: Implementing JS->C callbacks requires addFunction and extra glue.
|
|
23
|
-
// For now, we warn that this is not yet supported in the pure WASM wrapper.
|
|
24
|
-
console.warn(`[WASM] Warning: registerCommand('${name}') is not supported in JS wrapper yet.`);
|
|
25
23
|
}
|
|
26
24
|
|
|
27
25
|
setArgs(argv) {
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "papagaio",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.39.2",
|
|
4
4
|
"description": "easy yet powerful preprocessor",
|
|
5
5
|
"main": "dist/wasm/papagaio.js",
|
|
6
6
|
"bin": {
|
|
@@ -26,7 +26,6 @@
|
|
|
26
26
|
"eval",
|
|
27
27
|
"parser",
|
|
28
28
|
"codegen",
|
|
29
|
-
"regex",
|
|
30
29
|
"syntax",
|
|
31
30
|
"easy"
|
|
32
31
|
],
|