use crate::resolution::tracked_index::tracked_paths;
pub(crate) fn tracked_shell_scripts() -> Box<[Box<str>]> {
tracked_paths("*.sh")
}
pub(crate) fn joined_lines(source: &str) -> Box<str> {
let continued = source.replace("\\\n", " ");
let lines: Box<[Box<str>]> = continued
.lines()
.map(|line| {
let words: Box<[&str]> = line.split_whitespace().collect();
words.join(" ").into()
})
.collect();
lines.join("\n").into()
}
pub(crate) fn defined_functions(source: &str) -> Box<[Box<str>]> {
source
.lines()
.filter_map(|line| line.strip_suffix("() {"))
.map(Box::from)
.collect()
}
pub(crate) fn function_body(source: &str, name: &str) -> Box<str> {
let opening: Box<str> = format!("\n{name}() {{\n").into();
let start = source
.find(&*opening)
.unwrap_or_else(|| panic!("{name} should be defined"))
+ opening.len();
let length = source[start..]
.find("\n}\n")
.unwrap_or_else(|| panic!("{name} should have a closing brace"));
source[start..start + length].into()
}
pub(crate) fn offset_of(text: &str, fragment: &str, subject: &str) -> usize {
text.find(fragment)
.unwrap_or_else(|| panic!("{subject}: the text read holds no [{fragment}]"))
}
pub(crate) fn assert_contains_all(text: &str, table: &[&str], subject: &str) {
assert!(
!table.is_empty(),
"{subject}: an empty table requires nothing"
);
for fragment in table {
assert!(text.contains(fragment), "{subject} is missing [{fragment}]");
}
}
pub(crate) fn assert_in_order(text: &str, steps: &[&str], subject: &str) {
assert!(
!steps.is_empty(),
"{subject}: an empty sequence requires nothing"
);
let mut previous: Option<usize> = None;
for step in steps {
let offset = offset_of(text, step, subject);
if let Some(earlier) = previous {
assert!(offset > earlier, "{subject}: [{step}] runs out of order");
}
previous = Some(offset);
}
}
pub(crate) fn assert_exactly_once(text: &str, fragment: &str, subject: &str) {
assert_eq!(
text.matches(fragment).count(),
1,
"{subject} must be stated exactly once [{fragment}]"
);
}