1use super::script;
2use std::path::PathBuf;
3
4pub struct ScriptInvocation<'a> {
5 pub target: PathBuf,
6 pub args: Vec<&'a String>,
7}
8
9pub enum FindResult<'a> {
10 File(ScriptInvocation<'a>),
11 Directory(PathBuf),
12}
13
14pub fn find_script<'a>(
15 command_directory_path: &str,
16 args: &'a [String],
17) -> Result<FindResult<'a>, String> {
18 let mut target = PathBuf::from(&command_directory_path);
19 let mut args_peekable = args.iter().peekable();
20 while let Some(arg) = args_peekable.peek() {
21 if arg.is_empty() {
22 break;
23 }
24 target.push(arg);
25 if let Some(resolved) = script::resolve_source_path(&target) {
26 target = resolved;
27 args_peekable.next();
28 let remaining_args: Vec<_> = args_peekable.collect();
29 return Ok(FindResult::File(ScriptInvocation {
30 target,
31 args: remaining_args,
32 }));
33 } else if target.is_dir() {
34 args_peekable.next();
35 } else {
36 target.pop();
37 break;
38 }
39 }
40 let remaining_args: Vec<_> = args_peekable.collect();
41 match remaining_args.len() {
42 0 => Ok(FindResult::Directory(target)),
43 _ => Err(format!(
44 "command {} not found in directory {}",
45 remaining_args[0],
46 target.to_str().unwrap_or("")
47 )),
48 }
49}