Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions crates/cli/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub enum CliRequest {
wsl: Option<String>,
wait: bool,
open_new_workspace: Option<bool>,
reuse: bool,
env: Option<HashMap<String, String>>,
user_data_dir: Option<String>,
},
Expand Down
8 changes: 6 additions & 2 deletions crates/cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,14 @@ struct Args {
#[arg(short, long)]
wait: bool,
/// Add files to the currently open workspace
#[arg(short, long, overrides_with = "new")]
#[arg(short, long, overrides_with_all = ["new", "reuse"])]
add: bool,
/// Create a new workspace
#[arg(short, long, overrides_with = "add")]
#[arg(short, long, overrides_with_all = ["add", "reuse"])]
new: bool,
/// Reuse an existing window, replacing its workspace
#[arg(short, long, overrides_with_all = ["add", "new"])]
reuse: bool,
/// Sets a custom directory for all user data (e.g., database, extensions, logs).
/// This overrides the default platform-specific data directory location.
/// On macOS, the default is `~/Library/Application Support/Zed`.
Expand Down Expand Up @@ -358,6 +361,7 @@ fn main() -> Result<()> {
wsl,
wait: args.wait,
open_new_workspace,
reuse: args.reuse,
env,
user_data_dir: user_data_dir_for_thread,
})?;
Expand Down
113 changes: 112 additions & 1 deletion crates/zed/src/zed/open_listener.rs
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,7 @@ pub async fn handle_cli_connection(
wait,
wsl,
open_new_workspace,
reuse,
env,
user_data_dir: _,
} => {
Expand Down Expand Up @@ -358,6 +359,7 @@ pub async fn handle_cli_connection(
paths,
diff_paths,
open_new_workspace,
reuse,
&responses,
wait,
app_state.clone(),
Expand All @@ -377,6 +379,7 @@ async fn open_workspaces(
paths: Vec<String>,
diff_paths: Vec<[String; 2]>,
open_new_workspace: Option<bool>,
reuse: bool,
responses: &IpcSender<CliResponse>,
wait: bool,
app_state: Arc<AppState>,
Expand Down Expand Up @@ -436,6 +439,7 @@ async fn open_workspaces(
workspace_paths,
diff_paths.clone(),
open_new_workspace,
reuse,
wait,
responses,
env.as_ref(),
Expand Down Expand Up @@ -482,6 +486,7 @@ async fn open_local_workspace(
workspace_paths: Vec<String>,
diff_paths: Vec<[String; 2]>,
open_new_workspace: Option<bool>,
reuse: bool,
wait: bool,
responses: &IpcSender<CliResponse>,
env: Option<&HashMap<String, String>>,
Expand All @@ -492,12 +497,30 @@ async fn open_local_workspace(

let paths_with_position =
derive_paths_with_position(app_state.fs.as_ref(), workspace_paths).await;

// Handle reuse flag by finding existing window to replace
let replace_window = if reuse {
cx.update(|cx| workspace::local_workspace_windows(cx).into_iter().next())
.ok()
.flatten()
} else {
None
};

// For reuse, force new workspace creation but with replace_window set
let effective_open_new_workspace = if reuse {
Some(true)
} else {
open_new_workspace
};

match open_paths_with_positions(
&paths_with_position,
&diff_paths,
app_state.clone(),
workspace::OpenOptions {
open_new_workspace,
open_new_workspace: effective_open_new_workspace,
replace_window,
env: env.cloned(),
..Default::default()
},
Expand Down Expand Up @@ -609,7 +632,9 @@ mod tests {
};
use editor::Editor;
use gpui::TestAppContext;
use language::LineEnding;
use remote::SshConnectionOptions;
use rope::Rope;
use serde_json::json;
use std::sync::Arc;
use util::path;
Expand Down Expand Up @@ -775,6 +800,7 @@ mod tests {
vec![],
open_new_workspace,
false,
false,
&response_tx,
None,
&app_state,
Expand All @@ -786,4 +812,89 @@ mod tests {

assert!(!errored);
}

#[gpui::test]
async fn test_reuse_flag_functionality(cx: &mut TestAppContext) {
let app_state = init_test(cx);
app_state.fs.create_dir(Path::new("/root")).await.unwrap();
app_state
.fs
.create_file(Path::new("/root/file1.txt"), Default::default())
.await
.unwrap();
app_state
.fs
.save(
Path::new("/root/file1.txt"),
&Rope::from("content1"),
LineEnding::Unix,
)
.await
.unwrap();
app_state
.fs
.create_file(Path::new("/root/file2.txt"), Default::default())
.await
.unwrap();
app_state
.fs
.save(
Path::new("/root/file2.txt"),
&Rope::from("content2"),
LineEnding::Unix,
)
.await
.unwrap();

// First, open a workspace normally
let (response_tx, _response_rx) = ipc::channel::<CliResponse>().unwrap();
let workspace_paths = vec!["/root/file1.txt".to_string()];

let _errored = cx
.spawn({
let app_state = app_state.clone();
let response_tx = response_tx.clone();
|mut cx| async move {
open_local_workspace(
workspace_paths,
vec![],
None,
false,
false,
&response_tx,
None,
&app_state,
&mut cx,
)
.await
}
})
.await;

// Now test the reuse functionality - should replace the existing workspace
let workspace_paths_reuse = vec!["/root/file2.txt".to_string()];

let errored_reuse = cx
.spawn({
let app_state = app_state.clone();
let response_tx = response_tx.clone();
|mut cx| async move {
open_local_workspace(
workspace_paths_reuse,
vec![],
None, // open_new_workspace will be overridden by reuse logic
true, // reuse = true
false,
&response_tx,
None,
&app_state,
&mut cx,
)
.await
}
})
.await;

assert!(!errored_reuse);
}
}
1 change: 1 addition & 0 deletions crates/zed/src/zed/windows_only_instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ fn send_args_to_instance(args: &Args) -> anyhow::Result<()> {
wait: false,
wsl: args.wsl.clone(),
open_new_workspace: None,
reuse: false,
env: None,
user_data_dir: args.user_data_dir.clone(),
}
Expand Down