<commit_before>use std::path::{Path, PathBuf};
use std::time::Duration;

use anyhow::anyhow;
use clap::{
    error::ErrorKind, value_parser, Arg, ArgAction, ArgGroup, ArgMatches, Command, Parser,
    ValueEnum,
};
#[cfg(feature = "completions")]
use clap_complete::Shell;
use normpath::PathExt;

use crate::error::print_error;
use crate::exec::CommandSet;
use crate::filesystem;
#[cfg(unix)]
use crate::filter::OwnerFilter;
use crate::filter::SizeFilter;

#[derive(Parser)]
#[command(
    name = "fd",
    version,
    about = "A program to find entries in your filesystem",
    after_long_help = "Bugs can be reported on GitHub: https://github.com/sharkdp/fd/issues",
    max_term_width = 98,
    args_override_self = true,
    group(ArgGroup::new("execs").args(&["exec", "exec_batch", "list_details"]).conflicts_with_all(&[
            "max_results", "has_results", "count"])),
)]
pub struct Opts {
    /// Search hidden files and directories
    #[arg(
        long,
        short = 'H',
        long_help = "Include hidden directories and files in the search results (default: \
                         hidden files and directories are skipped). Files and directories are \
                         considered to be hidden if their name starts with a `.` sign (dot). \
                         The flag can be overridden with --no-hidden."
    )]
    pub hidden: bool,

    /// Overrides --hidden
    #[arg(long, overrides_with = "hidden", hide = true, action = ArgAction::SetTrue)]
    no_hidden: (),

    /// Do not respect .(git|fd)ignore files
    #[arg(
        long,
        short = 'I',
        long_help = "Show search results from files and directories that would otherwise be \
                         ignored by '.gitignore', '.ignore', '.fdignore', or the global ignore file. \
                         The flag can be overridden with --ignore."
    )]
    pub no_ignore: bool,

    /// Overrides --no-ignore
    #[arg(long, overrides_with = "no_ignore", hide = true, action = ArgAction::SetTrue)]
    ignore: (),

    /// Do not respect .gitignore files
    #[arg(
        long,
        hide_short_help = true,
        long_help = "Show search results from files and directories that would otherwise be \
                         ignored by '.gitignore' files. The flag can be overridden with --ignore-vcs."
    )]
    pub no_ignore_vcs: bool,

    /// Overrides --no-ignore-vcs
    #[arg(long, overrides_with = "no_ignore_vcs", hide = true, action = ArgAction::SetTrue)]
    ignore_vcs: (),

    /// Do not respect .(git|fd)ignore files in parent directories
    #[arg(
        long,
        hide_short_help = true,
        long_help = "Show search results from files and directories that would otherwise be \
                     ignored by '.gitignore', '.ignore', or '.fdignore' files in parent directories."
    )]
    pub no_ignore_parent: bool,

    /// Do not respect the global ignore file
    #[arg(long, hide = true)]
    pub no_global_ignore_file: bool,

    /// Unrestricted search, alias for '--no-ignore --hidden'
    #[arg(long = "unrestricted", short = 'u', overrides_with_all(&["ignore", "no_hidden"]), action(ArgAction::Count), hide_short_help = true,
    long_help = "Perform an unrestricted search, including ignored and hidden files. This is \
                 an alias for '--no-ignore --hidden'."
        )]
    rg_alias_hidden_ignore: u8,

    /// Case-sensitive search (default: smart case)
    #[arg(
        long,
        short = 's',
        overrides_with("ignore_case"),
        long_help = "Perform a case-sensitive search. By default, fd uses case-insensitive \
                     searches, unless the pattern contains an uppercase character (smart \
                     case)."
    )]
    pub case_sensitive: bool,

    /// Case-insensitive search (default: smart case)
    #[arg(
        long,
        short = 'i',
        overrides_with("case_sensitive"),
        long_help = "Perform a case-insensitive search. By default, fd uses case-insensitive \
                     searches, unless the pattern contains an uppercase character (smart \
                     case)."
    )]
    pub ignore_case: bool,

    /// Glob-based search (default: regular expression)
    #[arg(
        long,
        short = 'g',
        conflicts_with("fixed_strings"),
        long_help = "Perform a glob-based search instead of a regular expression search."
    )]
    pub glob: bool,

    /// Regular-expression based search (default)
    #[arg(
        long,
        overrides_with("glob"),
        hide_short_help = true,
        long_help = "Perform a regular-expression based search (default). This can be used to \
                     override --glob."
    )]
    pub regex: bool,

    /// Treat pattern as literal string stead of regex
    #[arg(
        long,
        short = 'F',
        alias = "literal",
        hide_short_help = true,
        long_help = "Treat the pattern as a literal string instead of a regular expression. Note \
                     that this also performs substring comparison. If you want to match on an \
                     exact filename, consider using '--glob'."
    )]
    pub fixed_strings: bool,

    /// Additional search patterns that need to be matched
    #[arg(
        long = "and",
        value_name = "pattern",
        long_help = "Add additional required search patterns, all of which must be matched. Multiple \
                     additional patterns can be specified. The patterns are regular expressions, \
                     unless '--glob' or '--fixed-strings' is used.",
        hide_short_help = true
    )]
    pub exprs: Option<Vec<String>>,

    /// Show absolute instead of relative paths
    #[arg(
        long,
        short = 'a',
        long_help = "Shows the full path starting from the root as opposed to relative paths. \
                     The flag can be overridden with --relative-path."
    )]
    pub absolute_path: bool,

    /// Overrides --absolute-path
    #[arg(long, overrides_with = "absolute_path", hide = true, action = ArgAction::SetTrue)]
    relative_path: (),

    /// Use a long listing format with file metadata
    #[arg(
        long,
        short = 'l',
        conflicts_with("absolute_path"),
        long_help = "Use a detailed listing format like 'ls -l'. This is basically an alias \
                     for '--exec-batch ls -l' with some additional 'ls' options. This can be \
                     used to see more metadata, to show symlink targets and to achieve a \
                     deterministic sort order."
    )]
    pub list_details: bool,

    /// Follow symbolic links
    #[arg(
        long,<commit_msg>Use allow_hyphen_values = true for --and <pattern><commit_after>use std::path::{Path, PathBuf};
