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
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Move cursor to absolute position (1-based coordinates)
|
|
3
|
+
* Format: \x1b[row;colH
|
|
4
|
+
*/
|
|
5
|
+
export declare function moveCursorTo(x: number, y: number): string;
|
|
6
|
+
/**
|
|
7
|
+
* Move cursor up N lines
|
|
8
|
+
* Format: \x1b[nA
|
|
9
|
+
*/
|
|
10
|
+
export declare function moveCursorUp(n: number): string;
|
|
11
|
+
/**
|
|
12
|
+
* Move cursor down N lines
|
|
13
|
+
* Format: \x1b[nB
|
|
14
|
+
*/
|
|
15
|
+
export declare function moveCursorDown(n: number): string;
|
|
16
|
+
/**
|
|
17
|
+
* Move cursor right N columns
|
|
18
|
+
* Format: \x1b[nC
|
|
19
|
+
*/
|
|
20
|
+
export declare function moveCursorRight(n: number): string;
|
|
21
|
+
/**
|
|
22
|
+
* Move cursor left N columns
|
|
23
|
+
* Format: \x1b[nD
|
|
24
|
+
*/
|
|
25
|
+
export declare function moveCursorLeft(n: number): string;
|
|
26
|
+
/**
|
|
27
|
+
* Move cursor to start of line (move left a large number to ensure we're at column 1)
|
|
28
|
+
* Format: \x1b[1000D
|
|
29
|
+
* This is more reliable than \r in some terminals
|
|
30
|
+
* From: https://www.lihaoyi.com/post/BuildyourownCommandLinewithANSIescapecodes.html
|
|
31
|
+
*/
|
|
32
|
+
export declare const MOVE_TO_START_OF_LINE = "\u001B[1000D";
|
|
33
|
+
export declare const CLEAR_LINE = "\u001B[2K";
|
|
34
|
+
export declare const CLEAR_TO_END = "\u001B[0K";
|
|
35
|
+
export declare const CLEAR_TO_START = "\u001B[1K";
|
|
36
|
+
export declare const HIDE_CURSOR = "\u001B[?25l";
|
|
37
|
+
export declare const SHOW_CURSOR = "\u001B[?25h";
|
|
38
|
+
export declare const SAVE_CURSOR = "\u001B[s";
|
|
39
|
+
export declare const RESTORE_CURSOR = "\u001B[u";
|
|
40
|
+
export declare const RESET = "\u001B[0m";
|
|
41
|
+
/**
|
|
42
|
+
* Delete N lines starting from the current line
|
|
43
|
+
* Format: \x1b[nM (deletes n lines, shifting content up)
|
|
44
|
+
*/
|
|
45
|
+
export declare function deleteLines(n: number): string;
|
|
46
|
+
/**
|
|
47
|
+
* Erase Display (ED) - Clear from cursor to end of screen
|
|
48
|
+
* Format: \x1b[J or \x1b[0J
|
|
49
|
+
* This clears everything from the cursor position to the end of the screen
|
|
50
|
+
*/
|
|
51
|
+
export declare const ERASE_TO_END = "\u001B[J";
|
|
52
|
+
/**
|
|
53
|
+
* Erase Display (ED) - Clear from cursor to beginning of screen
|
|
54
|
+
* Format: \x1b[1J
|
|
55
|
+
* This clears everything from the beginning of the screen to the cursor position
|
|
56
|
+
*/
|
|
57
|
+
export declare const ERASE_TO_START = "\u001B[1J";
|
|
58
|
+
/**
|
|
59
|
+
* Erase Display (ED) - Clear entire screen
|
|
60
|
+
* Format: \x1b[2J
|
|
61
|
+
* This clears the entire screen and moves cursor to home position
|
|
62
|
+
*/
|
|
63
|
+
export declare const ERASE_SCREEN = "\u001B[2J";
|
|
64
|
+
/**
|
|
65
|
+
* Disable terminal auto-wrap mode (DECAWM off)
|
|
66
|
+
*
|
|
67
|
+
* When auto-wrap is disabled:
|
|
68
|
+
* - Text that exceeds terminal width is cut off (doesn't wrap to next line)
|
|
69
|
+
* - Useful for right-pinned elements like OhMyZsh prompts
|
|
70
|
+
* - Content stays at fixed column position, making updates easier
|
|
71
|
+
*
|
|
72
|
+
* Equivalent to: `tput rmam` (reset mode automatic margins)
|
|
73
|
+
* Format: \x1b[?7l
|
|
74
|
+
*
|
|
75
|
+
* IMPORTANT: Always re-enable auto-wrap after writing non-wrapping content!
|
|
76
|
+
* Use ENABLE_AUTO_WRAP to restore default behavior.
|
|
77
|
+
*/
|
|
78
|
+
export declare const DISABLE_AUTO_WRAP = "\u001B[?7l";
|
|
79
|
+
/**
|
|
80
|
+
* Enable terminal auto-wrap mode (DECAWM on)
|
|
81
|
+
*
|
|
82
|
+
* Re-enables automatic wrapping (default terminal behavior).
|
|
83
|
+
* Text that exceeds terminal width will wrap to the next line.
|
|
84
|
+
*
|
|
85
|
+
* Equivalent to: `tput smam` (set mode automatic margins)
|
|
86
|
+
* Format: \x1b[?7h
|
|
87
|
+
*
|
|
88
|
+
* This is the default terminal state. Use this to restore after DISABLE_AUTO_WRAP.
|
|
89
|
+
*/
|
|
90
|
+
export declare const ENABLE_AUTO_WRAP = "\u001B[?7h";
|
|
91
|
+
/**
|
|
92
|
+
* Query cursor position (DSR - Device Status Report)
|
|
93
|
+
* Format: \x1b[6n
|
|
94
|
+
*
|
|
95
|
+
* Sends a query to the terminal asking for the current cursor position.
|
|
96
|
+
* Terminal responds with: \x1b[row;colR (e.g., \x1b[10;5R means row 10, column 5)
|
|
97
|
+
*
|
|
98
|
+
* This can be used to query the actual cursor position after resize/scroll,
|
|
99
|
+
* instead of relying on SAVE/RESTORE which may become invalid.
|
|
100
|
+
*
|
|
101
|
+
* Note: Requires reading from stdin and parsing the response asynchronously.
|
|
102
|
+
*/
|
|
103
|
+
export declare const QUERY_CURSOR_POSITION = "\u001B[6n";
|
|
104
|
+
//# sourceMappingURL=ansi.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ansi.d.ts","sourceRoot":"","sources":["../../src/native/ansi.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAGzD;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE9C;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,iBAAe,CAAC;AAGlD,eAAO,MAAM,UAAU,cAAY,CAAC;AACpC,eAAO,MAAM,YAAY,cAAY,CAAC;AACtC,eAAO,MAAM,cAAc,cAAY,CAAC;AACxC,eAAO,MAAM,WAAW,gBAAc,CAAC;AACvC,eAAO,MAAM,WAAW,gBAAc,CAAC;AACvC,eAAO,MAAM,WAAW,aAAW,CAAC;AACpC,eAAO,MAAM,cAAc,aAAW,CAAC;AACvC,eAAO,MAAM,KAAK,cAAY,CAAC;AAE/B;;;GAGG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED;;;;GAIG;AACH,eAAO,MAAM,YAAY,aAAW,CAAC;AAErC;;;;GAIG;AACH,eAAO,MAAM,cAAc,cAAY,CAAC;AAExC;;;;GAIG;AACH,eAAO,MAAM,YAAY,cAAY,CAAC;AAEtC;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,iBAAiB,eAAa,CAAC;AAE5C;;;;;;;;;;GAUG;AACH,eAAO,MAAM,gBAAgB,eAAa,CAAC;AAE3C;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,qBAAqB,cAAY,CAAC"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
// ANSI escape code generation - TypeScript implementation
|
|
2
|
+
// Optimized for Node.js string operations
|
|
3
|
+
/**
|
|
4
|
+
* Move cursor to absolute position (1-based coordinates)
|
|
5
|
+
* Format: \x1b[row;colH
|
|
6
|
+
*/
|
|
7
|
+
export function moveCursorTo(x, y) {
|
|
8
|
+
// Use template literals - V8 optimizes these well
|
|
9
|
+
return `\x1b[${y};${x}H`;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Move cursor up N lines
|
|
13
|
+
* Format: \x1b[nA
|
|
14
|
+
*/
|
|
15
|
+
export function moveCursorUp(n) {
|
|
16
|
+
return `\x1b[${n}A`;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Move cursor down N lines
|
|
20
|
+
* Format: \x1b[nB
|
|
21
|
+
*/
|
|
22
|
+
export function moveCursorDown(n) {
|
|
23
|
+
return `\x1b[${n}B`;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Move cursor right N columns
|
|
27
|
+
* Format: \x1b[nC
|
|
28
|
+
*/
|
|
29
|
+
export function moveCursorRight(n) {
|
|
30
|
+
return `\x1b[${n}C`;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Move cursor left N columns
|
|
34
|
+
* Format: \x1b[nD
|
|
35
|
+
*/
|
|
36
|
+
export function moveCursorLeft(n) {
|
|
37
|
+
return `\x1b[${n}D`;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Move cursor to start of line (move left a large number to ensure we're at column 1)
|
|
41
|
+
* Format: \x1b[1000D
|
|
42
|
+
* This is more reliable than \r in some terminals
|
|
43
|
+
* From: https://www.lihaoyi.com/post/BuildyourownCommandLinewithANSIescapecodes.html
|
|
44
|
+
*/
|
|
45
|
+
export const MOVE_TO_START_OF_LINE = '\x1b[1000D';
|
|
46
|
+
// ANSI constants - pre-computed for performance
|
|
47
|
+
export const CLEAR_LINE = '\x1b[2K';
|
|
48
|
+
export const CLEAR_TO_END = '\x1b[0K';
|
|
49
|
+
export const CLEAR_TO_START = '\x1b[1K';
|
|
50
|
+
export const HIDE_CURSOR = '\x1b[?25l';
|
|
51
|
+
export const SHOW_CURSOR = '\x1b[?25h';
|
|
52
|
+
export const SAVE_CURSOR = '\x1b[s';
|
|
53
|
+
export const RESTORE_CURSOR = '\x1b[u';
|
|
54
|
+
export const RESET = '\x1b[0m';
|
|
55
|
+
/**
|
|
56
|
+
* Delete N lines starting from the current line
|
|
57
|
+
* Format: \x1b[nM (deletes n lines, shifting content up)
|
|
58
|
+
*/
|
|
59
|
+
export function deleteLines(n) {
|
|
60
|
+
return `\x1b[${n}M`;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Erase Display (ED) - Clear from cursor to end of screen
|
|
64
|
+
* Format: \x1b[J or \x1b[0J
|
|
65
|
+
* This clears everything from the cursor position to the end of the screen
|
|
66
|
+
*/
|
|
67
|
+
export const ERASE_TO_END = '\x1b[J';
|
|
68
|
+
/**
|
|
69
|
+
* Erase Display (ED) - Clear from cursor to beginning of screen
|
|
70
|
+
* Format: \x1b[1J
|
|
71
|
+
* This clears everything from the beginning of the screen to the cursor position
|
|
72
|
+
*/
|
|
73
|
+
export const ERASE_TO_START = '\x1b[1J';
|
|
74
|
+
/**
|
|
75
|
+
* Erase Display (ED) - Clear entire screen
|
|
76
|
+
* Format: \x1b[2J
|
|
77
|
+
* This clears the entire screen and moves cursor to home position
|
|
78
|
+
*/
|
|
79
|
+
export const ERASE_SCREEN = '\x1b[2J';
|
|
80
|
+
/**
|
|
81
|
+
* Disable terminal auto-wrap mode (DECAWM off)
|
|
82
|
+
*
|
|
83
|
+
* When auto-wrap is disabled:
|
|
84
|
+
* - Text that exceeds terminal width is cut off (doesn't wrap to next line)
|
|
85
|
+
* - Useful for right-pinned elements like OhMyZsh prompts
|
|
86
|
+
* - Content stays at fixed column position, making updates easier
|
|
87
|
+
*
|
|
88
|
+
* Equivalent to: `tput rmam` (reset mode automatic margins)
|
|
89
|
+
* Format: \x1b[?7l
|
|
90
|
+
*
|
|
91
|
+
* IMPORTANT: Always re-enable auto-wrap after writing non-wrapping content!
|
|
92
|
+
* Use ENABLE_AUTO_WRAP to restore default behavior.
|
|
93
|
+
*/
|
|
94
|
+
export const DISABLE_AUTO_WRAP = '\x1b[?7l';
|
|
95
|
+
/**
|
|
96
|
+
* Enable terminal auto-wrap mode (DECAWM on)
|
|
97
|
+
*
|
|
98
|
+
* Re-enables automatic wrapping (default terminal behavior).
|
|
99
|
+
* Text that exceeds terminal width will wrap to the next line.
|
|
100
|
+
*
|
|
101
|
+
* Equivalent to: `tput smam` (set mode automatic margins)
|
|
102
|
+
* Format: \x1b[?7h
|
|
103
|
+
*
|
|
104
|
+
* This is the default terminal state. Use this to restore after DISABLE_AUTO_WRAP.
|
|
105
|
+
*/
|
|
106
|
+
export const ENABLE_AUTO_WRAP = '\x1b[?7h';
|
|
107
|
+
/**
|
|
108
|
+
* Query cursor position (DSR - Device Status Report)
|
|
109
|
+
* Format: \x1b[6n
|
|
110
|
+
*
|
|
111
|
+
* Sends a query to the terminal asking for the current cursor position.
|
|
112
|
+
* Terminal responds with: \x1b[row;colR (e.g., \x1b[10;5R means row 10, column 5)
|
|
113
|
+
*
|
|
114
|
+
* This can be used to query the actual cursor position after resize/scroll,
|
|
115
|
+
* instead of relying on SAVE/RESTORE which may become invalid.
|
|
116
|
+
*
|
|
117
|
+
* Note: Requires reading from stdin and parsing the response asynchronously.
|
|
118
|
+
*/
|
|
119
|
+
export const QUERY_CURSOR_POSITION = '\x1b[6n';
|
|
120
|
+
//# sourceMappingURL=ansi.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ansi.js","sourceRoot":"","sources":["../../src/native/ansi.ts"],"names":[],"mappings":"AAAA,0DAA0D;AAC1D,0CAA0C;AAE1C;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,CAAS,EAAE,CAAS;IAC/C,kDAAkD;IAClD,OAAO,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC;AAC3B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,CAAS;IACpC,OAAO,QAAQ,CAAC,GAAG,CAAC;AACtB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,CAAS;IACtC,OAAO,QAAQ,CAAC,GAAG,CAAC;AACtB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,CAAS;IACvC,OAAO,QAAQ,CAAC,GAAG,CAAC;AACtB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,CAAS;IACtC,OAAO,QAAQ,CAAC,GAAG,CAAC;AACtB,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,YAAY,CAAC;AAElD,gDAAgD;AAChD,MAAM,CAAC,MAAM,UAAU,GAAG,SAAS,CAAC;AACpC,MAAM,CAAC,MAAM,YAAY,GAAG,SAAS,CAAC;AACtC,MAAM,CAAC,MAAM,cAAc,GAAG,SAAS,CAAC;AACxC,MAAM,CAAC,MAAM,WAAW,GAAG,WAAW,CAAC;AACvC,MAAM,CAAC,MAAM,WAAW,GAAG,WAAW,CAAC;AACvC,MAAM,CAAC,MAAM,WAAW,GAAG,QAAQ,CAAC;AACpC,MAAM,CAAC,MAAM,cAAc,GAAG,QAAQ,CAAC;AACvC,MAAM,CAAC,MAAM,KAAK,GAAG,SAAS,CAAC;AAE/B;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,CAAS;IACnC,OAAO,QAAQ,CAAC,GAAG,CAAC;AACtB,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,QAAQ,CAAC;AAErC;;;;GAIG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,SAAS,CAAC;AAExC;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,SAAS,CAAC;AAEtC;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,UAAU,CAAC;AAE5C;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,UAAU,CAAC;AAE3C;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,SAAS,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ansi.test.d.ts","sourceRoot":"","sources":["../../src/native/ansi.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import * as ansi from './ansi';
|
|
3
|
+
describe('ANSI', () => {
|
|
4
|
+
describe('moveCursorTo', () => {
|
|
5
|
+
it('should generate correct ANSI for cursor position', () => {
|
|
6
|
+
const seq = ansi.moveCursorTo(10, 5);
|
|
7
|
+
expect(seq).toBe('\x1b[5;10H');
|
|
8
|
+
});
|
|
9
|
+
it('should handle zero coordinates', () => {
|
|
10
|
+
const seq = ansi.moveCursorTo(0, 0);
|
|
11
|
+
expect(seq).toBe('\x1b[0;0H');
|
|
12
|
+
});
|
|
13
|
+
it('should handle large coordinates', () => {
|
|
14
|
+
const seq = ansi.moveCursorTo(200, 100);
|
|
15
|
+
expect(seq).toBe('\x1b[100;200H');
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
describe('moveCursorUp', () => {
|
|
19
|
+
it('should generate correct ANSI for moving up', () => {
|
|
20
|
+
const seq = ansi.moveCursorUp(3);
|
|
21
|
+
expect(seq).toBe('\x1b[3A');
|
|
22
|
+
});
|
|
23
|
+
it('should handle zero', () => {
|
|
24
|
+
const seq = ansi.moveCursorUp(0);
|
|
25
|
+
expect(seq).toBe('\x1b[0A');
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
describe('moveCursorDown', () => {
|
|
29
|
+
it('should generate correct ANSI for moving down', () => {
|
|
30
|
+
const seq = ansi.moveCursorDown(2);
|
|
31
|
+
expect(seq).toBe('\x1b[2B');
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
describe('moveCursorRight', () => {
|
|
35
|
+
it('should generate correct ANSI for moving right', () => {
|
|
36
|
+
const seq = ansi.moveCursorRight(5);
|
|
37
|
+
expect(seq).toBe('\x1b[5C');
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
describe('moveCursorLeft', () => {
|
|
41
|
+
it('should generate correct ANSI for moving left', () => {
|
|
42
|
+
const seq = ansi.moveCursorLeft(3);
|
|
43
|
+
expect(seq).toBe('\x1b[3D');
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
describe('constants', () => {
|
|
47
|
+
it('should have correct ANSI constants', () => {
|
|
48
|
+
expect(ansi.CLEAR_LINE).toBe('\x1b[2K');
|
|
49
|
+
expect(ansi.HIDE_CURSOR).toBe('\x1b[?25l');
|
|
50
|
+
expect(ansi.SHOW_CURSOR).toBe('\x1b[?25h');
|
|
51
|
+
expect(ansi.SAVE_CURSOR).toBe('\x1b[s');
|
|
52
|
+
expect(ansi.RESTORE_CURSOR).toBe('\x1b[u');
|
|
53
|
+
expect(ansi.RESET).toBe('\x1b[0m');
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
//# sourceMappingURL=ansi.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ansi.test.js","sourceRoot":"","sources":["../../src/native/ansi.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RenderBuffer batches ANSI operations to minimize syscalls.
|
|
3
|
+
*
|
|
4
|
+
* Node.js stdout.write() is buffered, but batching multiple operations
|
|
5
|
+
* into a single write is still more efficient than multiple small writes.
|
|
6
|
+
*/
|
|
7
|
+
export declare class RenderBuffer {
|
|
8
|
+
private buffer;
|
|
9
|
+
private readonly stdout;
|
|
10
|
+
constructor(stdout?: NodeJS.WriteStream);
|
|
11
|
+
/**
|
|
12
|
+
* Append data to the buffer (does not write immediately)
|
|
13
|
+
*/
|
|
14
|
+
write(data: string): void;
|
|
15
|
+
/**
|
|
16
|
+
* Flush all buffered data to stdout in a single write.
|
|
17
|
+
* This minimizes syscalls and improves performance.
|
|
18
|
+
*
|
|
19
|
+
* Note: process.stdout.write() is synchronous by default (blocks until written),
|
|
20
|
+
* so we don't need writeSync. For tests, we can mock stdout.write.
|
|
21
|
+
*/
|
|
22
|
+
flush(): void;
|
|
23
|
+
/**
|
|
24
|
+
* Clear the buffer without writing
|
|
25
|
+
*/
|
|
26
|
+
clear(): void;
|
|
27
|
+
/**
|
|
28
|
+
* Get current buffer size (for debugging)
|
|
29
|
+
*/
|
|
30
|
+
get size(): number;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=buffer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buffer.d.ts","sourceRoot":"","sources":["../../src/native/buffer.ts"],"names":[],"mappings":"AAGA;;;;;GAKG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;gBAEhC,MAAM,GAAE,MAAM,CAAC,WAA4B;IAIvD;;OAEG;IACH,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAIzB;;;;;;OAMG;IACH,KAAK,IAAI,IAAI;IASb;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// Render buffer for batching ANSI operations - TypeScript implementation
|
|
2
|
+
// Optimized for Node.js stdout writes
|
|
3
|
+
/**
|
|
4
|
+
* RenderBuffer batches ANSI operations to minimize syscalls.
|
|
5
|
+
*
|
|
6
|
+
* Node.js stdout.write() is buffered, but batching multiple operations
|
|
7
|
+
* into a single write is still more efficient than multiple small writes.
|
|
8
|
+
*/
|
|
9
|
+
export class RenderBuffer {
|
|
10
|
+
buffer = '';
|
|
11
|
+
stdout;
|
|
12
|
+
constructor(stdout = process.stdout) {
|
|
13
|
+
this.stdout = stdout;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Append data to the buffer (does not write immediately)
|
|
17
|
+
*/
|
|
18
|
+
write(data) {
|
|
19
|
+
this.buffer += data;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Flush all buffered data to stdout in a single write.
|
|
23
|
+
* This minimizes syscalls and improves performance.
|
|
24
|
+
*
|
|
25
|
+
* Note: process.stdout.write() is synchronous by default (blocks until written),
|
|
26
|
+
* so we don't need writeSync. For tests, we can mock stdout.write.
|
|
27
|
+
*/
|
|
28
|
+
flush() {
|
|
29
|
+
if (this.buffer.length > 0) {
|
|
30
|
+
// process.stdout.write() is synchronous and blocks until written
|
|
31
|
+
// This is fine for terminal output where we want immediate rendering
|
|
32
|
+
this.stdout.write(this.buffer);
|
|
33
|
+
this.buffer = '';
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Clear the buffer without writing
|
|
38
|
+
*/
|
|
39
|
+
clear() {
|
|
40
|
+
this.buffer = '';
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Get current buffer size (for debugging)
|
|
44
|
+
*/
|
|
45
|
+
get size() {
|
|
46
|
+
return this.buffer.length;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=buffer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buffer.js","sourceRoot":"","sources":["../../src/native/buffer.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,sCAAsC;AAEtC;;;;;GAKG;AACH,MAAM,OAAO,YAAY;IACf,MAAM,GAAW,EAAE,CAAC;IACX,MAAM,CAAqB;IAE5C,YAAY,SAA6B,OAAO,CAAC,MAAM;QACrD,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,IAAY;QAChB,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC;IACtB,CAAC;IAED;;;;;;OAMG;IACH,KAAK;QACH,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3B,iEAAiE;YACjE,qEAAqE;YACrE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC/B,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;QACnB,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;IACnB,CAAC;IAED;;OAEG;IACH,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;IAC5B,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buffer.test.d.ts","sourceRoot":"","sources":["../../src/native/buffer.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { RenderBuffer } from './buffer';
|
|
3
|
+
describe('RenderBuffer', () => {
|
|
4
|
+
describe('initialization', () => {
|
|
5
|
+
it('should initialize with empty buffer', () => {
|
|
6
|
+
const buffer = new RenderBuffer();
|
|
7
|
+
expect(buffer.size).toBe(0);
|
|
8
|
+
});
|
|
9
|
+
it('should use process.stdout by default', () => {
|
|
10
|
+
const buffer = new RenderBuffer();
|
|
11
|
+
expect(buffer).toBeDefined();
|
|
12
|
+
expect(buffer.size).toBe(0);
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
describe('write', () => {
|
|
16
|
+
it('should append data to buffer', () => {
|
|
17
|
+
const buffer = new RenderBuffer();
|
|
18
|
+
buffer.write('hello');
|
|
19
|
+
buffer.write(' world');
|
|
20
|
+
expect(buffer.size).toBe(11);
|
|
21
|
+
});
|
|
22
|
+
it('should handle large content', () => {
|
|
23
|
+
const buffer = new RenderBuffer();
|
|
24
|
+
const largeContent = 'x'.repeat(1000);
|
|
25
|
+
buffer.write(largeContent);
|
|
26
|
+
expect(buffer.size).toBe(1000);
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
describe('clear', () => {
|
|
30
|
+
it('should clear the buffer', () => {
|
|
31
|
+
const buffer = new RenderBuffer();
|
|
32
|
+
buffer.write('test');
|
|
33
|
+
buffer.clear();
|
|
34
|
+
expect(buffer.size).toBe(0);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
describe('flush', () => {
|
|
38
|
+
it('should write buffered data to stdout', () => {
|
|
39
|
+
const buffer = new RenderBuffer();
|
|
40
|
+
buffer.write('hello');
|
|
41
|
+
buffer.write(' world');
|
|
42
|
+
buffer.flush();
|
|
43
|
+
// Should have written to stdout (visible in test output)
|
|
44
|
+
expect(buffer.size).toBe(0);
|
|
45
|
+
});
|
|
46
|
+
it('should not write if buffer is empty', () => {
|
|
47
|
+
const buffer = new RenderBuffer();
|
|
48
|
+
buffer.flush();
|
|
49
|
+
// Should not throw
|
|
50
|
+
expect(buffer.size).toBe(0);
|
|
51
|
+
});
|
|
52
|
+
it('should handle multiple writes and flush', () => {
|
|
53
|
+
const buffer = new RenderBuffer();
|
|
54
|
+
buffer.write('part1');
|
|
55
|
+
buffer.write('part2');
|
|
56
|
+
buffer.write('part3');
|
|
57
|
+
expect(buffer.size).toBe(15);
|
|
58
|
+
buffer.flush();
|
|
59
|
+
// Should have written to stdout (visible in test output)
|
|
60
|
+
expect(buffer.size).toBe(0);
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
//# sourceMappingURL=buffer.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buffer.test.js","sourceRoot":"","sources":["../../src/native/buffer.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export type DiffOp = {
|
|
2
|
+
type: 'no_change';
|
|
3
|
+
} | {
|
|
4
|
+
type: 'update_line';
|
|
5
|
+
line: number;
|
|
6
|
+
content: string;
|
|
7
|
+
} | {
|
|
8
|
+
type: 'delete_line';
|
|
9
|
+
line: number;
|
|
10
|
+
} | {
|
|
11
|
+
type: 'insert_line';
|
|
12
|
+
line: number;
|
|
13
|
+
content: string;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Diff two frames to generate minimal update operations.
|
|
17
|
+
* This minimizes the number of writes to stdout by only updating changed lines.
|
|
18
|
+
*/
|
|
19
|
+
export declare function diffFrames(prev: string[], curr: string[]): DiffOp[];
|
|
20
|
+
//# sourceMappingURL=diff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../src/native/diff.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,MAAM,GACd;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,GACrB;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACtD;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACrC;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAE3D;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAyBnE"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Diffing algorithm for efficient updates - TypeScript implementation
|
|
2
|
+
// Optimized for Node.js performance
|
|
3
|
+
/**
|
|
4
|
+
* Diff two frames to generate minimal update operations.
|
|
5
|
+
* This minimizes the number of writes to stdout by only updating changed lines.
|
|
6
|
+
*/
|
|
7
|
+
export function diffFrames(prev, curr) {
|
|
8
|
+
const ops = [];
|
|
9
|
+
const maxLen = Math.max(prev.length, curr.length);
|
|
10
|
+
for (let i = 0; i < maxLen; i++) {
|
|
11
|
+
const prevLine = i < prev.length ? prev[i] : null;
|
|
12
|
+
const currLine = i < curr.length ? curr[i] : null;
|
|
13
|
+
if (prevLine === null && currLine !== null) {
|
|
14
|
+
// Line inserted
|
|
15
|
+
ops.push({ type: 'insert_line', line: i, content: currLine });
|
|
16
|
+
}
|
|
17
|
+
else if (prevLine !== null && currLine === null) {
|
|
18
|
+
// Line deleted
|
|
19
|
+
ops.push({ type: 'delete_line', line: i });
|
|
20
|
+
}
|
|
21
|
+
else if (prevLine !== null && currLine !== null) {
|
|
22
|
+
// Check if line changed (use strict equality for fast comparison)
|
|
23
|
+
if (prevLine !== currLine) {
|
|
24
|
+
ops.push({ type: 'update_line', line: i, content: currLine });
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
ops.push({ type: 'no_change' });
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return ops;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=diff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.js","sourceRoot":"","sources":["../../src/native/diff.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,oCAAoC;AAQpC;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,IAAc,EAAE,IAAc;IACvD,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IAElD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAChC,MAAM,QAAQ,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAClD,MAAM,QAAQ,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAElD,IAAI,QAAQ,KAAK,IAAI,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;YAC3C,gBAAgB;YAChB,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC;QAChE,CAAC;aAAM,IAAI,QAAQ,KAAK,IAAI,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;YAClD,eAAe;YACf,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;QAC7C,CAAC;aAAM,IAAI,QAAQ,KAAK,IAAI,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;YAClD,kEAAkE;YAClE,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;gBAC1B,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC;YAChE,CAAC;iBAAM,CAAC;gBACN,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC;YAClC,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.test.d.ts","sourceRoot":"","sources":["../../src/native/diff.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { diffFrames } from './diff';
|
|
3
|
+
describe('diffFrames', () => {
|
|
4
|
+
describe('identical frames', () => {
|
|
5
|
+
it('should return no_change ops for identical frames', () => {
|
|
6
|
+
const prev = ['line1', 'line2'];
|
|
7
|
+
const curr = ['line1', 'line2'];
|
|
8
|
+
const ops = diffFrames(prev, curr);
|
|
9
|
+
expect(ops).toHaveLength(2);
|
|
10
|
+
expect(ops[0].type).toBe('no_change');
|
|
11
|
+
expect(ops[1].type).toBe('no_change');
|
|
12
|
+
});
|
|
13
|
+
});
|
|
14
|
+
describe('changed line', () => {
|
|
15
|
+
it('should detect line updates', () => {
|
|
16
|
+
const prev = ['line1', 'line2'];
|
|
17
|
+
const curr = ['line1', 'line2_changed'];
|
|
18
|
+
const ops = diffFrames(prev, curr);
|
|
19
|
+
expect(ops).toHaveLength(2);
|
|
20
|
+
expect(ops[0].type).toBe('no_change');
|
|
21
|
+
expect(ops[1].type).toBe('update_line');
|
|
22
|
+
if (ops[1].type === 'update_line') {
|
|
23
|
+
expect(ops[1].line).toBe(1);
|
|
24
|
+
expect(ops[1].content).toBe('line2_changed');
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
describe('inserted line', () => {
|
|
29
|
+
it('should detect new lines', () => {
|
|
30
|
+
const prev = ['line1'];
|
|
31
|
+
const curr = ['line1', 'line2'];
|
|
32
|
+
const ops = diffFrames(prev, curr);
|
|
33
|
+
expect(ops).toHaveLength(2);
|
|
34
|
+
expect(ops[0].type).toBe('no_change');
|
|
35
|
+
expect(ops[1].type).toBe('insert_line');
|
|
36
|
+
if (ops[1].type === 'insert_line') {
|
|
37
|
+
expect(ops[1].line).toBe(1);
|
|
38
|
+
expect(ops[1].content).toBe('line2');
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
describe('deleted line', () => {
|
|
43
|
+
it('should detect removed lines', () => {
|
|
44
|
+
const prev = ['line1', 'line2'];
|
|
45
|
+
const curr = ['line1'];
|
|
46
|
+
const ops = diffFrames(prev, curr);
|
|
47
|
+
expect(ops).toHaveLength(2);
|
|
48
|
+
expect(ops[0].type).toBe('no_change');
|
|
49
|
+
expect(ops[1].type).toBe('delete_line');
|
|
50
|
+
if (ops[1].type === 'delete_line') {
|
|
51
|
+
expect(ops[1].line).toBe(1);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
describe('multiple changes', () => {
|
|
56
|
+
it('should handle complex diffs', () => {
|
|
57
|
+
const prev = ['line1', 'line2', 'line3'];
|
|
58
|
+
const curr = ['line1_changed', 'line2', 'line3', 'line4'];
|
|
59
|
+
const ops = diffFrames(prev, curr);
|
|
60
|
+
expect(ops).toHaveLength(4);
|
|
61
|
+
expect(ops[0].type).toBe('update_line');
|
|
62
|
+
expect(ops[1].type).toBe('no_change');
|
|
63
|
+
expect(ops[2].type).toBe('no_change');
|
|
64
|
+
expect(ops[3].type).toBe('insert_line');
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
describe('empty frames', () => {
|
|
68
|
+
it('should handle empty frames', () => {
|
|
69
|
+
const prev = [];
|
|
70
|
+
const curr = [];
|
|
71
|
+
const ops = diffFrames(prev, curr);
|
|
72
|
+
expect(ops).toHaveLength(0);
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
describe('completely different frames', () => {
|
|
76
|
+
it('should detect all changes', () => {
|
|
77
|
+
const prev = ['old1', 'old2'];
|
|
78
|
+
const curr = ['new1', 'new2'];
|
|
79
|
+
const ops = diffFrames(prev, curr);
|
|
80
|
+
expect(ops).toHaveLength(2);
|
|
81
|
+
expect(ops[0].type).toBe('update_line');
|
|
82
|
+
expect(ops[1].type).toBe('update_line');
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
describe('edge cases', () => {
|
|
86
|
+
it('should handle prev longer than curr', () => {
|
|
87
|
+
const prev = ['line1', 'line2', 'line3'];
|
|
88
|
+
const curr = ['line1'];
|
|
89
|
+
const ops = diffFrames(prev, curr);
|
|
90
|
+
expect(ops).toHaveLength(3);
|
|
91
|
+
expect(ops[0].type).toBe('no_change');
|
|
92
|
+
expect(ops[1].type).toBe('delete_line');
|
|
93
|
+
expect(ops[2].type).toBe('delete_line');
|
|
94
|
+
});
|
|
95
|
+
it('should handle curr longer than prev', () => {
|
|
96
|
+
const prev = ['line1'];
|
|
97
|
+
const curr = ['line1', 'line2', 'line3'];
|
|
98
|
+
const ops = diffFrames(prev, curr);
|
|
99
|
+
expect(ops).toHaveLength(3);
|
|
100
|
+
expect(ops[0].type).toBe('no_change');
|
|
101
|
+
expect(ops[1].type).toBe('insert_line');
|
|
102
|
+
expect(ops[2].type).toBe('insert_line');
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
//# sourceMappingURL=diff.test.js.map
|