//! [Clap] struct used to parse command line arguments. use crate::extension_set::ExtensionSet; use crate::string_type::String as StringType; use cfg_if::cfg_if; use clap::{AppSettings, Clap}; use std::path::PathBuf; cfg_if! { if #[cfg(windows)] { const DEFAULT_FORMAT: &str = "powershell"; } else { const DEFAULT_FORMAT: &str = "script"; } } #[derive(Clap, PartialEq, Debug)] pub enum OutputFormat { /// A Bourne shell compatible script. Script, /// A PowerShell script. PowerShell, /// Also a PowerShell script, with different casing to allow for `fif -o powershell`. Powershell, /// Plain text. Text, } // TODO: convert this to macro style?: https://docs.rs/clap/3.0.0-beta.2/clap/index.html#using-macros #[derive(Clap, Debug)] #[clap( version = option_env!("CARGO_PKG_VERSION").unwrap_or("???"), author = option_env!("CARGO_PKG_AUTHORS").unwrap_or("Lynnesbian"), about = option_env!("CARGO_PKG_DESCRIPTION").unwrap_or("File Info Fixer"), before_help = "Copyright © 2021 Lynnesbian under the GPL3 (or later) License.", before_long_help = "Copyright © 2021 Lynnesbian\n\ This program is free software: you can redistribute it and/or modify \ it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 \ of the License, or (at your option) any later version.", setting(AppSettings::ColoredHelp) )] pub struct Parameters { /// Only examine files with these extensions (Comma-separated list) #[clap(short, long, use_delimiter = true, require_delimiter = true, group = "extensions")] pub exts: Option>, /// Use a preset list of extensions as the search filter #[clap(short = 'E', long, arg_enum, group = "extensions")] pub ext_set: Option, /// Don't skip hidden files and directories #[clap(short, long)] pub scan_hidden: bool, /// Scan files without extensions #[clap(short = 'S', long)] pub scan_extensionless: bool, /// Output format to use #[clap(short, long, default_value = DEFAULT_FORMAT, arg_enum)] pub output_format: OutputFormat, /// Follow symlinks #[clap(short, long)] pub follow_symlinks: bool, /// Directory to process // TODO: right now this can only take a single directory - should this be improved? #[clap(name = "DIR", default_value = ".", parse(from_os_str))] pub dirs: PathBuf, } /// Further options relating to scanning. #[derive(PartialEq, Debug)] pub struct ScanOpts { /// Whether hidden files and directories should be scanned. pub hidden: bool, /// Whether files without extensions should be scanned. pub extensionless: bool, /// Should symlinks be followed? pub follow_symlinks: bool, } impl Parameters { pub fn extensions(&self) -> Option> { if let Some(exts) = &self.exts { // extensions supplied like "-e png,jpg,jpeg" Some(exts.iter().map(|s| s.as_str()).collect()) } else if let Some(exts) = &self.ext_set { // extensions supplied like "-E images" Some(exts.extensions()) } else { // neither -E nor -e was passed None } } pub const fn get_scan_opts(&self) -> ScanOpts { ScanOpts { hidden: self.scan_hidden, extensionless: self.scan_extensionless, follow_symlinks: self.follow_symlinks, } } }