diff --git a/Cargo.lock b/Cargo.lock index 75c084d3ef..abf9a12f0e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1097,6 +1097,7 @@ dependencies = [ "ipc-channel", "plist", "serde", + "sysinfo", ] [[package]] diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index f2bab22ea7..98c5ba60ab 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -18,6 +18,7 @@ clap = { version = "3.1", features = ["derive"] } dirs = "3.0" ipc-channel = "0.16" serde = { version = "1.0", features = ["derive", "rc"] } +sysinfo = "0.27" [target.'cfg(target_os = "macos")'.dependencies] core-foundation = "0.9" diff --git a/crates/cli/src/main.rs b/crates/cli/src/main.rs index a31e59587f..8ef1b1fb2b 100644 --- a/crates/cli/src/main.rs +++ b/crates/cli/src/main.rs @@ -14,8 +14,10 @@ use std::{ fs::{self, OpenOptions}, io, path::{Path, PathBuf}, - ptr, + ptr, thread, + time::Duration, }; +use sysinfo::{Pid, System, SystemExt}; #[derive(Parser)] #[clap(name = "zed", global_setting(clap::AppSettings::NoAutoVersion))] @@ -32,6 +34,8 @@ struct Args { /// Custom Zed.app path #[clap(short, long)] bundle_path: Option, + #[clap(short, long)] + restart_from: Option, } #[derive(Debug, Deserialize)] @@ -60,6 +64,13 @@ fn main() -> Result<()> { return Ok(()); } + if let Some(parent_pid) = args.restart_from { + let mut system = System::new(); + while system.refresh_process(parent_pid) { + thread::sleep(Duration::from_millis(100)); + } + } + for path in args.paths.iter() { if !path.exists() { touch(path.as_path())?; diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 8d81ae7f2e..bf4fb11522 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -101,6 +101,7 @@ actions!( NewTerminal, NewSearch, Feedback, + Restart ] ); diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index 77fd516b86..5679bce53a 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -567,6 +567,14 @@ async fn handle_cli_connection( if let Some(request) = requests.next().await { match request { CliRequest::Open { paths, wait } => { + let paths = if paths.is_empty() { + workspace::last_opened_workspace_paths() + .await + .map(|location| location.paths().to_vec()) + .unwrap_or(paths) + } else { + paths + }; let (workspace, items) = cx .update(|cx| workspace::open_paths(&paths, &app_state, cx)) .await; diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index bf9afe136e..d6e8a1a4be 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -23,7 +23,8 @@ use gpui::{ }, impl_actions, platform::{WindowBounds, WindowOptions}, - AssetSource, AsyncAppContext, Platform, PromptLevel, TitlebarOptions, ViewContext, WindowKind, + AssetSource, AsyncAppContext, Platform, PromptLevel, Task, TitlebarOptions, ViewContext, + WindowKind, }; use language::Rope; use lazy_static::lazy_static; @@ -34,11 +35,11 @@ use search::{BufferSearchBar, ProjectSearchBar}; use serde::Deserialize; use serde_json::to_string_pretty; use settings::{keymap_file_json_schema, settings_file_json_schema, Settings}; -use std::{borrow::Cow, env, path::Path, str, sync::Arc}; +use std::{borrow::Cow, env, path::Path, process::Command, str, sync::Arc}; use util::{channel::ReleaseChannel, paths, ResultExt, StaffMode}; use uuid::Uuid; pub use workspace; -use workspace::{sidebar::SidebarSide, AppState, Workspace}; +use workspace::{sidebar::SidebarSide, AppState, Restart, Workspace}; #[derive(Deserialize, Clone, PartialEq)] pub struct OpenBrowser { @@ -129,7 +130,10 @@ pub fn init(app_state: &Arc, cx: &mut gpui::MutableAppContext) { } }, ); - cx.add_global_action(quit); + cx.add_global_action(|_: &Quit, cx| { + quit(cx).detach_and_log_err(cx); + }); + cx.add_global_action(restart); cx.add_global_action(move |action: &OpenBrowser, cx| cx.platform().open_url(&action.url)); cx.add_global_action(move |_: &IncreaseBufferFontSize, cx| { cx.update_global::(|settings, cx| { @@ -403,7 +407,29 @@ pub fn build_window_options( } } -fn quit(_: &Quit, cx: &mut gpui::MutableAppContext) { +fn restart(_: &Restart, cx: &mut gpui::MutableAppContext) { + let cli_process = dbg!(cx.platform().path_for_auxiliary_executable("cli")) + .log_err() + .and_then(|path| { + Command::new(path) + .args(["--restart-from", &format!("{}", dbg!(std::process::id()))]) + .spawn() + .log_err() + }); + + cx.spawn(|mut cx| async move { + let did_quit = dbg!(cx.update(quit).await?); + if !did_quit { + if let Some(mut cli_process) = cli_process { + cli_process.kill().log_err(); + } + } + Ok::<(), anyhow::Error>(()) + }) + .detach_and_log_err(cx); +} + +fn quit(cx: &mut gpui::MutableAppContext) -> Task> { let mut workspaces = cx .window_ids() .filter_map(|window_id| cx.root_view::(window_id)) @@ -426,7 +452,7 @@ fn quit(_: &Quit, cx: &mut gpui::MutableAppContext) { .next() .await; if answer != Some(0) { - return Ok(()); + return Ok(false); } } @@ -438,13 +464,13 @@ fn quit(_: &Quit, cx: &mut gpui::MutableAppContext) { }) .await? { - return Ok(()); + return Ok(false); } } + dbg!("about to quit"); cx.platform().quit(); - anyhow::Ok(()) + anyhow::Ok(true) }) - .detach_and_log_err(cx); } fn about(_: &mut Workspace, _: &About, cx: &mut gpui::ViewContext) {