1
1
mirror of https://github.com/wez/wezterm.git synced 2024-11-22 22:42:48 +03:00

migrate some more code to the newer spawn mechanism

This commit is contained in:
Wez Furlong 2020-01-16 09:15:07 -08:00
parent 75eb16bec4
commit 9ec4694d89
10 changed files with 159 additions and 83 deletions

95
Cargo.lock generated
View File

@ -131,6 +131,31 @@ version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8"
[[package]]
name = "async-std"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0bf6039b315300e057d198b9d3ab92ee029e31c759b7f1afae538145e6f18a3e"
dependencies = [
"async-task",
"crossbeam-channel 0.4.0",
"crossbeam-deque",
"crossbeam-utils 0.7.0",
"futures-core",
"futures-io",
"futures-timer",
"kv-log-macro",
"log",
"memchr",
"mio",
"mio-uds",
"num_cpus",
"once_cell",
"pin-project-lite",
"pin-utils",
"slab",
]
[[package]]
name = "async-task"
version = "1.2.1"
@ -500,6 +525,15 @@ dependencies = [
"crossbeam-utils 0.6.6",
]
[[package]]
name = "crossbeam-channel"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acec9a3b0b3559f15aee4f90746c4e5e293b701c0f7d3925d24e01645267b68c"
dependencies = [
"crossbeam-utils 0.7.0",
]
[[package]]
name = "crossbeam-deque"
version = "0.7.2"
@ -977,6 +1011,24 @@ version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
[[package]]
name = "futures-core"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79564c427afefab1dfb3298535b21eda083ef7935b4f0ecbfcb121f0aec10866"
[[package]]
name = "futures-io"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e676577d229e70952ab25f3945795ba5b16d63ca794ca9d2c860e5595d20b5ff"
[[package]]
name = "futures-timer"
version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1de7508b218029b0f01662ed8f61b1c964b3ae99d6f25462d0f55a595109df6"
[[package]]
name = "getrandom"
version = "0.1.14"
@ -1073,7 +1125,7 @@ checksum = "08d331ebcdbca4acbefe5da8c3299b2e246f198a8294cc5163354e743398b89d"
dependencies = [
"base64",
"byteorder",
"crossbeam-channel",
"crossbeam-channel 0.3.9",
"flate2",
"nom 4.2.3",
"num-traits 0.2.11",
@ -1232,6 +1284,15 @@ version = "3.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc"
[[package]]
name = "kv-log-macro"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c54d9f465d530a752e6ebdc217e081a7a614b48cb200f6f0aee21ba6bc9aabb"
dependencies = [
"log",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
@ -1504,6 +1565,17 @@ dependencies = [
"slab",
]
[[package]]
name = "mio-uds"
version = "0.6.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125"
dependencies = [
"iovec",
"libc",
"mio",
]
[[package]]
name = "miow"
version = "0.2.1"
@ -1755,6 +1827,12 @@ dependencies = [
"objc",
]
[[package]]
name = "once_cell"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f5941ec2d5ee5916c709580d71553b81a633df245bcc73c04dcbd62152ceefc4"
[[package]]
name = "open"
version = "1.3.2"
@ -1919,6 +1997,18 @@ dependencies = [
"siphasher",
]
[[package]]
name = "pin-project-lite"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8822eb8bb72452f038ebf6048efa02c3fe22bf83f76519c9583e47fc194a422"
[[package]]
name = "pin-utils"
version = "0.1.0-alpha.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587"
[[package]]
name = "pkg-config"
version = "0.3.17"
@ -2020,6 +2110,7 @@ name = "promise"
version = "0.2.0"
dependencies = [
"anyhow",
"async-std",
"async-task",
"lazy_static",
"thiserror",
@ -3153,7 +3244,7 @@ dependencies = [
"core-foundation 0.7.0",
"core-graphics 0.19.0",
"core-text 15.0.0",
"crossbeam-channel",
"crossbeam-channel 0.3.9",
"daemonize",
"dirs 1.0.5",
"downcast-rs",

View File

@ -6,6 +6,7 @@ edition = "2018"
[dependencies]
async-task = "1.2"
async-std = "1.4"
anyhow = "1.0"
thiserror = "1.0"
lazy_static = "1.3"

View File

@ -148,3 +148,6 @@ where
task.schedule();
handle
}
/// Block the current thread until the passed future completes.
pub use async_std::task::block_on;

View File

@ -5,10 +5,10 @@ use super::utilsprites::RenderMetrics;
use crate::config::{configuration, ConfigHandle};
use crate::font::units::*;
use crate::font::FontConfiguration;
use crate::frontend::front_end;
use crate::frontend::gui::scrollbar::*;
use crate::frontend::gui::selection::*;
use crate::frontend::gui::tabbar::{TabBarItem, TabBarState};
use crate::frontend::{executor, front_end};
use crate::keyassignment::{KeyAssignment, KeyMap, SpawnTabDomain};
use crate::mux::renderable::{Renderable, RenderableDimensions, StableCursorPosition};
use crate::mux::tab::{Tab, TabId};
@ -178,12 +178,11 @@ impl<'a> term::TerminalHost for Host<'a> {
// of our window loop; on Windows it can cause a panic due to
// triggering our WndProc recursively.
let link = link.clone();
promise::Future::with_executor(executor(), move || {
promise::spawn::spawn(async move {
log::error!("clicking {}", link.uri());
if let Err(err) = open::that(link.uri()) {
log::error!("failed to open {}: {:?}", link.uri(), err);
}
Ok(())
});
}
}
@ -1161,13 +1160,10 @@ impl TermWindow {
let future = self.window.as_ref().unwrap().get_clipboard();
promise::spawn::spawn(async move {
if let Ok(clip) = future.await {
promise::Future::with_executor(executor(), move || {
let mux = Mux::get().unwrap();
if let Some(tab) = mux.get_tab(tab_id) {
tab.trickle_paste(clip)?;
}
Ok(())
});
let mux = Mux::get().unwrap();
if let Some(tab) = mux.get_tab(tab_id) {
tab.trickle_paste(clip).ok();
}
}
});
}
@ -1202,7 +1198,7 @@ impl TermWindow {
}
pub fn spawn_new_window(&mut self) {
promise::Future::with_executor(executor(), move || {
async fn new_window() -> anyhow::Result<()> {
let mux = Mux::get().unwrap();
let fonts = Rc::new(FontConfiguration::new());
let window_id = mux.new_empty_window();
@ -1212,6 +1208,9 @@ impl TermWindow {
let front_end = front_end().expect("to be called on gui thread");
front_end.spawn_new_window(&fonts, &tab, window_id)?;
Ok(())
}
promise::spawn::spawn(async move {
new_window().await.ok();
});
}
@ -2536,12 +2535,11 @@ impl TermWindow {
// of our window loop; on Windows it can cause a panic due to
// triggering our WndProc recursively.
let link = self.current_highlight.as_ref().unwrap().clone();
promise::Future::with_executor(executor(), move || {
promise::spawn::spawn(async move {
log::error!("clicking {}", link.uri());
if let Err(err) = open::that(link.uri()) {
log::error!("failed to open {}: {:?}", link.uri(), err);
}
Ok(())
});
} else {
self.window.as_ref().unwrap().set_clipboard(text);
@ -2656,13 +2654,10 @@ impl TermWindow {
let future = self.window.as_ref().unwrap().get_clipboard();
promise::spawn::spawn(async move {
if let Ok(clip) = future.await {
promise::Future::with_executor(executor(), move || {
let mux = Mux::get().unwrap();
if let Some(tab) = mux.get_tab(tab_id) {
tab.trickle_paste(clip)?;
}
Ok(())
});
let mux = Mux::get().unwrap();
if let Some(tab) = mux.get_tab(tab_id) {
tab.trickle_paste(clip).ok();
}
}
});
return;

View File

@ -44,14 +44,6 @@ pub fn executor() -> Box<dyn Executor> {
}
}
pub fn low_pri_executor() -> Box<dyn Executor> {
let locked = LOW_PRI_EXECUTOR.lock().unwrap();
match locked.as_ref() {
Some(exec) => exec.clone_executor(),
None => panic!("executor machinery not yet configured"),
}
}
pub fn front_end() -> Option<Rc<dyn FrontEnd>> {
let mut res = None;
FRONT_END.with(|f| {

View File

@ -1,4 +1,3 @@
use crate::frontend::{executor, low_pri_executor};
use crate::mux::tab::{Tab, TabId};
use crate::mux::window::{Window, WindowId};
use crate::ratelim::RateLimiter;
@ -7,7 +6,6 @@ use anyhow::{anyhow, Error};
use domain::{Domain, DomainId};
use log::{debug, error};
use portable_pty::ExitStatus;
use promise::Future;
use std::cell::{Ref, RefCell, RefMut};
use std::collections::HashMap;
use std::io::Read;
@ -68,7 +66,7 @@ fn read_from_tab_pty(tab_id: TabId, mut reader: Box<dyn std::io::Read>) {
let len = len as usize;
let data = buf[pos..pos + len].to_vec();
pos += len;
Future::with_executor(low_pri_executor(), move || {
promise::spawn::spawn_into_main_thread_with_low_priority(async move {
let mux = Mux::get().unwrap();
if let Some(tab) = mux.get_tab(tab_id) {
tab.advance_bytes(
@ -79,7 +77,6 @@ fn read_from_tab_pty(tab_id: TabId, mut reader: Box<dyn std::io::Read>) {
);
mux.notify(MuxNotification::TabOutput(tab_id));
}
Ok(())
});
}
Err(delay) => {
@ -91,10 +88,9 @@ fn read_from_tab_pty(tab_id: TabId, mut reader: Box<dyn std::io::Read>) {
}
}
}
Future::with_executor(executor(), move || {
promise::spawn::spawn_into_main_thread(async move {
let mux = Mux::get().unwrap();
mux.remove_tab(tab_id);
Ok(())
});
}

View File

@ -1,4 +1,3 @@
use crate::frontend::executor;
use crate::mux::domain::DomainId;
use crate::mux::renderable::Renderable;
use crate::mux::Mux;
@ -27,7 +26,7 @@ struct Paste {
fn schedule_next_paste(paste: &Arc<Mutex<Paste>>) {
let paste = Arc::clone(paste);
promise::Future::with_executor(executor(), move || {
promise::spawn::spawn(async move {
let mut locked = paste.lock().unwrap();
let mux = Mux::get().unwrap();
let tab = mux.get_tab(locked.tab_id).unwrap();
@ -42,8 +41,6 @@ fn schedule_next_paste(paste: &Arc<Mutex<Paste>>) {
locked.offset += chunk;
schedule_next_paste(&paste);
}
Ok(())
});
}

View File

@ -56,7 +56,7 @@ fn password_prompt(
(output, unicode_column_width(placeholder) * cursor_position)
}
}
match termwiztermtab::run(60, 10, move |mut term| {
match promise::spawn::block_on(termwiztermtab::run(60, 10, move |mut term| {
term.render(&[
// Change::Attribute(AttributeChange::Intensity(Intensity::Bold)),
Change::Title(title.to_string()),
@ -73,9 +73,7 @@ fn password_prompt(
} else {
bail!("prompt cancelled");
}
})
.wait()
{
})) {
Ok(p) => Some(p),
Err(p) => {
log::error!("failed to prompt for pw: {}", p);
@ -95,7 +93,7 @@ fn input_prompt(
"SSH Authentication for {} @ {}\r\n{}\r\n{}\r\n",
username, remote_address, instructions, prompt
);
match termwiztermtab::run(60, 10, move |mut term| {
match promise::spawn::block_on(termwiztermtab::run(60, 10, move |mut term| {
term.render(&[
Change::Title(title.to_string()),
Change::Text(text.to_string()),
@ -110,9 +108,7 @@ fn input_prompt(
} else {
bail!("prompt cancelled");
}
})
.wait()
{
})) {
Ok(p) => Some(p),
Err(p) => {
log::error!("failed to prompt for pw: {}", p);
@ -229,27 +225,27 @@ pub fn ssh_connect(remote_address: &str, username: &str) -> anyhow::Result<ssh2:
remote_address, key_type, fingerprint
);
let allow = termwiztermtab::run(80, 10, move |mut term| {
let title = "🔐 wezterm: SSH authentication".to_string();
term.render(&[Change::Title(title), Change::Text(message.to_string())])?;
let allow =
promise::spawn::block_on(termwiztermtab::run(80, 10, move |mut term| {
let title = "🔐 wezterm: SSH authentication".to_string();
term.render(&[Change::Title(title), Change::Text(message.to_string())])?;
let mut editor = LineEditor::new(term);
editor.set_prompt("Enter [Y/n]> ");
let mut editor = LineEditor::new(term);
editor.set_prompt("Enter [Y/n]> ");
let mut host = NopLineEditorHost::default();
loop {
let line = match editor.read_line(&mut host) {
Ok(Some(line)) => line,
Ok(None) | Err(_) => return Ok(false),
};
match line.as_ref() {
"y" | "Y" | "yes" | "YES" => return Ok(true),
"n" | "N" | "no" | "NO" => return Ok(false),
_ => continue,
let mut host = NopLineEditorHost::default();
loop {
let line = match editor.read_line(&mut host) {
Ok(Some(line)) => line,
Ok(None) | Err(_) => return Ok(false),
};
match line.as_ref() {
"y" | "Y" | "yes" | "YES" => return Ok(true),
"n" | "N" | "no" | "NO" => return Ok(false),
_ => continue,
}
}
}
})
.wait()?;
}))?;
if !allow {
bail!("user declined to trust host");

View File

@ -5,7 +5,7 @@
use crate::config::configuration;
use crate::font::FontConfiguration;
use crate::frontend::{executor, front_end};
use crate::frontend::{front_end};
use crate::mux::domain::{alloc_domain_id, Domain, DomainId, DomainState};
use crate::mux::renderable::{Renderable, RenderableDimensions, StableCursorPosition};
use crate::mux::tab::{alloc_tab_id, Tab, TabId};
@ -15,7 +15,6 @@ use anyhow::{bail, Error};
use crossbeam_channel::{unbounded as channel, Receiver, Sender};
use filedescriptor::Pipe;
use portable_pty::*;
use promise::{Future, Promise};
use rangeset::RangeSet;
use std::cell::RefCell;
use std::cell::RefMut;
@ -375,11 +374,14 @@ impl termwiz::terminal::Terminal for TermWizTerminal {
/// from the terminal window.
/// When it completes its loop it will fulfil a promise and yield
/// the return value from the function.
pub fn run<T: Send + 'static, F: Send + 'static + Fn(TermWizTerminal) -> anyhow::Result<T>>(
pub async fn run<
T: Send + 'static,
F: Send + 'static + Fn(TermWizTerminal) -> anyhow::Result<T>,
>(
width: usize,
height: usize,
f: F,
) -> Future<T> {
) -> anyhow::Result<T> {
let (render_tx, render_rx) = channel();
let (input_tx, input_rx) = channel();
@ -394,10 +396,12 @@ pub fn run<T: Send + 'static, F: Send + 'static + Fn(TermWizTerminal) -> anyhow:
},
};
let mut promise = Promise::new();
let future = promise.get_future().expect("just made the promise");
Future::with_executor(executor(), move || {
async fn register_tab(
input_tx: Sender<InputEvent>,
render_rx: Receiver<Vec<Change>>,
width: usize,
height: usize,
) -> anyhow::Result<()> {
let mux = Mux::get().unwrap();
// TODO: make a singleton
@ -426,20 +430,22 @@ pub fn run<T: Send + 'static, F: Send + 'static + Fn(TermWizTerminal) -> anyhow:
gui.spawn_new_window(&fontconfig, &tab, window_id)?;
Ok(())
}
promise::spawn::spawn_into_main_thread(async move {
register_tab(input_tx, render_rx, width, height).await.ok();
});
std::thread::spawn(move || {
promise.result(f(tw_term));
});
future
promise::spawn::spawn_into_new_thread(move || f(tw_term))
.await
.unwrap_or_else(|| bail!("task panicked or was cancelled"))
}
pub fn message_box_ok(message: &str) {
let title = "wezterm";
let message = message.to_string();
run(60, 10, move |mut term| {
promise::spawn::block_on(run(60, 10, move |mut term| {
term.render(&[
Change::Title(title.to_string()),
Change::Text(message.to_string()),
@ -452,7 +458,6 @@ pub fn message_box_ok(message: &str) {
let mut host = NopLineEditorHost::default();
editor.read_line(&mut host).ok();
Ok(())
})
.wait()
}))
.ok();
}

View File

@ -488,7 +488,7 @@ impl Display for ITermFileData {
fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
write!(f, "File")?;
let mut sep = "=";
let emit_sep = |sep, f: &mut Formatter| {
let emit_sep = |sep, f: &mut Formatter| -> Result<&str, FmtError> {
write!(f, "{}", sep)?;
Ok(";")
};