use super::*;
fn inner_input(
state: &mut Ed<'_>,
full_command: &str,
mut input: Vec<String>,
index: usize,
) -> Result<()> {
let buffer = state.history.current_mut(full_command.into());
let mut tail = buffer.split_off(index);
for line in input.drain(..) {
buffer.push(Line::new(line).map_err(InternalError::InvalidLineText)?);
}
buffer.append(&mut tail);
Ok(())
}
enum InlineSide {
Before,
After,
}
fn inner_inline_input(
state: &mut Ed<'_>,
full_command: &str,
mut input: Vec<String>,
line: usize,
side: InlineSide,
) -> Result<()> {
let buffer = state.history.current_mut(full_command.into());
let mut tail = buffer.split_off(line);
let indexed_line = buffer.split_off(line - 1);
if input.len() == 0 { return Err(EdError::NoOp); }
let mut input_iter = input.drain(..);
match side {
InlineSide::Before => {
let mut joined_line = input_iter.next_back().unwrap();
joined_line.pop(); joined_line.push_str(&indexed_line[0].text[..]);
for line in input_iter {
buffer.push(Line::new(line).map_err(InternalError::InvalidLineText)?);
}
buffer.push(Line::new(joined_line)
.map_err(InternalError::InvalidLineText)?
);
},
InlineSide::After => {
let mut joined_line = (&indexed_line[0].text[..]).to_owned();
joined_line.pop(); joined_line.push_str(&input_iter.next().unwrap());
buffer.push(Line::new(joined_line)
.map_err(InternalError::InvalidLineText)?
);
for line in input_iter {
buffer.push(Line::new(line).map_err(InternalError::InvalidLineText)?);
}
},
}
buffer.append(&mut tail);
state.clipboard = (&*indexed_line).into();
Ok(())
}
pub fn input(
state: &mut Ed<'_>,
ui: &mut dyn UI,
pflags: &mut PrintingFlags,
full_command: &str,
selection: Option<Sel<'_>>,
command: char,
flags: &str,
) -> Result<()> {
let mut flags = parse_flags(flags, "pnl")?;
pflags.p = flags.remove(&'p').unwrap();
pflags.n = flags.remove(&'n').unwrap();
pflags.l = flags.remove(&'l').unwrap();
let buffer = state.history.current();
let index = match command {
'a' | 'A' => {
let i = interpret_index_from_selection(&state, selection, state.selection, true)?;
if command == 'a' { buffer.verify_index(i)? } else { buffer.verify_line(i)? }
i
},
'i' | 'I' => {
let mut i = interpret_index_from_selection(&state, selection, state.selection, false)?;
if command == 'i' {
i = i.saturating_sub(1);
buffer.verify_index(i)?;
}
else { buffer.verify_line(i)? }
i
},
_ => ed_unreachable!()?,
};
let input = ui.get_input(
state,
'.',
#[cfg(feature = "initial_input_data")]
None,
)?;
state.selection = if !input.is_empty() {
let start = index + 1; let end = start + input.len() - 1; match command {
'A' => {
inner_inline_input(state, full_command, input, index, InlineSide::After)?;
(start - 1, end - 1)
},
'I' => {
inner_inline_input(state, full_command, input, index, InlineSide::Before)?;
(start - 1,end - 1)
},
'a' | 'i' => {
inner_input(state, full_command, input, index)?;
(start, end)
},
_ => ed_unreachable!()?,
}
}
else {
state.selection
};
Ok(())
}