reovim_module_vim/visual/
manipulation.rs1use {
11 reovim_driver_command::{Command, CommandContext, CommandHandler, CommandResult},
12 reovim_driver_session::{
13 SessionRuntime, TransitionContext,
14 api::{ModeApi, SelectionMode},
15 },
16 reovim_kernel::api::v1::CommandId,
17};
18
19use crate::{ids, modes::VimMode};
20
21#[derive(Debug, Clone, Copy, Default)]
26pub struct SwapAnchor;
27
28impl Command for SwapAnchor {
29 fn id(&self) -> CommandId {
30 ids::VISUAL_SWAP_ANCHOR
31 }
32
33 fn description(&self) -> &'static str {
34 "Swap cursor and anchor in visual mode"
35 }
36}
37
38impl CommandHandler for SwapAnchor {
39 #[cfg_attr(coverage_nightly, coverage(off))]
40 fn execute(&self, runtime: &mut SessionRuntime<'_>, _args: &CommandContext) -> CommandResult {
41 let Some(selection) = runtime.windows().active().and_then(|w| w.selection.clone()) else {
43 return CommandResult::Success; };
45
46 let swapped = reovim_driver_session::api::Selection {
48 start: selection.end,
49 end: selection.start,
50 mode: selection.mode,
51 };
52
53 if let Some(window) = runtime.windows_mut().active_mut() {
54 window.selection = Some(swapped);
55 }
56
57 CommandResult::Success
58 }
59}
60
61#[derive(Debug, Clone, Copy, Default)]
66pub struct ToggleVisualChar;
67
68impl Command for ToggleVisualChar {
69 fn id(&self) -> CommandId {
70 ids::TOGGLE_VISUAL_CHAR
71 }
72
73 fn description(&self) -> &'static str {
74 "Toggle to character-wise visual mode"
75 }
76}
77
78impl CommandHandler for ToggleVisualChar {
79 #[cfg_attr(coverage_nightly, coverage(off))]
80 fn execute(&self, runtime: &mut SessionRuntime<'_>, _args: &CommandContext) -> CommandResult {
81 let selection = runtime.windows().active().and_then(|w| w.selection.clone());
82
83 let target_mode = match selection {
84 Some(sel) if sel.mode == SelectionMode::Character => {
85 if let Some(window) = runtime.windows_mut().active_mut() {
87 window.selection = None;
88 }
89 VimMode::NORMAL_ID
90 }
91 Some(mut sel) => {
92 sel.mode = SelectionMode::Character;
94 if let Some(window) = runtime.windows_mut().active_mut() {
95 window.selection = Some(sel);
96 }
97 VimMode::VISUAL_ID
98 }
99 None => {
100 return CommandResult::Success;
102 }
103 };
104
105 runtime.set_mode(target_mode, TransitionContext::new());
106
107 CommandResult::Success
108 }
109}
110
111#[derive(Debug, Clone, Copy, Default)]
116pub struct ToggleVisualLine;
117
118impl Command for ToggleVisualLine {
119 fn id(&self) -> CommandId {
120 ids::TOGGLE_VISUAL_LINE
121 }
122
123 fn description(&self) -> &'static str {
124 "Toggle to line-wise visual mode"
125 }
126}
127
128impl CommandHandler for ToggleVisualLine {
129 #[cfg_attr(coverage_nightly, coverage(off))]
130 fn execute(&self, runtime: &mut SessionRuntime<'_>, _args: &CommandContext) -> CommandResult {
131 let selection = runtime.windows().active().and_then(|w| w.selection.clone());
132
133 let target_mode = match selection {
134 Some(sel) if sel.mode == SelectionMode::Line => {
135 if let Some(window) = runtime.windows_mut().active_mut() {
137 window.selection = None;
138 }
139 VimMode::NORMAL_ID
140 }
141 Some(mut sel) => {
142 sel.mode = SelectionMode::Line;
144 if let Some(window) = runtime.windows_mut().active_mut() {
145 window.selection = Some(sel);
146 }
147 VimMode::VISUAL_LINE_ID
148 }
149 None => {
150 return CommandResult::Success;
152 }
153 };
154
155 runtime.set_mode(target_mode, TransitionContext::new());
156
157 CommandResult::Success
158 }
159}
160
161#[derive(Debug, Clone, Copy, Default)]
166pub struct ToggleVisualBlock;
167
168impl Command for ToggleVisualBlock {
169 fn id(&self) -> CommandId {
170 ids::TOGGLE_VISUAL_BLOCK
171 }
172
173 fn description(&self) -> &'static str {
174 "Toggle to block-wise visual mode"
175 }
176}
177
178impl CommandHandler for ToggleVisualBlock {
179 #[cfg_attr(coverage_nightly, coverage(off))]
180 fn execute(&self, runtime: &mut SessionRuntime<'_>, _args: &CommandContext) -> CommandResult {
181 let selection = runtime.windows().active().and_then(|w| w.selection.clone());
182
183 let target_mode = match selection {
184 Some(sel) if sel.mode == SelectionMode::Block => {
185 if let Some(window) = runtime.windows_mut().active_mut() {
187 window.selection = None;
188 }
189 VimMode::NORMAL_ID
190 }
191 Some(mut sel) => {
192 sel.mode = SelectionMode::Block;
194 if let Some(window) = runtime.windows_mut().active_mut() {
195 window.selection = Some(sel);
196 }
197 VimMode::VISUAL_BLOCK_ID
198 }
199 None => {
200 return CommandResult::Success;
202 }
203 };
204
205 runtime.set_mode(target_mode, TransitionContext::new());
206
207 CommandResult::Success
208 }
209}
210
211#[derive(Debug, Clone, Copy, Default)]
220pub struct ReselectLast;
221
222impl Command for ReselectLast {
223 fn id(&self) -> CommandId {
224 ids::RESELECT_LAST
225 }
226
227 fn description(&self) -> &'static str {
228 "Reselect the last visual selection (gv)"
229 }
230}
231
232impl CommandHandler for ReselectLast {
233 #[cfg_attr(coverage_nightly, coverage(off))]
234 fn execute(&self, _runtime: &mut SessionRuntime<'_>, _args: &CommandContext) -> CommandResult {
235 CommandResult::Success
238 }
239}