From 315e45f543cfe0b88ca784688f7948a864ef149f Mon Sep 17 00:00:00 2001 From: Owen Law <81528246+someone13574@users.noreply.github.com> Date: Mon, 20 May 2024 21:33:19 -0400 Subject: [PATCH] Match the startup behavior of the CLI to the main app (#12044) Currently the main binary will open an empty file if no previous workspaces exist or, if it is the first startup, show the welcome page. When starting via the CLI it will simply drop you in an empty workspace: no empty file and no welcome page. This changes the CLI startup to match the behavior of the non-CLI startup, so they will both create an empty file or show the welcome page if no path was given and no workspaces were opened in the past. Release Notes: - Matched startup behavior of the CLI to the behavior of the main app. --- crates/zed/src/zed/open_listener.rs | 163 +++++++++++++++------------- 1 file changed, 90 insertions(+), 73 deletions(-) diff --git a/crates/zed/src/zed/open_listener.rs b/crates/zed/src/zed/open_listener.rs index 9e8e9afe1de6a170b3546f9f86611e23076c614d..eda7b6f2ecbbfbf1fd1992bb9ae86cfd83335ae5 100644 --- a/crates/zed/src/zed/open_listener.rs +++ b/crates/zed/src/zed/open_listener.rs @@ -3,6 +3,7 @@ use cli::{ipc, IpcHandshake}; use cli::{ipc::IpcSender, CliRequest, CliResponse}; use client::parse_zed_link; use collections::HashMap; +use db::kvp::KEY_VALUE_STORE; use editor::scroll::Autoscroll; use editor::Editor; use futures::channel::mpsc::{UnboundedReceiver, UnboundedSender}; @@ -17,6 +18,7 @@ use std::time::Duration; use std::{process, thread}; use util::paths::PathLikeWithPosition; use util::ResultExt; +use welcome::{show_welcome_view, FIRST_OPEN}; use workspace::item::ItemHandle; use workspace::{AppState, Workspace}; @@ -313,90 +315,105 @@ pub async fn handle_cli_connection( let mut errored = false; - match open_paths_with_positions( - &paths, - app_state, - workspace::OpenOptions { - open_new_workspace, - ..Default::default() - }, - &mut cx, - ) - .await - { - Ok((workspace, items)) => { - let mut item_release_futures = Vec::new(); - - for (item, path) in items.into_iter().zip(&paths) { - match item { - Some(Ok(item)) => { - cx.update(|cx| { - let released = oneshot::channel(); - item.on_release( - cx, - Box::new(move |_| { - let _ = released.0.send(()); - }), - ) - .detach(); - item_release_futures.push(released.1); - }) - .log_err(); - } - Some(Err(err)) => { - responses - .send(CliResponse::Stderr { - message: format!("error opening {:?}: {}", path, err), + if !paths.is_empty() { + match open_paths_with_positions( + &paths, + app_state, + workspace::OpenOptions { + open_new_workspace, + ..Default::default() + }, + &mut cx, + ) + .await + { + Ok((workspace, items)) => { + let mut item_release_futures = Vec::new(); + + for (item, path) in items.into_iter().zip(&paths) { + match item { + Some(Ok(item)) => { + cx.update(|cx| { + let released = oneshot::channel(); + item.on_release( + cx, + Box::new(move |_| { + let _ = released.0.send(()); + }), + ) + .detach(); + item_release_futures.push(released.1); }) .log_err(); - errored = true; + } + Some(Err(err)) => { + responses + .send(CliResponse::Stderr { + message: format!( + "error opening {:?}: {}", + path, err + ), + }) + .log_err(); + errored = true; + } + None => {} } - None => {} } - } - if wait { - let background = cx.background_executor().clone(); - let wait = async move { - if paths.is_empty() { - let (done_tx, done_rx) = oneshot::channel(); - let _subscription = workspace.update(&mut cx, |_, cx| { - cx.on_release(move |_, _, _| { - let _ = done_tx.send(()); - }) - }); - let _ = done_rx.await; - } else { - let _ = - futures::future::try_join_all(item_release_futures).await; - }; - } - .fuse(); - futures::pin_mut!(wait); - - loop { - // Repeatedly check if CLI is still open to avoid wasting resources - // waiting for files or workspaces to close. - let mut timer = background.timer(Duration::from_secs(1)).fuse(); - futures::select_biased! { - _ = wait => break, - _ = timer => { - if responses.send(CliResponse::Ping).is_err() { - break; + if wait { + let background = cx.background_executor().clone(); + let wait = async move { + if paths.is_empty() { + let (done_tx, done_rx) = oneshot::channel(); + let _subscription = workspace.update(&mut cx, |_, cx| { + cx.on_release(move |_, _, _| { + let _ = done_tx.send(()); + }) + }); + let _ = done_rx.await; + } else { + let _ = futures::future::try_join_all(item_release_futures) + .await; + }; + } + .fuse(); + futures::pin_mut!(wait); + + loop { + // Repeatedly check if CLI is still open to avoid wasting resources + // waiting for files or workspaces to close. + let mut timer = background.timer(Duration::from_secs(1)).fuse(); + futures::select_biased! { + _ = wait => break, + _ = timer => { + if responses.send(CliResponse::Ping).is_err() { + break; + } } } } } } + Err(error) => { + errored = true; + responses + .send(CliResponse::Stderr { + message: format!("error opening {:?}: {}", paths, error), + }) + .log_err(); + } } - Err(error) => { - errored = true; - responses - .send(CliResponse::Stderr { - message: format!("error opening {:?}: {}", paths, error), - }) - .log_err(); - } + } else if matches!(KEY_VALUE_STORE.read_kvp(FIRST_OPEN), Ok(None)) { + cx.update(|cx| show_welcome_view(app_state, cx)).log_err(); + } else { + cx.update(|cx| { + workspace::open_new(app_state, cx, |workspace, cx| { + Editor::new_file(workspace, &Default::default(), cx) + }) + .detach(); + }) + .log_err(); } responses