use super::*;
enum TransferType {
Copy,
Move,
}
fn inner_transfer(
state: &mut Ed<'_>,
full_command: &str,
selection: (usize, usize),
index: usize,
mode: TransferType,
) -> Result<(usize, usize)> {
let buffer = state.history.current(); buffer.verify_selection(selection)?;
buffer.verify_index(index)?;
if let TransferType::Move = mode {
if index >= selection.0 && index < selection.1 {
return Err(EdError::NoOp).into();
}
}
let buffer = state.history.current_mut(full_command.into());
match mode {
TransferType::Copy => {
let tmp: Clipboard = buffer[selection.0 - 1 .. selection.1].into();
let mut tail = buffer.split_off(index);
let start_ind = buffer.len() + 1; buffer.append(&mut (&tmp).into());
let end_ind = buffer.len();
buffer.append(&mut tail);
Ok((start_ind, end_ind))
},
TransferType::Move => {
if index < selection.0 {
let mut tail = buffer.split_off(selection.1);
let mut data = buffer.split_off(selection.0 - 1);
let mut middle = buffer.split_off(index);
let start_ind = buffer.len() + 1;
buffer.append(&mut data);
let end_ind = buffer.len();
buffer.append(&mut middle);
buffer.append(&mut tail);
Ok((start_ind, end_ind))
}
else if index >= selection.1 {
let mut tail = buffer.split_off(index);
let mut middle = buffer.split_off(selection.1);
let mut data = buffer.split_off(selection.0 - 1);
buffer.append(&mut middle);
let start_ind = buffer.len() + 1;
buffer.append(&mut data);
let end_ind = buffer.len();
buffer.append(&mut tail);
Ok((start_ind, end_ind))
}
else {
ed_unreachable!()
}
},
}
}
pub fn transfer(
state: &mut Ed<'_>,
pflags: &mut PrintingFlags,
full_command: &str,
selection: Option<Sel<'_>>,
command: char,
tail: &str,
) -> Result<()> {
let selection = interpret_selection(&state, selection, state.selection)?;
let (ind_end, ind) = parse_index(tail)?;
let index = if command == 'm' || command == 't' {
interpret_index(
&state,
ind.unwrap_or_else(|| Ind::BufferLen),
state.selection.1,
)?
}
else {
interpret_index(
&state,
ind.unwrap_or_else(|| Ind::Literal(1)),
state.selection.0,
)?
};
let mut flags = parse_flags(&tail[ind_end..], "pnl")?;
pflags.p = flags.remove(&'p').unwrap();
pflags.n = flags.remove(&'n').unwrap();
pflags.l = flags.remove(&'l').unwrap();
state.selection = match command {
'm' => inner_transfer(state, full_command, selection, index, TransferType::Move)?,
'M' => inner_transfer(state, full_command, selection, index.saturating_sub(1), TransferType::Move)?,
't' => inner_transfer(state, full_command, selection, index, TransferType::Copy)?,
'T' => inner_transfer(state, full_command, selection, index.saturating_sub(1), TransferType::Copy)?,
_ => return ed_unreachable!(),
};
Ok(())
}