use std::time::Duration;

use anyhow::anyhow;
use clap::{
    error::ErrorKind, value_parser, Arg, ArgAction, ArgGroup, ArgMatches, Command, Parser,
    ValueEnum,
};
#[cfg(feature = "completions")]
use clap_complete::Shell;
use normpath::PathExt;

use crate::error::print_error;
use crate::exec::CommandSet;
use crate::filesystem;
#[cfg(unix)]
use crate::filter::OwnerFilter;
use crate::filter::SizeFilter;

#[derive(Parser)]
#[command(
    name = "fd",
    version,
    about = "A program to find entries in your filesystem",
    after_long_help = "Bugs can be reported on GitHub: https://github.com/sharkdp/fd/issues",
    max_term_width = 98,
    args_override_self = true,
    group(ArgGroup::new("execs").args(&["exec", "exec_batch", "list_details"]).conflicts_with_all(&[
            "max_results", "has_results", "count"])),
)]
pub struct Opts {
    /// Search hidden files and directories
    #[arg(
        long,
        short = 'H',
        long_help = "Include hidden directories and files in the search results (default: \
                         hidden files and directories are skipped). Files and directories are \
                         considered to be hidden if their name starts with a `.` sign (dot). \
                         The flag can be overridden with --no-hidden."
    )]
    pub hidden: bool,

    /// Overrides --hidden
    #[arg(long, overrides_with = "hidden", hide = true, action = ArgAction::SetTrue)]
    no_hidden: (),

    /// Do not respect .(git|fd)ignore files
    #[arg(
        long,
        short = 'I',
        long_help = "Show search results from files and directories that would otherwise be \
                         ignored by '.gitignore', '.ignore', '.fdignore', or the global ignore file. \
                         The flag can be overridden with --ignore."
    )]
    pub no_ignore: bool,

    /// Overrides --no-ignore
    #[arg(long, overrides_with = "no_ignore", hide = true, action = ArgAction::SetTrue)]
    ignore: (),

    /// Do not respect .gitignore files
    #[arg(
        long,
        hide_short_help = true,
        long_help = "Show search results from files and directories that would otherwise be \
                         ignored by '.gitignore' files. The flag can be overridden with --ignore-vcs."
    )]
    pub no_ignore_vcs: bool,

    /// Overrides --no-ignore-vcs
    #[arg(long, overrides_with = "no_ignore_vcs", hide = true, action = ArgAction::SetTrue)]
    ignore_vcs: (),

    /// Do not respect .(git|fd)ignore files in parent directories
    #[arg(
        long,
        hide_short_help = true,
        long_help = "Show search results from files and directories that would otherwise be \
                     ignored by '.gitignore', '.ignore', or '.fdignore' files in parent directories."
    )]
    pub no_ignore_parent: bool,

    /// Do not respect the global ignore file
    #[arg(long, hide = true)]
    pub no_global_ignore_file: bool,

    /// Unrestricted search, alias for '--no-ignore --hidden'
    #[arg(long = "unrestricted", short = 'u', overrides_with_all(&["ignore", "no_hidden"]), action(ArgAction::Count), hide_short_help = true,
    long_help = "Perform an unrestricted search, including ignored and hidden files. This is \
                 an alias for '--no-ignore --hidden'."
        )]
    rg_alias_hidden_ignore: u8,

    /// Case-sensitive search (default: smart case)
    #[arg(
        long,
        short = 's',
        overrides_with("ignore_case"),
        long_help = "Perform a case-sensitive search. By default, fd uses case-insensitive \
                     searches, unless the pattern contains an uppercase character (smart \
                     case)."
    )]
    pub case_sensitive: bool,

    /// Case-insensitive search (default: smart case)
    #[arg(
        long,
        short = 'i',
        overrides_with("case_sensitive"),
        long_help = "Perform a case-insensitive search. By default, fd uses case-insensitive \
                     searches, unless the pattern contains an uppercase character (smart \
                     case)."
    )]
    pub ignore_case: bool,

    /// Glob-based search (default: regular expression)
    #[arg(
        long,
        short = 'g',
        conflicts_with("fixed_strings"),
        long_help = "Perform a glob-based search instead of a regular expression search."
    )]
    pub glob: bool,

    /// Regular-expression based search (default)
    #[arg(
        long,
        overrides_with("glob"),
        hide_short_help = true,
        long_help = "Perform a regular-expression based search (default). This can be used to \
                     override --glob."
    )]
    pub regex: bool,

    /// Treat pattern as literal string stead of regex
    #[arg(
        long,
        short = 'F',
        alias = "literal",
        hide_short_help = true,
        long_help = "Treat the pattern as a literal string instead of a regular expression. Note \
                     that this also performs substring comparison. If you want to match on an \
                     exact filename, consider using '--glob'."
    )]
    pub fixed_strings: bool,

    /// Additional search patterns that need to be matched
    #[arg(
        long = "and",
        value_name = "pattern",
        long_help = "Add additional required search patterns, all of which must be matched. Multiple \
                     additional patterns can be specified. The patterns are regular expressions, \
                     unless '--glob' or '--fixed-strings' is used.",
        hide_short_help = true,
        allow_hyphen_values = true
    )]
    pub exprs: Option<Vec<String>>,

    /// Show absolute instead of relative paths
    #[arg(
        long,
        short = 'a',
        long_help = "Shows the full path starting from the root as opposed to relative paths. \
                     The flag can be overridden with --relative-path."
    )]
    pub absolute_path: bool,

    /// Overrides --absolute-path
    #[arg(long, overrides_with = "absolute_path", hide = true, action = ArgAction::SetTrue)]
    relative_path: (),

    /// Use a long listing format with file metadata
    #[arg(
        long,
        short = 'l',
        conflicts_with("absolute_path"),
        long_help = "Use a detailed listing format like 'ls -l'. This is basically an alias \
                     for '--exec-batch ls -l' with some additional 'ls' options. This can be \
                     used to see more metadata, to show symlink targets and to achieve a \
                     deterministic sort order."
    )]
    pub list_details: bool,

    /// Follow symbolic links
    #[arg(
        long,
{'fraction_non_alphanumeric': 0.11053141536856227, 'fraction_numerical': 0.0004471938585376761, 'mean_word_length': 2.1796208530805687, 'pattern_counts': {'":': 0, '<': 8, '<?xml version=': 0, '>': 8, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1239394', 'n_tokens_mistral': 3773, 'n_tokens_neox': 3662, 'n_words': 1272}