use reovim_kernel::api::v1::RegisterContent;
use super::{Operator, OperatorContext, OperatorError, Range, char_col_to_byte, 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();
if range.is_linewise {
let line_count = buffer.line_count();
let clamped_end = end.line.min(line_count.saturating_sub(1));
for line_idx in start.line..=clamped_end {
if let Some(line) = buffer.line(line_idx) {
yanked_text.push_str(line);
yanked_text.push('\n');
}
}
} else if start.line == end.line {
if let Some(line) = buffer.line(start.line) {
let char_len = line.chars().count();
let start_col = start.column.min(char_len);
let end_col = end.column.min(char_len);
if start_col < end_col {
let start_byte = char_col_to_byte(line, start_col);
let end_byte = char_col_to_byte(line, end_col);
yanked_text.push_str(&line[start_byte..end_byte]);
}
}
} else {
for line_idx in start.line..=end.line {
if let Some(line) = buffer.line(line_idx) {
if line_idx == start.line {
let char_len = line.chars().count();
let start_col = start.column.min(char_len);
let start_byte = char_col_to_byte(line, start_col);
yanked_text.push_str(&line[start_byte..]);
yanked_text.push('\n');
} else if line_idx == end.line {
let char_len = line.chars().count();
let end_col = end.column.min(char_len);
let end_byte = char_col_to_byte(line, end_col);
yanked_text.push_str(&line[..end_byte]);
} 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 }
}