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,59 @@
|
|
|
1
|
+
// Simple color formatting API - less markup required
|
|
2
|
+
import { applyStyle } from './colors';
|
|
3
|
+
/**
|
|
4
|
+
* Simple color formatting using template-like syntax
|
|
5
|
+
* Example: color`Hello ${'world'}.red.bold`
|
|
6
|
+
*/
|
|
7
|
+
export function color(strings, ...values) {
|
|
8
|
+
let result = '';
|
|
9
|
+
for (let i = 0; i < strings.length; i++) {
|
|
10
|
+
result += strings[i];
|
|
11
|
+
if (i < values.length) {
|
|
12
|
+
result += String(values[i]);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return result;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Create a color formatter function
|
|
19
|
+
* Usage: const red = colorFn('red', { bold: true });
|
|
20
|
+
* red('Hello') // returns styled text
|
|
21
|
+
*/
|
|
22
|
+
export function colorFn(color, style) {
|
|
23
|
+
return (text) => applyStyle(text, { color, ...style });
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Pre-defined color formatters for convenience
|
|
27
|
+
*/
|
|
28
|
+
export const colors = {
|
|
29
|
+
black: (text) => applyStyle(text, { color: 'black' }),
|
|
30
|
+
red: (text) => applyStyle(text, { color: 'red' }),
|
|
31
|
+
green: (text) => applyStyle(text, { color: 'green' }),
|
|
32
|
+
yellow: (text) => applyStyle(text, { color: 'yellow' }),
|
|
33
|
+
blue: (text) => applyStyle(text, { color: 'blue' }),
|
|
34
|
+
magenta: (text) => applyStyle(text, { color: 'magenta' }),
|
|
35
|
+
cyan: (text) => applyStyle(text, { color: 'cyan' }),
|
|
36
|
+
white: (text) => applyStyle(text, { color: 'white' }),
|
|
37
|
+
brightBlack: (text) => applyStyle(text, { color: 'brightBlack' }),
|
|
38
|
+
brightRed: (text) => applyStyle(text, { color: 'brightRed' }),
|
|
39
|
+
brightGreen: (text) => applyStyle(text, { color: 'brightGreen' }),
|
|
40
|
+
brightYellow: (text) => applyStyle(text, { color: 'brightYellow' }),
|
|
41
|
+
brightBlue: (text) => applyStyle(text, { color: 'brightBlue' }),
|
|
42
|
+
brightMagenta: (text) => applyStyle(text, { color: 'brightMagenta' }),
|
|
43
|
+
brightCyan: (text) => applyStyle(text, { color: 'brightCyan' }),
|
|
44
|
+
brightWhite: (text) => applyStyle(text, { color: 'brightWhite' }),
|
|
45
|
+
bold: (text) => applyStyle(text, { bold: true }),
|
|
46
|
+
dim: (text) => applyStyle(text, { color: 'brightBlack' }), // Dim effect
|
|
47
|
+
italic: (text) => applyStyle(text, { italic: true }),
|
|
48
|
+
underline: (text) => applyStyle(text, { underline: true }),
|
|
49
|
+
};
|
|
50
|
+
function createColorChain() {
|
|
51
|
+
const chain = {};
|
|
52
|
+
for (const key in colors) {
|
|
53
|
+
const fn = colors[key];
|
|
54
|
+
chain[key] = Object.assign((text) => fn(text), chain);
|
|
55
|
+
}
|
|
56
|
+
return chain;
|
|
57
|
+
}
|
|
58
|
+
export const c = createColorChain();
|
|
59
|
+
//# sourceMappingURL=colors-simple.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"colors-simple.js","sourceRoot":"","sources":["../../src/utils/colors-simple.ts"],"names":[],"mappings":"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"}
|
package/lib/utils/colors.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"colors.d.ts","sourceRoot":"","sources":["../../src/
|
|
1
|
+
{"version":3,"file":"colors.d.ts","sourceRoot":"","sources":["../../src/utils/colors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,SAAS,EAAE,MAAM,UAAU,CAAC;AAwC5C,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,SAAS,GAAG,MAAM,CA8BlE"}
|
package/lib/utils/colors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"colors.js","sourceRoot":"","sources":["../../src/
|
|
1
|
+
{"version":3,"file":"colors.js","sourceRoot":"","sources":["../../src/utils/colors.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,GAA0B;IACzC,KAAK,EAAE,IAAI;IACX,GAAG,EAAE,IAAI;IACT,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,IAAI;IACZ,IAAI,EAAE,IAAI;IACV,OAAO,EAAE,IAAI;IACb,IAAI,EAAE,IAAI;IACV,KAAK,EAAE,IAAI;IACX,WAAW,EAAE,IAAI;IACjB,SAAS,EAAE,IAAI;IACf,WAAW,EAAE,IAAI;IACjB,YAAY,EAAE,IAAI;IAClB,UAAU,EAAE,IAAI;IAChB,aAAa,EAAE,IAAI;IACnB,UAAU,EAAE,IAAI;IAChB,WAAW,EAAE,IAAI;CAClB,CAAC;AAEF,MAAM,cAAc,GAA0B;IAC5C,KAAK,EAAE,IAAI;IACX,GAAG,EAAE,IAAI;IACT,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,IAAI;IACZ,IAAI,EAAE,IAAI;IACV,OAAO,EAAE,IAAI;IACb,IAAI,EAAE,IAAI;IACV,KAAK,EAAE,IAAI;IACX,WAAW,EAAE,KAAK;IAClB,SAAS,EAAE,KAAK;IAChB,WAAW,EAAE,KAAK;IAClB,YAAY,EAAE,KAAK;IACnB,UAAU,EAAE,KAAK;IACjB,aAAa,EAAE,KAAK;IACpB,UAAU,EAAE,KAAK;IACjB,WAAW,EAAE,KAAK;CACnB,CAAC;AAEF,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,KAAiB;IACxD,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IAExB,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QAChB,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;IACvC,CAAC;IAED,IAAI,KAAK,CAAC,eAAe,EAAE,CAAC;QAC1B,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC;IACpD,CAAC;IAED,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QACjB,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;QACpB,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,QAAQ,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,SAAS,CAAC;AAClD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"colors.test.d.ts","sourceRoot":"","sources":["../../src/utils/colors.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { applyStyle } from './colors';
|
|
3
|
+
describe('applyStyle', () => {
|
|
4
|
+
it('should return text unchanged when no style is provided', () => {
|
|
5
|
+
const text = 'Hello, World!';
|
|
6
|
+
expect(applyStyle(text)).toBe(text);
|
|
7
|
+
expect(applyStyle(text, undefined)).toBe(text);
|
|
8
|
+
});
|
|
9
|
+
it('should apply foreground color', () => {
|
|
10
|
+
const text = 'Red text';
|
|
11
|
+
const styled = applyStyle(text, { color: 'red' });
|
|
12
|
+
expect(styled).toContain('\x1b[');
|
|
13
|
+
expect(styled).toContain('31'); // ANSI code for red
|
|
14
|
+
expect(styled).toContain('m');
|
|
15
|
+
expect(styled).toContain(text);
|
|
16
|
+
expect(styled).toContain('\x1b[0m'); // Reset
|
|
17
|
+
});
|
|
18
|
+
it('should apply background color', () => {
|
|
19
|
+
const text = 'Blue background';
|
|
20
|
+
const styled = applyStyle(text, { backgroundColor: 'blue' });
|
|
21
|
+
expect(styled).toContain('44'); // ANSI code for blue background
|
|
22
|
+
expect(styled).toContain(text);
|
|
23
|
+
});
|
|
24
|
+
it('should apply bold style', () => {
|
|
25
|
+
const text = 'Bold text';
|
|
26
|
+
const styled = applyStyle(text, { bold: true });
|
|
27
|
+
expect(styled).toContain('1'); // ANSI code for bold
|
|
28
|
+
expect(styled).toContain(text);
|
|
29
|
+
});
|
|
30
|
+
it('should apply italic style', () => {
|
|
31
|
+
const text = 'Italic text';
|
|
32
|
+
const styled = applyStyle(text, { italic: true });
|
|
33
|
+
expect(styled).toContain('3'); // ANSI code for italic
|
|
34
|
+
expect(styled).toContain(text);
|
|
35
|
+
});
|
|
36
|
+
it('should apply underline style', () => {
|
|
37
|
+
const text = 'Underlined text';
|
|
38
|
+
const styled = applyStyle(text, { underline: true });
|
|
39
|
+
expect(styled).toContain('4'); // ANSI code for underline
|
|
40
|
+
expect(styled).toContain(text);
|
|
41
|
+
});
|
|
42
|
+
it('should apply multiple styles', () => {
|
|
43
|
+
const text = 'Styled text';
|
|
44
|
+
const styled = applyStyle(text, {
|
|
45
|
+
color: 'green',
|
|
46
|
+
backgroundColor: 'yellow',
|
|
47
|
+
bold: true,
|
|
48
|
+
italic: true,
|
|
49
|
+
underline: true,
|
|
50
|
+
});
|
|
51
|
+
expect(styled).toContain('32'); // green
|
|
52
|
+
expect(styled).toContain('43'); // yellow background
|
|
53
|
+
expect(styled).toContain('1'); // bold
|
|
54
|
+
expect(styled).toContain('3'); // italic
|
|
55
|
+
expect(styled).toContain('4'); // underline
|
|
56
|
+
expect(styled).toContain(text);
|
|
57
|
+
expect(styled).toContain('\x1b[0m'); // Reset at end
|
|
58
|
+
});
|
|
59
|
+
it('should handle all color values', () => {
|
|
60
|
+
const colors = [
|
|
61
|
+
'black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white',
|
|
62
|
+
];
|
|
63
|
+
colors.forEach(color => {
|
|
64
|
+
const styled = applyStyle('test', { color });
|
|
65
|
+
expect(styled).toContain('\x1b[');
|
|
66
|
+
expect(styled).toContain('m');
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
it('should handle bright colors', () => {
|
|
70
|
+
const styled = applyStyle('test', { color: 'brightRed' });
|
|
71
|
+
expect(styled).toContain('91'); // ANSI code for bright red
|
|
72
|
+
});
|
|
73
|
+
it('should handle bright background colors', () => {
|
|
74
|
+
const styled = applyStyle('test', { backgroundColor: 'brightBlue' });
|
|
75
|
+
expect(styled).toContain('104'); // ANSI code for bright blue background
|
|
76
|
+
});
|
|
77
|
+
it('should properly format ANSI escape sequences', () => {
|
|
78
|
+
const styled = applyStyle('test', { color: 'red', bold: true });
|
|
79
|
+
// Should be: \x1b[31;1mtest\x1b[0m
|
|
80
|
+
expect(styled).toMatch(/^\x1b\[31;1mtest\x1b\[0m$/);
|
|
81
|
+
});
|
|
82
|
+
it('should reset styles at the end', () => {
|
|
83
|
+
const styled = applyStyle('test', { color: 'blue' });
|
|
84
|
+
expect(styled.endsWith('\x1b[0m')).toBe(true);
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
//# sourceMappingURL=colors.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"colors.test.js","sourceRoot":"","sources":["../../src/utils/colors.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface CursorPosition {
|
|
2
|
+
row: number;
|
|
3
|
+
col: number;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Query the terminal for the current cursor position
|
|
7
|
+
*
|
|
8
|
+
* This uses ANSI DSR (Device Status Report) escape code to ask the terminal
|
|
9
|
+
* for its current cursor position. The terminal responds with the position.
|
|
10
|
+
*
|
|
11
|
+
* @param timeout - Maximum time to wait for response in milliseconds (default: 1000)
|
|
12
|
+
* @returns Promise resolving to cursor position {row, col} (1-based)
|
|
13
|
+
* @throws Error if timeout or parsing fails
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* const pos = await queryCursorPosition();
|
|
18
|
+
* console.log(`Cursor at row ${pos.row}, column ${pos.col}`);
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export declare function queryCursorPosition(timeout?: number): Promise<CursorPosition>;
|
|
22
|
+
//# sourceMappingURL=cursor-position.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cursor-position.d.ts","sourceRoot":"","sources":["../../src/utils/cursor-position.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,MAAa,GAAG,OAAO,CAAC,cAAc,CAAC,CAgInF"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
// Utility to query terminal cursor position using ANSI DSR (Device Status Report)
|
|
2
|
+
// This allows us to get the actual cursor position after resize/scroll events
|
|
3
|
+
import { QUERY_CURSOR_POSITION } from '../native/ansi';
|
|
4
|
+
import { logToFile } from './debug-log';
|
|
5
|
+
/**
|
|
6
|
+
* Query the terminal for the current cursor position
|
|
7
|
+
*
|
|
8
|
+
* This uses ANSI DSR (Device Status Report) escape code to ask the terminal
|
|
9
|
+
* for its current cursor position. The terminal responds with the position.
|
|
10
|
+
*
|
|
11
|
+
* @param timeout - Maximum time to wait for response in milliseconds (default: 1000)
|
|
12
|
+
* @returns Promise resolving to cursor position {row, col} (1-based)
|
|
13
|
+
* @throws Error if timeout or parsing fails
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* const pos = await queryCursorPosition();
|
|
18
|
+
* console.log(`Cursor at row ${pos.row}, column ${pos.col}`);
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export function queryCursorPosition(timeout = 1000) {
|
|
22
|
+
return new Promise((resolve, reject) => {
|
|
23
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
24
|
+
reject(new Error('Not a TTY - cannot query cursor position'));
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const wasRaw = process.stdin.isRaw || false;
|
|
28
|
+
// Check if stdin was paused before we started
|
|
29
|
+
const wasPaused = !process.stdin.readableFlowing;
|
|
30
|
+
let resolved = false;
|
|
31
|
+
const cleanup = () => {
|
|
32
|
+
if (!resolved) {
|
|
33
|
+
resolved = true;
|
|
34
|
+
// CRITICAL: Remove listeners FIRST before changing stdin state
|
|
35
|
+
// This ensures no data handlers interfere with future input
|
|
36
|
+
try {
|
|
37
|
+
process.stdin.removeListener('data', onData);
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
// Ignore if listener wasn't added
|
|
41
|
+
}
|
|
42
|
+
try {
|
|
43
|
+
process.removeListener('SIGINT', onSIGINT);
|
|
44
|
+
}
|
|
45
|
+
catch (err) {
|
|
46
|
+
// Ignore if listener wasn't added
|
|
47
|
+
}
|
|
48
|
+
try {
|
|
49
|
+
// CRITICAL: Check if stdin is already in raw mode (might be from waitForSpacebar)
|
|
50
|
+
// If it is, don't change it - let waitForSpacebar manage it
|
|
51
|
+
const currentRaw = process.stdin.isRaw || false;
|
|
52
|
+
if (currentRaw && !wasRaw) {
|
|
53
|
+
// Stdin is in raw mode but wasn't before - probably waitForSpacebar set it
|
|
54
|
+
// Don't interfere - just log and leave it alone
|
|
55
|
+
logToFile(`[cursor-position] Cleanup: stdin is in raw mode (likely from waitForSpacebar), leaving it unchanged`);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
// Restore to previous state
|
|
59
|
+
process.stdin.setRawMode(wasRaw);
|
|
60
|
+
logToFile(`[cursor-position] Cleanup: restored stdin to previous raw mode (wasRaw=${wasRaw}, currentRaw=${currentRaw})`);
|
|
61
|
+
}
|
|
62
|
+
// CRITICAL: Always resume stdin after query to ensure it's ready for input
|
|
63
|
+
// Even if it was paused before, we need it active for waitForSpacebar
|
|
64
|
+
process.stdin.resume();
|
|
65
|
+
logToFile(`[cursor-position] Cleanup: resumed stdin`);
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
logToFile(`[cursor-position] Cleanup: error restoring stdin: ${err instanceof Error ? err.message : String(err)}`);
|
|
69
|
+
// Ignore errors when restoring raw mode
|
|
70
|
+
}
|
|
71
|
+
if (timeoutId) {
|
|
72
|
+
clearTimeout(timeoutId);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
const onData = (data) => {
|
|
77
|
+
// Only process data if we haven't resolved yet
|
|
78
|
+
if (resolved) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
// Handle Ctrl+C explicitly - in raw mode, Ctrl+C is \u0003
|
|
82
|
+
if (data === '\u0003') {
|
|
83
|
+
cleanup();
|
|
84
|
+
process.exit(130); // Standard exit code for SIGINT
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
// Terminal responds with: \x1b[row;colR
|
|
88
|
+
// Example: \x1b[10;5R means row 10, column 5
|
|
89
|
+
const match = /\[(\d+);(\d+)R/.exec(data);
|
|
90
|
+
if (match) {
|
|
91
|
+
const row = parseInt(match[1], 10);
|
|
92
|
+
const col = parseInt(match[2], 10);
|
|
93
|
+
cleanup();
|
|
94
|
+
resolve({ row, col });
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
const onSIGINT = () => {
|
|
98
|
+
// DEBUG: Log when SIGINT fires
|
|
99
|
+
logToFile(`[cursor-position] SIGINT handler FIRED! resolved=${resolved}`);
|
|
100
|
+
// Only exit if we're still waiting for the cursor position
|
|
101
|
+
// If cleanup was already called, this shouldn't fire, but be defensive
|
|
102
|
+
// CRITICAL: Check resolved flag BEFORE doing anything
|
|
103
|
+
if (resolved) {
|
|
104
|
+
// Already resolved - don't do anything, just return
|
|
105
|
+
// This handler should have been removed, but if it fires, ignore it
|
|
106
|
+
logToFile(`[cursor-position] SIGINT handler IGNORED (already resolved)`);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
logToFile(`[cursor-position] SIGINT handler calling cleanup() and process.exit(130)`);
|
|
110
|
+
cleanup();
|
|
111
|
+
// Only exit if we're actually in the middle of a query
|
|
112
|
+
// If resolved is true, cleanup() will set it, so this check is redundant but safe
|
|
113
|
+
if (!resolved) {
|
|
114
|
+
process.exit(130); // Standard exit code for SIGINT
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
// Set timeout
|
|
118
|
+
const timeoutId = setTimeout(() => {
|
|
119
|
+
cleanup();
|
|
120
|
+
reject(new Error('Timeout waiting for cursor position response'));
|
|
121
|
+
}, timeout);
|
|
122
|
+
try {
|
|
123
|
+
// Set stdin to raw mode to capture the response
|
|
124
|
+
process.stdin.setRawMode(true);
|
|
125
|
+
process.stdin.resume();
|
|
126
|
+
process.stdin.setEncoding('utf8');
|
|
127
|
+
process.stdin.on('data', onData);
|
|
128
|
+
// Handle SIGINT explicitly (Ctrl+C)
|
|
129
|
+
process.on('SIGINT', onSIGINT);
|
|
130
|
+
// Send the query
|
|
131
|
+
process.stdout.write(QUERY_CURSOR_POSITION);
|
|
132
|
+
}
|
|
133
|
+
catch (err) {
|
|
134
|
+
cleanup();
|
|
135
|
+
reject(err);
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=cursor-position.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cursor-position.js","sourceRoot":"","sources":["../../src/utils/cursor-position.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAClF,8EAA8E;AAE9E,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAOxC;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,mBAAmB,CAAC,UAAkB,IAAI;IACxD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YAClD,MAAM,CAAC,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC,CAAC;YAC9D,OAAO;QACT,CAAC;QAED,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC;QAC5C,8CAA8C;QAC9C,MAAM,SAAS,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,eAAe,CAAC;QACjD,IAAI,QAAQ,GAAG,KAAK,CAAC;QAErB,MAAM,OAAO,GAAG,GAAG,EAAE;YACnB,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,QAAQ,GAAG,IAAI,CAAC;gBAEhB,+DAA+D;gBAC/D,4DAA4D;gBAC5D,IAAI,CAAC;oBACH,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;gBAC/C,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,kCAAkC;gBACpC,CAAC;gBACD,IAAI,CAAC;oBACH,OAAO,CAAC,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;gBAC7C,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,kCAAkC;gBACpC,CAAC;gBAED,IAAI,CAAC;oBACH,kFAAkF;oBAClF,4DAA4D;oBAC5D,MAAM,UAAU,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC;oBAChD,IAAI,UAAU,IAAI,CAAC,MAAM,EAAE,CAAC;wBAC1B,2EAA2E;wBAC3E,gDAAgD;wBAChD,SAAS,CAAC,qGAAqG,CAAC,CAAC;oBACnH,CAAC;yBAAM,CAAC;wBACN,4BAA4B;wBAC5B,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;wBACjC,SAAS,CAAC,0EAA0E,MAAM,gBAAgB,UAAU,GAAG,CAAC,CAAC;oBAC3H,CAAC;oBAED,2EAA2E;oBAC3E,sEAAsE;oBACtE,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;oBACvB,SAAS,CAAC,0CAA0C,CAAC,CAAC;gBACxD,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,SAAS,CAAC,qDAAqD,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;oBACnH,wCAAwC;gBAC1C,CAAC;gBAED,IAAI,SAAS,EAAE,CAAC;oBACd,YAAY,CAAC,SAAS,CAAC,CAAC;gBAC1B,CAAC;YACH,CAAC;QACH,CAAC,CAAC;QAEF,MAAM,MAAM,GAAG,CAAC,IAAY,EAAE,EAAE;YAC9B,+CAA+C;YAC/C,IAAI,QAAQ,EAAE,CAAC;gBACb,OAAO;YACT,CAAC;YAED,2DAA2D;YAC3D,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACtB,OAAO,EAAE,CAAC;gBACV,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,gCAAgC;gBACnD,OAAO;YACT,CAAC;YAED,wCAAwC;YACxC,6CAA6C;YAC7C,MAAM,KAAK,GAAG,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC1C,IAAI,KAAK,EAAE,CAAC;gBACV,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACnC,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACnC,OAAO,EAAE,CAAC;gBACV,OAAO,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;YACxB,CAAC;QACH,CAAC,CAAC;QAEF,MAAM,QAAQ,GAAG,GAAG,EAAE;YACpB,+BAA+B;YAC/B,SAAS,CAAC,oDAAoD,QAAQ,EAAE,CAAC,CAAC;YAE1E,2DAA2D;YAC3D,uEAAuE;YACvE,sDAAsD;YACtD,IAAI,QAAQ,EAAE,CAAC;gBACb,oDAAoD;gBACpD,oEAAoE;gBACpE,SAAS,CAAC,6DAA6D,CAAC,CAAC;gBACzE,OAAO;YACT,CAAC;YAED,SAAS,CAAC,0EAA0E,CAAC,CAAC;YACtF,OAAO,EAAE,CAAC;YACV,uDAAuD;YACvD,kFAAkF;YAClF,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,gCAAgC;YACrD,CAAC;QACH,CAAC,CAAC;QAEF,cAAc;QACd,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE;YAChC,OAAO,EAAE,CAAC;YACV,MAAM,CAAC,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC,CAAC;QACpE,CAAC,EAAE,OAAO,CAAC,CAAC;QAEZ,IAAI,CAAC;YACH,gDAAgD;YAChD,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;YAC/B,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YACvB,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;YAClC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YAEjC,oCAAoC;YACpC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;YAE/B,iBAAiB;YACjB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;QAC9C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,EAAE,CAAC;YACV,MAAM,CAAC,GAAG,CAAC,CAAC;QACd,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debug-log.d.ts","sourceRoot":"","sources":["../../src/utils/debug-log.ts"],"names":[],"mappings":"AAyCA,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE/C"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// Shared debug logging utility - singleton pattern
|
|
2
|
+
// All files should use this instead of duplicating logging code
|
|
3
|
+
import * as fs from 'fs';
|
|
4
|
+
import * as path from 'path';
|
|
5
|
+
class DebugLog {
|
|
6
|
+
static instance = null;
|
|
7
|
+
logPath;
|
|
8
|
+
cleared = false;
|
|
9
|
+
constructor() {
|
|
10
|
+
this.logPath = path.join(process.cwd(), 'linecraft-debug.log');
|
|
11
|
+
}
|
|
12
|
+
static getInstance() {
|
|
13
|
+
if (!DebugLog.instance) {
|
|
14
|
+
DebugLog.instance = new DebugLog();
|
|
15
|
+
}
|
|
16
|
+
return DebugLog.instance;
|
|
17
|
+
}
|
|
18
|
+
log(message) {
|
|
19
|
+
try {
|
|
20
|
+
// Clear log file on first write
|
|
21
|
+
if (!this.cleared) {
|
|
22
|
+
fs.writeFileSync(this.logPath, `# Linecraft Debug Log\n# This file will be appended to during rendering operations\n# Monitor this file to see debug output from expandTo() and renderNow()\n\n`);
|
|
23
|
+
this.cleared = true;
|
|
24
|
+
}
|
|
25
|
+
const timestamp = new Date().toISOString();
|
|
26
|
+
fs.appendFileSync(this.logPath, `[${timestamp}] ${message}\n`);
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
// Silently fail - don't break functionality if logging fails
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export function logToFile(message) {
|
|
34
|
+
DebugLog.getInstance().log(message);
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=debug-log.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debug-log.js","sourceRoot":"","sources":["../../src/utils/debug-log.ts"],"names":[],"mappings":"AAAA,mDAAmD;AACnD,gEAAgE;AAEhE,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B,MAAM,QAAQ;IACJ,MAAM,CAAC,QAAQ,GAAoB,IAAI,CAAC;IACxC,OAAO,CAAS;IAChB,OAAO,GAAY,KAAK,CAAC;IAEjC;QACE,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,qBAAqB,CAAC,CAAC;IACjE,CAAC;IAED,MAAM,CAAC,WAAW;QAChB,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;YACvB,QAAQ,CAAC,QAAQ,GAAG,IAAI,QAAQ,EAAE,CAAC;QACrC,CAAC;QACD,OAAO,QAAQ,CAAC,QAAQ,CAAC;IAC3B,CAAC;IAED,GAAG,CAAC,OAAe;QACjB,IAAI,CAAC;YACH,gCAAgC;YAChC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;gBAClB,EAAE,CAAC,aAAa,CACd,IAAI,CAAC,OAAO,EACZ,iKAAiK,CAClK,CAAC;gBACF,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;YACtB,CAAC;YAED,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;YAC3C,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,SAAS,KAAK,OAAO,IAAI,CAAC,CAAC;QACjE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,6DAA6D;QAC/D,CAAC;IACH,CAAC;;AAGH,MAAM,UAAU,SAAS,CAAC,OAAe;IACvC,QAAQ,CAAC,WAAW,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AACtC,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get the terminal width in columns.
|
|
3
|
+
* Returns the actual width if available, or a sensible default.
|
|
4
|
+
*
|
|
5
|
+
* CRITICAL: We subtract 1 to leave a margin, preventing content from reaching
|
|
6
|
+
* the terminal edge. This prevents auto-wrap issues and cursor positioning problems,
|
|
7
|
+
* similar to how OhMyZsh works. Content will never exceed (terminalWidth - 1).
|
|
8
|
+
*/
|
|
9
|
+
export declare function getTerminalWidth(): number;
|
|
10
|
+
/**
|
|
11
|
+
* Get the terminal height in rows.
|
|
12
|
+
* Returns the actual height if available, or a sensible default.
|
|
13
|
+
*/
|
|
14
|
+
export declare function getTerminalHeight(): number;
|
|
15
|
+
/**
|
|
16
|
+
* Check if stdout is a TTY (interactive terminal)
|
|
17
|
+
*/
|
|
18
|
+
export declare function isTTY(): boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Listen for terminal resize events and call the callback with new dimensions
|
|
21
|
+
* Returns a cleanup function to remove the listener
|
|
22
|
+
*
|
|
23
|
+
* Uses singleton pattern: only one listener on process.stdout, but tracks all callbacks
|
|
24
|
+
* This prevents MaxListenersExceededWarning when multiple regions are created
|
|
25
|
+
*/
|
|
26
|
+
export declare function onResize(callback: (width: number, height: number) => void): () => void;
|
|
27
|
+
//# sourceMappingURL=terminal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal.d.ts","sourceRoot":"","sources":["../../src/utils/terminal.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CA8BzC;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAgB1C;AAED;;GAEG;AACH,wBAAgB,KAAK,IAAI,OAAO,CAE/B;AAOD;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,MAAM,IAAI,CA2CtF"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
// Terminal utilities for detecting terminal size and capabilities
|
|
2
|
+
/**
|
|
3
|
+
* Get the terminal width in columns.
|
|
4
|
+
* Returns the actual width if available, or a sensible default.
|
|
5
|
+
*
|
|
6
|
+
* CRITICAL: We subtract 1 to leave a margin, preventing content from reaching
|
|
7
|
+
* the terminal edge. This prevents auto-wrap issues and cursor positioning problems,
|
|
8
|
+
* similar to how OhMyZsh works. Content will never exceed (terminalWidth - 1).
|
|
9
|
+
*/
|
|
10
|
+
export function getTerminalWidth() {
|
|
11
|
+
let width;
|
|
12
|
+
// process.stdout.columns is the standard way to get terminal width
|
|
13
|
+
// It's undefined if stdout is not a TTY (e.g., piped output)
|
|
14
|
+
if (process.stdout.isTTY && process.stdout.columns) {
|
|
15
|
+
width = process.stdout.columns;
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
// Fallback to environment variable (some terminals set this)
|
|
19
|
+
const envCols = process.env.COLUMNS;
|
|
20
|
+
if (envCols) {
|
|
21
|
+
const cols = parseInt(envCols, 10);
|
|
22
|
+
if (!isNaN(cols) && cols > 0) {
|
|
23
|
+
width = cols;
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
width = 80; // Default fallback
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
width = 80; // Default fallback
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
// CRITICAL: Reserve 2 columns to prevent cursor wrapping
|
|
34
|
+
// - Writing exactly (terminal_width - 1) characters puts cursor at last column, causing wrap
|
|
35
|
+
// - We need to write (terminal_width - 2) characters to keep cursor safe
|
|
36
|
+
// - After writing (width - 2) characters, cursor is at column (width - 2), leaving columns (width - 1) and width empty
|
|
37
|
+
//
|
|
38
|
+
// Example: If terminal is 80 columns, we can write up to 78 characters.
|
|
39
|
+
// After writing 78 characters, cursor is at column 78, columns 79-80 stay empty.
|
|
40
|
+
return Math.max(1, width - 2);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Get the terminal height in rows.
|
|
44
|
+
* Returns the actual height if available, or a sensible default.
|
|
45
|
+
*/
|
|
46
|
+
export function getTerminalHeight() {
|
|
47
|
+
if (process.stdout.isTTY && process.stdout.rows) {
|
|
48
|
+
return process.stdout.rows;
|
|
49
|
+
}
|
|
50
|
+
// Fallback to environment variable
|
|
51
|
+
const envRows = process.env.LINES;
|
|
52
|
+
if (envRows) {
|
|
53
|
+
const rows = parseInt(envRows, 10);
|
|
54
|
+
if (!isNaN(rows) && rows > 0) {
|
|
55
|
+
return rows;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// Default fallback
|
|
59
|
+
return 24;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Check if stdout is a TTY (interactive terminal)
|
|
63
|
+
*/
|
|
64
|
+
export function isTTY() {
|
|
65
|
+
return process.stdout.isTTY === true;
|
|
66
|
+
}
|
|
67
|
+
// Singleton pattern for resize listeners to prevent memory leak
|
|
68
|
+
// Multiple regions can register callbacks, but we only add one listener to process.stdout
|
|
69
|
+
let resizeListenersSetup = false;
|
|
70
|
+
const resizeCallbacks = new Set();
|
|
71
|
+
/**
|
|
72
|
+
* Listen for terminal resize events and call the callback with new dimensions
|
|
73
|
+
* Returns a cleanup function to remove the listener
|
|
74
|
+
*
|
|
75
|
+
* Uses singleton pattern: only one listener on process.stdout, but tracks all callbacks
|
|
76
|
+
* This prevents MaxListenersExceededWarning when multiple regions are created
|
|
77
|
+
*/
|
|
78
|
+
export function onResize(callback) {
|
|
79
|
+
if (!process.stdout.isTTY) {
|
|
80
|
+
// Not a TTY, return no-op cleanup
|
|
81
|
+
return () => { };
|
|
82
|
+
}
|
|
83
|
+
// Add callback to set
|
|
84
|
+
resizeCallbacks.add(callback);
|
|
85
|
+
// Set up singleton listener if not already set up
|
|
86
|
+
if (!resizeListenersSetup) {
|
|
87
|
+
resizeListenersSetup = true;
|
|
88
|
+
const resizeHandler = () => {
|
|
89
|
+
// Read directly from stdout to ensure we get the latest values
|
|
90
|
+
// process.stdout.columns/rows are updated by Node.js when resize happens
|
|
91
|
+
// CRITICAL: Apply the same margin as getTerminalWidth() - reserve 2 columns
|
|
92
|
+
const rawWidth = process.stdout.isTTY && process.stdout.columns
|
|
93
|
+
? process.stdout.columns
|
|
94
|
+
: 80;
|
|
95
|
+
const width = Math.max(1, rawWidth - 2);
|
|
96
|
+
const height = process.stdout.isTTY && process.stdout.rows
|
|
97
|
+
? process.stdout.rows
|
|
98
|
+
: getTerminalHeight();
|
|
99
|
+
// Call all registered callbacks
|
|
100
|
+
for (const cb of resizeCallbacks) {
|
|
101
|
+
cb(width, height);
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
// Listen to the 'resize' event on stdout (Node.js emits this on SIGWINCH)
|
|
105
|
+
// Only add ONE listener, regardless of how many callbacks are registered
|
|
106
|
+
process.stdout.on('resize', resizeHandler);
|
|
107
|
+
}
|
|
108
|
+
// Return cleanup function
|
|
109
|
+
return () => {
|
|
110
|
+
resizeCallbacks.delete(callback);
|
|
111
|
+
// Note: We don't remove the listener from process.stdout even when all callbacks are removed
|
|
112
|
+
// because it's harmless to keep it, and removing/re-adding could cause issues
|
|
113
|
+
// The listener will be cleaned up when the process exits
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=terminal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal.js","sourceRoot":"","sources":["../../src/utils/terminal.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Truncate text with ellipsis at the end
|
|
3
|
+
*/
|
|
4
|
+
export declare function truncateEnd(text: string, maxWidth: number): string;
|
|
5
|
+
/**
|
|
6
|
+
* Truncate text with ellipsis at the beginning
|
|
7
|
+
*/
|
|
8
|
+
export declare function truncateStart(text: string, maxWidth: number): string;
|
|
9
|
+
/**
|
|
10
|
+
* Truncate text with ellipsis in the middle
|
|
11
|
+
*/
|
|
12
|
+
export declare function truncateMiddle(text: string, maxWidth: number): string;
|
|
13
|
+
/**
|
|
14
|
+
* Wrap text to fit within a width, breaking on spaces
|
|
15
|
+
*/
|
|
16
|
+
export declare function wrapText(text: string, width: number): string[];
|
|
17
|
+
/**
|
|
18
|
+
* Get the visual width of text (accounting for ANSI codes)
|
|
19
|
+
*/
|
|
20
|
+
export declare function getTextWidth(text: string): number;
|
|
21
|
+
//# sourceMappingURL=text.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../src/utils/text.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQlE;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQpE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAUrE;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CA+B9D;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIjD"}
|