From f849857309ec7c79d3e9f39287c515c6d76c2160 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 18 Mar 2021 17:54:35 -0600 Subject: [PATCH] Handle command line arguments and populate worktree --- Cargo.lock | 10 +++---- gpui/src/app.rs | 31 ++++++++++--------- zed/Cargo.toml | 2 +- zed/src/lib.rs | 6 ++-- zed/src/main.rs | 58 +++++++++++++++++++++++++++++------- zed/src/worktree/worktree.rs | 31 +++++++++++-------- 6 files changed, 93 insertions(+), 45 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5b013463fd..58aff982bf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -435,10 +435,10 @@ dependencies = [ ] [[package]] -name = "crossbeam-queue" -version = "0.3.1" +name = "crossbeam-channel" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f6cb3c7f5b8e51bc3ebb73a2327ad4abdbd119dc13223f14f961d2f38486756" +checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775" dependencies = [ "cfg-if 1.0.0", "crossbeam-utils 0.8.2", @@ -808,7 +808,7 @@ name = "ignore" version = "0.4.11" source = "git+https://github.com/zed-industries/ripgrep?rev=1d152118f35b3e3590216709b86277062d79b8a0#1d152118f35b3e3590216709b86277062d79b8a0" dependencies = [ - "crossbeam-channel", + "crossbeam-channel 0.4.4", "crossbeam-utils 0.7.2", "globset", "lazy_static", @@ -1647,7 +1647,7 @@ version = "0.1.0" dependencies = [ "anyhow", "arrayvec", - "crossbeam-queue", + "crossbeam-channel 0.5.0", "dirs", "easy-parallel", "gpui", diff --git a/gpui/src/app.rs b/gpui/src/app.rs index 798e152e68..d377afc2db 100644 --- a/gpui/src/app.rs +++ b/gpui/src/app.rs @@ -1,7 +1,8 @@ use crate::{ elements::Element, - executor, + executor::{self}, keymap::{self, Keystroke}, + platform::{self, App as _}, util::post_inc, }; use anyhow::{anyhow, Result}; @@ -66,16 +67,22 @@ pub struct App(Rc>); impl App { pub fn test>(f: impl FnOnce(App) -> F) -> T { + let platform = platform::current::app(); // TODO: Make a test platform app let foreground = Rc::new(executor::Foreground::test()); - let app = Self(Rc::new(RefCell::new( - MutableAppContext::with_foreground_executor(foreground.clone()), - ))); + let app = Self(Rc::new(RefCell::new(MutableAppContext::new( + foreground.clone(), + Arc::new(platform), + )))); app.0.borrow_mut().weak_self = Some(Rc::downgrade(&app.0)); smol::block_on(foreground.run(f(app))) } pub fn new() -> Result { - let app = Self(Rc::new(RefCell::new(MutableAppContext::new()?))); + let platform = Arc::new(platform::current::app()); + let foreground = Rc::new(executor::Foreground::platform(platform.dispatcher())?); + let app = Self(Rc::new(RefCell::new(MutableAppContext::new( + foreground, platform, + )))); app.0.borrow_mut().weak_self = Some(Rc::downgrade(&app.0)); Ok(app) } @@ -269,6 +276,7 @@ type ActionCallback = type GlobalActionCallback = dyn FnMut(&dyn Any, &mut MutableAppContext); pub struct MutableAppContext { + platform: Arc, ctx: AppContext, actions: HashMap>>>, global_actions: HashMap>>, @@ -292,14 +300,9 @@ pub struct MutableAppContext { } impl MutableAppContext { - pub fn new() -> Result { - Ok(Self::with_foreground_executor(Rc::new( - executor::Foreground::platform(todo!())?, - ))) - } - - fn with_foreground_executor(foreground: Rc) -> Self { + pub fn new(foreground: Rc, platform: Arc) -> Self { Self { + platform, ctx: AppContext { models: HashMap::new(), windows: HashMap::new(), @@ -1441,8 +1444,8 @@ impl<'a, T: Entity> ModelContext<'a, T> { self.app .background .spawn(async move { - if let Err(_) = tx.send(future.await).await { - log::error!("Error sending background task result to main thread",); + if let Err(e) = tx.send(future.await).await { + log::error!("error sending background task result to main thread: {}", e); } }) .detach(); diff --git a/zed/Cargo.toml b/zed/Cargo.toml index 1dadf4c9ca..553cafd37f 100644 --- a/zed/Cargo.toml +++ b/zed/Cargo.toml @@ -15,7 +15,7 @@ path = "src/main.rs" [dependencies] anyhow = "1.0.38" arrayvec = "0.5.2" -crossbeam-queue = "0.3.1" +crossbeam-channel = "0.5.0" dirs = "3.0" easy-parallel = "3.1.0" gpui = {path = "../gpui"} diff --git a/zed/src/lib.rs b/zed/src/lib.rs index 7cc43687ec..3192f91250 100644 --- a/zed/src/lib.rs +++ b/zed/src/lib.rs @@ -1,6 +1,6 @@ -mod editor; +pub mod editor; mod operation_queue; -mod settings; +pub mod settings; mod sum_tree; #[cfg(test)] mod test; @@ -8,5 +8,5 @@ mod time; mod timer; mod util; mod watch; -mod workspace; +pub mod workspace; mod worktree; diff --git a/zed/src/main.rs b/zed/src/main.rs index 038c5917f8..0884913b48 100644 --- a/zed/src/main.rs +++ b/zed/src/main.rs @@ -3,10 +3,15 @@ use gpui::{ executor, geometry::{rect::RectF, vector::vec2f}, platform::{current as platform, App as _, Runner as _, WindowOptions}, + FontCache, }; use log::LevelFilter; use simplelog::SimpleLogger; use std::{fs, mem, rc::Rc, sync::Arc}; +use zed::{ + editor, settings, + workspace::{self, OpenParams}, +}; fn main() { init_logger(); @@ -18,23 +23,56 @@ fn main() { .expect("could not foreground create executor"), ); + let font_cache = FontCache::new(); + + let (settings_tx, settings_rx) = settings::channel(&font_cache).unwrap(); + + let mut app = gpui::App::new().unwrap(); + platform::runner() .on_finish_launching(move || { log::info!("finish launching"); + + workspace::init(&mut app); + editor::init(&mut app); + if stdout_is_a_pty() { platform.activate(true); } - let window = platform - .open_window( - WindowOptions { - bounds: RectF::new(vec2f(0., 0.), vec2f(1024., 768.)), - title: Some("Zed"), - }, - foreground, - ) - .expect("error opening window"); - mem::forget(window); // Leak window for now so it doesn't close + let paths = std::env::args() + .skip(1) + .filter_map(|arg| match fs::canonicalize(arg) { + Ok(path) => Some(path), + Err(error) => { + log::error!("error parsing path argument: {}", error); + None + } + }) + .collect::>(); + + if !paths.is_empty() { + app.dispatch_global_action( + "workspace:open_paths", + OpenParams { + paths, + settings: settings_rx, + }, + ); + mem::forget(app); // This is here until we hold on to the app for some reason + } + + // let window = platform + // .open_window( + // WindowOptions { + // bounds: RectF::new(vec2f(0., 0.), vec2f(1024., 768.)), + // title: Some("Zed"), + // }, + // foreground, + // ) + // .expect("error opening window"); + + // mem::forget(window); // Leak window for now so it doesn't close }) .run(); } diff --git a/zed/src/worktree/worktree.rs b/zed/src/worktree/worktree.rs index 8454e78c18..f22603da87 100644 --- a/zed/src/worktree/worktree.rs +++ b/zed/src/worktree/worktree.rs @@ -5,7 +5,7 @@ use super::{ }; use crate::{editor::History, timer, util::post_inc}; use anyhow::{anyhow, Result}; -use crossbeam_queue::SegQueue; +use crossbeam_channel as channel; use easy_parallel::Parallel; use gpui::{AppContext, Entity, ModelContext, ModelHandle}; use ignore::dir::{Ignore, IgnoreBuilder}; @@ -39,7 +39,7 @@ struct DirToScan { path: PathBuf, relative_path: PathBuf, ignore: Option, - dirs_to_scan: Arc>>, + dirs_to_scan: channel::Sender>, } impl Worktree { @@ -61,10 +61,14 @@ impl Worktree { let tree = tree.clone(); let (tx, rx) = smol::channel::bounded(1); - std::thread::spawn(move || { - let _ = smol::block_on(tx.send(tree.scan_dirs())); - }); - let _ = ctx.spawn(async move { rx.recv().await.unwrap() }, Self::done_scanning); + + ctx.background_executor() + .spawn(async move { + tx.send(tree.scan_dirs()).await.unwrap(); + }) + .detach(); + + let _ = ctx.spawn_local(async move { rx.recv().await.unwrap() }, Self::done_scanning); let _ = ctx.spawn_stream_local( timer::repeat(Duration::from_millis(100)).map(|_| ()), @@ -95,19 +99,22 @@ impl Worktree { if metadata.file_type().is_dir() { let is_ignored = is_ignored || name == ".git"; let id = self.push_dir(None, name, ino, is_symlink, is_ignored); - let queue = Arc::new(SegQueue::new()); + let (tx, rx) = channel::unbounded(); - queue.push(Ok(DirToScan { + let tx_ = tx.clone(); + tx.send(Ok(DirToScan { id, path, relative_path, ignore: Some(ignore), - dirs_to_scan: queue.clone(), - })); + dirs_to_scan: tx_, + })) + .unwrap(); + drop(tx); Parallel::>::new() .each(0..16, |_| { - while let Some(result) = queue.pop() { + while let Ok(result) = rx.recv() { self.scan_dir(result?)?; } Ok(()) @@ -150,7 +157,7 @@ impl Worktree { new_children.push(id); let dirs_to_scan = to_scan.dirs_to_scan.clone(); - let _ = to_scan.dirs_to_scan.push(Ok(DirToScan { + let _ = to_scan.dirs_to_scan.send(Ok(DirToScan { id, path, relative_path,