+added console spport for lyngio

+added console support to lyng/jlyng CLI
+added unicode escapes
+created tetris console sample
This commit is contained in:
sergeych committed 2026-03-19 01:09:32 +03:00
1 parent 1a080bc53e
commit d9d7cafec8
44 files changed
+3842 -28

No files matched your search

+5
View File
@@ -14,8 +14,13 @@ Primary sources used: `lynglib/src/commonMain/kotlin/net/sergeych/lyng/{Parser,T
## 2. Lexical Syntax
- Comments: `// line`, `/* block */`.
- Strings: `"..."` (supports escapes). Multiline string content is normalized by indentation logic.
- Supported escapes: `\n`, `\r`, `\t`, `\"`, `\\`, `\uXXXX` (4 hex digits).
- Unicode escapes use exactly 4 hex digits (for example: `"\u0416"` -> `Ж`).
- Unknown `\x` escapes in strings are preserved literally as two characters (`\` and `x`).
- Numbers: `Int` (`123`, `1_000`), `Real` (`1.2`, `1e3`), hex (`0xFF`).
- Char: `'a'`, escaped chars supported.
- Supported escapes: `\n`, `\r`, `\t`, `\'`, `\\`, `\uXXXX` (4 hex digits).
- Backslash character in a char literal must be written as `'\\'` (forms like `'\'` are invalid).
- Labels:
- statement label: `loop@ for (...) { ... }`
- label reference: `break@loop`, `continue@loop`, `return@fnLabel`
+2 -1
View File
@@ -63,8 +63,9 @@ Sources: `lynglib/src/commonMain/kotlin/net/sergeych/lyng/Script.kt`, `lynglib/s
Requires installing `lyngio` into the import manager from host code.
- `import lyng.io.fs` (filesystem `Path` API)
- `import lyng.io.process` (process execution API)
- `import lyng.io.console` (console capabilities, geometry, ANSI/output, events)
## 7. AI Generation Tips
- Assume `lyng.stdlib` APIs exist in regular script contexts.
- For platform-sensitive code (`fs`, `process`), gate assumptions and mention required module install.
- For platform-sensitive code (`fs`, `process`, `console`), gate assumptions and mention required module install.
- Prefer extension-method style (`items.filter { ... }`) and standard scope helpers (`let`/`also`/`apply`/`run`).
+101
View File
@@ -0,0 +1,101 @@
### lyng.io.console
`lyng.io.console` provides optional rich console support for terminal applications.
> **Note:** this module is part of `lyngio`. It must be explicitly installed into the import manager by host code.
>
> **CLI note:** the `lyng` CLI now installs `lyng.io.console` in its base scope by default, so scripts can simply `import lyng.io.console`.
#### Install in host
```kotlin
import net.sergeych.lyng.Script
import net.sergeych.lyng.io.console.createConsoleModule
import net.sergeych.lyngio.console.security.PermitAllConsoleAccessPolicy
suspend fun initScope() {
val scope = Script.newScope()
createConsoleModule(PermitAllConsoleAccessPolicy, scope)
}
```
#### Use in Lyng script
```lyng
import lyng.io.console
println("supported = " + Console.isSupported())
println("tty = " + Console.isTty())
println("ansi = " + Console.ansiLevel())
println("geometry = " + Console.geometry())
Console.write("hello\n")
Console.home()
Console.clear()
Console.moveTo(1, 1)
Console.clearLine()
Console.enterAltScreen()
Console.leaveAltScreen()
Console.setCursorVisible(true)
Console.flush()
```
Interactive sample script in this repo:
```bash
lyng examples/tetris_console.lyng
```
#### API
- `Console.isSupported(): Bool` — whether console control is available on this platform/runtime.
- `Console.isTty(): Bool` — whether output is attached to a TTY.
- `Console.ansiLevel(): String` — `NONE`, `BASIC16`, `ANSI256`, `TRUECOLOR`.
- `Console.geometry(): ConsoleGeometry?` — `{columns, rows}` as typed object or `null`.
- `Console.details(): ConsoleDetails` — consolidated capability object.
- `Console.write(text: String)` — writes to console output.
- `Console.flush()` — flushes buffered output.
- `Console.home()` — moves cursor to top-left.
- `Console.clear()` — clears visible screen.
- `Console.moveTo(row: Int, column: Int)` — moves cursor to 1-based row/column.
- `Console.clearLine()` — clears current line.
- `Console.enterAltScreen()` — switch to alternate screen buffer.
- `Console.leaveAltScreen()` — return to normal screen buffer.
- `Console.setCursorVisible(visible: Bool)` — shows/hides cursor.
- `Console.events(): ConsoleEventStream` — endless iterable source of typed events: `ConsoleResizeEvent`, `ConsoleKeyEvent`.
- `Console.setRawMode(enabled: Bool): Bool` — requests raw input mode, returns `true` if changed.
#### Event Iteration
Use events from a loop, typically in a separate coroutine:
```lyng
launch {
for (ev in Console.events()) {
if (ev is ConsoleKeyEvent) {
// handle key
}
}
}
```
#### Event format
`Console.events()` emits `ConsoleEvent` with at least:
- `type: String` — `resize`, `keydown`, `keyup`
Additional fields:
- `ConsoleResizeEvent`: `columns`, `rows`
- `ConsoleKeyEvent`: `key`, `code`, `ctrl`, `alt`, `shift`, `meta`
#### Security policy
The module uses `ConsoleAccessPolicy` with operations:
- `WriteText(length)`
- `ReadEvents`
- `SetRawMode(enabled)`
For permissive mode, use `PermitAllConsoleAccessPolicy`.
+17 -9
View File
@@ -6,12 +6,13 @@
1. **Security:** I/O and process execution are sensitive operations. By keeping them in a separate module, we ensure that the Lyng core remains 100% safe by default. You only enable what you explicitly need.
2. **Footprint:** Not every script needs filesystem or process access. Keeping these as a separate module helps minimize the dependency footprint for small embedded projects.
3. **Control:** `lyngio` provides fine-grained security policies (`FsAccessPolicy`, `ProcessAccessPolicy`) that allow you to control exactly what a script can do.
3. **Control:** `lyngio` provides fine-grained security policies (`FsAccessPolicy`, `ProcessAccessPolicy`, `ConsoleAccessPolicy`) that allow you to control exactly what a script can do.
#### Included Modules
- **[lyng.io.fs](lyng.io.fs.md):** Async filesystem access. Provides the `Path` class for file/directory operations, streaming, and globbing.
- **[lyng.io.process](lyng.io.process.md):** External process execution and shell commands. Provides `Process`, `RunningProcess`, and `Platform` information.
- **[lyng.io.console](lyng.io.console.md):** Rich console/TTY access. Provides `Console` capability detection, geometry, output, and iterable events.
---
@@ -39,8 +40,10 @@ To use `lyngio` modules in your scripts, you must install them into your Lyng sc
import net.sergeych.lyng.Script
import net.sergeych.lyng.io.fs.createFs
import net.sergeych.lyng.io.process.createProcessModule
import net.sergeych.lyng.io.console.createConsoleModule
import net.sergeych.lyngio.fs.security.PermitAllAccessPolicy
import net.sergeych.lyngio.process.security.PermitAllProcessAccessPolicy
import net.sergeych.lyngio.console.security.PermitAllConsoleAccessPolicy
suspend fun runMyScript() {
val scope = Script.newScope()
@@ -48,14 +51,17 @@ suspend fun runMyScript() {
// Install modules with policies
createFs(PermitAllAccessPolicy, scope)
createProcessModule(PermitAllProcessAccessPolicy, scope)
createConsoleModule(PermitAllConsoleAccessPolicy, scope)
// Now scripts can import them
scope.eval("""
import lyng.io.fs
import lyng.io.process
import lyng.io.console
println("Working dir: " + Path(".").readUtf8())
println("OS: " + Platform.details().name)
println("TTY: " + Console.isTty())
""")
}
```
@@ -68,20 +74,22 @@ suspend fun runMyScript() {
- **Filesystem Security:** Implement `FsAccessPolicy` to restrict access to specific paths or operations (e.g., read-only access to a sandbox directory).
- **Process Security:** Implement `ProcessAccessPolicy` to restrict which executables can be run or to disable shell execution entirely.
- **Console Security:** Implement `ConsoleAccessPolicy` to control output writes, event reads, and raw mode switching.
For more details, see the specific module documentation:
- [Filesystem Security Details](lyng.io.fs.md#access-policy-security)
- [Process Security Details](lyng.io.process.md#security-policy)
- [Console Module Details](lyng.io.console.md)
---
#### Platform Support Overview
| Platform | lyng.io.fs | lyng.io.process |
| :--- | :---: | :---: |
| **JVM** | ✅ | ✅ |
| **Native (Linux/macOS)** | ✅ | ✅ |
| **Native (Windows)** | ✅ | 🚧 (Planned) |
| **Android** | ✅ | ❌ |
| **NodeJS** | ✅ | ❌ |
| **Browser / Wasm** | ✅ (In-memory) | ❌ |
| Platform | lyng.io.fs | lyng.io.process | lyng.io.console |
| :--- | :---: | :---: | :---: |
| **JVM** | ✅ | ✅ | ✅ (baseline) |
| **Native (Linux/macOS)** | ✅ | ✅ | 🚧 |
| **Native (Windows)** | ✅ | 🚧 (Planned) | 🚧 |
| **Android** | ✅ | ❌ | ❌ |
| **NodeJS** | ✅ | ❌ | ❌ |
| **Browser / Wasm** | ✅ (In-memory) | ❌ | ❌ |
+8 -2
View File
@@ -1555,18 +1555,21 @@ The type for the character objects is `Char`.
| \t | 0x07, tabulation |
| \\ | \ slash character |
| \" | " double quote |
| \uXXXX | unicode code point |
Unicode escape form is exactly 4 hex digits, e.g. `"\u263A"` -> `☺`.
Other `\c` combinations, where c is any char except mentioned above, are left intact, e.g.:
val s = "\a"
assert(s[0] == '\')
assert(s[0] == '\\')
assert(s[1] == 'a')
>>> void
same as:
val s = "\\a"
assert(s[0] == '\')
assert(s[0] == '\\')
assert(s[1] == 'a')
>>> void
@@ -1581,6 +1584,9 @@ Are the same as in string literals with little difference:
| \t | 0x07, tabulation |
| \\ | \ slash character |
| \' | ' apostrophe |
| \uXXXX | unicode code point |
For char literals, use `'\\'` to represent a single backslash character; `'\'` is invalid.
### Char instance members