Skip to main content

tome/
finder.rs

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}