From e467881a8c20454d6f866ec3126263d482e097d6 Mon Sep 17 00:00:00 2001 From: Jared Miller Date: Tue, 27 Jan 2026 20:41:12 -0500 Subject: [PATCH] Forward awareness/cursor to vim from bridge --- adapters/vim/bridge.test.ts | 66 +++++++++++++++++++++++++++++++++++++ adapters/vim/bridge.ts | 15 +++++++++ 2 files changed, 81 insertions(+) diff --git a/adapters/vim/bridge.test.ts b/adapters/vim/bridge.test.ts index 3452c47..b921de9 100644 --- a/adapters/vim/bridge.test.ts +++ b/adapters/vim/bridge.test.ts @@ -192,3 +192,69 @@ describe("Bridge lifecycle", () => { expect(exitCode).toBe(0); }); }); + +describe("awareness", () => { + test("forwards awareness from daemon to vim", async () => { + // Start daemon + const server = Bun.serve({ + port: 4043, + fetch(req, server) { + if (new URL(req.url).pathname === "/ws") { + server.upgrade(req); + return; + } + return new Response("not found", { status: 404 }); + }, + websocket: { + open(ws) { + // Simulate sending awareness after join + setTimeout(() => { + ws.send(JSON.stringify({ + type: "awareness", + data: { clientId: 99, cursor: { line: 3, col: 7 }, name: "peer" } + })); + }, 100); + }, + message() {}, + close() {}, + }, + }); + + const output: string[] = []; + const bridge = spawn({ + cmd: ["bun", "adapters/vim/bridge.ts"], + env: { ...process.env, COLLABD_URL: "ws://localhost:4043/ws" }, + stdin: "pipe", + stdout: "pipe", + }); + + const reader = bridge.stdout.getReader(); + const decoder = new TextDecoder(); + + // Collect output + (async () => { + while (true) { + const { done, value } = await reader.read(); + if (done) break; + output.push(decoder.decode(value)); + } + })(); + + await new Promise(r => setTimeout(r, 50)); + bridge.stdin.write(JSON.stringify({ type: "connect", room: "test" }) + "\n"); + await new Promise(r => setTimeout(r, 200)); + + const awarenessMsg = output.join("").split("\n") + .filter(Boolean) + .map(l => JSON.parse(l)) + .find(m => m.type === "cursor"); + + expect(awarenessMsg).toBeDefined(); + expect(awarenessMsg.data.line).toBe(3); + expect(awarenessMsg.data.col).toBe(7); + expect(awarenessMsg.data.name).toBe("peer"); + + bridge.kill(); + server.stop(); + }); +}); diff --git a/adapters/vim/bridge.ts b/adapters/vim/bridge.ts index 646855c..cfb0928 100644 --- a/adapters/vim/bridge.ts +++ b/adapters/vim/bridge.ts @@ -58,6 +58,21 @@ function connect(roomName: string) { send({ type: "peers", count: msg.count }); break; } + case "awareness": { + // Forward cursor info to vim + if (msg.data?.cursor) { + send({ + type: "cursor", + data: { + clientId: msg.data.clientId, + line: msg.data.cursor.line, + col: msg.data.cursor.col, + name: msg.data.name || `peer-${msg.data.clientId}`, + }, + }); + } + break; + } } };