reovim_module_bufferline/
commands.rs1use {
4 reovim_driver_command::{Command, CommandHandler, CommandResult},
5 reovim_driver_command_types::CommandContext,
6 reovim_driver_session::{BufferApi, ExtensionApi, SessionRuntime},
7 reovim_kernel::api::v1::CommandId,
8};
9
10use crate::{ids, state::BufferlineState};
11
12#[derive(Debug, Clone, Copy, Default)]
18pub struct PinBuffer;
19
20impl Command for PinBuffer {
21 fn id(&self) -> CommandId {
22 ids::PIN_BUFFER
23 }
24
25 fn description(&self) -> &'static str {
26 "Toggle pin for active buffer"
27 }
28}
29
30impl CommandHandler for PinBuffer {
31 #[cfg_attr(coverage_nightly, coverage(off))]
32 fn execute(&self, runtime: &mut SessionRuntime<'_>, _args: &CommandContext) -> CommandResult {
33 let Some(buf_id) = runtime.active_buffer() else {
34 return CommandResult::Success;
35 };
36 let id = buf_id.as_usize() as u64;
37
38 let Some(state) = runtime.shared_ext_mut::<BufferlineState>() else {
39 return CommandResult::Success;
40 };
41
42 if state.is_pinned(id) {
43 state.unpin(id);
44 } else {
45 state.pin(id);
46 }
47
48 CommandResult::Success
49 }
50}
51
52#[derive(Debug, Clone, Copy, Default)]
58pub struct UnpinBuffer;
59
60impl Command for UnpinBuffer {
61 fn id(&self) -> CommandId {
62 ids::UNPIN_BUFFER
63 }
64
65 fn description(&self) -> &'static str {
66 "Unpin active buffer"
67 }
68}
69
70impl CommandHandler for UnpinBuffer {
71 #[cfg_attr(coverage_nightly, coverage(off))]
72 fn execute(&self, runtime: &mut SessionRuntime<'_>, _args: &CommandContext) -> CommandResult {
73 let Some(buf_id) = runtime.active_buffer() else {
74 return CommandResult::Success;
75 };
76 let id = buf_id.as_usize() as u64;
77
78 if let Some(state) = runtime.shared_ext_mut::<BufferlineState>() {
79 state.unpin(id);
80 }
81
82 CommandResult::Success
83 }
84}
85
86#[derive(Debug, Clone, Copy, Default)]
92pub struct CloseBuffer;
93
94impl Command for CloseBuffer {
95 fn id(&self) -> CommandId {
96 ids::CLOSE_BUFFER
97 }
98
99 fn description(&self) -> &'static str {
100 "Close active buffer"
101 }
102}
103
104impl CommandHandler for CloseBuffer {
105 #[cfg_attr(coverage_nightly, coverage(off))]
106 fn execute(&self, runtime: &mut SessionRuntime<'_>, _args: &CommandContext) -> CommandResult {
107 let Some(buf_id) = runtime.active_buffer() else {
108 return CommandResult::Success;
109 };
110 let id = buf_id.as_usize() as u64;
111
112 if let Some(state) = runtime.shared_ext_mut::<BufferlineState>() {
114 state.unpin(id);
115 }
116
117 let _ = runtime.kernel().buffers.unregister(buf_id);
119
120 CommandResult::Success
121 }
122}
123
124#[derive(Debug, Clone, Copy, Default)]
130pub struct NextBuffer;
131
132impl Command for NextBuffer {
133 fn id(&self) -> CommandId {
134 ids::NEXT_BUFFER
135 }
136
137 fn description(&self) -> &'static str {
138 "Switch to next buffer"
139 }
140}
141
142impl CommandHandler for NextBuffer {
143 #[cfg_attr(coverage_nightly, coverage(off))]
144 fn execute(&self, runtime: &mut SessionRuntime<'_>, _args: &CommandContext) -> CommandResult {
145 cycle_buffer(runtime, &Direction::Next)
146 }
147}
148
149#[derive(Debug, Clone, Copy, Default)]
155pub struct PrevBuffer;
156
157impl Command for PrevBuffer {
158 fn id(&self) -> CommandId {
159 ids::PREV_BUFFER
160 }
161
162 fn description(&self) -> &'static str {
163 "Switch to previous buffer"
164 }
165}
166
167impl CommandHandler for PrevBuffer {
168 #[cfg_attr(coverage_nightly, coverage(off))]
169 fn execute(&self, runtime: &mut SessionRuntime<'_>, _args: &CommandContext) -> CommandResult {
170 cycle_buffer(runtime, &Direction::Prev)
171 }
172}
173
174enum Direction {
179 Next,
180 Prev,
181}
182
183#[cfg_attr(coverage_nightly, coverage(off))]
184fn cycle_buffer(runtime: &mut SessionRuntime<'_>, direction: &Direction) -> CommandResult {
185 let Some(current) = runtime.active_buffer() else {
186 return CommandResult::Success;
187 };
188
189 let mut buf_ids = runtime.kernel().buffers.list();
190 if buf_ids.len() < 2 {
191 return CommandResult::Success;
192 }
193 buf_ids.sort_unstable();
194
195 let current_idx = buf_ids.iter().position(|&id| id == current).unwrap_or(0);
196
197 let next_idx = match direction {
198 Direction::Next => (current_idx + 1) % buf_ids.len(),
199 Direction::Prev => {
200 if current_idx == 0 {
201 buf_ids.len() - 1
202 } else {
203 current_idx - 1
204 }
205 }
206 };
207
208 runtime.set_active_buffer(Some(buf_ids[next_idx]));
209 CommandResult::Success
210}
211
212#[must_use]
218pub fn command_handlers() -> Vec<Box<dyn CommandHandler>> {
219 vec![
220 Box::new(PinBuffer),
221 Box::new(UnpinBuffer),
222 Box::new(CloseBuffer),
223 Box::new(NextBuffer),
224 Box::new(PrevBuffer),
225 ]
226}
227
228#[cfg(test)]
229#[path = "commands_tests.rs"]
230mod tests;