mirror of https://github.com/sharkdp/fd.git
Code clean-ups, documentation
This commit is contained in:
parent
0f5ede48d5
commit
bf013da8ff
|
@ -1,5 +1,6 @@
|
||||||
use std::collections::HashMap;
|
/// A parser for the `LS_COLORS` environment variable.
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
use ansi_term::{Style, Colour};
|
use ansi_term::{Style, Colour};
|
||||||
|
|
||||||
/// Maps file extensions to ANSI colors / styles.
|
/// Maps file extensions to ANSI colors / styles.
|
||||||
|
@ -14,11 +15,19 @@ const LS_CODES: &'static [&'static str] =
|
||||||
"ec", "su", "su", "sg", "sg", "st", "ow", "ow", "tw", "tw", "ca", "mh",
|
"ec", "su", "su", "sg", "sg", "st", "ow", "ow", "tw", "tw", "ca", "mh",
|
||||||
"cl"];
|
"cl"];
|
||||||
|
|
||||||
|
/// Defines how different file system entries should be colorized / styled.
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct LsColors {
|
pub struct LsColors {
|
||||||
|
/// ANSI Style for directories.
|
||||||
pub directory: Style,
|
pub directory: Style,
|
||||||
|
|
||||||
|
/// ANSI style for symbolic links.
|
||||||
pub symlink: Style,
|
pub symlink: Style,
|
||||||
|
|
||||||
|
/// A map that defines ANSI styles for different file extensions.
|
||||||
pub extensions: ExtensionStyles,
|
pub extensions: ExtensionStyles,
|
||||||
|
|
||||||
|
/// A map that defines ANSI styles for different specific filenames.
|
||||||
pub filenames: FilenameStyles,
|
pub filenames: FilenameStyles,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,6 +44,7 @@ impl Default for LsColors {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LsColors {
|
impl LsColors {
|
||||||
|
/// Parse a single text-decoration code (normal, bold, italic, ...).
|
||||||
fn parse_decoration(code: &str) -> Option<fn(Colour) -> Style> {
|
fn parse_decoration(code: &str) -> Option<fn(Colour) -> Style> {
|
||||||
match code {
|
match code {
|
||||||
"0" | "00" => Some(Colour::normal),
|
"0" | "00" => Some(Colour::normal),
|
||||||
|
@ -97,7 +107,7 @@ impl LsColors {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a new LS_COLORS entry
|
/// Add a new `LS_COLORS` entry.
|
||||||
fn add_entry(&mut self, input: &str) {
|
fn add_entry(&mut self, input: &str) {
|
||||||
let mut parts = input.trim().split('=');
|
let mut parts = input.trim().split('=');
|
||||||
if let Some(pattern) = parts.next() {
|
if let Some(pattern) = parts.next() {
|
||||||
|
|
69
src/main.rs
69
src/main.rs
|
@ -22,14 +22,31 @@ use lscolors::LsColors;
|
||||||
|
|
||||||
/// Configuration options for *fd*.
|
/// Configuration options for *fd*.
|
||||||
struct FdOptions {
|
struct FdOptions {
|
||||||
|
/// Determines whether the regex search is case-sensitive or case-insensitive.
|
||||||
case_sensitive: bool,
|
case_sensitive: bool,
|
||||||
|
|
||||||
|
/// Whether to search within the full file path or just the base name (filename or directory
|
||||||
|
/// name).
|
||||||
search_full_path: bool,
|
search_full_path: bool,
|
||||||
|
|
||||||
|
/// Whether to ignore hidden files and directories (or not).
|
||||||
ignore_hidden: bool,
|
ignore_hidden: bool,
|
||||||
|
|
||||||
|
/// Whether to respect VCS ignore files (`.gitignore`, `.ignore`, ..) or not.
|
||||||
read_ignore: bool,
|
read_ignore: bool,
|
||||||
|
|
||||||
|
/// Whether to follow symlinks or not.
|
||||||
follow_links: bool,
|
follow_links: 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.
|
||||||
max_depth: Option<usize>,
|
max_depth: Option<usize>,
|
||||||
colored: bool,
|
|
||||||
ls_colors: LsColors
|
/// `None` if the output should not be colorized. Otherwise, a `LsColors` instance that defines
|
||||||
|
/// how to style different filetypes.
|
||||||
|
ls_colors: Option<LsColors>
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Print a search result to the console.
|
/// Print a search result to the console.
|
||||||
|
@ -41,9 +58,7 @@ fn print_entry(path_root: &Path, path_entry: &Path, config: &FdOptions) {
|
||||||
None => return
|
None => return
|
||||||
};
|
};
|
||||||
|
|
||||||
if !config.colored {
|
if let Some(ref ls_colors) = config.ls_colors {
|
||||||
println!("{}", path_str);
|
|
||||||
} else {
|
|
||||||
let mut component_path = path_root.to_path_buf();
|
let mut component_path = path_root.to_path_buf();
|
||||||
|
|
||||||
// Traverse the path and colorize each component
|
// Traverse the path and colorize each component
|
||||||
|
@ -59,15 +74,15 @@ fn print_entry(path_root: &Path, path_entry: &Path, config: &FdOptions) {
|
||||||
if component_path.symlink_metadata()
|
if component_path.symlink_metadata()
|
||||||
.map(|md| md.file_type().is_symlink())
|
.map(|md| md.file_type().is_symlink())
|
||||||
.unwrap_or(false) {
|
.unwrap_or(false) {
|
||||||
config.ls_colors.symlink
|
ls_colors.symlink
|
||||||
} else if component_path.is_dir() {
|
} else if component_path.is_dir() {
|
||||||
config.ls_colors.directory
|
ls_colors.directory
|
||||||
} else {
|
} else {
|
||||||
// Look up file name
|
// Look up file name
|
||||||
let o_style =
|
let o_style =
|
||||||
component_path.file_name()
|
component_path.file_name()
|
||||||
.and_then(|n| n.to_str())
|
.and_then(|n| n.to_str())
|
||||||
.and_then(|n| config.ls_colors.filenames.get(n));
|
.and_then(|n| ls_colors.filenames.get(n));
|
||||||
|
|
||||||
match o_style {
|
match o_style {
|
||||||
Some(s) => *s,
|
Some(s) => *s,
|
||||||
|
@ -75,7 +90,7 @@ fn print_entry(path_root: &Path, path_entry: &Path, config: &FdOptions) {
|
||||||
// Look up file extension
|
// Look up file extension
|
||||||
component_path.extension()
|
component_path.extension()
|
||||||
.and_then(|e| e.to_str())
|
.and_then(|e| e.to_str())
|
||||||
.and_then(|e| config.ls_colors.extensions.get(e))
|
.and_then(|e| ls_colors.extensions.get(e))
|
||||||
.cloned()
|
.cloned()
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
}
|
}
|
||||||
|
@ -89,11 +104,13 @@ fn print_entry(path_root: &Path, path_entry: &Path, config: &FdOptions) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
println!();
|
println!();
|
||||||
|
} else {
|
||||||
|
// Uncolored output:
|
||||||
|
println!("{}", path_str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Recursively scan the given root path and search for files / pathnames
|
/// Recursively scan the given root path and search for files / pathnames matching the pattern.
|
||||||
/// matching the pattern.
|
|
||||||
fn scan(root: &Path, pattern: &Regex, config: &FdOptions) {
|
fn scan(root: &Path, pattern: &Regex, config: &FdOptions) {
|
||||||
let walker = WalkBuilder::new(root)
|
let walker = WalkBuilder::new(root)
|
||||||
.hidden(config.ignore_hidden)
|
.hidden(config.ignore_hidden)
|
||||||
|
@ -176,28 +193,34 @@ fn main() {
|
||||||
};
|
};
|
||||||
let current_dir = current_dir_buf.as_path();
|
let current_dir = current_dir_buf.as_path();
|
||||||
|
|
||||||
|
// The search will be case-sensitive if the command line flag is set or
|
||||||
|
// if the pattern has an uppercase character (smart case).
|
||||||
|
let case_sensitive = matches.opt_present("sensitive") ||
|
||||||
|
pattern.chars().any(char::is_uppercase);
|
||||||
|
|
||||||
let colored_output = !matches.opt_present("no-color") &&
|
let colored_output = !matches.opt_present("no-color") &&
|
||||||
stdout_isatty();
|
stdout_isatty();
|
||||||
|
|
||||||
let ls_colors =
|
let ls_colors =
|
||||||
env::var("LS_COLORS")
|
if colored_output {
|
||||||
.ok()
|
Some(
|
||||||
.map(|val| LsColors::from_string(&val))
|
env::var("LS_COLORS")
|
||||||
.unwrap_or_default();
|
.ok()
|
||||||
|
.map(|val| LsColors::from_string(&val))
|
||||||
|
.unwrap_or_default()
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
let config = FdOptions {
|
let config = FdOptions {
|
||||||
// The search will be case-sensitive if the command line flag is set or
|
case_sensitive: case_sensitive,
|
||||||
// if the pattern has an uppercase character (smart case).
|
|
||||||
case_sensitive: matches.opt_present("sensitive") ||
|
|
||||||
pattern.chars().any(char::is_uppercase),
|
|
||||||
search_full_path: matches.opt_present("full-path"),
|
search_full_path: matches.opt_present("full-path"),
|
||||||
ignore_hidden: !matches.opt_present("hidden"),
|
ignore_hidden: !matches.opt_present("hidden"),
|
||||||
read_ignore: !matches.opt_present("no-ignore"),
|
read_ignore: !matches.opt_present("no-ignore"),
|
||||||
follow_links: matches.opt_present("follow"),
|
follow_links: matches.opt_present("follow"),
|
||||||
max_depth:
|
max_depth: matches.opt_str("max-depth")
|
||||||
matches.opt_str("max-depth")
|
.and_then(|ds| usize::from_str_radix(&ds, 10).ok()),
|
||||||
.and_then(|ds| usize::from_str_radix(&ds, 10).ok()),
|
|
||||||
colored: colored_output,
|
|
||||||
ls_colors: ls_colors
|
ls_colors: ls_colors
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue