1use sim_kernel::{Error, Result};
4
5pub fn edit(text: &str, old: &str, new: &str, replace_all: bool) -> Result<String> {
10 if old.is_empty() {
11 return Err(Error::Eval("edit: old pattern is empty".to_owned()));
12 }
13 let matches = text.matches(old).count();
14 match matches {
15 0 => Err(Error::Eval(format!("edit: pattern not found: {old:?}"))),
16 n if n > 1 && !replace_all => Err(Error::Eval(format!(
17 "edit: pattern is not unique ({n} matches); pass replace_all"
18 ))),
19 _ if replace_all => Ok(text.replace(old, new)),
20 _ => Ok(text.replacen(old, new, 1)),
21 }
22}
23
24pub fn edit_lines(text: &str, start: usize, end: usize, new: &str) -> Result<String> {
29 if start == 0 {
30 return Err(Error::Eval(
31 "edit-lines: start must be at least 1".to_owned(),
32 ));
33 }
34 if end < start {
35 return Err(Error::Eval(
36 "edit-lines: end must be greater than or equal to start".to_owned(),
37 ));
38 }
39
40 let lines = text.split_inclusive('\n').collect::<Vec<_>>();
41 if end > lines.len() {
42 return Err(Error::Eval(format!(
43 "edit-lines: range {start}..{end} exceeds {} line(s)",
44 lines.len()
45 )));
46 }
47
48 let mut edited = String::new();
49 for line in &lines[..start - 1] {
50 edited.push_str(line);
51 }
52 edited.push_str(new);
53 for line in &lines[end..] {
54 edited.push_str(line);
55 }
56 Ok(edited)
57}