• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

MitMaro / git-interactive-rebase-tool / 24379379782

14 Apr 2026 03:27AM UTC coverage: 93.969% (-3.6%) from 97.589%
24379379782

Pull #988

github

web-flow
Merge 0e7f07116 into 4d16b296a
Pull Request #988: Bump rand from 0.9.0 to 0.9.4

5531 of 5886 relevant lines covered (93.97%)

6.26 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.55
/src/input/thread.rs
1
mod state;
2

3
use std::{
4
        sync::Arc,
5
        thread::sleep,
6
        time::{Duration, Instant},
7
};
8

9
use captur::capture;
10

11
pub(crate) use self::state::State;
12
use crate::{
13
        input::{Event, EventReaderFn},
14
        runtime::{Installer, Threadable},
15
};
16

17
/// The name of the input thread.
18
pub(crate) const THREAD_NAME: &str = "input";
19
const MINIMUM_PAUSE_RATE: Duration = Duration::from_millis(250);
20

21
/// A thread for reading and handling input events.
22
#[derive(Debug)]
23
pub(crate) struct Thread<EventProvider>
24
where EventProvider: EventReaderFn
25
{
26
        event_provider: Arc<EventProvider>,
27
        state: State,
28
}
29

30
impl<EventProvider> Threadable for Thread<EventProvider>
31
where EventProvider: EventReaderFn
32
{
33
        fn install(&self, installer: &Installer) {
7✔
34
                let state = self.state();
7✔
35
                let event_provider = Arc::clone(&self.event_provider);
14✔
36

37
                installer.spawn(THREAD_NAME, |notifier| {
14✔
38
                        move || {
14✔
39
                                capture!(notifier, state, event_provider);
×
40
                                let mut time = Instant::now();
14✔
41
                                notifier.busy();
7✔
42
                                while !state.is_ended() {
14✔
43
                                        while state.is_paused() {
14✔
44
                                                notifier.wait();
1✔
45
                                                sleep(time.saturating_duration_since(Instant::now()));
1✔
46
                                                time += MINIMUM_PAUSE_RATE;
1✔
47
                                        }
48
                                        notifier.busy();
7✔
49
                                        if let Ok(Some(event)) = (event_provider)() {
13✔
50
                                                state.enqueue_event(Event::from(event));
8✔
51
                                        }
52
                                }
53

54
                                notifier.end();
7✔
55
                                notifier.request_end();
7✔
56
                        }
57
                });
58
        }
59

60
        fn pause(&self) {
1✔
61
                self.state.pause();
1✔
62
        }
63

64
        fn resume(&self) {
1✔
65
                self.state.resume();
1✔
66
        }
67

68
        fn end(&self) {
4✔
69
                self.state.end();
4✔
70
        }
71
}
72

73
impl<EventProvider> Thread<EventProvider>
74
where EventProvider: EventReaderFn
75
{
76
        /// Create a new instance of a thread.
77
        pub(crate) fn new(event_provider: EventProvider) -> Self {
11✔
78
                Self {
79
                        event_provider: Arc::new(event_provider),
11✔
80
                        state: State::new(),
11✔
81
                }
82
        }
83

84
        /// Get a cloned copy of the state of the thread.
85
        #[must_use]
86
        pub(crate) fn state(&self) -> State {
11✔
87
                self.state.clone()
11✔
88
        }
89
}
90

91
#[cfg(test)]
92
mod tests {
93
        use anyhow::anyhow;
94

95
        use super::*;
96
        use crate::{
97
                input::{KeyCode, KeyEvent, KeyModifiers},
98
                runtime::Status,
99
                test_helpers::{create_event_reader, testers},
100
        };
101

102
        #[test]
103
        fn set_pause_resume() {
104
                let event_provider = create_event_reader(|| Ok(None));
105
                let thread: Thread<_> = Thread::new(event_provider);
106
                let state = thread.state();
107
                thread.pause();
108
                assert!(state.is_paused());
109
                thread.resume();
110
                assert!(!state.is_paused());
111
        }
112

113
        #[test]
114
        fn set_end() {
115
                let event_provider = create_event_reader(|| Ok(None));
116
                let thread: Thread<_> = Thread::new(event_provider);
117
                let state = thread.state();
118
                thread.end();
119
                assert!(state.is_ended());
120
        }
121

122
        #[test]
123
        fn read_event_from_event_provider() {
124
                let event_provider = create_event_reader(|| {
125
                        Ok(Some(Event::Key(KeyEvent::new(
126
                                KeyCode::Char('a'),
127
                                KeyModifiers::empty(),
128
                        ))))
129
                });
130
                let thread: Thread<_> = Thread::new(event_provider);
131
                let state = thread.state();
132

133
                let tester = testers::Threadable::new();
134
                tester.start_threadable(&thread, THREAD_NAME);
135

136
                let event_received;
137
                loop {
138
                        let event = state.read_event();
139
                        if event != Event::None {
140
                                event_received = event;
141
                                break;
142
                        }
143
                }
144
                state.end();
145

146
                assert_eq!(event_received, Event::from('a'));
147
        }
148

149
        #[test]
150
        fn read_none_event() {
151
                let event_provider = create_event_reader(|| Ok(None));
152
                let thread: Thread<_> = Thread::new(event_provider);
153
                let state = thread.state();
154

155
                let tester = testers::Threadable::new();
156
                tester.start_threadable(&thread, THREAD_NAME);
157
                tester.wait_for_status(&Status::Busy);
158
                let event_received = state.read_event();
159
                state.end();
160
                tester.wait_for_finished();
161
                assert_eq!(event_received, Event::None);
162
        }
163

164
        #[test]
165
        fn read_error() {
166
                let event_provider = create_event_reader(|| Err(anyhow!("Err")));
167
                let thread: Thread<_> = Thread::new(event_provider);
168
                let state = thread.state();
169

170
                let tester = testers::Threadable::new();
171
                tester.start_threadable(&thread, THREAD_NAME);
172
                tester.wait_for_status(&Status::Busy);
173
                let event_received = state.read_event();
174
                state.end();
175
                tester.wait_for_finished();
176
                assert_eq!(event_received, Event::None);
177
        }
178

179
        #[test]
180
        fn pause_resume() {
181
                let event_provider = create_event_reader(|| Ok(None));
182
                let thread: Thread<_> = Thread::new(event_provider);
183
                let state = thread.state();
184

185
                let tester = testers::Threadable::new();
186
                tester.start_threadable(&thread, THREAD_NAME);
187
                tester.wait_for_status(&Status::Busy);
188
                state.pause();
189
                tester.wait_for_status(&Status::Waiting);
190
                state.resume();
191
                tester.wait_for_status(&Status::Busy);
192
                state.end();
193
                tester.wait_for_finished();
194
        }
195
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc