WIP
This commit is contained in:
parent
aa3fb28f81
commit
7bb99c9b9c
3 changed files with 109 additions and 12 deletions
|
@ -1,9 +1,10 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
AnyWindowHandle, AppContext, Context, Handle, ModelContext, Result, ViewContext, WindowContext,
|
AnyWindowHandle, AppContext, Context, Handle, ModelContext, Result, Task, ViewContext,
|
||||||
|
WindowContext,
|
||||||
};
|
};
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use std::sync::Weak;
|
use std::{future::Future, sync::Weak};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct AsyncAppContext(pub(crate) Weak<Mutex<AppContext>>);
|
pub struct AsyncAppContext(pub(crate) Weak<Mutex<AppContext>>);
|
||||||
|
@ -99,6 +100,22 @@ impl AsyncAppContext {
|
||||||
let mut app_context = app.lock();
|
let mut app_context = app.lock();
|
||||||
app_context.update_window(handle.id, update)
|
app_context.update_window(handle.id, update)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn spawn<Fut, R>(
|
||||||
|
&self,
|
||||||
|
f: impl FnOnce(AsyncAppContext) -> Fut + Send + 'static,
|
||||||
|
) -> Result<Task<R>>
|
||||||
|
where
|
||||||
|
Fut: Future<Output = R> + Send + 'static,
|
||||||
|
R: Send + 'static,
|
||||||
|
{
|
||||||
|
let app = self
|
||||||
|
.0
|
||||||
|
.upgrade()
|
||||||
|
.ok_or_else(|| anyhow!("app was released"))?;
|
||||||
|
let app_context = app.lock();
|
||||||
|
Ok(app_context.spawn(f))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
use crate::{AppContext, PlatformDispatcher};
|
use crate::{AppContext, PlatformDispatcher};
|
||||||
|
use futures::channel::mpsc;
|
||||||
use smol::prelude::*;
|
use smol::prelude::*;
|
||||||
use std::{
|
use std::{
|
||||||
fmt::Debug,
|
fmt::Debug,
|
||||||
|
marker::PhantomData,
|
||||||
|
mem,
|
||||||
pin::Pin,
|
pin::Pin,
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
task::{Context, Poll},
|
task::{Context, Poll},
|
||||||
|
@ -133,7 +136,73 @@ impl Executor {
|
||||||
futures::executor::block_on(future)
|
futures::executor::block_on(future)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn scoped<'scope, F>(&self, scheduler: F)
|
||||||
|
where
|
||||||
|
F: FnOnce(&mut Scope<'scope>),
|
||||||
|
{
|
||||||
|
let mut scope = Scope::new(self.clone());
|
||||||
|
(scheduler)(&mut scope);
|
||||||
|
let spawned = mem::take(&mut scope.futures)
|
||||||
|
.into_iter()
|
||||||
|
.map(|f| self.spawn(f))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
for task in spawned {
|
||||||
|
task.await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_main_thread(&self) -> bool {
|
pub fn is_main_thread(&self) -> bool {
|
||||||
self.dispatcher.is_main_thread()
|
self.dispatcher.is_main_thread()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct Scope<'a> {
|
||||||
|
executor: Executor,
|
||||||
|
futures: Vec<Pin<Box<dyn Future<Output = ()> + Send + 'static>>>,
|
||||||
|
tx: Option<mpsc::Sender<()>>,
|
||||||
|
rx: mpsc::Receiver<()>,
|
||||||
|
lifetime: PhantomData<&'a ()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Scope<'a> {
|
||||||
|
fn new(executor: Executor) -> Self {
|
||||||
|
let (tx, rx) = mpsc::channel(1);
|
||||||
|
Self {
|
||||||
|
executor,
|
||||||
|
tx: Some(tx),
|
||||||
|
rx,
|
||||||
|
futures: Default::default(),
|
||||||
|
lifetime: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn spawn<F>(&mut self, f: F)
|
||||||
|
where
|
||||||
|
F: Future<Output = ()> + Send + 'a,
|
||||||
|
{
|
||||||
|
let tx = self.tx.clone().unwrap();
|
||||||
|
|
||||||
|
// Safety: The 'a lifetime is guaranteed to outlive any of these futures because
|
||||||
|
// dropping this `Scope` blocks until all of the futures have resolved.
|
||||||
|
let f = unsafe {
|
||||||
|
mem::transmute::<
|
||||||
|
Pin<Box<dyn Future<Output = ()> + Send + 'a>>,
|
||||||
|
Pin<Box<dyn Future<Output = ()> + Send + 'static>>,
|
||||||
|
>(Box::pin(async move {
|
||||||
|
f.await;
|
||||||
|
drop(tx);
|
||||||
|
}))
|
||||||
|
};
|
||||||
|
self.futures.push(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Drop for Scope<'a> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
self.tx.take().unwrap();
|
||||||
|
|
||||||
|
// Wait until the channel is closed, which means that all of the spawned
|
||||||
|
// futures have resolved.
|
||||||
|
self.executor.block(self.rx.next());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ use cli::{
|
||||||
};
|
};
|
||||||
use fs::RealFs;
|
use fs::RealFs;
|
||||||
use futures::{channel::mpsc, SinkExt, StreamExt};
|
use futures::{channel::mpsc, SinkExt, StreamExt};
|
||||||
use gpui2::{App, AsyncAppContext, Task};
|
use gpui2::{App, AssetSource, AsyncAppContext, Task};
|
||||||
use log::LevelFilter;
|
use log::LevelFilter;
|
||||||
|
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
|
@ -29,7 +29,10 @@ use std::{
|
||||||
},
|
},
|
||||||
thread,
|
thread,
|
||||||
};
|
};
|
||||||
use util::{channel::RELEASE_CHANNEL, http, paths, ResultExt};
|
use util::{
|
||||||
|
channel::{parse_zed_link, RELEASE_CHANNEL},
|
||||||
|
http, paths, ResultExt,
|
||||||
|
};
|
||||||
use zed2::{ensure_only_instance, AppState, Assets, IsOnlyInstance};
|
use zed2::{ensure_only_instance, AppState, Assets, IsOnlyInstance};
|
||||||
// use zed2::{
|
// use zed2::{
|
||||||
// assets::Assets,
|
// assets::Assets,
|
||||||
|
@ -59,8 +62,8 @@ fn main() {
|
||||||
|
|
||||||
let fs = Arc::new(RealFs);
|
let fs = Arc::new(RealFs);
|
||||||
let user_settings_file_rx =
|
let user_settings_file_rx =
|
||||||
watch_config_file(app.executor(), fs.clone(), paths::SETTINGS.clone());
|
watch_config_file(&app.executor(), fs.clone(), paths::SETTINGS.clone());
|
||||||
let user_keymap_file_rx = watch_config_file(app.executor(), fs.clone(), paths::KEYMAP.clone());
|
let user_keymap_file_rx = watch_config_file(&app.executor(), fs.clone(), paths::KEYMAP.clone());
|
||||||
|
|
||||||
let login_shell_env_loaded = if stdout_is_a_pty() {
|
let login_shell_env_loaded = if stdout_is_a_pty() {
|
||||||
Task::ready(())
|
Task::ready(())
|
||||||
|
@ -194,7 +197,7 @@ fn main() {
|
||||||
listener.open_urls(urls)
|
listener.open_urls(urls)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
upload_previous_panics(http.clone(), cx);
|
// upload_previous_panics(http.clone(), cx);
|
||||||
|
|
||||||
// TODO Development mode that forces the CLI mode usually runs Zed binary as is instead
|
// TODO Development mode that forces the CLI mode usually runs Zed binary as is instead
|
||||||
// of an *app, hence gets no specific callbacks run. Emulate them here, if needed.
|
// of an *app, hence gets no specific callbacks run. Emulate them here, if needed.
|
||||||
|
@ -248,8 +251,15 @@ fn main() {
|
||||||
// .detach();
|
// .detach();
|
||||||
}
|
}
|
||||||
OpenRequest::CliConnection { connection } => {
|
OpenRequest::CliConnection { connection } => {
|
||||||
cx.spawn(|cx| handle_cli_connection(connection, app_state.clone(), cx))
|
if cx
|
||||||
.detach();
|
.spawn(|cx| {
|
||||||
|
handle_cli_connection(connection, app_state.clone(), cx)
|
||||||
|
})
|
||||||
|
.map(Task::detach)
|
||||||
|
.is_err()
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
OpenRequest::JoinChannel { channel_id } => {
|
OpenRequest::JoinChannel { channel_id } => {
|
||||||
// cx
|
// cx
|
||||||
|
@ -626,9 +636,10 @@ fn collect_url_args() -> Vec<String> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_embedded_fonts(app: &App) {
|
fn load_embedded_fonts(app: &App) {
|
||||||
let font_paths = Assets.list("fonts");
|
let font_paths = Assets.list(&"fonts".into()).unwrap();
|
||||||
let embedded_fonts = Mutex::new(Vec::new());
|
let embedded_fonts = Mutex::new(Vec::new());
|
||||||
smol::block_on(app.background().scoped(|scope| {
|
let executor = app.executor();
|
||||||
|
executor.block(executor.scoped(|scope| {
|
||||||
for font_path in &font_paths {
|
for font_path in &font_paths {
|
||||||
if !font_path.ends_with(".ttf") {
|
if !font_path.ends_with(".ttf") {
|
||||||
continue;
|
continue;
|
||||||
|
@ -755,7 +766,7 @@ async fn handle_cli_connection(
|
||||||
if let Some(request) = requests.next().await {
|
if let Some(request) = requests.next().await {
|
||||||
match request {
|
match request {
|
||||||
CliRequest::Open { paths, wait } => {
|
CliRequest::Open { paths, wait } => {
|
||||||
let mut caret_positions = HashMap::new();
|
// let mut caret_positions = HashMap::new();
|
||||||
|
|
||||||
// todo!("workspace")
|
// todo!("workspace")
|
||||||
// let paths = if paths.is_empty() {
|
// let paths = if paths.is_empty() {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue