feat: add concurrent working threads option to CLI args
[ouch.git] / src / cli / mod.rs
blob4144e53efd95507394cad95031e33772123a8379
1 //! CLI related functions, uses the clap argparsing definitions from `args.rs`.
3 mod args;
5 use std::{
6     io,
7     path::{Path, PathBuf},
8 };
10 use clap::Parser;
11 use fs_err as fs;
13 pub use self::args::{CliArgs, Subcommand};
14 use crate::{
15     accessible::set_accessible,
16     utils::{is_path_stdin, FileVisibilityPolicy},
17     QuestionPolicy,
20 impl CliArgs {
21     /// A helper method that calls `clap::Parser::parse`.
22     ///
23     /// And:
24     ///   1. Make paths absolute.
25     ///   2. Checks the QuestionPolicy.
26     pub fn parse_and_validate_args() -> crate::Result<(Self, QuestionPolicy, FileVisibilityPolicy)> {
27         let mut args = Self::parse();
29         set_accessible(args.accessible);
31         if let Some(threads) = args.threads {
32             rayon::ThreadPoolBuilder::new()
33                 .num_threads(threads)
34                 .build_global()
35                 .unwrap();
36         }
38         let (Subcommand::Compress { files, .. }
39         | Subcommand::Decompress { files, .. }
40         | Subcommand::List { archives: files, .. }) = &mut args.cmd;
41         *files = canonicalize_files(files)?;
43         let skip_questions_positively = match (args.yes, args.no) {
44             (false, false) => QuestionPolicy::Ask,
45             (true, false) => QuestionPolicy::AlwaysYes,
46             (false, true) => QuestionPolicy::AlwaysNo,
47             (true, true) => unreachable!(),
48         };
50         let file_visibility_policy = FileVisibilityPolicy::new()
51             .read_git_exclude(args.gitignore)
52             .read_ignore(args.gitignore)
53             .read_git_ignore(args.gitignore)
54             .read_hidden(args.hidden);
56         Ok((args, skip_questions_positively, file_visibility_policy))
57     }
60 fn canonicalize_files(files: &[impl AsRef<Path>]) -> io::Result<Vec<PathBuf>> {
61     files
62         .iter()
63         .map(|f| {
64             if is_path_stdin(f.as_ref()) {
65                 Ok(f.as_ref().to_path_buf())
66             } else {
67                 fs::canonicalize(f)
68             }
69         })
70         .collect()