use {
reovim_driver_command::{ArgValue, Command, CommandContext, CommandHandler, CommandResult},
reovim_driver_session::{SessionRuntime, api::ChangeTracker},
reovim_kernel::api::v1::{CommandId, Cursor, Motion, MotionEngine, Position},
};
use crate::ids::EXECUTE_FIND_CHAR;
pub struct ExecuteFindChar;
impl Command for ExecuteFindChar {
fn id(&self) -> CommandId {
EXECUTE_FIND_CHAR
}
fn description(&self) -> &'static str {
"Execute a find-char motion (f, F, t, T) with the target character from context"
}
}
impl CommandHandler for ExecuteFindChar {
#[cfg_attr(coverage_nightly, coverage(off))]
fn execute(&self, runtime: &mut SessionRuntime<'_>, args: &CommandContext) -> CommandResult {
let Some(target_char) = args.char("find_char") else {
return CommandResult::error("find_char argument required");
};
let forward = args.string("find_direction") != Some("backward");
let inclusive = match args.get("find_inclusive") {
Some(ArgValue::Bool(b)) => *b,
_ => true,
};
let count = args.count().unwrap_or(1);
let Some(buffer_id) = args.buffer_id() else {
return CommandResult::error("No active buffer");
};
let Some(window) = runtime.windows().active() else {
return CommandResult::error("No active window");
};
let cursor_line = window.cursor.line;
let cursor_col = window.cursor.column;
let cursor = Cursor::new(Position::new(cursor_line, cursor_col));
let motion = Motion::FindChar {
char: target_char,
direction: if forward {
reovim_kernel::api::v1::Direction::Forward
} else {
reovim_kernel::api::v1::Direction::Backward
},
till: !inclusive,
};
let target = runtime.with_buffer_read(buffer_id, |buffer| {
MotionEngine::calculate(buffer, &cursor, motion, count)
});
let Some(target) = target else {
return CommandResult::error("Buffer not found");
};
if let Some(pos) = target {
if let Some(window) = runtime.windows_mut().active_mut() {
window.cursor = pos.into();
}
runtime.record_cursor_move(buffer_id);
}
CommandResult::Success
}
}