use super::*;
fn replace_selection(
state: &mut Ed<'_>,
full_command: &str,
selection: (usize, usize),
mut input: Vec<&str>,
) -> Result<()> {
let buffer = state.history.current_mut(full_command.into());
let mut tail = buffer.split_off(selection.1);
state.clipboard = buffer.split_off(selection.0 - 1)[..].into();
for line in input.drain(..) {
buffer.push(Line::new(line).map_err(InternalError::InvalidLineText)?);
}
buffer.append(&mut tail);
Ok(())
}
pub fn run_command(
state: &mut Ed<'_>,
ui: &mut dyn UI,
full_command: &str,
selection: Option<Sel<'_>>,
ch: char,
command: &str,
) -> Result<()> {
let sel = if ch == '!' {
if selection.is_some() { return Err(EdError::SelectionForbidden); }
None
}
else {
let sel = interpret_selection(&state, selection, state.selection)?;
state.history.current().verify_selection(sel)?;
Some(sel)
};
let (changed, substituted) = command_substitutions(
command,
&state.file,
&state.prev_shell_command,
)?;
state.prev_shell_command = substituted.clone();
if changed {ui.print_message( &substituted )?;}
match sel {
None => {
let res = state.io.run_command(
&mut ui.lock_ui(),
substituted,
);
ui.print_message(&ch.to_string())?;
res?;
},
Some(s) => {
let data = state.history.current().get_lines(s)?;
let mut transformed = state.io.run_transform_command(
&mut ui.lock_ui(),
substituted,
data,
)?;
if !transformed.ends_with('\n') { transformed.push('\n'); }
let lines: Vec<&str> = transformed.split_inclusive('\n').collect();
let nr_lines = lines.len();
replace_selection(state, full_command, s, lines)?;
state.selection = if nr_lines != 0 {
(s.0, s.0 + nr_lines - 1)
}
else {
(1.max(s.0 - 1), s.0 - 1)
};
ui.print_message(&format!(
"Transformation returned {} bytes through command `{}`",
transformed.len(),
&state.prev_shell_command,
))?;
},
}
Ok(())
}