( options: TheaterOptions, body: (theater: ChatTheater) => Effect.Effect<A, E, R>, )
| 175 | // --------------------------------------------------------------------------- |
| 176 | |
| 177 | const deskTheater = <A, E, R>( |
| 178 | options: TheaterOptions, |
| 179 | body: (theater: ChatTheater) => Effect.Effect<A, E, R>, |
| 180 | ): Effect.Effect<A, E, R> => |
| 181 | Effect.gen(function* () { |
| 182 | const root = mkdtempSync(join(tmpdir(), "desk-theater-")); |
| 183 | const fifo = join(root, "events.fifo"); |
| 184 | spawnSync("mkfifo", [fifo]); |
| 185 | |
| 186 | const xterm = spawn( |
| 187 | "xterm", |
| 188 | [ |
| 189 | // -u8 + a UTF-8 locale: the renderer speaks box-drawing and bullets. |
| 190 | ...["-u8", "-fa", "DejaVu Sans Mono", "-fs", "13"], |
| 191 | ...["-bg", "#0b0b10", "-fg", "#e8e8ea"], |
| 192 | ...["-geometry", "112x34+48+40", "-T", options.title], |
| 193 | ...["-e", "bun", RENDERER, options.title, fifo], |
| 194 | ], |
| 195 | { stdio: "ignore", env: { ...process.env, LANG: "C.UTF-8", LC_ALL: "C.UTF-8" } }, |
| 196 | ); |
| 197 | // Opening the write end parks until the renderer opens the read end. |
| 198 | const writer = createWriteStream(fifo); |
| 199 | const push = (event: TheaterEvent) => |
| 200 | Effect.sync(() => { |
| 201 | writer.write(encode(event)); |
| 202 | }); |
| 203 | |
| 204 | const result = yield* Effect.exit(body(makeTheater(push))); |
| 205 | yield* push({ type: "done" }); |
| 206 | yield* Effect.promise(async () => { |
| 207 | // Renderer acks the footer, lingers for the camera, then exits with |
| 208 | // its xterm. Don't hang the run on a wedged terminal. |
| 209 | const ackDeadline = Date.now() + 30_000; |
| 210 | while (!existsSync(`${fifo}.done`) && Date.now() < ackDeadline) await sleep(200); |
| 211 | const exitDeadline = Date.now() + 10_000; |
| 212 | while (xterm.exitCode === null && Date.now() < exitDeadline) await sleep(200); |
| 213 | if (xterm.exitCode === null) xterm.kill(); |
| 214 | writer.end(); |
| 215 | }); |
| 216 | return yield* result; |
| 217 | }); |
no test coverage detected