This PR adds the `cli_default_open_behavior` setting and a first-run TUI prompt that appears when `zed <path>` is invoked without flags while existing windows are open and the setting hasn't been configured yet. ## What it does ### Setting and prompt - Adds a new `cli_default_open_behavior` workspace setting with two values: `existing_window` (default) and `new_window`. - When the user runs `zed <path>` for the first time with existing Zed windows open, a `dialoguer::Select` prompt in the CLI asks them to choose their preferred behavior. The choice is persisted to `settings.json`. - The prompt is skipped when: - An explicit flag (`-n`, `-e`, `-a`) is given - No existing Zed windows are open - The setting is already configured in `settings.json` - The paths being opened are already contained in an existing workspace ### IPC transport abstraction - Introduces a `CliResponseSink` trait in the `cli` crate that abstracts `IpcSender<CliResponse>`, with an implementation for the real IPC sender. - Replaces `IpcSender<CliResponse>` with `Box<dyn CliResponseSink>` / `&dyn CliResponseSink` across all signatures in `open_listener.rs`: `OpenRequestKind::CliConnection`, `handle_cli_connection`, `maybe_prompt_open_behavior`, `open_workspaces`, `open_local_workspace`. - Extracts the inline CLI response loop from `main.rs` into a testable `cli::run_cli_response_loop` function. - Switches the request channel from bounded `mpsc::channel(16)` to `mpsc::unbounded()`, eliminating `smol::block_on` in the bridge thread. ### End-to-end tests Seven new tests exercise both the CLI-side response loop and the Zed-side handler connected through in-memory channels, using `allow_parking()` so the real `cli::run_cli_response_loop` runs on an OS thread while the GPUI executor drives the Zed handler: - No flags, no windows → no prompt, opens new window - No flags, existing windows, user picks "existing window" → prompt, setting persisted - No flags, existing windows, user picks "new window" → prompt, setting persisted - Setting already configured → no prompt - Paths already in existing workspace → no prompt - Explicit `-e` flag → no prompt - Explicit `-n` flag → no prompt Existing tests that previously used `ipc::channel()` now use a `DiscardResponseSink`, removing OS-level IPC from all tests. Release Notes: - Added a first-run prompt when using `zed <path>` to choose between opening in an existing window or a new window. The choice is saved to settings and can be changed later via the `cli_default_open_behavior` setting. --------- Co-authored-by: Nathan Sobo <nathan@zed.dev>
55 lines
1.1 KiB
TOML
55 lines
1.1 KiB
TOML
[package]
|
|
name = "cli"
|
|
version = "0.1.0"
|
|
edition.workspace = true
|
|
publish.workspace = true
|
|
license = "GPL-3.0-or-later"
|
|
|
|
[lints]
|
|
workspace = true
|
|
|
|
[lib]
|
|
path = "src/cli.rs"
|
|
doctest = false
|
|
|
|
[[bin]]
|
|
name = "cli"
|
|
path = "src/main.rs"
|
|
|
|
[features]
|
|
no-bundled-uninstall = []
|
|
default = []
|
|
|
|
[dependencies]
|
|
anyhow.workspace = true
|
|
askpass.workspace = true
|
|
clap.workspace = true
|
|
collections.workspace = true
|
|
console.workspace = true
|
|
dialoguer.workspace = true
|
|
ipc-channel = "0.19"
|
|
parking_lot.workspace = true
|
|
paths.workspace = true
|
|
release_channel.workspace = true
|
|
serde.workspace = true
|
|
util.workspace = true
|
|
tempfile.workspace = true
|
|
rayon.workspace = true
|
|
walkdir = "2.5"
|
|
|
|
[dev-dependencies]
|
|
serde_json.workspace = true
|
|
util = { workspace = true, features = ["test-support"] }
|
|
|
|
[target.'cfg(any(target_os = "linux", target_os = "freebsd"))'.dependencies]
|
|
exec.workspace = true
|
|
fork.workspace = true
|
|
|
|
[target.'cfg(target_os = "macos")'.dependencies]
|
|
core-foundation.workspace = true
|
|
core-services = "0.2"
|
|
plist = "1.3"
|
|
|
|
[target.'cfg(target_os = "windows")'.dependencies]
|
|
windows.workspace = true
|