1#!/usr/bin/env node
2
3const { spawn, execFileSync } = require("child_process");
4
5const RESOLUTION_REGEX = /(\d+) x (\d+)/;
6const DIGIT_FLAG_REGEX = /^--?(\d+)$/;
7
8// Parse the number of Zed instances to spawn.
9let instanceCount = 1;
10let isReleaseMode = false;
11let isTop = false;
12
13const args = process.argv.slice(2);
14for (const arg of args) {
15 const digitMatch = arg.match(DIGIT_FLAG_REGEX);
16 if (digitMatch) {
17 instanceCount = parseInt(digitMatch[1]);
18 continue;
19 }
20
21 if (arg == "--release") {
22 isReleaseMode = true;
23 continue;
24 }
25
26 if (arg == "--top") {
27 isTop = true;
28 }
29}
30
31// Parse the resolution of the main screen
32const displayInfo = JSON.parse(
33 execFileSync("system_profiler", ["SPDisplaysDataType", "-json"], {
34 encoding: "utf8",
35 }),
36);
37const mainDisplayResolution =
38 displayInfo?.SPDisplaysDataType[0]?.spdisplays_ndrvs
39 ?.find((entry) => entry.spdisplays_main === "spdisplays_yes")
40 ?._spdisplays_resolution?.match(RESOLUTION_REGEX);
41if (!mainDisplayResolution) {
42 throw new Error("Could not parse screen resolution");
43}
44const screenWidth = parseInt(mainDisplayResolution[1]);
45let screenHeight = parseInt(mainDisplayResolution[2]);
46
47if (isTop) {
48 screenHeight = Math.floor(screenHeight / 2);
49}
50
51// Determine the window size for each instance
52let instanceWidth = screenWidth;
53let instanceHeight = screenHeight;
54if (instanceCount > 1) {
55 instanceWidth = Math.floor(screenWidth / 2);
56 if (instanceCount > 2) {
57 instanceHeight = Math.floor(screenHeight / 2);
58 }
59}
60
61let users = ["nathansobo", "as-cii", "maxbrunsfeld", "iamnbutler"];
62
63const RUST_LOG = process.env.RUST_LOG || "info";
64
65// If a user is specified, make sure it's first in the list
66const user = process.env.ZED_IMPERSONATE;
67if (user) {
68 users = [user].concat(users.filter((u) => u !== user));
69}
70
71const positions = [
72 "0,0",
73 `${instanceWidth},0`,
74 `0,${instanceHeight}`,
75 `${instanceWidth},${instanceHeight}`,
76];
77
78const buildArgs = (() => {
79 const buildArgs = ["build"];
80 if (isReleaseMode) {
81 buildArgs.push("--release");
82 }
83
84 return buildArgs;
85})();
86const zedBinary = (() => {
87 const target = isReleaseMode ? "release" : "debug";
88 return `target/${target}/Zed`;
89})();
90
91execFileSync("cargo", buildArgs, { stdio: "inherit" });
92setTimeout(() => {
93 for (let i = 0; i < instanceCount; i++) {
94 spawn(zedBinary, i == 0 ? args : [], {
95 stdio: "inherit",
96 env: {
97 ZED_IMPERSONATE: users[i],
98 ZED_WINDOW_POSITION: positions[i],
99 ZED_STATELESS: "1",
100 ZED_ALWAYS_ACTIVE: "1",
101 ZED_SERVER_URL: "http://localhost:8080",
102 ZED_ADMIN_API_TOKEN: "secret",
103 ZED_WINDOW_SIZE: `${instanceWidth},${instanceHeight}`,
104 PATH: process.env.PATH,
105 RUST_LOG,
106 },
107 });
108 }
109}, 0.1);