use std::path::PathBuf; use anyhow::Result; use collections::HashMap; pub use ipc_channel::ipc; use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize)] pub struct IpcHandshake { pub requests: ipc::IpcSender, pub responses: ipc::IpcReceiver, } /// Controls how CLI paths are opened — whether to reuse existing windows, /// create new ones, or add to the sidebar. #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)] #[serde(rename_all = "snake_case")] pub enum OpenBehavior { /// Consult the user's `cli_default_open_behavior` setting to choose between /// `ExistingWindow` or `Classic`. #[default] Default, /// Always create a new window. No matching against existing worktrees. /// Corresponds to `zed -n`. AlwaysNew, /// Match broadly including subdirectories, and fall back to any existing /// window if no worktree matched. Corresponds to `zed -a`. Add, /// Open directories as a new workspace in the current Zed window's sidebar. /// Reuse existing windows for files in open worktrees. /// Corresponds to `zed -e`. ExistingWindow, /// New window for directories, reuse existing window for files in open /// worktrees. The classic pre-sidebar behavior. /// Corresponds to `zed --classic`. Classic, /// Replace the content of an existing window with a new workspace. /// Corresponds to `zed -r`. Reuse, } /// The setting-level enum for configuring default behavior. This only has /// two values because the other modes are always explicitly requested via /// CLI flags. #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum CliBehaviorSetting { /// Open directories as a new workspace in the current Zed window's sidebar. ExistingWindow, /// Classic behavior: open directories in a new window, but reuse an /// existing window when opening files that are already part of an open /// project. NewWindow, } #[derive(Debug, Serialize, Deserialize)] pub enum CliRequest { Open { paths: Vec, urls: Vec, diff_paths: Vec<[String; 2]>, diff_all: bool, wsl: Option, wait: bool, #[serde(default)] open_behavior: OpenBehavior, env: Option>, user_data_dir: Option, dev_container: bool, #[serde(default)] cwd: Option, }, SetOpenBehavior { behavior: CliBehaviorSetting, }, } #[derive(Debug, Serialize, Deserialize)] pub enum CliResponse { Ping, Stdout { message: String }, Stderr { message: String }, Exit { status: i32 }, PromptOpenBehavior, } /// When Zed started not as an *.app but as a binary (e.g. local development), /// there's a possibility to tell it to behave "regularly". /// /// Note that in the main zed binary, this variable is unset after it's read for the first time, /// therefore it should always be accessed through the `FORCE_CLI_MODE` static. pub const FORCE_CLI_MODE_ENV_VAR_NAME: &str = "ZED_FORCE_CLI_MODE"; /// Abstracts the transport for sending CLI responses (Zed → CLI). /// /// Production code uses `IpcSender`. Tests can provide in-memory /// implementations to avoid OS-level IPC. pub trait CliResponseSink: Send + 'static { fn send(&self, response: CliResponse) -> Result<()>; } impl CliResponseSink for ipc::IpcSender { fn send(&self, response: CliResponse) -> Result<()> { ipc::IpcSender::send(self, response).map_err(|error| anyhow::anyhow!("{error}")) } }