linecraft 0.1.0 → 0.2.0
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/LICENSE +1 -1
- package/README.md +313 -64
- package/lib/api/color.d.ts +6 -0
- package/lib/api/color.d.ts.map +1 -0
- package/lib/api/color.js +9 -0
- package/lib/api/color.js.map +1 -0
- package/lib/api/color.test.d.ts +2 -0
- package/lib/api/color.test.d.ts.map +1 -0
- package/lib/api/color.test.js +23 -0
- package/lib/api/color.test.js.map +1 -0
- package/lib/api/flex.d.ts +55 -0
- package/lib/api/flex.d.ts.map +1 -0
- package/lib/api/flex.js +86 -0
- package/lib/api/flex.js.map +1 -0
- package/lib/api/flex.test.d.ts +2 -0
- package/lib/api/flex.test.d.ts.map +1 -0
- package/lib/api/flex.test.js +82 -0
- package/lib/api/flex.test.js.map +1 -0
- package/lib/api/grid.d.ts +22 -0
- package/lib/api/grid.d.ts.map +1 -0
- package/lib/api/grid.js +65 -0
- package/lib/api/grid.js.map +1 -0
- package/lib/api/grid.test.d.ts +2 -0
- package/lib/api/grid.test.d.ts.map +1 -0
- package/lib/api/grid.test.js +48 -0
- package/lib/api/grid.test.js.map +1 -0
- package/lib/components/base.d.ts +53 -0
- package/lib/components/base.d.ts.map +1 -0
- package/lib/components/base.js +47 -0
- package/lib/components/base.js.map +1 -0
- package/lib/components/col.d.ts +35 -0
- package/lib/components/col.d.ts.map +1 -0
- package/lib/components/col.js +168 -0
- package/lib/components/col.js.map +1 -0
- package/lib/components/col.test.d.ts +2 -0
- package/lib/components/col.test.d.ts.map +1 -0
- package/lib/components/col.test.js +96 -0
- package/lib/components/col.test.js.map +1 -0
- package/lib/components/index.d.ts +3 -0
- package/lib/components/index.d.ts.map +1 -0
- package/lib/components/index.js +5 -0
- package/lib/components/index.js.map +1 -0
- package/lib/components/progress-bar-grid.d.ts +20 -0
- package/lib/components/progress-bar-grid.d.ts.map +1 -0
- package/lib/components/progress-bar-grid.js +44 -0
- package/lib/components/progress-bar-grid.js.map +1 -0
- package/lib/components/progress-bar-grid.test.d.ts +2 -0
- package/lib/components/progress-bar-grid.test.d.ts.map +1 -0
- package/lib/components/progress-bar-grid.test.js +101 -0
- package/lib/components/progress-bar-grid.test.js.map +1 -0
- package/lib/components/progress-bar.d.ts +26 -3
- package/lib/components/progress-bar.d.ts.map +1 -1
- package/lib/components/progress-bar.js +62 -6
- package/lib/components/progress-bar.js.map +1 -1
- package/lib/components/progress-bar.test.d.ts +2 -0
- package/lib/components/progress-bar.test.d.ts.map +1 -0
- package/lib/components/progress-bar.test.js +153 -0
- package/lib/components/progress-bar.test.js.map +1 -0
- package/lib/components/prompt.d.ts +14 -0
- package/lib/components/prompt.d.ts.map +1 -0
- package/lib/components/prompt.js +77 -0
- package/lib/components/prompt.js.map +1 -0
- package/lib/components/renderable.d.ts +42 -0
- package/lib/components/renderable.d.ts.map +1 -0
- package/lib/components/renderable.js +225 -0
- package/lib/components/renderable.js.map +1 -0
- package/lib/components/spinner.d.ts +2 -2
- package/lib/components/spinner.d.ts.map +1 -1
- package/lib/components/spinner.js +3 -1
- package/lib/components/spinner.js.map +1 -1
- package/lib/components/spinner.test.d.ts +2 -0
- package/lib/components/spinner.test.d.ts.map +1 -0
- package/lib/components/spinner.test.js +168 -0
- package/lib/components/spinner.test.js.map +1 -0
- package/lib/components/style.d.ts +16 -0
- package/lib/components/style.d.ts.map +1 -0
- package/lib/components/style.js +72 -0
- package/lib/components/style.js.map +1 -0
- package/lib/components/style.test.d.ts +2 -0
- package/lib/components/style.test.d.ts.map +1 -0
- package/lib/components/style.test.js +135 -0
- package/lib/components/style.test.js.map +1 -0
- package/lib/components/text.d.ts +24 -0
- package/lib/components/text.d.ts.map +1 -0
- package/lib/components/text.js +65 -0
- package/lib/components/text.js.map +1 -0
- package/lib/drawing/boxes.d.ts +33 -0
- package/lib/drawing/boxes.d.ts.map +1 -0
- package/lib/drawing/boxes.js +76 -0
- package/lib/drawing/boxes.js.map +1 -0
- package/lib/index.d.ts +18 -11
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +21 -10
- package/lib/index.js.map +1 -1
- package/lib/index.test.d.ts +2 -0
- package/lib/index.test.d.ts.map +1 -0
- package/lib/index.test.js +80 -0
- package/lib/index.test.js.map +1 -0
- package/lib/layout/flex.d.ts +39 -0
- package/lib/layout/flex.d.ts.map +1 -0
- package/lib/layout/flex.js +300 -0
- package/lib/layout/flex.js.map +1 -0
- package/lib/layout/flex.test.d.ts +2 -0
- package/lib/layout/flex.test.d.ts.map +1 -0
- package/lib/layout/flex.test.js +206 -0
- package/lib/layout/flex.test.js.map +1 -0
- package/lib/layout/grid.d.ts +53 -0
- package/lib/layout/grid.d.ts.map +1 -0
- package/lib/layout/grid.js +421 -0
- package/lib/layout/grid.js.map +1 -0
- package/lib/layout/grid.test.d.ts +2 -0
- package/lib/layout/grid.test.d.ts.map +1 -0
- package/lib/layout/grid.test.js +139 -0
- package/lib/layout/grid.test.js.map +1 -0
- package/lib/native/ansi.d.ts +104 -0
- package/lib/native/ansi.d.ts.map +1 -0
- package/lib/native/ansi.js +120 -0
- package/lib/native/ansi.js.map +1 -0
- package/lib/native/ansi.test.d.ts +2 -0
- package/lib/native/ansi.test.d.ts.map +1 -0
- package/lib/native/ansi.test.js +57 -0
- package/lib/native/ansi.test.js.map +1 -0
- package/lib/native/buffer.d.ts +32 -0
- package/lib/native/buffer.d.ts.map +1 -0
- package/lib/native/buffer.js +49 -0
- package/lib/native/buffer.js.map +1 -0
- package/lib/native/buffer.test.d.ts +2 -0
- package/lib/native/buffer.test.d.ts.map +1 -0
- package/lib/native/buffer.test.js +64 -0
- package/lib/native/buffer.test.js.map +1 -0
- package/lib/native/diff.d.ts +20 -0
- package/lib/native/diff.d.ts.map +1 -0
- package/lib/native/diff.js +33 -0
- package/lib/native/diff.js.map +1 -0
- package/lib/native/diff.test.d.ts +2 -0
- package/lib/native/diff.test.d.ts.map +1 -0
- package/lib/native/diff.test.js +106 -0
- package/lib/native/diff.test.js.map +1 -0
- package/lib/native/region-old.d.ts +117 -0
- package/lib/native/region-old.d.ts.map +1 -0
- package/lib/native/region-old.js +539 -0
- package/lib/native/region-old.js.map +1 -0
- package/lib/native/region-renderer.d.ts +167 -0
- package/lib/native/region-renderer.d.ts.map +1 -0
- package/lib/native/region-renderer.js +1238 -0
- package/lib/native/region-renderer.js.map +1 -0
- package/lib/native/region-simple.d.ts +44 -0
- package/lib/native/region-simple.d.ts.map +1 -0
- package/lib/native/region-simple.js +290 -0
- package/lib/native/region-simple.js.map +1 -0
- package/lib/native/region.d.ts +53 -0
- package/lib/native/region.d.ts.map +1 -0
- package/lib/native/region.js +426 -0
- package/lib/native/region.js.map +1 -0
- package/lib/native/region.test.d.ts +2 -0
- package/lib/native/region.test.d.ts.map +1 -0
- package/lib/native/region.test.js +248 -0
- package/lib/native/region.test.js.map +1 -0
- package/lib/native/throttle.d.ts +29 -0
- package/lib/native/throttle.d.ts.map +1 -0
- package/lib/native/throttle.js +57 -0
- package/lib/native/throttle.js.map +1 -0
- package/lib/native/throttle.test.d.ts +2 -0
- package/lib/native/throttle.test.d.ts.map +1 -0
- package/lib/native/throttle.test.js +86 -0
- package/lib/native/throttle.test.js.map +1 -0
- package/lib/native.d.ts +5 -11
- package/lib/native.d.ts.map +1 -1
- package/lib/native.js +8 -64
- package/lib/native.js.map +1 -1
- package/lib/region.d.ts +48 -5
- package/lib/region.d.ts.map +1 -1
- package/lib/region.js +474 -36
- package/lib/region.js.map +1 -1
- package/lib/region.test.d.ts +2 -0
- package/lib/region.test.d.ts.map +1 -0
- package/lib/region.test.js +227 -0
- package/lib/region.test.js.map +1 -0
- package/lib/region.visual.test.d.ts +2 -0
- package/lib/region.visual.test.d.ts.map +1 -0
- package/lib/region.visual.test.js +55 -0
- package/lib/region.visual.test.js.map +1 -0
- package/lib/test-helpers/capturable-terminal.d.ts +61 -0
- package/lib/test-helpers/capturable-terminal.d.ts.map +1 -0
- package/lib/test-helpers/capturable-terminal.js +113 -0
- package/lib/test-helpers/capturable-terminal.js.map +1 -0
- package/lib/test-helpers/capturable-terminal.test.d.ts +2 -0
- package/lib/test-helpers/capturable-terminal.test.d.ts.map +1 -0
- package/lib/test-helpers/capturable-terminal.test.js +45 -0
- package/lib/test-helpers/capturable-terminal.test.js.map +1 -0
- package/lib/test-helpers/mock-region.d.ts +21 -0
- package/lib/test-helpers/mock-region.d.ts.map +1 -0
- package/lib/test-helpers/mock-region.js +37 -0
- package/lib/test-helpers/mock-region.js.map +1 -0
- package/lib/test-helpers/virtual-terminal-diff-reflow.test.d.ts +2 -0
- package/lib/test-helpers/virtual-terminal-diff-reflow.test.d.ts.map +1 -0
- package/lib/test-helpers/virtual-terminal-diff-reflow.test.js +256 -0
- package/lib/test-helpers/virtual-terminal-diff-reflow.test.js.map +1 -0
- package/lib/test-helpers/virtual-terminal-flex-resize.test.d.ts +2 -0
- package/lib/test-helpers/virtual-terminal-flex-resize.test.d.ts.map +1 -0
- package/lib/test-helpers/virtual-terminal-flex-resize.test.js +438 -0
- package/lib/test-helpers/virtual-terminal-flex-resize.test.js.map +1 -0
- package/lib/test-helpers/virtual-terminal.d.ts +176 -0
- package/lib/test-helpers/virtual-terminal.d.ts.map +1 -0
- package/lib/test-helpers/virtual-terminal.js +492 -0
- package/lib/test-helpers/virtual-terminal.js.map +1 -0
- package/lib/test-helpers/virtual-terminal.test.d.ts +2 -0
- package/lib/test-helpers/virtual-terminal.test.d.ts.map +1 -0
- package/lib/test-helpers/virtual-terminal.test.js +219 -0
- package/lib/test-helpers/virtual-terminal.test.js.map +1 -0
- package/lib/ts/components/spinner.test.d.ts +2 -0
- package/lib/ts/components/spinner.test.d.ts.map +1 -0
- package/lib/ts/components/spinner.test.js +168 -0
- package/lib/ts/components/spinner.test.js.map +1 -0
- package/lib/ts/utils/colors.test.d.ts +2 -0
- package/lib/ts/utils/colors.test.d.ts.map +1 -0
- package/lib/ts/utils/colors.test.js +87 -0
- package/lib/ts/utils/colors.test.js.map +1 -0
- package/lib/types.d.ts +8 -2
- package/lib/types.d.ts.map +1 -1
- package/lib/types.js.map +1 -1
- package/lib/utils/colors-simple.d.ts +51 -0
- package/lib/utils/colors-simple.d.ts.map +1 -0
- package/lib/utils/colors-simple.js +59 -0
- package/lib/utils/colors-simple.js.map +1 -0
- package/lib/utils/colors.d.ts +1 -1
- package/lib/utils/colors.d.ts.map +1 -1
- package/lib/utils/colors.js.map +1 -1
- package/lib/utils/colors.test.d.ts +2 -0
- package/lib/utils/colors.test.d.ts.map +1 -0
- package/lib/utils/colors.test.js +87 -0
- package/lib/utils/colors.test.js.map +1 -0
- package/lib/utils/cursor-position.d.ts +22 -0
- package/lib/utils/cursor-position.d.ts.map +1 -0
- package/lib/utils/cursor-position.js +139 -0
- package/lib/utils/cursor-position.js.map +1 -0
- package/lib/utils/debug-log.d.ts +2 -0
- package/lib/utils/debug-log.d.ts.map +1 -0
- package/lib/utils/debug-log.js +36 -0
- package/lib/utils/debug-log.js.map +1 -0
- package/lib/utils/terminal.d.ts +27 -0
- package/lib/utils/terminal.d.ts.map +1 -0
- package/lib/utils/terminal.js +116 -0
- package/lib/utils/terminal.js.map +1 -0
- package/lib/utils/text.d.ts +21 -0
- package/lib/utils/text.d.ts.map +1 -0
- package/lib/utils/text.js +82 -0
- package/lib/utils/text.js.map +1 -0
- package/lib/utils/wait-for-spacebar.d.ts +10 -0
- package/lib/utils/wait-for-spacebar.d.ts.map +1 -0
- package/lib/utils/wait-for-spacebar.js +71 -0
- package/lib/utils/wait-for-spacebar.js.map +1 -0
- package/package.json +31 -28
- package/.cursor/plan.md +0 -952
- package/TESTING.md +0 -102
- package/build.zig +0 -100
- package/examples/basic-progress.ts +0 -21
- package/examples/multi-lane.ts +0 -29
- package/examples/spinner.ts +0 -20
- package/examples/test-basic.ts +0 -23
- package/src/ts/components/progress-bar.ts +0 -53
- package/src/ts/components/spinner.ts +0 -56
- package/src/ts/index.ts +0 -37
- package/src/ts/native.ts +0 -86
- package/src/ts/region.ts +0 -89
- package/src/ts/types/ffi-napi.d.ts +0 -11
- package/src/ts/types/ref-napi.d.ts +0 -5
- package/src/ts/types.ts +0 -53
- package/src/ts/utils/colors.ts +0 -72
- package/src/zig/ansi.zig +0 -21
- package/src/zig/buffer.zig +0 -37
- package/src/zig/diff.zig +0 -43
- package/src/zig/region.zig +0 -292
- package/src/zig/renderer.zig +0 -92
- package/src/zig/test_ansi.zig +0 -66
- package/src/zig/test_buffer.zig +0 -82
- package/src/zig/test_diff.zig +0 -220
- package/src/zig/test_integration.zig +0 -76
- package/src/zig/test_region.zig +0 -191
- package/src/zig/test_runner.zig +0 -27
- package/src/zig/test_throttle.zig +0 -59
- package/src/zig/throttle.zig +0 -38
- package/tsconfig.json +0 -21
package/TESTING.md
DELETED
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
# Testing EchoKit
|
|
2
|
-
|
|
3
|
-
## Running Tests
|
|
4
|
-
|
|
5
|
-
### All Tests
|
|
6
|
-
```bash
|
|
7
|
-
zig build test
|
|
8
|
-
# or
|
|
9
|
-
pnpm test
|
|
10
|
-
```
|
|
11
|
-
|
|
12
|
-
### Individual Test Modules
|
|
13
|
-
```bash
|
|
14
|
-
# ANSI tests only
|
|
15
|
-
zig build test:ansi
|
|
16
|
-
|
|
17
|
-
# Throttle tests only
|
|
18
|
-
zig build test:throttle
|
|
19
|
-
|
|
20
|
-
# Buffer tests only
|
|
21
|
-
zig build test:buffer
|
|
22
|
-
|
|
23
|
-
# Diff tests only
|
|
24
|
-
zig build test:diff
|
|
25
|
-
|
|
26
|
-
# Region tests only
|
|
27
|
-
zig build test:region
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
## Test Coverage
|
|
31
|
-
|
|
32
|
-
### ANSI Module (`test_ansi.zig`)
|
|
33
|
-
- ✅ `move_cursor_to` - Generates correct cursor positioning ANSI
|
|
34
|
-
- ✅ `move_cursor_up` - Generates correct up movement ANSI
|
|
35
|
-
- ✅ `move_cursor_down` - Generates correct down movement ANSI
|
|
36
|
-
- ✅ ANSI constants - All constants verified
|
|
37
|
-
- ✅ `move_cursor_to` with zero coordinates
|
|
38
|
-
- ✅ `move_cursor_to` with large coordinates
|
|
39
|
-
- ✅ `move_cursor_up` with zero
|
|
40
|
-
|
|
41
|
-
### Throttle Module (`test_throttle.zig`)
|
|
42
|
-
- ✅ Initialization - Creates throttle with correct FPS
|
|
43
|
-
- ✅ `set_fps` - Changes FPS correctly
|
|
44
|
-
- ✅ `should_render` - Allows first frame
|
|
45
|
-
- ✅ `should_render` - Respects interval (blocks immediate second frame)
|
|
46
|
-
- ✅ `time_until_next_frame` - Calculates remaining time correctly
|
|
47
|
-
- ✅ Very high FPS (1000 FPS)
|
|
48
|
-
- ✅ Very low FPS (1 FPS)
|
|
49
|
-
|
|
50
|
-
### Buffer Module (`test_buffer.zig`)
|
|
51
|
-
- ✅ Initialization - Creates empty buffer
|
|
52
|
-
- ✅ `write` - Appends data correctly
|
|
53
|
-
- ✅ `clear` - Clears buffer
|
|
54
|
-
- ✅ `flush` - Writes to stdout and clears
|
|
55
|
-
- ✅ Large content handling
|
|
56
|
-
- ✅ Multiple writes and flush
|
|
57
|
-
|
|
58
|
-
### Diff Module (`test_diff.zig`)
|
|
59
|
-
- ✅ Identical frames - Returns no_change ops
|
|
60
|
-
- ✅ Changed line - Detects line updates
|
|
61
|
-
- ✅ Inserted line - Detects new lines
|
|
62
|
-
- ✅ Deleted line - Detects removed lines
|
|
63
|
-
- ✅ Multiple changes - Handles complex diffs
|
|
64
|
-
- ✅ Empty frames
|
|
65
|
-
- ✅ Completely different frames
|
|
66
|
-
|
|
67
|
-
### Region Module (`test_region.zig`)
|
|
68
|
-
- ✅ Initialization - Creates region with correct dimensions
|
|
69
|
-
- ✅ `set_line` - Expands automatically when needed
|
|
70
|
-
- ✅ `set_line` - Rejects line 0 (1-based indexing)
|
|
71
|
-
- ✅ `set` - Splits content by newlines correctly
|
|
72
|
-
- ✅ `expand_to` - Expands region height
|
|
73
|
-
- ✅ `clear_line` - Clears individual lines
|
|
74
|
-
- ✅ Throttle configuration - Sets FPS correctly
|
|
75
|
-
- ✅ `set_line` with empty string
|
|
76
|
-
- ✅ `set` with empty content
|
|
77
|
-
- ✅ `set` with single line (no newline)
|
|
78
|
-
- ✅ Multiple `set_line` calls
|
|
79
|
-
- ✅ `clear` all lines
|
|
80
|
-
|
|
81
|
-
### Integration Tests (`test_integration.zig`)
|
|
82
|
-
- ✅ Region with diff and throttle together
|
|
83
|
-
- ✅ Region expansion with multiple operations
|
|
84
|
-
- ✅ `set` then `set_line` interaction
|
|
85
|
-
|
|
86
|
-
## Test Output
|
|
87
|
-
|
|
88
|
-
All tests print visible output to the console using `std.debug.print()`. Each test shows:
|
|
89
|
-
- ✓ Checkmark for passed assertions
|
|
90
|
-
- Test name and module
|
|
91
|
-
- Relevant values being tested
|
|
92
|
-
|
|
93
|
-
Example output:
|
|
94
|
-
```
|
|
95
|
-
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
96
|
-
Testing: ANSI Module
|
|
97
|
-
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
98
|
-
✓ move_cursor_to(10, 5): [1b[5;10H
|
|
99
|
-
✓ move_cursor_up(3): [1b[3A
|
|
100
|
-
✓ All ANSI constants verified
|
|
101
|
-
```
|
|
102
|
-
|
package/build.zig
DELETED
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
const std = @import("std");
|
|
2
|
-
|
|
3
|
-
pub fn build(b: *std.Build) void {
|
|
4
|
-
const target = b.standardTargetOptions(.{});
|
|
5
|
-
const optimize = b.standardOptimizeOption(.{});
|
|
6
|
-
|
|
7
|
-
// Create shared library for Node.js addon
|
|
8
|
-
// In Zig 0.15.x, target and optimize must be set in createModule
|
|
9
|
-
const lib = b.addLibrary(.{
|
|
10
|
-
.name = "echokit",
|
|
11
|
-
.root_module = b.createModule(.{
|
|
12
|
-
.root_source_file = b.path("src/zig/renderer.zig"),
|
|
13
|
-
.target = target,
|
|
14
|
-
.optimize = optimize,
|
|
15
|
-
}),
|
|
16
|
-
.linkage = .dynamic, // Shared library for Node.js addon
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
// Link with libc (needed for N-API)
|
|
20
|
-
lib.linkLibC();
|
|
21
|
-
|
|
22
|
-
// Install the library (defaults to zig-out/lib/)
|
|
23
|
-
b.installArtifact(lib);
|
|
24
|
-
|
|
25
|
-
// Test all modules together
|
|
26
|
-
// Using addTest automatically discovers all test functions
|
|
27
|
-
const test_exe = b.addTest(.{
|
|
28
|
-
.root_module = b.createModule(.{
|
|
29
|
-
.root_source_file = b.path("src/zig/test_runner.zig"),
|
|
30
|
-
.target = target,
|
|
31
|
-
.optimize = optimize,
|
|
32
|
-
}),
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
const run_tests = b.addRunArtifact(test_exe);
|
|
36
|
-
run_tests.has_side_effects = true;
|
|
37
|
-
const test_step = b.step("test", "Run all Zig tests with visible console output");
|
|
38
|
-
test_step.dependOn(&run_tests.step);
|
|
39
|
-
|
|
40
|
-
// Individual test modules (can be run separately for focused testing)
|
|
41
|
-
const test_ansi = b.addTest(.{
|
|
42
|
-
.root_module = b.createModule(.{
|
|
43
|
-
.root_source_file = b.path("src/zig/test_ansi.zig"),
|
|
44
|
-
.target = target,
|
|
45
|
-
.optimize = optimize,
|
|
46
|
-
}),
|
|
47
|
-
});
|
|
48
|
-
const run_test_ansi = b.addRunArtifact(test_ansi);
|
|
49
|
-
run_test_ansi.has_side_effects = true;
|
|
50
|
-
const test_ansi_step = b.step("test:ansi", "Run ANSI tests only");
|
|
51
|
-
test_ansi_step.dependOn(&run_test_ansi.step);
|
|
52
|
-
|
|
53
|
-
const test_throttle = b.addTest(.{
|
|
54
|
-
.root_module = b.createModule(.{
|
|
55
|
-
.root_source_file = b.path("src/zig/test_throttle.zig"),
|
|
56
|
-
.target = target,
|
|
57
|
-
.optimize = optimize,
|
|
58
|
-
}),
|
|
59
|
-
});
|
|
60
|
-
const run_test_throttle = b.addRunArtifact(test_throttle);
|
|
61
|
-
run_test_throttle.has_side_effects = true;
|
|
62
|
-
const test_throttle_step = b.step("test:throttle", "Run Throttle tests only");
|
|
63
|
-
test_throttle_step.dependOn(&run_test_throttle.step);
|
|
64
|
-
|
|
65
|
-
const test_buffer = b.addTest(.{
|
|
66
|
-
.root_module = b.createModule(.{
|
|
67
|
-
.root_source_file = b.path("src/zig/test_buffer.zig"),
|
|
68
|
-
.target = target,
|
|
69
|
-
.optimize = optimize,
|
|
70
|
-
}),
|
|
71
|
-
});
|
|
72
|
-
const run_test_buffer = b.addRunArtifact(test_buffer);
|
|
73
|
-
run_test_buffer.has_side_effects = true;
|
|
74
|
-
const test_buffer_step = b.step("test:buffer", "Run Buffer tests only");
|
|
75
|
-
test_buffer_step.dependOn(&run_test_buffer.step);
|
|
76
|
-
|
|
77
|
-
const test_diff = b.addTest(.{
|
|
78
|
-
.root_module = b.createModule(.{
|
|
79
|
-
.root_source_file = b.path("src/zig/test_diff.zig"),
|
|
80
|
-
.target = target,
|
|
81
|
-
.optimize = optimize,
|
|
82
|
-
}),
|
|
83
|
-
});
|
|
84
|
-
const run_test_diff = b.addRunArtifact(test_diff);
|
|
85
|
-
run_test_diff.has_side_effects = true;
|
|
86
|
-
const test_diff_step = b.step("test:diff", "Run Diff tests only");
|
|
87
|
-
test_diff_step.dependOn(&run_test_diff.step);
|
|
88
|
-
|
|
89
|
-
const test_region = b.addTest(.{
|
|
90
|
-
.root_module = b.createModule(.{
|
|
91
|
-
.root_source_file = b.path("src/zig/test_region.zig"),
|
|
92
|
-
.target = target,
|
|
93
|
-
.optimize = optimize,
|
|
94
|
-
}),
|
|
95
|
-
});
|
|
96
|
-
const run_test_region = b.addRunArtifact(test_region);
|
|
97
|
-
run_test_region.has_side_effects = true;
|
|
98
|
-
const test_region_step = b.step("test:region", "Run Region tests only");
|
|
99
|
-
test_region_step.dependOn(&run_test_region.step);
|
|
100
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { createRegion, createProgressBar } from '../src/ts';
|
|
2
|
-
|
|
3
|
-
async function main() {
|
|
4
|
-
const region = createRegion({ width: 80 });
|
|
5
|
-
const progress = createProgressBar(region, 1, {
|
|
6
|
-
label: 'Installing packages',
|
|
7
|
-
width: 50,
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
for (let i = 0; i <= 100; i++) {
|
|
11
|
-
progress.update(i, 100);
|
|
12
|
-
await new Promise(resolve => setTimeout(resolve, 50));
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
progress.finish();
|
|
16
|
-
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
17
|
-
region.destroy();
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
main().catch(console.error);
|
|
21
|
-
|
package/examples/multi-lane.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { createRegion, createProgressBar } from '../src/ts/index.js';
|
|
2
|
-
|
|
3
|
-
async function updateProgress(progress: ReturnType<typeof createProgressBar>, total: number) {
|
|
4
|
-
for (let i = 0; i <= total; i++) {
|
|
5
|
-
progress.update(i, total);
|
|
6
|
-
await new Promise(resolve => setTimeout(resolve, 20 + Math.random() * 30));
|
|
7
|
-
}
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
async function main() {
|
|
11
|
-
const region = createRegion({ width: 80 });
|
|
12
|
-
|
|
13
|
-
const download = createProgressBar(region, 1, { label: 'Downloading' });
|
|
14
|
-
const extract = createProgressBar(region, 2, { label: 'Extracting' });
|
|
15
|
-
const install = createProgressBar(region, 3, { label: 'Installing' });
|
|
16
|
-
|
|
17
|
-
// Update lanes concurrently
|
|
18
|
-
await Promise.all([
|
|
19
|
-
updateProgress(download, 100),
|
|
20
|
-
updateProgress(extract, 100),
|
|
21
|
-
updateProgress(install, 100),
|
|
22
|
-
]);
|
|
23
|
-
|
|
24
|
-
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
25
|
-
region.destroy();
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
main().catch(console.error);
|
|
29
|
-
|
package/examples/spinner.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { createRegion, createSpinner } from '../src/ts/index.js';
|
|
2
|
-
|
|
3
|
-
async function main() {
|
|
4
|
-
const region = createRegion({ width: 80 });
|
|
5
|
-
const spinner = createSpinner(region, 1);
|
|
6
|
-
|
|
7
|
-
spinner.setText('Processing...');
|
|
8
|
-
spinner.start();
|
|
9
|
-
|
|
10
|
-
// Simulate work
|
|
11
|
-
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
12
|
-
|
|
13
|
-
spinner.stop();
|
|
14
|
-
region.setLine(1, '✓ Done!');
|
|
15
|
-
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
16
|
-
region.destroy();
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
main().catch(console.error);
|
|
20
|
-
|
package/examples/test-basic.ts
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
// Simple test to verify the Node.js API works
|
|
2
|
-
import { createRegion } from '../src/ts/index.js';
|
|
3
|
-
|
|
4
|
-
console.log('Creating region...');
|
|
5
|
-
const region = createRegion({ x: 0, y: 0, width: 80, height: 1 });
|
|
6
|
-
|
|
7
|
-
console.log('Setting line 1...');
|
|
8
|
-
region.setLine(1, 'Hello from EchoKit!');
|
|
9
|
-
|
|
10
|
-
console.log('Setting line 2 (should expand)...');
|
|
11
|
-
region.setLine(2, 'This is line 2');
|
|
12
|
-
|
|
13
|
-
console.log('Setting multiple lines...');
|
|
14
|
-
region.set('Line 1\nLine 2\nLine 3');
|
|
15
|
-
|
|
16
|
-
console.log('Flushing...');
|
|
17
|
-
region.flush();
|
|
18
|
-
|
|
19
|
-
console.log('Cleaning up...');
|
|
20
|
-
region.destroy();
|
|
21
|
-
|
|
22
|
-
console.log('Test complete!');
|
|
23
|
-
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { TerminalRegion } from '../region.js';
|
|
2
|
-
import type { ProgressBarOptions } from '../types.js';
|
|
3
|
-
|
|
4
|
-
export class ProgressBar {
|
|
5
|
-
private region: TerminalRegion;
|
|
6
|
-
private lineNumber: number; // 1-based
|
|
7
|
-
private current: number = 0;
|
|
8
|
-
private total: number = 100;
|
|
9
|
-
private label: string;
|
|
10
|
-
private width: number;
|
|
11
|
-
private completeChar: string;
|
|
12
|
-
private incompleteChar: string;
|
|
13
|
-
private brackets: [string, string];
|
|
14
|
-
|
|
15
|
-
constructor(region: TerminalRegion, lineNumber: number, options: ProgressBarOptions = {}) {
|
|
16
|
-
this.region = region;
|
|
17
|
-
this.lineNumber = lineNumber;
|
|
18
|
-
this.label = options.label || '';
|
|
19
|
-
this.width = options.width ?? 40;
|
|
20
|
-
this.completeChar = options.style?.complete ?? '█';
|
|
21
|
-
this.incompleteChar = options.style?.incomplete ?? '░';
|
|
22
|
-
this.brackets = options.style?.brackets ?? ['[', ']'];
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
update(current: number, total: number): void {
|
|
26
|
-
this.current = current;
|
|
27
|
-
this.total = total;
|
|
28
|
-
this.render();
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
setLabel(label: string): void {
|
|
32
|
-
this.label = label;
|
|
33
|
-
this.render();
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
private render(): void {
|
|
37
|
-
const percentage = Math.min(100, Math.max(0, (this.current / this.total) * 100));
|
|
38
|
-
const filled = Math.floor((percentage / 100) * this.width);
|
|
39
|
-
const empty = this.width - filled;
|
|
40
|
-
|
|
41
|
-
const bar = this.completeChar.repeat(filled) + this.incompleteChar.repeat(empty);
|
|
42
|
-
const text = `${this.label} ${this.brackets[0]}${bar}${this.brackets[1]} ${percentage.toFixed(1)}%`;
|
|
43
|
-
|
|
44
|
-
// Just update the line - Zig handles batching and rendering
|
|
45
|
-
this.region.setLine(this.lineNumber, text);
|
|
46
|
-
// Optional: call flush() if you need immediate rendering
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
finish(): void {
|
|
50
|
-
this.update(this.total, this.total);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { TerminalRegion } from '../region.js';
|
|
2
|
-
import type { SpinnerOptions } from '../types.js';
|
|
3
|
-
|
|
4
|
-
const DEFAULT_SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
5
|
-
|
|
6
|
-
export class Spinner {
|
|
7
|
-
private region: TerminalRegion;
|
|
8
|
-
private lineNumber: number; // 1-based
|
|
9
|
-
private frameIndex: number = 0;
|
|
10
|
-
private text: string = '';
|
|
11
|
-
private interval?: NodeJS.Timeout;
|
|
12
|
-
private isRunning: boolean = false;
|
|
13
|
-
private frames: string[];
|
|
14
|
-
private intervalMs: number;
|
|
15
|
-
|
|
16
|
-
constructor(region: TerminalRegion, lineNumber: number, options: SpinnerOptions = {}) {
|
|
17
|
-
this.region = region;
|
|
18
|
-
this.lineNumber = lineNumber;
|
|
19
|
-
this.frames = options.frames ?? DEFAULT_SPINNER_FRAMES;
|
|
20
|
-
this.intervalMs = options.interval ?? 100;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
start(): void {
|
|
24
|
-
if (this.isRunning) return;
|
|
25
|
-
this.isRunning = true;
|
|
26
|
-
this.interval = setInterval(() => {
|
|
27
|
-
this.render();
|
|
28
|
-
this.frameIndex = (this.frameIndex + 1) % this.frames.length;
|
|
29
|
-
}, this.intervalMs);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
stop(): void {
|
|
33
|
-
if (!this.isRunning) return;
|
|
34
|
-
this.isRunning = false;
|
|
35
|
-
if (this.interval) {
|
|
36
|
-
clearInterval(this.interval);
|
|
37
|
-
}
|
|
38
|
-
// Clear the spinner line
|
|
39
|
-
this.region.setLine(this.lineNumber, '');
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
setText(text: string): void {
|
|
43
|
-
this.text = text;
|
|
44
|
-
this.render();
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
private render(): void {
|
|
48
|
-
const frame = this.frames[this.frameIndex];
|
|
49
|
-
const line = `${frame} ${this.text}`;
|
|
50
|
-
|
|
51
|
-
// Just update the line - Zig handles batching and rendering
|
|
52
|
-
this.region.setLine(this.lineNumber, line);
|
|
53
|
-
// Spinner updates frequently, so Zig's throttling will handle smooth animation
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
package/src/ts/index.ts
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
export { TerminalRegion } from './region.js';
|
|
2
|
-
export { ProgressBar } from './components/progress-bar.js';
|
|
3
|
-
export { Spinner } from './components/spinner.js';
|
|
4
|
-
export type {
|
|
5
|
-
RegionOptions,
|
|
6
|
-
LineContent,
|
|
7
|
-
TextStyle,
|
|
8
|
-
Color,
|
|
9
|
-
ProgressBarOptions,
|
|
10
|
-
SpinnerOptions,
|
|
11
|
-
} from './types.js';
|
|
12
|
-
|
|
13
|
-
import { TerminalRegion } from './region.js';
|
|
14
|
-
import { ProgressBar } from './components/progress-bar.js';
|
|
15
|
-
import { Spinner } from './components/spinner.js';
|
|
16
|
-
import type { RegionOptions, ProgressBarOptions, SpinnerOptions } from './types.js';
|
|
17
|
-
|
|
18
|
-
export function createRegion(options?: RegionOptions): TerminalRegion {
|
|
19
|
-
return new TerminalRegion(options);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export function createProgressBar(
|
|
23
|
-
region: TerminalRegion,
|
|
24
|
-
lineNumber: number,
|
|
25
|
-
options?: ProgressBarOptions
|
|
26
|
-
): ProgressBar {
|
|
27
|
-
return new ProgressBar(region, lineNumber, options);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export function createSpinner(
|
|
31
|
-
region: TerminalRegion,
|
|
32
|
-
lineNumber: number,
|
|
33
|
-
options?: SpinnerOptions
|
|
34
|
-
): Spinner {
|
|
35
|
-
return new Spinner(region, lineNumber, options);
|
|
36
|
-
}
|
|
37
|
-
|
package/src/ts/native.ts
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import { fileURLToPath } from 'url';
|
|
2
|
-
import { dirname, join } from 'path';
|
|
3
|
-
import { Library } from 'ffi-napi';
|
|
4
|
-
import ref from 'ref-napi';
|
|
5
|
-
|
|
6
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
-
const __dirname = dirname(__filename);
|
|
8
|
-
|
|
9
|
-
// Determine the library path based on platform
|
|
10
|
-
function getLibraryPath(): string {
|
|
11
|
-
const platform = process.platform;
|
|
12
|
-
|
|
13
|
-
if (platform === 'darwin') {
|
|
14
|
-
return join(__dirname, '../../zig-out/lib/libechokit.dylib');
|
|
15
|
-
} else if (platform === 'win32') {
|
|
16
|
-
return join(__dirname, '../../zig-out/lib/echokit.dll');
|
|
17
|
-
} else {
|
|
18
|
-
return join(__dirname, '../../zig-out/lib/libechokit.so');
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// Load the Zig library using FFI
|
|
23
|
-
const lib = Library(getLibraryPath(), {
|
|
24
|
-
create_region: ['uint64', ['uint32', 'uint32', 'uint32', 'uint32']],
|
|
25
|
-
destroy_region: ['void', ['uint64']],
|
|
26
|
-
set_line: ['void', ['uint64', 'uint32', 'pointer', 'size_t']],
|
|
27
|
-
set: ['void', ['uint64', 'pointer', 'size_t']],
|
|
28
|
-
clear_line: ['void', ['uint64', 'uint32']],
|
|
29
|
-
clear_region: ['void', ['uint64']],
|
|
30
|
-
flush: ['void', ['uint64']],
|
|
31
|
-
set_throttle_fps: ['void', ['uint64', 'uint32']],
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
export interface NativeRegion {
|
|
35
|
-
createRegion(x: number, y: number, width: number, height: number): number;
|
|
36
|
-
destroyRegion(handle: number): void;
|
|
37
|
-
setLine(handle: number, lineNumber: number, content: string): void; // 1-based
|
|
38
|
-
set(handle: number, content: string): void;
|
|
39
|
-
clearLine(handle: number, lineNumber: number): void; // 1-based
|
|
40
|
-
clearRegion(handle: number): void;
|
|
41
|
-
flush(handle: number): void;
|
|
42
|
-
setThrottleFps(handle: number, fps: number): void;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export const native: NativeRegion = {
|
|
46
|
-
createRegion: (x: number, y: number, width: number, height: number): number => {
|
|
47
|
-
return Number(lib.create_region(x, y, width, height));
|
|
48
|
-
},
|
|
49
|
-
|
|
50
|
-
destroyRegion: (handle: number): void => {
|
|
51
|
-
lib.destroy_region(BigInt(handle));
|
|
52
|
-
},
|
|
53
|
-
|
|
54
|
-
setLine: (handle: number, lineNumber: number, content: string): void => {
|
|
55
|
-
const buf = Buffer.from(content, 'utf8');
|
|
56
|
-
// Allocate a buffer and copy the string data
|
|
57
|
-
const ptr = ref.alloc(buf.length);
|
|
58
|
-
buf.copy(ptr);
|
|
59
|
-
lib.set_line(BigInt(handle), lineNumber, ptr, buf.length);
|
|
60
|
-
},
|
|
61
|
-
|
|
62
|
-
set: (handle: number, content: string): void => {
|
|
63
|
-
const buf = Buffer.from(content, 'utf8');
|
|
64
|
-
// Allocate a buffer and copy the string data
|
|
65
|
-
const ptr = ref.alloc(buf.length);
|
|
66
|
-
buf.copy(ptr);
|
|
67
|
-
lib.set(BigInt(handle), ptr, buf.length);
|
|
68
|
-
},
|
|
69
|
-
|
|
70
|
-
clearLine: (handle: number, lineNumber: number): void => {
|
|
71
|
-
lib.clear_line(BigInt(handle), lineNumber);
|
|
72
|
-
},
|
|
73
|
-
|
|
74
|
-
clearRegion: (handle: number): void => {
|
|
75
|
-
lib.clear_region(BigInt(handle));
|
|
76
|
-
},
|
|
77
|
-
|
|
78
|
-
flush: (handle: number): void => {
|
|
79
|
-
lib.flush(BigInt(handle));
|
|
80
|
-
},
|
|
81
|
-
|
|
82
|
-
setThrottleFps: (handle: number, fps: number): void => {
|
|
83
|
-
lib.set_throttle_fps(BigInt(handle), fps);
|
|
84
|
-
},
|
|
85
|
-
};
|
|
86
|
-
|
package/src/ts/region.ts
DELETED
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import { native } from './native.js';
|
|
2
|
-
import { applyStyle } from './utils/colors.js';
|
|
3
|
-
import type { RegionOptions, LineContent, TextStyle } from './types.js';
|
|
4
|
-
|
|
5
|
-
export class TerminalRegion {
|
|
6
|
-
private handle: number;
|
|
7
|
-
private _width: number;
|
|
8
|
-
private _height: number; // Current height (may expand)
|
|
9
|
-
|
|
10
|
-
constructor(options: RegionOptions = {}) {
|
|
11
|
-
const x = options.x ?? 0;
|
|
12
|
-
const y = options.y ?? 0;
|
|
13
|
-
this._width = options.width ?? (process.stdout.columns ?? 80);
|
|
14
|
-
this._height = options.height ?? 1; // Default to 1 line, expands as needed
|
|
15
|
-
this.handle = native.createRegion(x, y, this._width, this._height);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
get width(): number {
|
|
19
|
-
return this._width;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
get height(): number {
|
|
23
|
-
return this._height;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
setLine(lineNumber: number, content: string | LineContent): void {
|
|
27
|
-
if (lineNumber < 1) {
|
|
28
|
-
throw new Error('Line numbers start at 1');
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// Zig handles batching and expansion automatically
|
|
32
|
-
const text = typeof content === 'string' ? content : content.text;
|
|
33
|
-
// Apply styling if provided
|
|
34
|
-
const styled = applyStyle(text, typeof content === 'object' ? content.style : undefined);
|
|
35
|
-
native.setLine(this.handle, lineNumber, styled);
|
|
36
|
-
// Zig will:
|
|
37
|
-
// - Convert to 0-based internally
|
|
38
|
-
// - Expand region if lineNumber > current height
|
|
39
|
-
// - Buffer this update in pending_frame
|
|
40
|
-
// - Check throttle
|
|
41
|
-
// - Schedule render if needed (or render immediately if throttle allows)
|
|
42
|
-
|
|
43
|
-
// Update our height tracking if Zig expanded
|
|
44
|
-
if (lineNumber > this._height) {
|
|
45
|
-
this._height = lineNumber;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
set(content: string | LineContent[]): void {
|
|
50
|
-
if (typeof content === 'string') {
|
|
51
|
-
// Single string with \n line breaks
|
|
52
|
-
native.set(this.handle, content);
|
|
53
|
-
// Update height based on line count
|
|
54
|
-
this._height = content.split('\n').length;
|
|
55
|
-
} else {
|
|
56
|
-
// Array of LineContent
|
|
57
|
-
const lines = content.map(c =>
|
|
58
|
-
applyStyle(c.text, c.style)
|
|
59
|
-
).join('\n');
|
|
60
|
-
native.set(this.handle, lines);
|
|
61
|
-
this._height = content.length;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
clearLine(lineNumber: number): void {
|
|
66
|
-
if (lineNumber < 1) {
|
|
67
|
-
throw new Error('Line numbers start at 1');
|
|
68
|
-
}
|
|
69
|
-
native.clearLine(this.handle, lineNumber);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
clear(): void {
|
|
73
|
-
native.clearRegion(this.handle);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
flush(): void {
|
|
77
|
-
// Force immediate render of any pending updates (bypasses throttle)
|
|
78
|
-
native.flush(this.handle);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
setThrottle(fps: number): void {
|
|
82
|
-
native.setThrottleFps(this.handle, fps);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
destroy(): void {
|
|
86
|
-
native.destroyRegion(this.handle);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|