use reovim_kernel::api::v1::RegisterContent;
use super::{Operator, OperatorContext, OperatorError, Range, registers};
#[derive(Debug, Clone, Copy)]
pub struct YankOperator;
impl Operator for YankOperator {
fn id(&self) -> &'static str {
"yank"
}
#[cfg_attr(coverage_nightly, coverage(off))]
fn execute(&self, ctx: &mut OperatorContext<'_>, range: Range) -> Result<(), OperatorError> {
let buffer_arc = ctx
.kernel
.buffers
.get(ctx.buffer_id)
.ok_or(OperatorError::BufferNotFound(ctx.buffer_id))?;
let buffer = buffer_arc.read();
let start = range.start;
let end = range.end;
let mut yanked_text = String::new();
let lines = buffer.lines();
if range.is_linewise {
let line_count = lines.len();
let clamped_end = end.line.min(line_count.saturating_sub(1));
for line_idx in start.line..=clamped_end {
if let Some(line) = lines.get(line_idx) {
yanked_text.push_str(line);
yanked_text.push('\n');
}
}
} else if start.line == end.line {
let line = &lines[start.line];
let start_col = start.column.min(line.len());
let end_col = end.column.min(line.len());
if start_col < end_col {
yanked_text.push_str(&line[start_col..end_col]);
}
} else {
for (line_idx, line) in lines.iter().enumerate().take(end.line + 1).skip(start.line) {
if line_idx == start.line {
let start_col = start.column.min(line.len());
yanked_text.push_str(&line[start_col..]);
yanked_text.push('\n');
} else if line_idx == end.line {
let end_col = end.column.min(line.len());
yanked_text.push_str(&line[..end_col]);
} else {
yanked_text.push_str(line);
yanked_text.push('\n');
}
}
}
drop(buffer);
let content = if range.is_linewise {
RegisterContent::linewise(yanked_text)
} else {
RegisterContent::characterwise(yanked_text)
};
registers::store_and_sync(ctx.kernel, ctx.registers, ctx.register, &content);
registers::push_to_history(ctx.clipboard_history, &content);
Ok(())
}
fn is_linewise(&self) -> bool {
false }
fn is_text_modifying(&self) -> bool {
false }
}