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