Handle command line arguments and populate worktree

This commit is contained in:
Nathan Sobo 2021-03-18 17:54:35 -06:00
parent 9bab29c72f
commit f849857309
6 changed files with 93 additions and 45 deletions

10
Cargo.lock generated
View file

@ -435,10 +435,10 @@ dependencies = [
] ]
[[package]] [[package]]
name = "crossbeam-queue" name = "crossbeam-channel"
version = "0.3.1" version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f6cb3c7f5b8e51bc3ebb73a2327ad4abdbd119dc13223f14f961d2f38486756" checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
"crossbeam-utils 0.8.2", "crossbeam-utils 0.8.2",
@ -808,7 +808,7 @@ name = "ignore"
version = "0.4.11" version = "0.4.11"
source = "git+https://github.com/zed-industries/ripgrep?rev=1d152118f35b3e3590216709b86277062d79b8a0#1d152118f35b3e3590216709b86277062d79b8a0" source = "git+https://github.com/zed-industries/ripgrep?rev=1d152118f35b3e3590216709b86277062d79b8a0#1d152118f35b3e3590216709b86277062d79b8a0"
dependencies = [ dependencies = [
"crossbeam-channel", "crossbeam-channel 0.4.4",
"crossbeam-utils 0.7.2", "crossbeam-utils 0.7.2",
"globset", "globset",
"lazy_static", "lazy_static",
@ -1647,7 +1647,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"arrayvec", "arrayvec",
"crossbeam-queue", "crossbeam-channel 0.5.0",
"dirs", "dirs",
"easy-parallel", "easy-parallel",
"gpui", "gpui",

View file

@ -1,7 +1,8 @@
use crate::{ use crate::{
elements::Element, elements::Element,
executor, executor::{self},
keymap::{self, Keystroke}, keymap::{self, Keystroke},
platform::{self, App as _},
util::post_inc, util::post_inc,
}; };
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
@ -66,16 +67,22 @@ pub struct App(Rc<RefCell<MutableAppContext>>);
impl App { impl App {
pub fn test<T, F: Future<Output = T>>(f: impl FnOnce(App) -> F) -> T { pub fn test<T, F: Future<Output = T>>(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 foreground = Rc::new(executor::Foreground::test());
let app = Self(Rc::new(RefCell::new( let app = Self(Rc::new(RefCell::new(MutableAppContext::new(
MutableAppContext::with_foreground_executor(foreground.clone()), foreground.clone(),
))); Arc::new(platform),
))));
app.0.borrow_mut().weak_self = Some(Rc::downgrade(&app.0)); app.0.borrow_mut().weak_self = Some(Rc::downgrade(&app.0));
smol::block_on(foreground.run(f(app))) smol::block_on(foreground.run(f(app)))
} }
pub fn new() -> Result<Self> { pub fn new() -> Result<Self> {
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)); app.0.borrow_mut().weak_self = Some(Rc::downgrade(&app.0));
Ok(app) Ok(app)
} }
@ -269,6 +276,7 @@ type ActionCallback =
type GlobalActionCallback = dyn FnMut(&dyn Any, &mut MutableAppContext); type GlobalActionCallback = dyn FnMut(&dyn Any, &mut MutableAppContext);
pub struct MutableAppContext { pub struct MutableAppContext {
platform: Arc<dyn platform::App>,
ctx: AppContext, ctx: AppContext,
actions: HashMap<TypeId, HashMap<String, Vec<Box<ActionCallback>>>>, actions: HashMap<TypeId, HashMap<String, Vec<Box<ActionCallback>>>>,
global_actions: HashMap<String, Vec<Box<GlobalActionCallback>>>, global_actions: HashMap<String, Vec<Box<GlobalActionCallback>>>,
@ -292,14 +300,9 @@ pub struct MutableAppContext {
} }
impl MutableAppContext { impl MutableAppContext {
pub fn new() -> Result<Self> { pub fn new(foreground: Rc<executor::Foreground>, platform: Arc<dyn platform::App>) -> Self {
Ok(Self::with_foreground_executor(Rc::new(
executor::Foreground::platform(todo!())?,
)))
}
fn with_foreground_executor(foreground: Rc<executor::Foreground>) -> Self {
Self { Self {
platform,
ctx: AppContext { ctx: AppContext {
models: HashMap::new(), models: HashMap::new(),
windows: HashMap::new(), windows: HashMap::new(),
@ -1441,8 +1444,8 @@ impl<'a, T: Entity> ModelContext<'a, T> {
self.app self.app
.background .background
.spawn(async move { .spawn(async move {
if let Err(_) = tx.send(future.await).await { if let Err(e) = tx.send(future.await).await {
log::error!("Error sending background task result to main thread",); log::error!("error sending background task result to main thread: {}", e);
} }
}) })
.detach(); .detach();

View file

@ -15,7 +15,7 @@ path = "src/main.rs"
[dependencies] [dependencies]
anyhow = "1.0.38" anyhow = "1.0.38"
arrayvec = "0.5.2" arrayvec = "0.5.2"
crossbeam-queue = "0.3.1" crossbeam-channel = "0.5.0"
dirs = "3.0" dirs = "3.0"
easy-parallel = "3.1.0" easy-parallel = "3.1.0"
gpui = {path = "../gpui"} gpui = {path = "../gpui"}

View file

@ -1,6 +1,6 @@
mod editor; pub mod editor;
mod operation_queue; mod operation_queue;
mod settings; pub mod settings;
mod sum_tree; mod sum_tree;
#[cfg(test)] #[cfg(test)]
mod test; mod test;
@ -8,5 +8,5 @@ mod time;
mod timer; mod timer;
mod util; mod util;
mod watch; mod watch;
mod workspace; pub mod workspace;
mod worktree; mod worktree;

View file

@ -3,10 +3,15 @@ use gpui::{
executor, executor,
geometry::{rect::RectF, vector::vec2f}, geometry::{rect::RectF, vector::vec2f},
platform::{current as platform, App as _, Runner as _, WindowOptions}, platform::{current as platform, App as _, Runner as _, WindowOptions},
FontCache,
}; };
use log::LevelFilter; use log::LevelFilter;
use simplelog::SimpleLogger; use simplelog::SimpleLogger;
use std::{fs, mem, rc::Rc, sync::Arc}; use std::{fs, mem, rc::Rc, sync::Arc};
use zed::{
editor, settings,
workspace::{self, OpenParams},
};
fn main() { fn main() {
init_logger(); init_logger();
@ -18,23 +23,56 @@ fn main() {
.expect("could not foreground create executor"), .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() platform::runner()
.on_finish_launching(move || { .on_finish_launching(move || {
log::info!("finish launching"); log::info!("finish launching");
workspace::init(&mut app);
editor::init(&mut app);
if stdout_is_a_pty() { if stdout_is_a_pty() {
platform.activate(true); 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::<Vec<_>>();
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(); .run();
} }

View file

@ -5,7 +5,7 @@ use super::{
}; };
use crate::{editor::History, timer, util::post_inc}; use crate::{editor::History, timer, util::post_inc};
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use crossbeam_queue::SegQueue; use crossbeam_channel as channel;
use easy_parallel::Parallel; use easy_parallel::Parallel;
use gpui::{AppContext, Entity, ModelContext, ModelHandle}; use gpui::{AppContext, Entity, ModelContext, ModelHandle};
use ignore::dir::{Ignore, IgnoreBuilder}; use ignore::dir::{Ignore, IgnoreBuilder};
@ -39,7 +39,7 @@ struct DirToScan {
path: PathBuf, path: PathBuf,
relative_path: PathBuf, relative_path: PathBuf,
ignore: Option<Ignore>, ignore: Option<Ignore>,
dirs_to_scan: Arc<SegQueue<io::Result<DirToScan>>>, dirs_to_scan: channel::Sender<io::Result<DirToScan>>,
} }
impl Worktree { impl Worktree {
@ -61,10 +61,14 @@ impl Worktree {
let tree = tree.clone(); let tree = tree.clone();
let (tx, rx) = smol::channel::bounded(1); let (tx, rx) = smol::channel::bounded(1);
std::thread::spawn(move || {
let _ = smol::block_on(tx.send(tree.scan_dirs())); ctx.background_executor()
}); .spawn(async move {
let _ = ctx.spawn(async move { rx.recv().await.unwrap() }, Self::done_scanning); 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( let _ = ctx.spawn_stream_local(
timer::repeat(Duration::from_millis(100)).map(|_| ()), timer::repeat(Duration::from_millis(100)).map(|_| ()),
@ -95,19 +99,22 @@ impl Worktree {
if metadata.file_type().is_dir() { if metadata.file_type().is_dir() {
let is_ignored = is_ignored || name == ".git"; let is_ignored = is_ignored || name == ".git";
let id = self.push_dir(None, name, ino, is_symlink, is_ignored); 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, id,
path, path,
relative_path, relative_path,
ignore: Some(ignore), ignore: Some(ignore),
dirs_to_scan: queue.clone(), dirs_to_scan: tx_,
})); }))
.unwrap();
drop(tx);
Parallel::<io::Result<()>>::new() Parallel::<io::Result<()>>::new()
.each(0..16, |_| { .each(0..16, |_| {
while let Some(result) = queue.pop() { while let Ok(result) = rx.recv() {
self.scan_dir(result?)?; self.scan_dir(result?)?;
} }
Ok(()) Ok(())
@ -150,7 +157,7 @@ impl Worktree {
new_children.push(id); new_children.push(id);
let dirs_to_scan = to_scan.dirs_to_scan.clone(); 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, id,
path, path,
relative_path, relative_path,