Repository: sharkdp/fd
File: src/main.rs (Rust)

Code before:
        return print_completions(shell);
    }

    set_working_dir(&opts)?;
    let search_paths = opts.search_paths()?;
    if search_paths.is_empty() {
        bail!("No valid search paths given.");
    }

    ensure_search_pattern_is_not_a_path(&opts)?;
    let pattern = &opts.pattern;
    let exprs = &opts.exprs;
    let empty = Vec::new();
    let patterns = exprs
        .as_ref()
        .unwrap_or(&empty)
        .into_iter()
        .chain(vec![pattern])
        .collect::<Vec<&String>>();
    let pattern_regexps = patterns
        .iter()
        .map(|pat| {
            let re = build_pattern_regex(pat, &opts);
            match re {
                Ok(r) => r,
                Err(e) => panic!("Bad pattern: {}", e),
            }
        })
        .collect::<Vec<String>>();

    let config = construct_config(opts, &pattern_regexps)?;
    ensure_use_hidden_option_for_leading_dot_pattern(&config, &pattern_regexps)?;
    let regexps = pattern_regexps
        .iter()
        .map(|pat| {
            let regex = build_regex(pat.to_string(), &config);
            match regex {
                Ok(r) => r,
                Err(e) => panic!("Bad regex: {}", e),
            }
        })
        .collect();
    walk::scan(&search_paths, Arc::new(regexps), Arc::new(config))
}

#[cfg(feature = "completions")]
#[cold]
fn print_completions(shell: clap_complete::Shell) -> Result<ExitCode> {
    // The program name is the first argument.
    let program_name = env::args().next().unwrap_or_else(|| "fd".to_string());
    let mut cmd = Opts::command();

Review comment (suggestion):
We probably shouldn't panic on bad user input. panics are usually reserved for logic errors in the program itself.  Instead we should be propagating this error up. 

Unfortunately, you can't really do that directly inside a map. You would need to map to a `Result<String>`, and then when you collect instead of collecting to a `Vec<String>` you would collect to a `Result<Vec<String>>` and use `?` to propagate the error up if needed (like `.collect::<Result<_>>()?`.

Code after:
        return print_completions(shell);
    }

    set_working_dir(&opts)?;
    let search_paths = opts.search_paths()?;
    if search_paths.is_empty() {
        bail!("No valid search paths given.");
    }

    ensure_search_pattern_is_not_a_path(&opts)?;
    let pattern = &opts.pattern;
    let exprs = &opts.exprs;
    let empty = Vec::new();

    let pattern_regexps = exprs
        .as_ref()
        .unwrap_or(&empty)
        .iter()
        .chain([pattern])
        .map(|pat| build_pattern_regex(pat, &opts))
        .collect::<Result<Vec<String>>>()?;

    let config = construct_config(opts, &pattern_regexps)?;

    ensure_use_hidden_option_for_leading_dot_pattern(&config, &pattern_regexps)?;

    let regexps = pattern_regexps
        .into_iter()
        .map(|pat| build_regex(pat, &config))
        .collect::<Result<Vec<Regex>>>()?;

    walk::scan(&search_paths, Arc::new(regexps), Arc::new(config))
}

#[cfg(feature = "completions")]
#[cold]
fn print_completions(shell: clap_complete::Shell) -> Result<ExitCode> {
    // The program name is the first argument.
    let first_arg = env::args().next();
    let program_name = first_arg
        .as_ref()
        .map(Path::new)
        .and_then(|path| path.file_stem())
        .and_then(|file| file.to_str())
        .unwrap_or("fd");
    let mut cmd = Opts::command();
    cmd.build();
    clap_complete::generate(shell, &mut cmd, program_name, &mut std::io::stdout());
    Ok(ExitCode::Success)
}