@nghyane/arcane-tui 0.1.7 → 0.1.8
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/package.json +1 -1
- package/src/components/editor.ts +8 -0
- package/src/tui.ts +6 -2
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@nghyane/arcane-tui",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.8",
|
|
5
5
|
"description": "Terminal User Interface library with differential rendering for efficient text-based applications",
|
|
6
6
|
"homepage": "https://github.com/nghyane/arcane",
|
|
7
7
|
"author": "Can Bölük",
|
package/src/components/editor.ts
CHANGED
|
@@ -93,6 +93,10 @@ function wordWrapLine(line: string, maxWidth: number): TextChunk[] {
|
|
|
93
93
|
|
|
94
94
|
// Skip leading whitespace at line start
|
|
95
95
|
if (atLineStart && token.isWhitespace) {
|
|
96
|
+
// Extend previous chunk's range to cover the skipped whitespace (no cursor gap)
|
|
97
|
+
if (chunks.length > 0) {
|
|
98
|
+
chunks[chunks.length - 1]!.endIndex = token.endIndex;
|
|
99
|
+
}
|
|
96
100
|
chunkStartIndex = token.endIndex;
|
|
97
101
|
continue;
|
|
98
102
|
}
|
|
@@ -162,6 +166,10 @@ function wordWrapLine(line: string, maxWidth: number): TextChunk[] {
|
|
|
162
166
|
// Start new line - skip leading whitespace
|
|
163
167
|
atLineStart = true;
|
|
164
168
|
if (token.isWhitespace) {
|
|
169
|
+
// Extend the just-pushed chunk's range to cover this whitespace (no cursor gap)
|
|
170
|
+
if (chunks.length > 0) {
|
|
171
|
+
chunks[chunks.length - 1]!.endIndex = token.endIndex;
|
|
172
|
+
}
|
|
165
173
|
currentChunk = "";
|
|
166
174
|
currentWidth = 0;
|
|
167
175
|
chunkStartIndex = token.endIndex;
|
package/src/tui.ts
CHANGED
|
@@ -646,6 +646,7 @@ export class TUI extends Container {
|
|
|
646
646
|
this.#selectionActive = false;
|
|
647
647
|
this.#selectionAnchor = null;
|
|
648
648
|
this.#selectionEnd = null;
|
|
649
|
+
this.requestRender();
|
|
649
650
|
}
|
|
650
651
|
|
|
651
652
|
#getSelectionRange(): { startRow: number; startCol: number; endRow: number; endCol: number } | null {
|
|
@@ -713,7 +714,9 @@ export class TUI extends Container {
|
|
|
713
714
|
|
|
714
715
|
// Output only the changed cells
|
|
715
716
|
let out = "\x1b[?2026h"; // Synchronized output
|
|
717
|
+
out += "\x1b7"; // Save cursor position
|
|
716
718
|
out += renderDiff(changes, width);
|
|
719
|
+
out += "\x1b8"; // Restore cursor position
|
|
717
720
|
out += "\x1b[?2026l";
|
|
718
721
|
this.terminal.write(out);
|
|
719
722
|
}
|
|
@@ -733,11 +736,12 @@ export class TUI extends Container {
|
|
|
733
736
|
const line = cache[row];
|
|
734
737
|
if (TERMINAL.isImageLine(line)) continue;
|
|
735
738
|
const lineStart = row === startRow ? startCol : 0;
|
|
736
|
-
const
|
|
739
|
+
const isFullLine = row !== endRow;
|
|
740
|
+
const lineEnd = isFullLine ? visibleWidth(line) : endCol;
|
|
737
741
|
const sliced = sliceByColumn(line, lineStart, lineEnd - lineStart, true);
|
|
738
742
|
// Strip ANSI from the sliced segment
|
|
739
743
|
const plain = sliced.replace(/\x1b\[[^a-zA-Z]*[a-zA-Z]|\x1b\][^\x07]*\x07|\x1b_[^\x07]*\x07/g, "");
|
|
740
|
-
textLines.push(plain);
|
|
744
|
+
textLines.push(isFullLine ? plain.trimEnd() : plain);
|
|
741
745
|
}
|
|
742
746
|
|
|
743
747
|
const text = textLines.join("\n");
|