use super::*;
fn mark_matching(
state: &mut Ed<'_>,
selection: (usize, usize),
pattern: &str,
inverse: bool,
recursion_depth: usize,
) -> Result<()> {
use regex::RegexBuilder;
let buffer = state.history.current();
buffer.verify_selection(selection)?;
let regex = RegexBuilder::new(pattern)
.multi_line(true)
.build()
.map_err(|e| EdError::regex_error(e, pattern))
?;
let mut match_found = false;
for (i, line) in buffer.iter().enumerate() {
let mut matched_vec = line.matched.borrow_mut();
matched_vec.truncate(recursion_depth);
if i >= selection.0 -1 && i < selection.1 {
if regex.is_match(&(line.text)) ^ inverse {
matched_vec.resize(recursion_depth, false);
matched_vec.push(true);
match_found = true;
}
}
}
if !match_found {
Err(EdError::RegexNoMatch(pattern.to_owned()))
} else {
Ok(())
}
}
fn get_marked(
state: &mut Ed<'_>,
recursion_depth: usize,
) -> Option<usize> {
let buffer = state.history.current();
for (index,line) in buffer.iter().enumerate() {
let mut matched_vec = line.matched.borrow_mut();
match matched_vec.get(recursion_depth) {
Some(x) => {
let tmp = *x;
matched_vec.truncate(recursion_depth);
if tmp { return Some(index + 1); }
},
None => (),
}
}
None
}
pub fn global(
state: &mut Ed<'_>,
ui: &mut dyn UI,
selection: Option<Sel<'_>>,
command: char,
tail: &str,
recursion_depth: usize,
) -> Result<()> {
let selection = interpret_selection(&state, selection, state.selection)?;
let mut expressions = parse_expressions(tail)?;
if expressions.len() < 2 {
return Err( EdError::ArgumentsWrongNr{expected: "2 or more".into(), received: expressions.len()} );
}
mark_matching(state, selection, &expressions[0], command == 'v', recursion_depth + 1)?;
let mut commands: Vec<String> = expressions.split_off(1).iter().map(|s| format!("{}\n", s)).collect();
if commands.last().map(|s| s.trim()) != Some("") {
let mut input = ui.get_input(
state,
tail.chars().next().unwrap(),
#[cfg(feature = "initial_input_data")]
None,
)?;
commands.append(&mut input);
}
else {
commands.pop();
}
if commands.is_empty() {
commands.push("p\n".to_string())
}
while let Some(index) = get_marked(state, recursion_depth + 1) {
let mut scripted = ScriptedUI{
input: commands.iter().cloned().collect(),
print_ui: Some(ui),
};
state.selection = (index, index);
loop {
if state.private_get_and_run_command(&mut scripted, recursion_depth + 1)? {
break;
}
}
}
Ok(())
}
pub fn global_interactive(
state: &mut Ed<'_>,
ui: &mut dyn UI,
selection: Option<Sel<'_>>,
command: char,
tail: &str,
recursion_depth: usize,
) -> Result<()> {
let selection = interpret_selection(&state, selection, state.selection)?;
let expressions = parse_expressions(tail)?;
if expressions.len() != 2 {
return Err( EdError::ArgumentsWrongNr{expected: "2".into(), received: expressions.len()} );
}
if !expressions[1].is_empty() && expressions[1] != "\n" {
return Err(EdError::FlagUndefined(expressions[1].chars().next().unwrap()));
}
mark_matching(state, selection, &expressions[0], command == 'V', recursion_depth + 1)?;
while let Some(index) = get_marked(state, recursion_depth + 1) {
ui.print_selection(state, (index, index), state.n, state.l)?;
let input = ui.get_input(
state,
tail.chars().next().unwrap(),
#[cfg(feature = "initial_input_data")]
None,
)?;
let mut scripted = ScriptedUI{
input: input.into(),
print_ui: Some(ui),
};
state.selection = (index, index);
loop {
if state.private_get_and_run_command(&mut scripted, recursion_depth + 1)? {
break;
}
}
}
Ok(())
}