@opentuah/core 0.1.88 → 0.1.90
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/3d.js +1 -1
- package/NativeSpanFeed.d.ts +41 -0
- package/README.md +4 -0
- package/{index-1n3xjscm.js → index-bsnn7gyg.js} +195 -9
- package/{index-1n3xjscm.js.map → index-bsnn7gyg.js.map} +5 -5
- package/index.d.ts +1 -0
- package/index.js +299 -2
- package/index.js.map +7 -6
- package/package.json +9 -9
- package/renderables/Input.d.ts +7 -0
- package/renderables/TextNode.d.ts +1 -1
- package/testing.js +1 -1
- package/zig-structs.d.ts +68 -0
- package/zig.d.ts +18 -0
package/index.d.ts
CHANGED
package/index.js
CHANGED
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
RendererControlState,
|
|
31
31
|
RootRenderable,
|
|
32
32
|
Selection,
|
|
33
|
+
SpanInfoStruct,
|
|
33
34
|
StdinBuffer,
|
|
34
35
|
StyledText,
|
|
35
36
|
TerminalConsole,
|
|
@@ -150,7 +151,7 @@ import {
|
|
|
150
151
|
white,
|
|
151
152
|
wrapWithDelegates,
|
|
152
153
|
yellow
|
|
153
|
-
} from "./index-
|
|
154
|
+
} from "./index-bsnn7gyg.js";
|
|
154
155
|
// src/text-buffer-view.ts
|
|
155
156
|
class TextBufferView {
|
|
156
157
|
lib;
|
|
@@ -2062,6 +2063,266 @@ function createTimeline(options = {}) {
|
|
|
2062
2063
|
engine.register(timeline);
|
|
2063
2064
|
return timeline;
|
|
2064
2065
|
}
|
|
2066
|
+
// src/NativeSpanFeed.ts
|
|
2067
|
+
import { toArrayBuffer } from "bun:ffi";
|
|
2068
|
+
function toPointer(value) {
|
|
2069
|
+
if (typeof value === "bigint") {
|
|
2070
|
+
if (value > BigInt(Number.MAX_SAFE_INTEGER)) {
|
|
2071
|
+
throw new Error("Pointer exceeds safe integer range");
|
|
2072
|
+
}
|
|
2073
|
+
return Number(value);
|
|
2074
|
+
}
|
|
2075
|
+
return value;
|
|
2076
|
+
}
|
|
2077
|
+
function toNumber(value) {
|
|
2078
|
+
return typeof value === "bigint" ? Number(value) : value;
|
|
2079
|
+
}
|
|
2080
|
+
|
|
2081
|
+
class NativeSpanFeed {
|
|
2082
|
+
static create(options) {
|
|
2083
|
+
const lib = resolveRenderLib();
|
|
2084
|
+
const streamPtr = lib.createNativeSpanFeed(options);
|
|
2085
|
+
const stream = new NativeSpanFeed(streamPtr);
|
|
2086
|
+
lib.registerNativeSpanFeedStream(streamPtr, stream.eventHandler);
|
|
2087
|
+
const status = lib.attachNativeSpanFeed(streamPtr);
|
|
2088
|
+
if (status !== 0) {
|
|
2089
|
+
lib.unregisterNativeSpanFeedStream(streamPtr);
|
|
2090
|
+
lib.destroyNativeSpanFeed(streamPtr);
|
|
2091
|
+
throw new Error(`Failed to attach stream: ${status}`);
|
|
2092
|
+
}
|
|
2093
|
+
return stream;
|
|
2094
|
+
}
|
|
2095
|
+
static attach(streamPtr, _options) {
|
|
2096
|
+
const lib = resolveRenderLib();
|
|
2097
|
+
const ptr = toPointer(streamPtr);
|
|
2098
|
+
const stream = new NativeSpanFeed(ptr);
|
|
2099
|
+
lib.registerNativeSpanFeedStream(ptr, stream.eventHandler);
|
|
2100
|
+
const status = lib.attachNativeSpanFeed(ptr);
|
|
2101
|
+
if (status !== 0) {
|
|
2102
|
+
lib.unregisterNativeSpanFeedStream(ptr);
|
|
2103
|
+
throw new Error(`Failed to attach stream: ${status}`);
|
|
2104
|
+
}
|
|
2105
|
+
return stream;
|
|
2106
|
+
}
|
|
2107
|
+
streamPtr;
|
|
2108
|
+
lib = resolveRenderLib();
|
|
2109
|
+
eventHandler;
|
|
2110
|
+
chunkMap = new Map;
|
|
2111
|
+
chunkSizes = new Map;
|
|
2112
|
+
dataHandlers = new Set;
|
|
2113
|
+
errorHandlers = new Set;
|
|
2114
|
+
drainBuffer = null;
|
|
2115
|
+
stateBuffer = null;
|
|
2116
|
+
closed = false;
|
|
2117
|
+
destroyed = false;
|
|
2118
|
+
draining = false;
|
|
2119
|
+
pendingDataAvailable = false;
|
|
2120
|
+
pendingClose = false;
|
|
2121
|
+
closing = false;
|
|
2122
|
+
pendingAsyncHandlers = 0;
|
|
2123
|
+
inCallback = false;
|
|
2124
|
+
closeQueued = false;
|
|
2125
|
+
constructor(streamPtr) {
|
|
2126
|
+
this.streamPtr = streamPtr;
|
|
2127
|
+
this.eventHandler = (eventId, arg0, arg1) => {
|
|
2128
|
+
this.handleEvent(eventId, arg0, arg1);
|
|
2129
|
+
};
|
|
2130
|
+
this.ensureDrainBuffer();
|
|
2131
|
+
}
|
|
2132
|
+
ensureDrainBuffer() {
|
|
2133
|
+
if (this.drainBuffer)
|
|
2134
|
+
return;
|
|
2135
|
+
const capacity = 256;
|
|
2136
|
+
this.drainBuffer = new Uint8Array(capacity * SpanInfoStruct.size);
|
|
2137
|
+
}
|
|
2138
|
+
onData(handler) {
|
|
2139
|
+
this.dataHandlers.add(handler);
|
|
2140
|
+
if (this.pendingDataAvailable) {
|
|
2141
|
+
this.pendingDataAvailable = false;
|
|
2142
|
+
this.drainAll();
|
|
2143
|
+
}
|
|
2144
|
+
return () => this.dataHandlers.delete(handler);
|
|
2145
|
+
}
|
|
2146
|
+
onError(handler) {
|
|
2147
|
+
this.errorHandlers.add(handler);
|
|
2148
|
+
return () => this.errorHandlers.delete(handler);
|
|
2149
|
+
}
|
|
2150
|
+
close() {
|
|
2151
|
+
if (this.destroyed)
|
|
2152
|
+
return;
|
|
2153
|
+
if (this.inCallback || this.draining || this.pendingAsyncHandlers > 0) {
|
|
2154
|
+
this.pendingClose = true;
|
|
2155
|
+
if (!this.closeQueued) {
|
|
2156
|
+
this.closeQueued = true;
|
|
2157
|
+
queueMicrotask(() => {
|
|
2158
|
+
this.closeQueued = false;
|
|
2159
|
+
this.processPendingClose();
|
|
2160
|
+
});
|
|
2161
|
+
}
|
|
2162
|
+
return;
|
|
2163
|
+
}
|
|
2164
|
+
this.performClose();
|
|
2165
|
+
}
|
|
2166
|
+
processPendingClose() {
|
|
2167
|
+
if (!this.pendingClose || this.destroyed)
|
|
2168
|
+
return;
|
|
2169
|
+
if (this.inCallback || this.draining || this.pendingAsyncHandlers > 0)
|
|
2170
|
+
return;
|
|
2171
|
+
this.pendingClose = false;
|
|
2172
|
+
this.performClose();
|
|
2173
|
+
}
|
|
2174
|
+
performClose() {
|
|
2175
|
+
if (this.closing)
|
|
2176
|
+
return;
|
|
2177
|
+
this.closing = true;
|
|
2178
|
+
if (!this.closed) {
|
|
2179
|
+
const status = this.lib.streamClose(this.streamPtr);
|
|
2180
|
+
if (status !== 0) {
|
|
2181
|
+
this.closing = false;
|
|
2182
|
+
return;
|
|
2183
|
+
}
|
|
2184
|
+
this.closed = true;
|
|
2185
|
+
}
|
|
2186
|
+
this.finalizeDestroy();
|
|
2187
|
+
}
|
|
2188
|
+
finalizeDestroy() {
|
|
2189
|
+
if (this.destroyed)
|
|
2190
|
+
return;
|
|
2191
|
+
this.lib.unregisterNativeSpanFeedStream(this.streamPtr);
|
|
2192
|
+
this.lib.destroyNativeSpanFeed(this.streamPtr);
|
|
2193
|
+
this.destroyed = true;
|
|
2194
|
+
this.chunkMap.clear();
|
|
2195
|
+
this.chunkSizes.clear();
|
|
2196
|
+
this.stateBuffer = null;
|
|
2197
|
+
this.drainBuffer = null;
|
|
2198
|
+
this.dataHandlers.clear();
|
|
2199
|
+
this.errorHandlers.clear();
|
|
2200
|
+
this.pendingDataAvailable = false;
|
|
2201
|
+
}
|
|
2202
|
+
handleEvent(eventId, arg0, arg1) {
|
|
2203
|
+
this.inCallback = true;
|
|
2204
|
+
try {
|
|
2205
|
+
switch (eventId) {
|
|
2206
|
+
case 8 /* StateBuffer */: {
|
|
2207
|
+
const len = toNumber(arg1);
|
|
2208
|
+
if (len > 0 && arg0) {
|
|
2209
|
+
const buffer = toArrayBuffer(arg0, 0, len);
|
|
2210
|
+
this.stateBuffer = new Uint8Array(buffer);
|
|
2211
|
+
}
|
|
2212
|
+
break;
|
|
2213
|
+
}
|
|
2214
|
+
case 7 /* DataAvailable */: {
|
|
2215
|
+
if (this.closing)
|
|
2216
|
+
break;
|
|
2217
|
+
if (this.dataHandlers.size === 0) {
|
|
2218
|
+
this.pendingDataAvailable = true;
|
|
2219
|
+
break;
|
|
2220
|
+
}
|
|
2221
|
+
this.drainAll();
|
|
2222
|
+
break;
|
|
2223
|
+
}
|
|
2224
|
+
case 2 /* ChunkAdded */: {
|
|
2225
|
+
const chunkLen = toNumber(arg1);
|
|
2226
|
+
if (chunkLen > 0 && arg0) {
|
|
2227
|
+
if (!this.chunkMap.has(arg0)) {
|
|
2228
|
+
const buffer = toArrayBuffer(arg0, 0, chunkLen);
|
|
2229
|
+
this.chunkMap.set(arg0, buffer);
|
|
2230
|
+
}
|
|
2231
|
+
this.chunkSizes.set(arg0, chunkLen);
|
|
2232
|
+
}
|
|
2233
|
+
break;
|
|
2234
|
+
}
|
|
2235
|
+
case 6 /* Error */: {
|
|
2236
|
+
const code = arg0;
|
|
2237
|
+
for (const handler of this.errorHandlers)
|
|
2238
|
+
handler(code);
|
|
2239
|
+
break;
|
|
2240
|
+
}
|
|
2241
|
+
case 5 /* Closed */: {
|
|
2242
|
+
this.closed = true;
|
|
2243
|
+
break;
|
|
2244
|
+
}
|
|
2245
|
+
default:
|
|
2246
|
+
break;
|
|
2247
|
+
}
|
|
2248
|
+
} finally {
|
|
2249
|
+
this.inCallback = false;
|
|
2250
|
+
}
|
|
2251
|
+
}
|
|
2252
|
+
decrementRefcount(chunkIndex) {
|
|
2253
|
+
if (this.stateBuffer && chunkIndex < this.stateBuffer.length) {
|
|
2254
|
+
const prev = this.stateBuffer[chunkIndex];
|
|
2255
|
+
this.stateBuffer[chunkIndex] = prev > 0 ? prev - 1 : 0;
|
|
2256
|
+
}
|
|
2257
|
+
}
|
|
2258
|
+
drainOnce() {
|
|
2259
|
+
if (!this.drainBuffer || this.draining || this.pendingClose)
|
|
2260
|
+
return 0;
|
|
2261
|
+
const capacity = Math.floor(this.drainBuffer.byteLength / SpanInfoStruct.size);
|
|
2262
|
+
if (capacity === 0)
|
|
2263
|
+
return 0;
|
|
2264
|
+
const count = this.lib.streamDrainSpans(this.streamPtr, this.drainBuffer, capacity);
|
|
2265
|
+
if (count === 0)
|
|
2266
|
+
return 0;
|
|
2267
|
+
this.draining = true;
|
|
2268
|
+
const spans = SpanInfoStruct.unpackList(this.drainBuffer.buffer, count);
|
|
2269
|
+
let firstError = null;
|
|
2270
|
+
try {
|
|
2271
|
+
for (const span of spans) {
|
|
2272
|
+
if (span.len === 0)
|
|
2273
|
+
continue;
|
|
2274
|
+
let buffer = this.chunkMap.get(span.chunkPtr);
|
|
2275
|
+
if (!buffer) {
|
|
2276
|
+
const size = this.chunkSizes.get(span.chunkPtr);
|
|
2277
|
+
if (!size)
|
|
2278
|
+
continue;
|
|
2279
|
+
buffer = toArrayBuffer(span.chunkPtr, 0, size);
|
|
2280
|
+
this.chunkMap.set(span.chunkPtr, buffer);
|
|
2281
|
+
}
|
|
2282
|
+
if (span.offset + span.len > buffer.byteLength)
|
|
2283
|
+
continue;
|
|
2284
|
+
const slice = new Uint8Array(buffer, span.offset, span.len);
|
|
2285
|
+
let asyncResults = null;
|
|
2286
|
+
for (const handler of this.dataHandlers) {
|
|
2287
|
+
try {
|
|
2288
|
+
const result = handler(slice);
|
|
2289
|
+
if (result && typeof result.then === "function") {
|
|
2290
|
+
asyncResults ??= [];
|
|
2291
|
+
asyncResults.push(result);
|
|
2292
|
+
}
|
|
2293
|
+
} catch (e) {
|
|
2294
|
+
firstError ??= e;
|
|
2295
|
+
}
|
|
2296
|
+
}
|
|
2297
|
+
const shouldStopAfterThisSpan = this.pendingClose;
|
|
2298
|
+
if (asyncResults) {
|
|
2299
|
+
const chunkIndex = span.chunkIndex;
|
|
2300
|
+
this.pendingAsyncHandlers += 1;
|
|
2301
|
+
Promise.allSettled(asyncResults).then(() => {
|
|
2302
|
+
this.decrementRefcount(chunkIndex);
|
|
2303
|
+
this.pendingAsyncHandlers -= 1;
|
|
2304
|
+
this.processPendingClose();
|
|
2305
|
+
});
|
|
2306
|
+
} else {
|
|
2307
|
+
this.decrementRefcount(span.chunkIndex);
|
|
2308
|
+
}
|
|
2309
|
+
if (shouldStopAfterThisSpan)
|
|
2310
|
+
break;
|
|
2311
|
+
}
|
|
2312
|
+
} finally {
|
|
2313
|
+
this.draining = false;
|
|
2314
|
+
}
|
|
2315
|
+
if (firstError)
|
|
2316
|
+
throw firstError;
|
|
2317
|
+
return count;
|
|
2318
|
+
}
|
|
2319
|
+
drainAll() {
|
|
2320
|
+
let count = this.drainOnce();
|
|
2321
|
+
while (count > 0) {
|
|
2322
|
+
count = this.drainOnce();
|
|
2323
|
+
}
|
|
2324
|
+
}
|
|
2325
|
+
}
|
|
2065
2326
|
// src/renderables/FrameBuffer.ts
|
|
2066
2327
|
class FrameBufferRenderable extends Renderable {
|
|
2067
2328
|
frameBuffer;
|
|
@@ -6363,6 +6624,41 @@ class InputRenderable extends TextareaRenderable {
|
|
|
6363
6624
|
this.emit("input" /* INPUT */, this.plainText);
|
|
6364
6625
|
return result;
|
|
6365
6626
|
}
|
|
6627
|
+
deleteLine() {
|
|
6628
|
+
const result = super.deleteLine();
|
|
6629
|
+
this.emit("input" /* INPUT */, this.plainText);
|
|
6630
|
+
return result;
|
|
6631
|
+
}
|
|
6632
|
+
deleteWordBackward() {
|
|
6633
|
+
const result = super.deleteWordBackward();
|
|
6634
|
+
this.emit("input" /* INPUT */, this.plainText);
|
|
6635
|
+
return result;
|
|
6636
|
+
}
|
|
6637
|
+
deleteWordForward() {
|
|
6638
|
+
const result = super.deleteWordForward();
|
|
6639
|
+
this.emit("input" /* INPUT */, this.plainText);
|
|
6640
|
+
return result;
|
|
6641
|
+
}
|
|
6642
|
+
deleteToLineStart() {
|
|
6643
|
+
const result = super.deleteToLineStart();
|
|
6644
|
+
this.emit("input" /* INPUT */, this.plainText);
|
|
6645
|
+
return result;
|
|
6646
|
+
}
|
|
6647
|
+
deleteToLineEnd() {
|
|
6648
|
+
const result = super.deleteToLineEnd();
|
|
6649
|
+
this.emit("input" /* INPUT */, this.plainText);
|
|
6650
|
+
return result;
|
|
6651
|
+
}
|
|
6652
|
+
undo() {
|
|
6653
|
+
const result = super.undo();
|
|
6654
|
+
this.emit("input" /* INPUT */, this.plainText);
|
|
6655
|
+
return result;
|
|
6656
|
+
}
|
|
6657
|
+
redo() {
|
|
6658
|
+
const result = super.redo();
|
|
6659
|
+
this.emit("input" /* INPUT */, this.plainText);
|
|
6660
|
+
return result;
|
|
6661
|
+
}
|
|
6366
6662
|
deleteCharacter(direction) {
|
|
6367
6663
|
if (direction === "backward") {
|
|
6368
6664
|
this.deleteCharBackward();
|
|
@@ -9377,6 +9673,7 @@ export {
|
|
|
9377
9673
|
RGBA,
|
|
9378
9674
|
PasteEvent,
|
|
9379
9675
|
OptimizedBuffer,
|
|
9676
|
+
NativeSpanFeed,
|
|
9380
9677
|
MouseParser,
|
|
9381
9678
|
MouseEvent,
|
|
9382
9679
|
MouseButton,
|
|
@@ -9424,5 +9721,5 @@ export {
|
|
|
9424
9721
|
ASCIIFont
|
|
9425
9722
|
};
|
|
9426
9723
|
|
|
9427
|
-
//# debugId=
|
|
9724
|
+
//# debugId=3AFAA02CD618183B64756E2164756E21
|
|
9428
9725
|
//# sourceMappingURL=index.js.map
|