diff --git a/.icons/zed.svg b/.icons/zed.svg new file mode 100644 index 000000000..06b5c183e --- /dev/null +++ b/.icons/zed.svg @@ -0,0 +1,3 @@ + + + diff --git a/registry/coder/modules/zed/README.md b/registry/coder/modules/zed/README.md new file mode 100644 index 000000000..ea11372eb --- /dev/null +++ b/registry/coder/modules/zed/README.md @@ -0,0 +1,65 @@ +--- +display_name: Zed +description: Add a one-click button to launch Zed +icon: ../../../../.icons/zed.svg +maintainer_github: coder +verified: true +tags: [ide, zed, editor] +--- + +# Zed + +Add a button to open any workspace with a single click in Zed. + +Zed is a high-performance, multiplayer code editor from the creators of Atom and Tree-sitter. + +> [!IMPORTANT] +> Zed needs you to either have Coder CLI installed with `coder config-ssh` run or [Coder Desktop](https://coder.com/docs/user-guides/desktop) + +```tf +module "zed" { + count = data.coder_workspace.me.start_count + source = "registry.coder.com/coder/zed/coder" + version = "1.0.0" + agent_id = coder_agent.example.id +} +``` + +## Examples + +### Open in a specific directory + +```tf +module "zed" { + count = data.coder_workspace.me.start_count + source = "registry.coder.com/coder/zed/coder" + version = "1.0.0" + agent_id = coder_agent.example.id + folder = "/home/coder/project" +} +``` + +### Custom display name and order + +```tf +module "zed" { + count = data.coder_workspace.me.start_count + source = "registry.coder.com/coder/zed/coder" + version = "1.0.0" + agent_id = coder_agent.example.id + display_name = "Zed Editor" + order = 1 +} +``` + +### With custom agent name + +```tf +module "zed" { + count = data.coder_workspace.me.start_count + source = "registry.coder.com/coder/zed/coder" + version = "1.0.0" + agent_id = coder_agent.example.id + agent_name = coder_agent.example.name +} +``` diff --git a/registry/coder/modules/zed/main.test.ts b/registry/coder/modules/zed/main.test.ts new file mode 100644 index 000000000..9a657e02a --- /dev/null +++ b/registry/coder/modules/zed/main.test.ts @@ -0,0 +1,81 @@ +import { describe, expect, it } from "bun:test"; +import { + runTerraformApply, + runTerraformInit, + testRequiredVariables, +} from "~test"; + +describe("zed", async () => { + await runTerraformInit(import.meta.dir); + + testRequiredVariables(import.meta.dir, { + agent_id: "foo", + }); + + it("default output", async () => { + const state = await runTerraformApply(import.meta.dir, { + agent_id: "foo", + }); + expect(state.outputs.zed_url.value).toBe( + "zed://ssh/default.coder", + ); + + const coder_app = state.resources.find( + (res) => res.type === "coder_app" && res.name === "zed", + ); + + expect(coder_app).not.toBeNull(); + expect(coder_app?.instances.length).toBe(1); + expect(coder_app?.instances[0].attributes.order).toBeNull(); + }); + + it("adds folder", async () => { + const state = await runTerraformApply(import.meta.dir, { + agent_id: "foo", + folder: "/foo/bar", + }); + expect(state.outputs.zed_url.value).toBe( + "zed://ssh/default.coder/foo/bar", + ); + }); + + it("expect order to be set", async () => { + const state = await runTerraformApply(import.meta.dir, { + agent_id: "foo", + order: "22", + }); + + const coder_app = state.resources.find( + (res) => res.type === "coder_app" && res.name === "zed", + ); + + expect(coder_app).not.toBeNull(); + expect(coder_app?.instances.length).toBe(1); + expect(coder_app?.instances[0].attributes.order).toBe(22); + }); + + it("expect display_name to be set", async () => { + const state = await runTerraformApply(import.meta.dir, { + agent_id: "foo", + display_name: "Custom Zed", + }); + + const coder_app = state.resources.find( + (res) => res.type === "coder_app" && res.name === "zed", + ); + + expect(coder_app).not.toBeNull(); + expect(coder_app?.instances.length).toBe(1); + expect(coder_app?.instances[0].attributes.display_name).toBe("Custom Zed"); + }); + + it("adds agent_name to hostname", async () => { + const state = await runTerraformApply(import.meta.dir, { + agent_id: "foo", + agent_name: "myagent", + }); + expect(state.outputs.zed_url.value).toBe( + "zed://ssh/myagent.default.default.coder", + ); + }); +}); diff --git a/registry/coder/modules/zed/main.tf b/registry/coder/modules/zed/main.tf new file mode 100644 index 000000000..2f6376a44 --- /dev/null +++ b/registry/coder/modules/zed/main.tf @@ -0,0 +1,77 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + coder = { + source = "coder/coder" + version = ">= 2.5" + } + } +} + +variable "agent_id" { + type = string + description = "The ID of a Coder agent" +} + +variable "agent_name" { + type = string + description = "The name of the agent" + default = "" +} + +variable "folder" { + type = string + description = "The folder to open in Zed" + default = "" +} + +variable "order" { + type = number + description = "The order determines the position of app in the UI presentation. The lowest order is shown first and apps with equal order are sorted by name (ascending order)" + default = null +} + +variable "group" { + type = string + description = "The name of a group that this app belongs to" + default = null +} + +variable "slug" { + type = string + description = "The slug of the app" + default = "zed" +} + +variable "display_name" { + type = string + description = "The display name of the app" + default = "Zed" +} + +data "coder_workspace" "me" {} +data "coder_workspace_owner" "me" {} + +locals { + workspace_name = lower(data.coder_workspace.me.name) + owner_name = lower(data.coder_workspace_owner.me.name) + agent_name = lower(var.agent_name) + hostname = var.agent_name != "" ? "${local.agent_name}.${local.workspace_name}.${local.owner_name}.coder" : "${local.workspace_name}.coder" +} + +resource "coder_app" "zed" { + agent_id = var.agent_id + display_name = var.display_name + slug = var.slug + icon = "/icon/zed.svg" + external = true + order = var.order + group = var.group + url = "zed://ssh/${local.hostname}${var.folder}" +} + +output "zed_url" { + value = coder_app.zed.url + description = "Zed URL" +}