import * as NodeServices from "@effect/platform-node/NodeServices";import { assert, it } from "@effect/vitest";import { assertSuccess } from "@effect/vitest/utils";import { FileSystem, Path, Effect } from "effect"; import { isCommandAvailable, launchDetached, resolveAvailableEditors, resolveEditorLaunch,} from "./open.ts"; it.layer(NodeServices.layer)("resolveEditorLaunch", (it) => { it.effect("returns commands for command-based editors", () => Effect.gen(function* () { const antigravityLaunch = yield* resolveEditorLaunch( { cwd: "/tmp/workspace", editor: "antigravity" }, "darwin", { PATH: "" }, ); assert.deepEqual(antigravityLaunch, { command: "agy", args: ["/tmp/workspace"], }); const cursorLaunch = yield* resolveEditorLaunch( { cwd: "/tmp/workspace", editor: "cursor" }, "darwin", { PATH: "" }, ); assert.deepEqual(cursorLaunch, { command: "cursor", args: ["/tmp/workspace"], }); const traeLaunch = yield* resolveEditorLaunch( { cwd: "/tmp/workspace", editor: "trae" }, "darwin", ); assert.deepEqual(traeLaunch, { command: "trae", args: ["/tmp/workspace"], }); const kiroLaunch = yield* resolveEditorLaunch( { cwd: "/tmp/workspace", editor: "kiro" }, "darwin", { PATH: "" }, ); assert.deepEqual(kiroLaunch, { command: "kiro", args: ["ide", "/tmp/workspace"], }); const vscodeLaunch = yield* resolveEditorLaunch( { cwd: "/tmp/workspace", editor: "vscode" }, "darwin", { PATH: "" }, ); assert.deepEqual(vscodeLaunch, { command: "code", args: ["/tmp/workspace"], }); const vscodeInsidersLaunch = yield* resolveEditorLaunch( { cwd: "/tmp/workspace", editor: "vscode-insiders" }, "darwin", ); assert.deepEqual(vscodeInsidersLaunch, { command: "code-insiders", args: ["/tmp/workspace"], }); const vscodiumLaunch = yield* resolveEditorLaunch( { cwd: "/tmp/workspace", editor: "vscodium" }, "darwin", ); assert.deepEqual(vscodiumLaunch, { command: "codium", args: ["/tmp/workspace"], }); const zedLaunch = yield* resolveEditorLaunch( { cwd: "/tmp/workspace", editor: "zed" }, "darwin", { PATH: "" }, ); assert.deepEqual(zedLaunch, { command: "zed", args: ["/tmp/workspace"], }); const ideaLaunch = yield* resolveEditorLaunch( { cwd: "/tmp/workspace", editor: "idea" }, "darwin", ); assert.deepEqual(ideaLaunch, { command: "idea", args: ["/tmp/workspace"], }); const aquaLaunch = yield* resolveEditorLaunch( { cwd: "/tmp/workspace", editor: "aqua" }, "darwin", ); assert.deepEqual(aquaLaunch, { command: "aqua", args: ["/tmp/workspace"], }); const clionLaunch = yield* resolveEditorLaunch( { cwd: "/tmp/workspace", editor: "clion" }, "darwin", ); assert.deepEqual(clionLaunch, { command: "clion", args: ["/tmp/workspace"], }); const datagripLaunch = yield* resolveEditorLaunch( { cwd: "/tmp/workspace", editor: "datagrip" }, "darwin", ); assert.deepEqual(datagripLaunch, { command: "datagrip", args: ["/tmp/workspace"], }); const dataspellLaunch = yield* resolveEditorLaunch( { cwd: "/tmp/workspace", editor: "dataspell" }, "darwin", ); assert.deepEqual(dataspellLaunch, { command: "dataspell", args: ["/tmp/workspace"], }); const golandLaunch = yield* resolveEditorLaunch( { cwd: "/tmp/workspace", editor: "goland" }, "darwin", ); assert.deepEqual(golandLaunch, { command: "goland", args: ["/tmp/workspace"], }); const phpstormLaunch = yield* resolveEditorLaunch( { cwd: "/tmp/workspace", editor: "phpstorm" }, "darwin", ); assert.deepEqual(phpstormLaunch, { command: "phpstorm", args: ["/tmp/workspace"], }); const pycharmLaunch = yield* resolveEditorLaunch( { cwd: "/tmp/workspace", editor: "pycharm" }, "darwin", ); assert.deepEqual(pycharmLaunch, { command: "pycharm", args: ["/tmp/workspace"], }); const riderLaunch = yield* resolveEditorLaunch( { cwd: "/tmp/workspace", editor: "rider" }, "darwin", ); assert.deepEqual(riderLaunch, { command: "rider", args: ["/tmp/workspace"], }); const rubymineLaunch = yield* resolveEditorLaunch( { cwd: "/tmp/workspace", editor: "rubymine" }, "darwin", ); assert.deepEqual(rubymineLaunch, { command: "rubymine", args: ["/tmp/workspace"], }); const rustroverLaunch = yield* resolveEditorLaunch( { cwd: "/tmp/workspace", editor: "rustrover" }, "darwin", ); assert.deepEqual(rustroverLaunch, { command: "rustrover", args: ["/tmp/workspace"], }); const webstormLaunch = yield* resolveEditorLaunch( { cwd: "/tmp/workspace", editor: "webstorm" }, "darwin", ); assert.deepEqual(webstormLaunch, { command: "webstorm", args: ["/tmp/workspace"], }); }), ); it.effect("applies launch-style-specific navigation arguments", () => Effect.gen(function* () { const lineOnly = yield* resolveEditorLaunch( { cwd: "/tmp/workspace/AGENTS.md:48", editor: "cursor" }, "darwin", { PATH: "" }, ); assert.deepEqual(lineOnly, { command: "cursor", args: ["--goto", "/tmp/workspace/AGENTS.md:48"], }); const lineAndColumn = yield* resolveEditorLaunch( { cwd: "/tmp/workspace/src/open.ts:71:5", editor: "cursor" }, "darwin", { PATH: "" }, ); assert.deepEqual(lineAndColumn, { command: "cursor", args: ["--goto", "/tmp/workspace/src/open.ts:71:5"], }); const traeLineAndColumn = yield* resolveEditorLaunch( { cwd: "/tmp/workspace/src/open.ts:71:5", editor: "trae" }, "darwin", ); assert.deepEqual(traeLineAndColumn, { command: "trae", args: ["--goto", "/tmp/workspace/src/open.ts:71:5"], }); const kiroLineAndColumn = yield* resolveEditorLaunch( { cwd: "/tmp/workspace/src/open.ts:71:5", editor: "kiro" }, "darwin", { PATH: "" }, ); assert.deepEqual(kiroLineAndColumn, { command: "kiro", args: ["ide", "--goto", "/tmp/workspace/src/open.ts:71:5"], }); const vscodeLineAndColumn = yield* resolveEditorLaunch( { cwd: "/tmp/workspace/src/open.ts:71:5", editor: "vscode" }, "darwin", { PATH: "" }, ); assert.deepEqual(vscodeLineAndColumn, { command: "code", args: ["--goto", "/tmp/workspace/src/open.ts:71:5"], }); const vscodeInsidersLineAndColumn = yield* resolveEditorLaunch( { cwd: "/tmp/workspace/src/open.ts:71:5", editor: "vscode-insiders" }, "darwin", ); assert.deepEqual(vscodeInsidersLineAndColumn, { command: "code-insiders", args: ["--goto", "/tmp/workspace/src/open.ts:71:5"], }); const vscodiumLineAndColumn = yield* resolveEditorLaunch( { cwd: "/tmp/workspace/src/open.ts:71:5", editor: "vscodium" }, "darwin", ); assert.deepEqual(vscodiumLineAndColumn, { command: "codium", args: ["--goto", "/tmp/workspace/src/open.ts:71:5"], }); const zedLineAndColumn = yield* resolveEditorLaunch( { cwd: "/tmp/workspace/src/open.ts:71:5", editor: "zed" }, "darwin", { PATH: "" }, ); assert.deepEqual(zedLineAndColumn, { command: "zed", args: ["/tmp/workspace/src/open.ts:71:5"], }); const zedLineOnly = yield* resolveEditorLaunch( { cwd: "/tmp/workspace/AGENTS.md:48", editor: "zed" }, "darwin", { PATH: "" }, ); assert.deepEqual(zedLineOnly, { command: "zed", args: ["/tmp/workspace/AGENTS.md:48"], }); const ideaLineOnly = yield* resolveEditorLaunch( { cwd: "/tmp/workspace/AGENTS.md:48", editor: "idea" }, "darwin", ); assert.deepEqual(ideaLineOnly, { command: "idea", args: ["--line", "48", "/tmp/workspace/AGENTS.md"], }); const ideaLineAndColumn = yield* resolveEditorLaunch( { cwd: "/tmp/workspace/src/open.ts:71:5", editor: "idea" }, "darwin", ); assert.deepEqual(ideaLineAndColumn, { command: "idea", args: ["--line", "71", "--column", "5", "/tmp/workspace/src/open.ts"], }); const aquaLineAndColumn = yield* resolveEditorLaunch( { cwd: "/tmp/workspace/src/open.ts:71:5", editor: "aqua" }, "darwin", ); assert.deepEqual(aquaLineAndColumn, { command: "aqua", args: ["--line", "71", "--column", "5", "/tmp/workspace/src/open.ts"], }); const clionLineAndColumn = yield* resolveEditorLaunch( { cwd: "/tmp/workspace/src/open.ts:71:5", editor: "clion" }, "darwin", ); assert.deepEqual(clionLineAndColumn, { command: "clion", args: ["--line", "71", "--column", "5", "/tmp/workspace/src/open.ts"], }); const datagripLineAndColumn = yield* resolveEditorLaunch( { cwd: "/tmp/workspace/src/open.ts:71:5", editor: "datagrip" }, "darwin", ); assert.deepEqual(datagripLineAndColumn, { command: "datagrip", args: ["--line", "71", "--column", "5", "/tmp/workspace/src/open.ts"], }); const dataspellLineAndColumn = yield* resolveEditorLaunch( { cwd: "/tmp/workspace/src/open.ts:71:5", editor: "dataspell" }, "darwin", ); assert.deepEqual(dataspellLineAndColumn, { command: "dataspell", args: ["--line", "71", "--column", "5", "/tmp/workspace/src/open.ts"], }); const golandLineAndColumn = yield* resolveEditorLaunch( { cwd: "/tmp/workspace/src/open.ts:71:5", editor: "goland" }, "darwin", ); assert.deepEqual(golandLineAndColumn, { command: "goland", args: ["--line", "71", "--column", "5", "/tmp/workspace/src/open.ts"], }); const phpstormLineAndColumn = yield* resolveEditorLaunch( { cwd: "/tmp/workspace/src/open.ts:71:5", editor: "phpstorm" }, "darwin", ); assert.deepEqual(phpstormLineAndColumn, { command: "phpstorm", args: ["--line", "71", "--column", "5", "/tmp/workspace/src/open.ts"], }); const pycharmLineAndColumn = yield* resolveEditorLaunch( { cwd: "/tmp/workspace/src/open.ts:71:5", editor: "pycharm" }, "darwin", ); assert.deepEqual(pycharmLineAndColumn, { command: "pycharm", args: ["--line", "71", "--column", "5", "/tmp/workspace/src/open.ts"], }); const riderLineAndColumn = yield* resolveEditorLaunch( { cwd: "/tmp/workspace/src/open.ts:71:5", editor: "rider" }, "darwin", ); assert.deepEqual(riderLineAndColumn, { command: "rider", args: ["--line", "71", "--column", "5", "/tmp/workspace/src/open.ts"], }); const rubymineLineAndColumn = yield* resolveEditorLaunch( { cwd: "/tmp/workspace/src/open.ts:71:5", editor: "rubymine" }, "darwin", ); assert.deepEqual(rubymineLineAndColumn, { command: "rubymine", args: ["--line", "71", "--column", "5", "/tmp/workspace/src/open.ts"], }); const rustroverLineAndColumn = yield* resolveEditorLaunch( { cwd: "/tmp/workspace/src/open.ts:71:5", editor: "rustrover" }, "darwin", ); assert.deepEqual(rustroverLineAndColumn, { command: "rustrover", args: ["--line", "71", "--column", "5", "/tmp/workspace/src/open.ts"], }); const webstormLineOnly = yield* resolveEditorLaunch( { cwd: "/tmp/workspace/AGENTS.md:48", editor: "webstorm" }, "darwin", ); assert.deepEqual(webstormLineOnly, { command: "webstorm", args: ["--line", "48", "/tmp/workspace/AGENTS.md"], }); }), ); it.effect("falls back to zeditor when zed is not installed", () => Effect.gen(function* () { const fs = yield* FileSystem.FileSystem; const path = yield* Path.Path; const dir = yield* fs.makeTempDirectoryScoped({ prefix: "t3-open-test-" }); yield* fs.writeFileString(path.join(dir, "zeditor"), "#!/bin/sh\nexit 0\n"); yield* fs.chmod(path.join(dir, "zeditor"), 0o755); const result = yield* resolveEditorLaunch({ cwd: "/tmp/workspace", editor: "zed" }, "linux", { PATH: dir, }); assert.deepEqual(result, { command: "zeditor", args: ["/tmp/workspace"], }); }), ); it.effect("falls back to the primary command when no alias is installed", () => Effect.gen(function* () { const result = yield* resolveEditorLaunch({ cwd: "/tmp/workspace", editor: "zed" }, "linux", { PATH: "", }); assert.deepEqual(result, { command: "zed", args: ["/tmp/workspace"], }); }), ); it.effect("maps file-manager editor to OS open commands", () => Effect.gen(function* () { const launch1 = yield* resolveEditorLaunch( { cwd: "/tmp/workspace", editor: "file-manager" }, "darwin", { PATH: "" }, ); assert.deepEqual(launch1, { command: "open", args: ["/tmp/workspace"], }); const launch2 = yield* resolveEditorLaunch( { cwd: "C:\\workspace", editor: "file-manager" }, "win32", { PATH: "" }, ); assert.deepEqual(launch2, { command: "explorer", args: ["C:\\workspace"], }); const launch3 = yield* resolveEditorLaunch( { cwd: "/tmp/workspace", editor: "file-manager" }, "linux", { PATH: "" }, ); assert.deepEqual(launch3, { command: "xdg-open", args: ["/tmp/workspace"], }); }), );}); it.layer(NodeServices.layer)("launchDetached", (it) => { it.effect("resolves when command can be spawned", () => Effect.gen(function* () { const result = yield* launchDetached({ command: process.execPath, args: ["-e", "process.exit(0)"], }).pipe(Effect.result); assertSuccess(result, undefined); }), ); it.effect("rejects when command does not exist", () => Effect.gen(function* () { const result = yield* launchDetached({ command: `t3code-no-such-command-${Date.now()}`, args: [], }).pipe(Effect.result); assert.equal(result._tag, "Failure"); }), );}); it.layer(NodeServices.layer)("isCommandAvailable", (it) => { it.effect("resolves win32 commands with PATHEXT", () =>Lines 1–500 of 639. Load more
import * as NodeServices from "@effect/platform-node/NodeServices"; import { assert, it } from "@effect/vitest"; import { assertSuccess } from "@effect/vitest/utils"; import { FileSystem, Path, Effect } from "effect"; import { isCommandAvailable, launchDetached, resolveAvailableEditors, resolveEditorLaunch, } from "./open.ts"; it.layer(NodeServices.layer)("resolveEditorLaunch", (it) => { it.effect("returns commands for command-based editors", () => Effect.gen(function* () { const antigravityLaunch = yield* resolveEditorLaunch( { cwd: "/tmp/workspace", editor: "antigravity" }, "darwin", { PATH: "" }, ); assert.deepEqual(antigravityLaunch, { command: "agy", args: ["/tmp/workspace"], }); const cursorLaunch = yield* resolveEditorLaunch( { cwd: "/tmp/workspace", editor: "cursor" }, "darwin", { PATH: "" }, ); assert.deepEqual(cursorLaunch, { command: "cursor", args: ["/tmp/workspace"], }); const traeLaunch = yield* resolveEditorLaunch( { cwd: "/tmp/workspace", editor: "trae" }, "darwin", ); assert.deepEqual(traeLaunch, { command: "trae", args: ["/tmp/workspace"], }); const kiroLaunch = yield* resolveEditorLaunch( { cwd: "/tmp/workspace", editor: "kiro" }, "darwin", { PATH: "" }, ); assert.deepEqual(kiroLaunch, { command: "kiro", args: ["ide", "/tmp/workspace"], }); const vscodeLaunch = yield* resolveEditorLaunch( { cwd: "/tmp/workspace", editor: "vscode" }, "darwin", { PATH: "" }, ); assert.deepEqual(vscodeLaunch, { command: "code", args: ["/tmp/workspace"], }); const vscodeInsidersLaunch = yield* resolveEditorLaunch( { cwd: "/tmp/workspace", editor: "vscode-insiders" }, "darwin", ); assert.deepEqual(vscodeInsidersLaunch, { command: "code-insiders", args: ["/tmp/workspace"], }); const vscodiumLaunch = yield* resolveEditorLaunch( { cwd: "/tmp/workspace", editor: "vscodium" }, "darwin", ); assert.deepEqual(vscodiumLaunch, { command: "codium", args: ["/tmp/workspace"], }); const zedLaunch = yield* resolveEditorLaunch( { cwd: "/tmp/workspace", editor: "zed" }, "darwin", { PATH: "" }, ); assert.deepEqual(zedLaunch, { command: "zed", args: ["/tmp/workspace"], }); const ideaLaunch = yield* resolveEditorLaunch( { cwd: "/tmp/workspace", editor: "idea" }, "darwin", ); assert.deepEqual(ideaLaunch, { command: "idea", args: ["/tmp/workspace"], }); const aquaLaunch = yield* resolveEditorLaunch( { cwd: "/tmp/workspace", editor: "aqua" }, "darwin", ); assert.deepEqual(aquaLaunch, { command: "aqua", args: ["/tmp/workspace"], }); const clionLaunch = yield* resolveEditorLaunch( { cwd: "/tmp/workspace", editor: "clion" }, "darwin", ); assert.deepEqual(clionLaunch, { command: "clion", args: ["/tmp/workspace"], }); const datagripLaunch = yield* resolveEditorLaunch( { cwd: "/tmp/workspace", editor: "datagrip" }, "darwin", ); assert.deepEqual(datagripLaunch, { command: "datagrip", args: ["/tmp/workspace"], }); const dataspellLaunch = yield* resolveEditorLaunch( { cwd: "/tmp/workspace", editor: "dataspell" }, "darwin", ); assert.deepEqual(dataspellLaunch, { command: "dataspell", args: ["/tmp/workspace"], }); const golandLaunch = yield* resolveEditorLaunch( { cwd: "/tmp/workspace", editor: "goland" }, "darwin", ); assert.deepEqual(golandLaunch, { command: "goland", args: ["/tmp/workspace"], }); const phpstormLaunch = yield* resolveEditorLaunch( { cwd: "/tmp/workspace", editor: "phpstorm" }, "darwin", ); assert.deepEqual(phpstormLaunch, { command: "phpstorm", args: ["/tmp/workspace"], }); const pycharmLaunch = yield* resolveEditorLaunch( { cwd: "/tmp/workspace", editor: "pycharm" }, "darwin", ); assert.deepEqual(pycharmLaunch, { command: "pycharm", args: ["/tmp/workspace"], }); const riderLaunch = yield* resolveEditorLaunch( { cwd: "/tmp/workspace", editor: "rider" }, "darwin", ); assert.deepEqual(riderLaunch, { command: "rider", args: ["/tmp/workspace"], }); const rubymineLaunch = yield* resolveEditorLaunch( { cwd: "/tmp/workspace", editor: "rubymine" }, "darwin", ); assert.deepEqual(rubymineLaunch, { command: "rubymine", args: ["/tmp/workspace"], }); const rustroverLaunch = yield* resolveEditorLaunch( { cwd: "/tmp/workspace", editor: "rustrover" }, "darwin", ); assert.deepEqual(rustroverLaunch, { command: "rustrover", args: ["/tmp/workspace"], }); const webstormLaunch = yield* resolveEditorLaunch( { cwd: "/tmp/workspace", editor: "webstorm" }, "darwin", ); assert.deepEqual(webstormLaunch, { command: "webstorm", args: ["/tmp/workspace"], }); }), ); it.effect("applies launch-style-specific navigation arguments", () => Effect.gen(function* () { const lineOnly = yield* resolveEditorLaunch( { cwd: "/tmp/workspace/AGENTS.md:48", editor: "cursor" }, "darwin", { PATH: "" }, ); assert.deepEqual(lineOnly, { command: "cursor", args: ["--goto", "/tmp/workspace/AGENTS.md:48"], }); const lineAndColumn = yield* resolveEditorLaunch( { cwd: "/tmp/workspace/src/open.ts:71:5", editor: "cursor" }, "darwin", { PATH: "" }, ); assert.deepEqual(lineAndColumn, { command: "cursor", args: ["--goto", "/tmp/workspace/src/open.ts:71:5"], }); const traeLineAndColumn = yield* resolveEditorLaunch( { cwd: "/tmp/workspace/src/open.ts:71:5", editor: "trae" }, "darwin", ); assert.deepEqual(traeLineAndColumn, { command: "trae", args: ["--goto", "/tmp/workspace/src/open.ts:71:5"], }); const kiroLineAndColumn = yield* resolveEditorLaunch( { cwd: "/tmp/workspace/src/open.ts:71:5", editor: "kiro" }, "darwin", { PATH: "" }, ); assert.deepEqual(kiroLineAndColumn, { command: "kiro", args: ["ide", "--goto", "/tmp/workspace/src/open.ts:71:5"], }); const vscodeLineAndColumn = yield* resolveEditorLaunch( { cwd: "/tmp/workspace/src/open.ts:71:5", editor: "vscode" }, "darwin", { PATH: "" }, ); assert.deepEqual(vscodeLineAndColumn, { command: "code", args: ["--goto", "/tmp/workspace/src/open.ts:71:5"], }); const vscodeInsidersLineAndColumn = yield* resolveEditorLaunch( { cwd: "/tmp/workspace/src/open.ts:71:5", editor: "vscode-insiders" }, "darwin", ); assert.deepEqual(vscodeInsidersLineAndColumn, { command: "code-insiders", args: ["--goto", "/tmp/workspace/src/open.ts:71:5"], }); const vscodiumLineAndColumn = yield* resolveEditorLaunch( { cwd: "/tmp/workspace/src/open.ts:71:5", editor: "vscodium" }, "darwin", ); assert.deepEqual(vscodiumLineAndColumn, { command: "codium", args: ["--goto", "/tmp/workspace/src/open.ts:71:5"], }); const zedLineAndColumn = yield* resolveEditorLaunch( { cwd: "/tmp/workspace/src/open.ts:71:5", editor: "zed" }, "darwin", { PATH: "" }, ); assert.deepEqual(zedLineAndColumn, { command: "zed", args: ["/tmp/workspace/src/open.ts:71:5"], }); const zedLineOnly = yield* resolveEditorLaunch( { cwd: "/tmp/workspace/AGENTS.md:48", editor: "zed" }, "darwin", { PATH: "" }, ); assert.deepEqual(zedLineOnly, { command: "zed", args: ["/tmp/workspace/AGENTS.md:48"], }); const ideaLineOnly = yield* resolveEditorLaunch( { cwd: "/tmp/workspace/AGENTS.md:48", editor: "idea" }, "darwin", ); assert.deepEqual(ideaLineOnly, { command: "idea", args: ["--line", "48", "/tmp/workspace/AGENTS.md"], }); const ideaLineAndColumn = yield* resolveEditorLaunch( { cwd: "/tmp/workspace/src/open.ts:71:5", editor: "idea" }, "darwin", ); assert.deepEqual(ideaLineAndColumn, { command: "idea", args: ["--line", "71", "--column", "5", "/tmp/workspace/src/open.ts"], }); const aquaLineAndColumn = yield* resolveEditorLaunch( { cwd: "/tmp/workspace/src/open.ts:71:5", editor: "aqua" }, "darwin", ); assert.deepEqual(aquaLineAndColumn, { command: "aqua", args: ["--line", "71", "--column", "5", "/tmp/workspace/src/open.ts"], }); const clionLineAndColumn = yield* resolveEditorLaunch( { cwd: "/tmp/workspace/src/open.ts:71:5", editor: "clion" }, "darwin", ); assert.deepEqual(clionLineAndColumn, { command: "clion", args: ["--line", "71", "--column", "5", "/tmp/workspace/src/open.ts"], }); const datagripLineAndColumn = yield* resolveEditorLaunch( { cwd: "/tmp/workspace/src/open.ts:71:5", editor: "datagrip" }, "darwin", ); assert.deepEqual(datagripLineAndColumn, { command: "datagrip", args: ["--line", "71", "--column", "5", "/tmp/workspace/src/open.ts"], }); const dataspellLineAndColumn = yield* resolveEditorLaunch( { cwd: "/tmp/workspace/src/open.ts:71:5", editor: "dataspell" }, "darwin", ); assert.deepEqual(dataspellLineAndColumn, { command: "dataspell", args: ["--line", "71", "--column", "5", "/tmp/workspace/src/open.ts"], }); const golandLineAndColumn = yield* resolveEditorLaunch( { cwd: "/tmp/workspace/src/open.ts:71:5", editor: "goland" }, "darwin", ); assert.deepEqual(golandLineAndColumn, { command: "goland", args: ["--line", "71", "--column", "5", "/tmp/workspace/src/open.ts"], }); const phpstormLineAndColumn = yield* resolveEditorLaunch( { cwd: "/tmp/workspace/src/open.ts:71:5", editor: "phpstorm" }, "darwin", ); assert.deepEqual(phpstormLineAndColumn, { command: "phpstorm", args: ["--line", "71", "--column", "5", "/tmp/workspace/src/open.ts"], }); const pycharmLineAndColumn = yield* resolveEditorLaunch( { cwd: "/tmp/workspace/src/open.ts:71:5", editor: "pycharm" }, "darwin", ); assert.deepEqual(pycharmLineAndColumn, { command: "pycharm", args: ["--line", "71", "--column", "5", "/tmp/workspace/src/open.ts"], }); const riderLineAndColumn = yield* resolveEditorLaunch( { cwd: "/tmp/workspace/src/open.ts:71:5", editor: "rider" }, "darwin", ); assert.deepEqual(riderLineAndColumn, { command: "rider", args: ["--line", "71", "--column", "5", "/tmp/workspace/src/open.ts"], }); const rubymineLineAndColumn = yield* resolveEditorLaunch( { cwd: "/tmp/workspace/src/open.ts:71:5", editor: "rubymine" }, "darwin", ); assert.deepEqual(rubymineLineAndColumn, { command: "rubymine", args: ["--line", "71", "--column", "5", "/tmp/workspace/src/open.ts"], }); const rustroverLineAndColumn = yield* resolveEditorLaunch( { cwd: "/tmp/workspace/src/open.ts:71:5", editor: "rustrover" }, "darwin", ); assert.deepEqual(rustroverLineAndColumn, { command: "rustrover", args: ["--line", "71", "--column", "5", "/tmp/workspace/src/open.ts"], }); const webstormLineOnly = yield* resolveEditorLaunch( { cwd: "/tmp/workspace/AGENTS.md:48", editor: "webstorm" }, "darwin", ); assert.deepEqual(webstormLineOnly, { command: "webstorm", args: ["--line", "48", "/tmp/workspace/AGENTS.md"], }); }), ); it.effect("falls back to zeditor when zed is not installed", () => Effect.gen(function* () { const fs = yield* FileSystem.FileSystem; const path = yield* Path.Path; const dir = yield* fs.makeTempDirectoryScoped({ prefix: "t3-open-test-" }); yield* fs.writeFileString(path.join(dir, "zeditor"), "#!/bin/sh\nexit 0\n"); yield* fs.chmod(path.join(dir, "zeditor"), 0o755); const result = yield* resolveEditorLaunch({ cwd: "/tmp/workspace", editor: "zed" }, "linux", { PATH: dir, }); assert.deepEqual(result, { command: "zeditor", args: ["/tmp/workspace"], }); }), ); it.effect("falls back to the primary command when no alias is installed", () => Effect.gen(function* () { const result = yield* resolveEditorLaunch({ cwd: "/tmp/workspace", editor: "zed" }, "linux", { PATH: "", }); assert.deepEqual(result, { command: "zed", args: ["/tmp/workspace"], }); }), ); it.effect("maps file-manager editor to OS open commands", () => Effect.gen(function* () { const launch1 = yield* resolveEditorLaunch( { cwd: "/tmp/workspace", editor: "file-manager" }, "darwin", { PATH: "" }, ); assert.deepEqual(launch1, { command: "open", args: ["/tmp/workspace"], }); const launch2 = yield* resolveEditorLaunch( { cwd: "C:\\workspace", editor: "file-manager" }, "win32", { PATH: "" }, ); assert.deepEqual(launch2, { command: "explorer", args: ["C:\\workspace"], }); const launch3 = yield* resolveEditorLaunch( { cwd: "/tmp/workspace", editor: "file-manager" }, "linux", { PATH: "" }, ); assert.deepEqual(launch3, { command: "xdg-open", args: ["/tmp/workspace"], }); }), ); }); it.layer(NodeServices.layer)("launchDetached", (it) => { it.effect("resolves when command can be spawned", () => Effect.gen(function* () { const result = yield* launchDetached({ command: process.execPath, args: ["-e", "process.exit(0)"], }).pipe(Effect.result); assertSuccess(result, undefined); }), ); it.effect("rejects when command does not exist", () => Effect.gen(function* () { const result = yield* launchDetached({ command: `t3code-no-such-command-${Date.now()}`, args: [], }).pipe(Effect.result); assert.equal(result._tag, "Failure"); }), ); }); it.layer(NodeServices.layer)("isCommandAvailable", (it) => { it.effect("resolves win32 commands with PATHEXT", () =>