Unnamed repository; edit this file 'description' to name the repository.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
use helix_view::Editor;

use crate::compositor::Compositor;

use futures_util::future::{self, BoxFuture, Future, FutureExt};
use futures_util::stream::{FuturesUnordered, StreamExt};

pub type Callback = Box<dyn FnOnce(&mut Editor, &mut Compositor) + Send>;
pub type JobFuture = BoxFuture<'static, anyhow::Result<Option<Callback>>>;

pub struct Job {
    pub future: BoxFuture<'static, anyhow::Result<Option<Callback>>>,
    /// Do we need to wait for this job to finish before exiting?
    pub wait: bool,
}

#[derive(Default)]
pub struct Jobs {
    pub futures: FuturesUnordered<JobFuture>,
    /// These are the ones that need to complete before we exit.
    pub wait_futures: FuturesUnordered<JobFuture>,
}

impl Job {
    pub fn new<F: Future<Output = anyhow::Result<()>> + Send + 'static>(f: F) -> Job {
        Job {
            future: f.map(|r| r.map(|()| None)).boxed(),
            wait: false,
        }
    }

    pub fn with_callback<F: Future<Output = anyhow::Result<Callback>> + Send + 'static>(
        f: F,
    ) -> Job {
        Job {
            future: f.map(|r| r.map(Some)).boxed(),
            wait: false,
        }
    }

    pub fn wait_before_exiting(mut self) -> Job {
        self.wait = true;
        self
    }
}

impl Jobs {
    pub fn new() -> Jobs {
        Jobs::default()
    }

    pub fn spawn<F: Future<Output = anyhow::Result<()>> + Send + 'static>(&mut self, f: F) {
        self.add(Job::new(f));
    }

    pub fn callback<F: Future<Output = anyhow::Result<Callback>> + Send + 'static>(
        &mut self,
        f: F,
    ) {
        self.add(Job::with_callback(f));
    }

    pub fn handle_callback(
        &self,
        editor: &mut Editor,
        compositor: &mut Compositor,
        call: anyhow::Result<Option<Callback>>,
    ) {
        match call {
            Ok(None) => {}
            Ok(Some(call)) => {
                call(editor, compositor);
            }
            Err(e) => {
                editor.set_error(format!("Async job failed: {}", e));
            }
        }
    }

    pub async fn next_job(&mut self) -> Option<anyhow::Result<Option<Callback>>> {
        tokio::select! {
            event = self.futures.next() => {  event }
            event = self.wait_futures.next() => { event }
        }
    }

    pub fn add(&self, j: Job) {
        if j.wait {
            self.wait_futures.push(j.future);
        } else {
            self.futures.push(j.future);
        }
    }

    /// Blocks until all the jobs that need to be waited on are done.
    pub fn finish(&mut self) {
        let wait_futures = std::mem::take(&mut self.wait_futures);
        helix_lsp::block_on(wait_futures.for_each(|_| future::ready(())));
    }
}
uot;Got:"); debug_info.push('\n'); let view = buffer_view(&self.buffer); debug_info.push_str(&view); debug_info.push('\n'); debug_info.push_str("Diff:"); debug_info.push('\n'); let nice_diff = diff .iter() .enumerate() .map(|(i, (x, y, cell))| { let expected_cell = expected.get(*x, *y); format!( "{}: at ({}, {}) expected {:?} got {:?}", i, x, y, expected_cell, cell ) }) .collect::<Vec<String>>() .join("\n"); debug_info.push_str(&nice_diff); panic!("{}", debug_info); } } impl Backend for TestBackend { fn draw<'a, I>(&mut self, content: I) -> Result<(), io::Error> where I: Iterator<Item = (u16, u16, &'a Cell)>, { for (x, y, c) in content { self.buffer[(x, y)] = c.clone(); } Ok(()) } fn hide_cursor(&mut self) -> Result<(), io::Error> { self.cursor = false; Ok(()) } fn show_cursor(&mut self, _kind: CursorKind) -> Result<(), io::Error> { self.cursor = true; Ok(()) } fn get_cursor(&mut self) -> Result<(u16, u16), io::Error> { Ok(self.pos) } fn set_cursor(&mut self, x: u16, y: u16) -> Result<(), io::Error> { self.pos = (x, y); Ok(()) } fn clear(&mut self) -> Result<(), io::Error> { self.buffer.reset(); Ok(()) } fn size(&self) -> Result<Rect, io::Error> { Ok(Rect::new(0, 0, self.width, self.height)) } fn flush(&mut self) -> Result<(), io::Error> { Ok(()) } }