1use crate::buffer::Buffer;
2use crate::core::CoreBuffer;
3use crate::draw;
4use crate::mode::{Mode, Normal, Transition, TransitionReturn};
5use futures::future::{FutureExt, LocalBoxFuture};
6
7pub struct BufferMode<'a, B: CoreBuffer> {
8 pub buf: Buffer<'a, B>,
9 mode: Box<dyn Mode<B>>,
10 is_recording: bool,
11 dot_macro: Vec<termion::event::Event>,
12 recording_macro: Vec<termion::event::Event>,
13}
14
15pub enum TabOperation {
16 Nothing,
17 Close,
18 NewTab,
19 ChangeTab(usize),
20 StartRmate,
21}
22
23impl<'a, B: CoreBuffer> BufferMode<'a, B> {
24 pub fn new(buf: Buffer<'a, B>) -> Self {
25 Self {
26 buf,
27 mode: Box::new(Normal::default()),
28 is_recording: false,
29 dot_macro: Vec::new(),
30 recording_macro: Vec::new(),
31 }
32 }
33
34 pub fn event(&mut self, event: termion::event::Event) -> LocalBoxFuture<'_, TabOperation> {
35 async move {
36 if self.is_recording {
37 self.recording_macro.push(event.clone());
38 }
39 match self.mode.event(&mut self.buf, event.clone()).await {
40 Transition::Exit => {
41 return TabOperation::Close;
42 }
43 Transition::Trans(mut t) => {
44 t.init(&mut self.buf);
45 self.mode = t;
46 }
47 Transition::DoMacro => {
48 for event in self.dot_macro.clone() {
49 self.event(event).await;
50 }
51 }
52 Transition::Return(TransitionReturn {
53 message,
54 is_commit_dot_macro,
55 }) => {
56 if self.is_recording && !self.recording_macro.is_empty() && is_commit_dot_macro
57 {
58 std::mem::swap(&mut self.dot_macro, &mut self.recording_macro);
59 self.recording_macro.clear();
60 }
61 self.is_recording = false;
62 let mut t = if let Some(s) = message {
63 Box::new(Normal::with_message(s))
64 } else {
65 Box::new(Normal::default())
66 };
67 t.init(&mut self.buf);
68 self.mode = t;
69 }
70 Transition::RecordMacro(mut t) => {
71 self.is_recording = true;
72 self.recording_macro.clear();
73 self.recording_macro.push(event);
74 t.init(&mut self.buf);
75 self.mode = t;
76 }
77 Transition::CreateNewTab => {
78 self.mode = Box::new(Normal::default());
79 return TabOperation::NewTab;
80 }
81 Transition::ChangeTab(i) => {
82 self.mode = Box::new(Normal::default());
83 return TabOperation::ChangeTab(i);
84 }
85 Transition::StartRmate => {
86 self.mode = Box::new(Normal::default());
87 return TabOperation::StartRmate;
88 }
89 Transition::Nothing => {}
90 }
91 TabOperation::Nothing
92 }
93 .boxed_local()
94 }
95
96 pub fn draw(&mut self, view: draw::TermView) -> draw::CursorState {
97 self.mode.draw(&mut self.buf, view)
98 }
99
100 pub fn background_task_duration(&mut self, duration: std::time::Duration) {
102 self.buf.extend_cache_duration(duration);
103 }
104}