Added workspace restart command

Mikayla Maki created

Change summary

Cargo.lock                        |  1 
crates/cli/Cargo.toml             |  1 
crates/cli/src/main.rs            | 13 +++++++++
crates/workspace/src/workspace.rs |  1 
crates/zed/src/main.rs            |  8 ++++++
crates/zed/src/zed.rs             | 44 ++++++++++++++++++++++++++------
6 files changed, 58 insertions(+), 10 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -1097,6 +1097,7 @@ dependencies = [
  "ipc-channel",
  "plist",
  "serde",
+ "sysinfo",
 ]
 
 [[package]]

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"

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<PathBuf>,
+    #[clap(short, long)]
+    restart_from: Option<Pid>,
 }
 
 #[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())?;

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;

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<AppState>, 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, _, _>(|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<Result<bool>> {
     let mut workspaces = cx
         .window_ids()
         .filter_map(|window_id| cx.root_view::<Workspace>(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<Workspace>) {