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.
This commit is contained in:
Owen Law 2024-05-20 21:33:19 -04:00 committed by GitHub
parent 1e18bcb949
commit 315e45f543
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -3,6 +3,7 @@ use cli::{ipc, IpcHandshake};
use cli::{ipc::IpcSender, CliRequest, CliResponse}; use cli::{ipc::IpcSender, CliRequest, CliResponse};
use client::parse_zed_link; use client::parse_zed_link;
use collections::HashMap; use collections::HashMap;
use db::kvp::KEY_VALUE_STORE;
use editor::scroll::Autoscroll; use editor::scroll::Autoscroll;
use editor::Editor; use editor::Editor;
use futures::channel::mpsc::{UnboundedReceiver, UnboundedSender}; use futures::channel::mpsc::{UnboundedReceiver, UnboundedSender};
@ -17,6 +18,7 @@ use std::time::Duration;
use std::{process, thread}; use std::{process, thread};
use util::paths::PathLikeWithPosition; use util::paths::PathLikeWithPosition;
use util::ResultExt; use util::ResultExt;
use welcome::{show_welcome_view, FIRST_OPEN};
use workspace::item::ItemHandle; use workspace::item::ItemHandle;
use workspace::{AppState, Workspace}; use workspace::{AppState, Workspace};
@ -313,90 +315,105 @@ pub async fn handle_cli_connection(
let mut errored = false; let mut errored = false;
match open_paths_with_positions( if !paths.is_empty() {
&paths, match open_paths_with_positions(
app_state, &paths,
workspace::OpenOptions { app_state,
open_new_workspace, workspace::OpenOptions {
..Default::default() open_new_workspace,
}, ..Default::default()
&mut cx, },
) &mut cx,
.await )
{ .await
Ok((workspace, items)) => { {
let mut item_release_futures = Vec::new(); Ok((workspace, items)) => {
let mut item_release_futures = Vec::new();
for (item, path) in items.into_iter().zip(&paths) { for (item, path) in items.into_iter().zip(&paths) {
match item { match item {
Some(Ok(item)) => { Some(Ok(item)) => {
cx.update(|cx| { cx.update(|cx| {
let released = oneshot::channel(); let released = oneshot::channel();
item.on_release( item.on_release(
cx, cx,
Box::new(move |_| { Box::new(move |_| {
let _ = released.0.send(()); let _ = released.0.send(());
}), }),
) )
.detach(); .detach();
item_release_futures.push(released.1); item_release_futures.push(released.1);
})
.log_err();
}
Some(Err(err)) => {
responses
.send(CliResponse::Stderr {
message: format!("error opening {:?}: {}", path, err),
}) })
.log_err(); .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 { if wait {
let background = cx.background_executor().clone(); let background = cx.background_executor().clone();
let wait = async move { let wait = async move {
if paths.is_empty() { if paths.is_empty() {
let (done_tx, done_rx) = oneshot::channel(); let (done_tx, done_rx) = oneshot::channel();
let _subscription = workspace.update(&mut cx, |_, cx| { let _subscription = workspace.update(&mut cx, |_, cx| {
cx.on_release(move |_, _, _| { cx.on_release(move |_, _, _| {
let _ = done_tx.send(()); let _ = done_tx.send(());
}) })
}); });
let _ = done_rx.await; let _ = done_rx.await;
} else { } else {
let _ = let _ = futures::future::try_join_all(item_release_futures)
futures::future::try_join_all(item_release_futures).await; .await;
}; };
} }
.fuse(); .fuse();
futures::pin_mut!(wait); futures::pin_mut!(wait);
loop { loop {
// Repeatedly check if CLI is still open to avoid wasting resources // Repeatedly check if CLI is still open to avoid wasting resources
// waiting for files or workspaces to close. // waiting for files or workspaces to close.
let mut timer = background.timer(Duration::from_secs(1)).fuse(); let mut timer = background.timer(Duration::from_secs(1)).fuse();
futures::select_biased! { futures::select_biased! {
_ = wait => break, _ = wait => break,
_ = timer => { _ = timer => {
if responses.send(CliResponse::Ping).is_err() { if responses.send(CliResponse::Ping).is_err() {
break; break;
}
} }
} }
} }
} }
} }
Err(error) => {
errored = true;
responses
.send(CliResponse::Stderr {
message: format!("error opening {:?}: {}", paths, error),
})
.log_err();
}
} }
Err(error) => { } else if matches!(KEY_VALUE_STORE.read_kvp(FIRST_OPEN), Ok(None)) {
errored = true; cx.update(|cx| show_welcome_view(app_state, cx)).log_err();
responses } else {
.send(CliResponse::Stderr { cx.update(|cx| {
message: format!("error opening {:?}: {}", paths, error), workspace::open_new(app_state, cx, |workspace, cx| {
}) Editor::new_file(workspace, &Default::default(), cx)
.log_err(); })
} .detach();
})
.log_err();
} }
responses responses