on 2158366 help sign in
100 lines 2.7 kB history raw
1use helix_view::Editor;
3use crate::compositor::Compositor;
5use futures_util::future::{self, BoxFuture, Future, FutureExt};
6use futures_util::stream::{FuturesUnordered, StreamExt};
8pub type Callback = Box<dyn FnOnce(&mut Editor, &mut Compositor) + Send>;
9pub type JobFuture = BoxFuture<'static, anyhow::Result<Option<Callback>>>;
11pub struct Job {
12 pub future: BoxFuture<'static, anyhow::Result<Option<Callback>>>,
13 /// Do we need to wait for this job to finish before exiting?
14 pub wait: bool,
17#[derive(Default)]
18pub struct Jobs {
19 pub futures: FuturesUnordered<JobFuture>,
20 /// These are the ones that need to complete before we exit.
21 pub wait_futures: FuturesUnordered<JobFuture>,
24impl Job {
25 pub fn new<F: Future<Output = anyhow::Result<()>> + Send + 'static>(f: F) -> Job {
26 Job {
27 future: f.map(|r| r.map(|()| None)).boxed(),
28 wait: false,
29 }
30 }
32 pub fn with_callback<F: Future<Output = anyhow::Result<Callback>> + Send + 'static>(
33 f: F,
34 ) -> Job {
35 Job {
36 future: f.map(|r| r.map(Some)).boxed(),
37 wait: false,
38 }
39 }
41 pub fn wait_before_exiting(mut self) -> Job {
42 self.wait = true;
43 self
44 }
47impl Jobs {
48 pub fn new() -> Jobs {
49 Jobs::default()
50 }
52 pub fn spawn<F: Future<Output = anyhow::Result<()>> + Send + 'static>(&mut self, f: F) {
53 self.add(Job::new(f));
54 }
56 pub fn callback<F: Future<Output = anyhow::Result<Callback>> + Send + 'static>(
57 &mut self,
58 f: F,
59 ) {
60 self.add(Job::with_callback(f));
61 }
63 pub fn handle_callback(
64 &mut self,
65 editor: &mut Editor,
66 compositor: &mut Compositor,
67 call: anyhow::Result<Option<Callback>>,
68 ) {
69 match call {
70 Ok(None) => {}
71 Ok(Some(call)) => {
72 call(editor, compositor);
73 }
74 Err(e) => {
75 editor.set_error(format!("Async job failed: {}", e));
76 }
77 }
78 }
80 pub async fn next_job(&mut self) -> Option<anyhow::Result<Option<Callback>>> {
81 tokio::select! {
82 event = self.futures.next() => { event }
83 event = self.wait_futures.next() => { event }
84 }
85 }
87 pub fn add(&mut self, j: Job) {
88 if j.wait {
89 self.wait_futures.push(j.future);
90 } else {
91 self.futures.push(j.future);
92 }
93 }
95 /// Blocks until all the jobs that need to be waited on are done.
96 pub fn finish(&mut self) {
97 let wait_futures = std::mem::take(&mut self.wait_futures);
98 helix_lsp::block_on(wait_futures.for_each(|_| future::ready(())));
99 }