2017-10-21 10:16:03 +02:00
|
|
|
// Copyright (c) 2017 fd developers
|
|
|
|
// Licensed under the Apache License, Version 2.0
|
|
|
|
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0>
|
|
|
|
// or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
|
|
|
|
// at your option. All files in the project carrying such
|
|
|
|
// notice may not be copied, modified, or distributed except
|
|
|
|
// according to those terms.
|
|
|
|
|
2018-01-01 12:09:33 +01:00
|
|
|
use std::collections::HashSet;
|
2017-10-10 08:01:17 +02:00
|
|
|
use std::process;
|
|
|
|
use std::time;
|
|
|
|
use std::io::Write;
|
|
|
|
|
2017-11-15 02:14:04 +01:00
|
|
|
use exec::CommandTemplate;
|
2017-10-10 08:01:17 +02:00
|
|
|
use lscolors::LsColors;
|
|
|
|
use walk::FileType;
|
2017-10-13 21:46:00 +02:00
|
|
|
use regex_syntax::{Expr, ExprBuilder};
|
2017-10-10 08:01:17 +02:00
|
|
|
|
|
|
|
/// Configuration options for *fd*.
|
|
|
|
pub struct FdOptions {
|
2017-10-12 01:21:44 +02:00
|
|
|
/// Whether the search is case-sensitive or case-insensitive.
|
2017-10-10 08:01:17 +02:00
|
|
|
pub case_sensitive: bool,
|
|
|
|
|
|
|
|
/// Whether to search within the full file path or just the base name (filename or directory
|
|
|
|
/// name).
|
|
|
|
pub search_full_path: bool,
|
|
|
|
|
|
|
|
/// Whether to ignore hidden files and directories (or not).
|
|
|
|
pub ignore_hidden: bool,
|
|
|
|
|
2017-11-21 22:54:00 +01:00
|
|
|
/// Whether to respect ignore files (`.gitignore`, `.ignore`, ..) or not.
|
2017-10-10 08:01:17 +02:00
|
|
|
pub read_ignore: bool,
|
|
|
|
|
2017-11-21 22:54:00 +01:00
|
|
|
/// Whether to respect VCS ignore files (`.gitignore`, ..) or not.
|
|
|
|
pub read_gitignore: bool,
|
|
|
|
|
2017-10-10 08:01:17 +02:00
|
|
|
/// Whether to follow symlinks or not.
|
|
|
|
pub follow_links: bool,
|
|
|
|
|
|
|
|
/// Whether elements of output should be separated by a null character
|
|
|
|
pub null_separator: bool,
|
|
|
|
|
|
|
|
/// The maximum search depth, or `None` if no maximum search depth should be set.
|
|
|
|
///
|
|
|
|
/// A depth of `1` includes all files under the current directory, a depth of `2` also includes
|
|
|
|
/// all files under subdirectories of the current directory, etc.
|
|
|
|
pub max_depth: Option<usize>,
|
|
|
|
|
|
|
|
/// The number of threads to use.
|
|
|
|
pub threads: usize,
|
|
|
|
|
|
|
|
/// Time to buffer results internally before streaming to the console. This is useful to
|
|
|
|
/// provide a sorted output, in case the total execution time is shorter than
|
|
|
|
/// `max_buffer_time`.
|
|
|
|
pub max_buffer_time: Option<time::Duration>,
|
|
|
|
|
|
|
|
/// `None` if the output should not be colorized. Otherwise, a `LsColors` instance that defines
|
|
|
|
/// how to style different filetypes.
|
|
|
|
pub ls_colors: Option<LsColors>,
|
|
|
|
|
|
|
|
/// The type of file to search for. All files other than the specified type will be ignored.
|
2018-01-01 12:09:33 +01:00
|
|
|
pub file_types: HashSet<FileType>,
|
2017-10-10 08:01:17 +02:00
|
|
|
|
|
|
|
/// The extension to search for. Only entries matching the extension will be included.
|
|
|
|
///
|
|
|
|
/// The value (if present) will be a lowercase string without leading dots.
|
2018-01-01 12:09:33 +01:00
|
|
|
pub extensions: Option<HashSet<String>>,
|
2017-10-14 18:04:11 +02:00
|
|
|
|
|
|
|
/// If a value is supplied, each item found will be used to generate and execute commands.
|
2017-11-15 02:14:04 +01:00
|
|
|
pub command: Option<CommandTemplate>,
|
2017-10-22 23:00:19 +02:00
|
|
|
|
|
|
|
/// A list of glob patterns that should be excluded from the search.
|
|
|
|
pub exclude_patterns: Vec<String>,
|
2017-10-10 08:01:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Print error message to stderr and exit with status `1`.
|
|
|
|
pub fn error(message: &str) -> ! {
|
|
|
|
writeln!(&mut ::std::io::stderr(), "{}", message).expect("Failed writing to stderr");
|
|
|
|
process::exit(1);
|
|
|
|
}
|
2017-10-13 21:46:00 +02:00
|
|
|
|
|
|
|
/// Determine if a regex pattern contains a literal uppercase character.
|
|
|
|
pub fn pattern_has_uppercase_char(pattern: &str) -> bool {
|
|
|
|
ExprBuilder::new()
|
|
|
|
.parse(pattern)
|
|
|
|
.map(|expr| expr_has_uppercase_char(&expr))
|
|
|
|
.unwrap_or(false)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Determine if a regex expression contains a literal uppercase character.
|
|
|
|
fn expr_has_uppercase_char(expr: &Expr) -> bool {
|
|
|
|
match *expr {
|
|
|
|
Expr::Literal { ref chars, .. } => chars.iter().any(|c| c.is_uppercase()),
|
2018-01-01 12:16:43 +01:00
|
|
|
Expr::Class(ref ranges) => ranges
|
|
|
|
.iter()
|
|
|
|
.any(|r| r.start.is_uppercase() || r.end.is_uppercase()),
|
|
|
|
Expr::Group { ref e, .. } | Expr::Repeat { ref e, .. } => expr_has_uppercase_char(e),
|
2017-10-13 21:46:00 +02:00
|
|
|
Expr::Concat(ref es) => es.iter().any(expr_has_uppercase_char),
|
|
|
|
Expr::Alternate(ref es) => es.iter().any(expr_has_uppercase_char),
|
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
2018-01-03 10:00:22 +01:00
|
|
|
|
|
|
|
/// Exit code representing a general error
|
|
|
|
pub const EXITCODE_ERROR: i32 = 1;
|
|
|
|
|
|
|
|
/// Exit code representing that the process was killed by SIGINT
|
|
|
|
pub const EXITCODE_SIGINT: i32 = 130;
|