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.
Files changed (283) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +313 -64
  3. package/lib/api/color.d.ts +6 -0
  4. package/lib/api/color.d.ts.map +1 -0
  5. package/lib/api/color.js +9 -0
  6. package/lib/api/color.js.map +1 -0
  7. package/lib/api/color.test.d.ts +2 -0
  8. package/lib/api/color.test.d.ts.map +1 -0
  9. package/lib/api/color.test.js +23 -0
  10. package/lib/api/color.test.js.map +1 -0
  11. package/lib/api/flex.d.ts +55 -0
  12. package/lib/api/flex.d.ts.map +1 -0
  13. package/lib/api/flex.js +86 -0
  14. package/lib/api/flex.js.map +1 -0
  15. package/lib/api/flex.test.d.ts +2 -0
  16. package/lib/api/flex.test.d.ts.map +1 -0
  17. package/lib/api/flex.test.js +82 -0
  18. package/lib/api/flex.test.js.map +1 -0
  19. package/lib/api/grid.d.ts +22 -0
  20. package/lib/api/grid.d.ts.map +1 -0
  21. package/lib/api/grid.js +65 -0
  22. package/lib/api/grid.js.map +1 -0
  23. package/lib/api/grid.test.d.ts +2 -0
  24. package/lib/api/grid.test.d.ts.map +1 -0
  25. package/lib/api/grid.test.js +48 -0
  26. package/lib/api/grid.test.js.map +1 -0
  27. package/lib/components/base.d.ts +53 -0
  28. package/lib/components/base.d.ts.map +1 -0
  29. package/lib/components/base.js +47 -0
  30. package/lib/components/base.js.map +1 -0
  31. package/lib/components/col.d.ts +35 -0
  32. package/lib/components/col.d.ts.map +1 -0
  33. package/lib/components/col.js +168 -0
  34. package/lib/components/col.js.map +1 -0
  35. package/lib/components/col.test.d.ts +2 -0
  36. package/lib/components/col.test.d.ts.map +1 -0
  37. package/lib/components/col.test.js +96 -0
  38. package/lib/components/col.test.js.map +1 -0
  39. package/lib/components/index.d.ts +3 -0
  40. package/lib/components/index.d.ts.map +1 -0
  41. package/lib/components/index.js +5 -0
  42. package/lib/components/index.js.map +1 -0
  43. package/lib/components/progress-bar-grid.d.ts +20 -0
  44. package/lib/components/progress-bar-grid.d.ts.map +1 -0
  45. package/lib/components/progress-bar-grid.js +44 -0
  46. package/lib/components/progress-bar-grid.js.map +1 -0
  47. package/lib/components/progress-bar-grid.test.d.ts +2 -0
  48. package/lib/components/progress-bar-grid.test.d.ts.map +1 -0
  49. package/lib/components/progress-bar-grid.test.js +101 -0
  50. package/lib/components/progress-bar-grid.test.js.map +1 -0
  51. package/lib/components/progress-bar.d.ts +26 -3
  52. package/lib/components/progress-bar.d.ts.map +1 -1
  53. package/lib/components/progress-bar.js +62 -6
  54. package/lib/components/progress-bar.js.map +1 -1
  55. package/lib/components/progress-bar.test.d.ts +2 -0
  56. package/lib/components/progress-bar.test.d.ts.map +1 -0
  57. package/lib/components/progress-bar.test.js +153 -0
  58. package/lib/components/progress-bar.test.js.map +1 -0
  59. package/lib/components/prompt.d.ts +14 -0
  60. package/lib/components/prompt.d.ts.map +1 -0
  61. package/lib/components/prompt.js +77 -0
  62. package/lib/components/prompt.js.map +1 -0
  63. package/lib/components/renderable.d.ts +42 -0
  64. package/lib/components/renderable.d.ts.map +1 -0
  65. package/lib/components/renderable.js +225 -0
  66. package/lib/components/renderable.js.map +1 -0
  67. package/lib/components/spinner.d.ts +2 -2
  68. package/lib/components/spinner.d.ts.map +1 -1
  69. package/lib/components/spinner.js +3 -1
  70. package/lib/components/spinner.js.map +1 -1
  71. package/lib/components/spinner.test.d.ts +2 -0
  72. package/lib/components/spinner.test.d.ts.map +1 -0
  73. package/lib/components/spinner.test.js +168 -0
  74. package/lib/components/spinner.test.js.map +1 -0
  75. package/lib/components/style.d.ts +16 -0
  76. package/lib/components/style.d.ts.map +1 -0
  77. package/lib/components/style.js +72 -0
  78. package/lib/components/style.js.map +1 -0
  79. package/lib/components/style.test.d.ts +2 -0
  80. package/lib/components/style.test.d.ts.map +1 -0
  81. package/lib/components/style.test.js +135 -0
  82. package/lib/components/style.test.js.map +1 -0
  83. package/lib/components/text.d.ts +24 -0
  84. package/lib/components/text.d.ts.map +1 -0
  85. package/lib/components/text.js +65 -0
  86. package/lib/components/text.js.map +1 -0
  87. package/lib/drawing/boxes.d.ts +33 -0
  88. package/lib/drawing/boxes.d.ts.map +1 -0
  89. package/lib/drawing/boxes.js +76 -0
  90. package/lib/drawing/boxes.js.map +1 -0
  91. package/lib/index.d.ts +18 -11
  92. package/lib/index.d.ts.map +1 -1
  93. package/lib/index.js +21 -10
  94. package/lib/index.js.map +1 -1
  95. package/lib/index.test.d.ts +2 -0
  96. package/lib/index.test.d.ts.map +1 -0
  97. package/lib/index.test.js +80 -0
  98. package/lib/index.test.js.map +1 -0
  99. package/lib/layout/flex.d.ts +39 -0
  100. package/lib/layout/flex.d.ts.map +1 -0
  101. package/lib/layout/flex.js +300 -0
  102. package/lib/layout/flex.js.map +1 -0
  103. package/lib/layout/flex.test.d.ts +2 -0
  104. package/lib/layout/flex.test.d.ts.map +1 -0
  105. package/lib/layout/flex.test.js +206 -0
  106. package/lib/layout/flex.test.js.map +1 -0
  107. package/lib/layout/grid.d.ts +53 -0
  108. package/lib/layout/grid.d.ts.map +1 -0
  109. package/lib/layout/grid.js +421 -0
  110. package/lib/layout/grid.js.map +1 -0
  111. package/lib/layout/grid.test.d.ts +2 -0
  112. package/lib/layout/grid.test.d.ts.map +1 -0
  113. package/lib/layout/grid.test.js +139 -0
  114. package/lib/layout/grid.test.js.map +1 -0
  115. package/lib/native/ansi.d.ts +104 -0
  116. package/lib/native/ansi.d.ts.map +1 -0
  117. package/lib/native/ansi.js +120 -0
  118. package/lib/native/ansi.js.map +1 -0
  119. package/lib/native/ansi.test.d.ts +2 -0
  120. package/lib/native/ansi.test.d.ts.map +1 -0
  121. package/lib/native/ansi.test.js +57 -0
  122. package/lib/native/ansi.test.js.map +1 -0
  123. package/lib/native/buffer.d.ts +32 -0
  124. package/lib/native/buffer.d.ts.map +1 -0
  125. package/lib/native/buffer.js +49 -0
  126. package/lib/native/buffer.js.map +1 -0
  127. package/lib/native/buffer.test.d.ts +2 -0
  128. package/lib/native/buffer.test.d.ts.map +1 -0
  129. package/lib/native/buffer.test.js +64 -0
  130. package/lib/native/buffer.test.js.map +1 -0
  131. package/lib/native/diff.d.ts +20 -0
  132. package/lib/native/diff.d.ts.map +1 -0
  133. package/lib/native/diff.js +33 -0
  134. package/lib/native/diff.js.map +1 -0
  135. package/lib/native/diff.test.d.ts +2 -0
  136. package/lib/native/diff.test.d.ts.map +1 -0
  137. package/lib/native/diff.test.js +106 -0
  138. package/lib/native/diff.test.js.map +1 -0
  139. package/lib/native/region-old.d.ts +117 -0
  140. package/lib/native/region-old.d.ts.map +1 -0
  141. package/lib/native/region-old.js +539 -0
  142. package/lib/native/region-old.js.map +1 -0
  143. package/lib/native/region-renderer.d.ts +167 -0
  144. package/lib/native/region-renderer.d.ts.map +1 -0
  145. package/lib/native/region-renderer.js +1238 -0
  146. package/lib/native/region-renderer.js.map +1 -0
  147. package/lib/native/region-simple.d.ts +44 -0
  148. package/lib/native/region-simple.d.ts.map +1 -0
  149. package/lib/native/region-simple.js +290 -0
  150. package/lib/native/region-simple.js.map +1 -0
  151. package/lib/native/region.d.ts +53 -0
  152. package/lib/native/region.d.ts.map +1 -0
  153. package/lib/native/region.js +426 -0
  154. package/lib/native/region.js.map +1 -0
  155. package/lib/native/region.test.d.ts +2 -0
  156. package/lib/native/region.test.d.ts.map +1 -0
  157. package/lib/native/region.test.js +248 -0
  158. package/lib/native/region.test.js.map +1 -0
  159. package/lib/native/throttle.d.ts +29 -0
  160. package/lib/native/throttle.d.ts.map +1 -0
  161. package/lib/native/throttle.js +57 -0
  162. package/lib/native/throttle.js.map +1 -0
  163. package/lib/native/throttle.test.d.ts +2 -0
  164. package/lib/native/throttle.test.d.ts.map +1 -0
  165. package/lib/native/throttle.test.js +86 -0
  166. package/lib/native/throttle.test.js.map +1 -0
  167. package/lib/native.d.ts +5 -11
  168. package/lib/native.d.ts.map +1 -1
  169. package/lib/native.js +8 -64
  170. package/lib/native.js.map +1 -1
  171. package/lib/region.d.ts +48 -5
  172. package/lib/region.d.ts.map +1 -1
  173. package/lib/region.js +474 -36
  174. package/lib/region.js.map +1 -1
  175. package/lib/region.test.d.ts +2 -0
  176. package/lib/region.test.d.ts.map +1 -0
  177. package/lib/region.test.js +227 -0
  178. package/lib/region.test.js.map +1 -0
  179. package/lib/region.visual.test.d.ts +2 -0
  180. package/lib/region.visual.test.d.ts.map +1 -0
  181. package/lib/region.visual.test.js +55 -0
  182. package/lib/region.visual.test.js.map +1 -0
  183. package/lib/test-helpers/capturable-terminal.d.ts +61 -0
  184. package/lib/test-helpers/capturable-terminal.d.ts.map +1 -0
  185. package/lib/test-helpers/capturable-terminal.js +113 -0
  186. package/lib/test-helpers/capturable-terminal.js.map +1 -0
  187. package/lib/test-helpers/capturable-terminal.test.d.ts +2 -0
  188. package/lib/test-helpers/capturable-terminal.test.d.ts.map +1 -0
  189. package/lib/test-helpers/capturable-terminal.test.js +45 -0
  190. package/lib/test-helpers/capturable-terminal.test.js.map +1 -0
  191. package/lib/test-helpers/mock-region.d.ts +21 -0
  192. package/lib/test-helpers/mock-region.d.ts.map +1 -0
  193. package/lib/test-helpers/mock-region.js +37 -0
  194. package/lib/test-helpers/mock-region.js.map +1 -0
  195. package/lib/test-helpers/virtual-terminal-diff-reflow.test.d.ts +2 -0
  196. package/lib/test-helpers/virtual-terminal-diff-reflow.test.d.ts.map +1 -0
  197. package/lib/test-helpers/virtual-terminal-diff-reflow.test.js +256 -0
  198. package/lib/test-helpers/virtual-terminal-diff-reflow.test.js.map +1 -0
  199. package/lib/test-helpers/virtual-terminal-flex-resize.test.d.ts +2 -0
  200. package/lib/test-helpers/virtual-terminal-flex-resize.test.d.ts.map +1 -0
  201. package/lib/test-helpers/virtual-terminal-flex-resize.test.js +438 -0
  202. package/lib/test-helpers/virtual-terminal-flex-resize.test.js.map +1 -0
  203. package/lib/test-helpers/virtual-terminal.d.ts +176 -0
  204. package/lib/test-helpers/virtual-terminal.d.ts.map +1 -0
  205. package/lib/test-helpers/virtual-terminal.js +492 -0
  206. package/lib/test-helpers/virtual-terminal.js.map +1 -0
  207. package/lib/test-helpers/virtual-terminal.test.d.ts +2 -0
  208. package/lib/test-helpers/virtual-terminal.test.d.ts.map +1 -0
  209. package/lib/test-helpers/virtual-terminal.test.js +219 -0
  210. package/lib/test-helpers/virtual-terminal.test.js.map +1 -0
  211. package/lib/ts/components/spinner.test.d.ts +2 -0
  212. package/lib/ts/components/spinner.test.d.ts.map +1 -0
  213. package/lib/ts/components/spinner.test.js +168 -0
  214. package/lib/ts/components/spinner.test.js.map +1 -0
  215. package/lib/ts/utils/colors.test.d.ts +2 -0
  216. package/lib/ts/utils/colors.test.d.ts.map +1 -0
  217. package/lib/ts/utils/colors.test.js +87 -0
  218. package/lib/ts/utils/colors.test.js.map +1 -0
  219. package/lib/types.d.ts +8 -2
  220. package/lib/types.d.ts.map +1 -1
  221. package/lib/types.js.map +1 -1
  222. package/lib/utils/colors-simple.d.ts +51 -0
  223. package/lib/utils/colors-simple.d.ts.map +1 -0
  224. package/lib/utils/colors-simple.js +59 -0
  225. package/lib/utils/colors-simple.js.map +1 -0
  226. package/lib/utils/colors.d.ts +1 -1
  227. package/lib/utils/colors.d.ts.map +1 -1
  228. package/lib/utils/colors.js.map +1 -1
  229. package/lib/utils/colors.test.d.ts +2 -0
  230. package/lib/utils/colors.test.d.ts.map +1 -0
  231. package/lib/utils/colors.test.js +87 -0
  232. package/lib/utils/colors.test.js.map +1 -0
  233. package/lib/utils/cursor-position.d.ts +22 -0
  234. package/lib/utils/cursor-position.d.ts.map +1 -0
  235. package/lib/utils/cursor-position.js +139 -0
  236. package/lib/utils/cursor-position.js.map +1 -0
  237. package/lib/utils/debug-log.d.ts +2 -0
  238. package/lib/utils/debug-log.d.ts.map +1 -0
  239. package/lib/utils/debug-log.js +36 -0
  240. package/lib/utils/debug-log.js.map +1 -0
  241. package/lib/utils/terminal.d.ts +27 -0
  242. package/lib/utils/terminal.d.ts.map +1 -0
  243. package/lib/utils/terminal.js +116 -0
  244. package/lib/utils/terminal.js.map +1 -0
  245. package/lib/utils/text.d.ts +21 -0
  246. package/lib/utils/text.d.ts.map +1 -0
  247. package/lib/utils/text.js +82 -0
  248. package/lib/utils/text.js.map +1 -0
  249. package/lib/utils/wait-for-spacebar.d.ts +10 -0
  250. package/lib/utils/wait-for-spacebar.d.ts.map +1 -0
  251. package/lib/utils/wait-for-spacebar.js +71 -0
  252. package/lib/utils/wait-for-spacebar.js.map +1 -0
  253. package/package.json +31 -28
  254. package/.cursor/plan.md +0 -952
  255. package/TESTING.md +0 -102
  256. package/build.zig +0 -100
  257. package/examples/basic-progress.ts +0 -21
  258. package/examples/multi-lane.ts +0 -29
  259. package/examples/spinner.ts +0 -20
  260. package/examples/test-basic.ts +0 -23
  261. package/src/ts/components/progress-bar.ts +0 -53
  262. package/src/ts/components/spinner.ts +0 -56
  263. package/src/ts/index.ts +0 -37
  264. package/src/ts/native.ts +0 -86
  265. package/src/ts/region.ts +0 -89
  266. package/src/ts/types/ffi-napi.d.ts +0 -11
  267. package/src/ts/types/ref-napi.d.ts +0 -5
  268. package/src/ts/types.ts +0 -53
  269. package/src/ts/utils/colors.ts +0 -72
  270. package/src/zig/ansi.zig +0 -21
  271. package/src/zig/buffer.zig +0 -37
  272. package/src/zig/diff.zig +0 -43
  273. package/src/zig/region.zig +0 -292
  274. package/src/zig/renderer.zig +0 -92
  275. package/src/zig/test_ansi.zig +0 -66
  276. package/src/zig/test_buffer.zig +0 -82
  277. package/src/zig/test_diff.zig +0 -220
  278. package/src/zig/test_integration.zig +0 -76
  279. package/src/zig/test_region.zig +0 -191
  280. package/src/zig/test_runner.zig +0 -27
  281. package/src/zig/test_throttle.zig +0 -59
  282. package/src/zig/throttle.zig +0 -38
  283. 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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"}
@@ -1,3 +1,3 @@
1
- import { TextStyle } from '../types.js';
1
+ import { TextStyle } from '../types';
2
2
  export declare function applyStyle(text: string, style?: TextStyle): string;
3
3
  //# sourceMappingURL=colors.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"colors.d.ts","sourceRoot":"","sources":["../../src/ts/utils/colors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,SAAS,EAAE,MAAM,aAAa,CAAC;AAwC/C,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,SAAS,GAAG,MAAM,CA8BlE"}
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"}
@@ -1 +1 @@
1
- {"version":3,"file":"colors.js","sourceRoot":"","sources":["../../src/ts/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"}
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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=colors.test.d.ts.map
@@ -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":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function logToFile(message: string): void;
2
+ //# sourceMappingURL=debug-log.d.ts.map
@@ -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"}