1use std::{collections::VecDeque, time::Duration};
4
5use crate::{Event, RecordError, RecordInput, TerminalKind};
6
7pub fn make_binary_description(hash: &str, num_bytes: u64) -> String {
9 format!("{hash} ({num_bytes} bytes)")
10}
11
12pub struct CrosstermInput;
17
18impl RecordInput for CrosstermInput {
19 fn terminal_kind(&self) -> TerminalKind {
20 TerminalKind::Crossterm
21 }
22
23 fn next_events(&mut self) -> Result<Vec<Event>, RecordError> {
24 let first_event =
26 crossterm::event::read().map_err(|err| RecordError::ReadInput(err.into()))?;
27 let mut events = vec![first_event.into()];
28 while crossterm::event::poll(Duration::ZERO)
32 .map_err(|err| RecordError::ReadInput(err.into()))?
33 {
34 let event =
35 crossterm::event::read().map_err(|err| RecordError::ReadInput(err.into()))?;
36 events.push(event.into());
37 }
38 Ok(events)
39 }
40
41 fn edit_commit_message(&mut self, message: &str) -> Result<String, RecordError> {
42 Ok(message.to_owned())
43 }
44}
45
46pub struct TestingInput {
48 pub width: usize,
50
51 pub height: usize,
53
54 pub events: Box<dyn Iterator<Item = Event>>,
56
57 pub commit_messages: VecDeque<String>,
59}
60
61impl TestingInput {
62 pub fn new(
64 width: usize,
65 height: usize,
66 events: impl IntoIterator<Item = Event> + 'static,
67 ) -> Self {
68 Self {
69 width,
70 height,
71 events: Box::new(events.into_iter()),
72 commit_messages: Default::default(),
73 }
74 }
75}
76
77impl RecordInput for TestingInput {
78 fn terminal_kind(&self) -> TerminalKind {
79 let Self {
80 width,
81 height,
82 events: _,
83 commit_messages: _,
84 } = self;
85 TerminalKind::Testing {
86 width: *width,
87 height: *height,
88 }
89 }
90
91 fn next_events(&mut self) -> Result<Vec<Event>, RecordError> {
92 Ok(vec![self.events.next().unwrap_or(Event::None)])
93 }
94
95 fn edit_commit_message(&mut self, _message: &str) -> Result<String, RecordError> {
96 self.commit_messages
97 .pop_front()
98 .ok_or_else(|| RecordError::Other("No more commit messages available".to_string()))
99 }
100}