[READ-ONLY] Mirror of https://github.com/bombshell-dev/tty. Platform independent 2D layout engine for terminal applications based on Clay
0

Configure Feed

Select the types of activity you want to include in your feed.

refactor: alignment to use string literals instead of magic numbers

+138 -12
+102
examples/inline-regions/index.ts
··· 48 48 49 49 const BRAILLE = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"]; 50 50 51 + function* queryCursor(): Operation<CursorEvent> { 52 + let parser = yield* until(createInput({ escLatency: 100 })); 53 + write(DSR()); 54 + 55 + let buf = new Uint8Array(32); 56 + while (true) { 57 + let n = Deno.stdin.readSync(buf); 58 + if (n === null) continue; 59 + let result = parser.scan(buf.subarray(0, n)); 60 + for (let ev of result.events) { 61 + if (ev.type === "cursor") { 62 + return ev; 63 + } 64 + } 65 + } 66 + } 67 + 68 + function waitKey() { 69 + let buf = new Uint8Array(32); 70 + while (true) { 71 + let n = Deno.stdin.readSync(buf); 72 + if (n === null) continue; 73 + for (let i = 0; i < n; i++) { 74 + if (buf[i] === 0x03) { 75 + Deno.stdin.setRaw(false); 76 + write(SHOWCURSOR()); 77 + Deno.exit(0); 78 + } 79 + } 80 + return; 81 + } 82 + } 83 + 84 + function box(msg: string, fg: number, border: number): Op[] { 85 + return [ 86 + open("root", { 87 + layout: { width: grow(), height: grow(), direction: "ttb" }, 88 + }), 89 + open("box", { 90 + layout: { 91 + width: grow(), 92 + height: grow(), 93 + direction: "ttb", 94 + padding: { left: 1 }, 95 + alignY: "center", 96 + }, 97 + border: { 98 + color: border, 99 + left: 1, 100 + right: 1, 101 + top: 1, 102 + bottom: 1, 103 + }, 104 + cornerRadius: { tl: 1, tr: 1, bl: 1, br: 1 }, 105 + }), 106 + text(msg, { color: fg }), 107 + close(), 108 + close(), 109 + ]; 110 + } 111 + 112 + function* transaction( 113 + height: number, 114 + renderFrame: (frame: number) => Op[], 115 + frames: number, 116 + interval: number, 117 + ): Operation<void> { 118 + let { columns } = Deno.consoleSize(); 119 + 120 + write(encode("\n".repeat(height))); 121 + 122 + let pos = yield* queryCursor(); 123 + /** 1-based terminal row where the region starts */ 124 + let row = pos.row - height + 1; 125 + 126 + write(ESC("7")); 127 + let tty = settings(cursor(false)); 128 + write(tty.apply); 129 + 130 + let term = validated( 131 + yield* until(createTerm({ width: columns, height })), 132 + ); 133 + for (let i = 0; i < frames; i++) { 134 + let result = term.render(renderFrame(i), { row }); 135 + write(new Uint8Array(result.output)); 136 + yield* sleep(interval); 137 + } 138 + 139 + write(tty.revert); 140 + write(ESC("8")); 141 + write(encode("\n")); 142 + } 143 + 144 + function say(msg: string) { 145 + write(encode(msg + "\n")); 146 + } 147 + 148 + function pause() { 149 + waitKey(); 150 + write(encode("\n")); 151 + } 152 + 51 153 await main(function* () { 52 154 let { columns } = terminalSize(); 53 155 setRawMode(true);
+7 -7
examples/keyboard/index.ts
··· 225 225 width: fixed(w), 226 226 height: grow(), 227 227 padding: { left: 1, right: 1 }, 228 - alignX: 2, 229 - alignY: 2, 228 + alignX: "center", 229 + alignY: "center", 230 230 }, 231 231 bg, 232 232 border: hover ··· 565 565 width: grow(), 566 566 height: grow(), 567 567 direction: "ttb", 568 - alignX: 2, 569 - alignY: 2, 568 + alignX: "center", 569 + alignY: "center", 570 570 padding: { left: 2, top: 1 }, 571 571 }, 572 572 }), ··· 583 583 layout: { 584 584 width: grow(), 585 585 direction: "ltr", 586 - alignY: 0, 586 + alignY: "top", 587 587 padding: { bottom: 1 }, 588 588 }, 589 589 }), ··· 634 634 635 635 // config panel (right) 636 636 ops.push( 637 - open("", { layout: { width: grow(), direction: "ltr", alignX: 1 } }), 637 + open("", { layout: { width: grow(), direction: "ltr", alignX: "right" } }), 638 638 ); 639 639 configPanel(ops, ctx); 640 640 ops.push(close()); ··· 648 648 layout: { 649 649 direction: "ltr", 650 650 gap: 3, 651 - alignY: 1, 651 + alignY: "bottom", 652 652 padding: { left: 1, right: 1, top: 1, bottom: 1 }, 653 653 }, 654 654 border: { color: kbColor, left: 1, right: 1, top: 1, bottom: 1 },
+15 -3
ops.ts
··· 132 132 ); 133 133 o += 4; 134 134 135 - view.setUint32(o, (l.alignX ?? 0) | ((l.alignY ?? 0) << 8), true); 135 + const alignX = l.alignX === "right" 136 + ? 1 137 + : l.alignX === "center" 138 + ? 2 139 + : 0; 140 + 141 + const alignY = l.alignY === "bottom" 142 + ? 1 143 + : l.alignY === "center" 144 + ? 2 145 + : 0; 146 + 147 + view.setUint32(o, alignX | (alignY << 8), true); 136 148 o += 4; 137 149 } 138 150 ··· 275 287 padding?: { left?: number; right?: number; top?: number; bottom?: number }; 276 288 gap?: number; 277 289 direction?: "ltr" | "ttb"; 278 - alignX?: number; 279 - alignY?: number; 290 + alignX?: "left" | "center" | "right"; 291 + alignY?: "top" | "center" | "bottom"; 280 292 }; 281 293 bg?: number; 282 294 cornerRadius?: { tl?: number; tr?: number; bl?: number; br?: number };
+14 -2
validate.ts
··· 56 56 direction: Type.Optional( 57 57 Type.Union([Type.Literal("ltr"), Type.Literal("ttb")]), 58 58 ), 59 - alignX: Type.Optional(u8), 60 - alignY: Type.Optional(u8), 59 + alignX: Type.Optional( 60 + Type.Union([ 61 + Type.Literal("left"), 62 + Type.Literal("center"), 63 + Type.Literal("right"), 64 + ]), 65 + ), 66 + alignY: Type.Optional( 67 + Type.Union([ 68 + Type.Literal("top"), 69 + Type.Literal("center"), 70 + Type.Literal("bottom"), 71 + ]), 72 + ), 61 73 }); 62 74 63 75 const CornerRadius = Type.Object({