reovim_module_vim/visual/
entry.rs1use {
9 reovim_driver_command::{Command, CommandContext, CommandHandler, CommandResult},
10 reovim_driver_session::{
11 BufferApi, SessionRuntime, TransitionContext,
12 api::{ChangeTracker, ModeApi, Selection},
13 },
14 reovim_kernel::api::v1::{CommandId, Position},
15};
16
17use crate::{ids, modes::VimMode};
18
19#[derive(Debug, Clone, Copy, Default)]
21pub struct EnterVisualMode;
22
23impl Command for EnterVisualMode {
24 fn id(&self) -> CommandId {
25 ids::ENTER_VISUAL
26 }
27
28 fn description(&self) -> &'static str {
29 "Enter visual mode (character-wise)"
30 }
31}
32
33impl CommandHandler for EnterVisualMode {
34 #[cfg_attr(coverage_nightly, coverage(off))]
35 fn execute(&self, runtime: &mut SessionRuntime<'_>, _args: &CommandContext) -> CommandResult {
36 let Some(window) = runtime.windows().active() else {
38 tracing::warn!("EnterVisualMode: No active window");
39 return CommandResult::error("No active window");
40 };
41 let pos = Position::new(window.cursor.line, window.cursor.column);
42
43 let selection = Selection::character(pos, Position::new(pos.line, pos.column + 1));
47 tracing::debug!(?pos, ?selection, "EnterVisualMode: Setting selection");
48
49 if let Some(window) = runtime.windows_mut().active_mut() {
50 window.selection = Some(selection);
51 }
52
53 if let Some(buffer_id) = runtime.active_buffer() {
55 runtime.record_selection_change(buffer_id);
56 }
57
58 let sel_check = runtime.windows().active().and_then(|w| w.selection.clone());
60 tracing::debug!(?sel_check, "EnterVisualMode: Selection after set");
61
62 runtime.set_mode(VimMode::VISUAL_ID, TransitionContext::new());
64
65 CommandResult::Success
66 }
67}
68
69#[derive(Debug, Clone, Copy, Default)]
71pub struct EnterVisualLineMode;
72
73impl Command for EnterVisualLineMode {
74 fn id(&self) -> CommandId {
75 ids::ENTER_VISUAL_LINE
76 }
77
78 fn description(&self) -> &'static str {
79 "Enter visual line mode"
80 }
81}
82
83impl CommandHandler for EnterVisualLineMode {
84 #[cfg_attr(coverage_nightly, coverage(off))]
85 fn execute(&self, runtime: &mut SessionRuntime<'_>, _args: &CommandContext) -> CommandResult {
86 let Some(window) = runtime.windows().active() else {
88 return CommandResult::error("No active window");
89 };
90 let pos = Position::new(window.cursor.line, window.cursor.column);
91
92 let selection = Selection::line(Position::new(pos.line, 0), Position::new(pos.line + 1, 0));
96
97 if let Some(window) = runtime.windows_mut().active_mut() {
98 window.selection = Some(selection);
99 }
100
101 if let Some(buffer_id) = runtime.active_buffer() {
103 runtime.record_selection_change(buffer_id);
104 }
105
106 runtime.set_mode(VimMode::VISUAL_LINE_ID, TransitionContext::new());
108
109 CommandResult::Success
110 }
111}
112
113#[derive(Debug, Clone, Copy, Default)]
115pub struct EnterVisualBlockMode;
116
117impl Command for EnterVisualBlockMode {
118 fn id(&self) -> CommandId {
119 ids::ENTER_VISUAL_BLOCK
120 }
121
122 fn description(&self) -> &'static str {
123 "Enter visual block mode"
124 }
125}
126
127impl CommandHandler for EnterVisualBlockMode {
128 #[cfg_attr(coverage_nightly, coverage(off))]
129 fn execute(&self, runtime: &mut SessionRuntime<'_>, _args: &CommandContext) -> CommandResult {
130 let Some(window) = runtime.windows().active() else {
132 return CommandResult::error("No active window");
133 };
134 let pos = Position::new(window.cursor.line, window.cursor.column);
135
136 let selection = Selection::block(pos, Position::new(pos.line, pos.column + 1));
140
141 if let Some(window) = runtime.windows_mut().active_mut() {
142 window.selection = Some(selection);
143 }
144
145 if let Some(buffer_id) = runtime.active_buffer() {
147 runtime.record_selection_change(buffer_id);
148 }
149
150 runtime.set_mode(VimMode::VISUAL_BLOCK_ID, TransitionContext::new());
152
153 CommandResult::Success
154 }
155}