mirror of
https://github.com/sharkdp/fd.git
synced 2024-10-31 19:41:01 +01:00
Improve smart case to only consider literal uppercase chars (#103)
This commit is contained in:
parent
8fc3a83d92
commit
b441528067
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -9,6 +9,7 @@ dependencies = [
|
|||||||
"ignore 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ignore 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ ansi_term = "0.9"
|
|||||||
clap = "2.26.0"
|
clap = "2.26.0"
|
||||||
atty = "0.2"
|
atty = "0.2"
|
||||||
regex = "0.2"
|
regex = "0.2"
|
||||||
|
regex-syntax = "0.4"
|
||||||
ignore = "0.2"
|
ignore = "0.2"
|
||||||
num_cpus = "1.6.2"
|
num_cpus = "1.6.2"
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ use std::io::Write;
|
|||||||
|
|
||||||
use lscolors::LsColors;
|
use lscolors::LsColors;
|
||||||
use walk::FileType;
|
use walk::FileType;
|
||||||
|
use regex_syntax::{Expr, ExprBuilder};
|
||||||
|
|
||||||
/// Root directory
|
/// Root directory
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
@ -78,3 +79,28 @@ pub fn error(message: &str) -> ! {
|
|||||||
writeln!(&mut ::std::io::stderr(), "{}", message).expect("Failed writing to stderr");
|
writeln!(&mut ::std::io::stderr(), "{}", message).expect("Failed writing to stderr");
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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()),
|
||||||
|
Expr::Class(ref ranges) => {
|
||||||
|
ranges.iter().any(|r| {
|
||||||
|
r.start.is_uppercase() || r.end.is_uppercase()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Expr::Group { ref e, .. } => expr_has_uppercase_char(e),
|
||||||
|
Expr::Repeat { ref e, .. } => expr_has_uppercase_char(e),
|
||||||
|
Expr::Concat(ref es) => es.iter().any(expr_has_uppercase_char),
|
||||||
|
Expr::Alternate(ref es) => es.iter().any(expr_has_uppercase_char),
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
10
src/main.rs
10
src/main.rs
@ -3,6 +3,7 @@ extern crate clap;
|
|||||||
extern crate ansi_term;
|
extern crate ansi_term;
|
||||||
extern crate atty;
|
extern crate atty;
|
||||||
extern crate regex;
|
extern crate regex;
|
||||||
|
extern crate regex_syntax;
|
||||||
extern crate ignore;
|
extern crate ignore;
|
||||||
extern crate num_cpus;
|
extern crate num_cpus;
|
||||||
|
|
||||||
@ -22,7 +23,7 @@ use std::time;
|
|||||||
use atty::Stream;
|
use atty::Stream;
|
||||||
use regex::RegexBuilder;
|
use regex::RegexBuilder;
|
||||||
|
|
||||||
use internal::{error, FdOptions, PathDisplay, ROOT_DIR};
|
use internal::{error, pattern_has_uppercase_char, FdOptions, PathDisplay, ROOT_DIR};
|
||||||
use lscolors::LsColors;
|
use lscolors::LsColors;
|
||||||
use walk::FileType;
|
use walk::FileType;
|
||||||
|
|
||||||
@ -65,11 +66,8 @@ fn main() {
|
|||||||
|
|
||||||
// The search will be case-sensitive if the command line flag is set or
|
// The search will be case-sensitive if the command line flag is set or
|
||||||
// if the pattern has an uppercase character (smart case).
|
// if the pattern has an uppercase character (smart case).
|
||||||
let case_sensitive = if !matches.is_present("ignore-case") {
|
let case_sensitive = !matches.is_present("ignore-case") &&
|
||||||
matches.is_present("case-sensitive") || pattern.chars().any(char::is_uppercase)
|
(matches.is_present("case-sensitive") || pattern_has_uppercase_char(pattern));
|
||||||
} else {
|
|
||||||
false
|
|
||||||
};
|
|
||||||
|
|
||||||
let colored_output = match matches.value_of("color") {
|
let colored_output = match matches.value_of("color") {
|
||||||
Some("always") => true,
|
Some("always") => true,
|
||||||
|
@ -115,6 +115,14 @@ fn test_smart_case() {
|
|||||||
te.assert_output(&["C.Foo"], "one/two/C.Foo2");
|
te.assert_output(&["C.Foo"], "one/two/C.Foo2");
|
||||||
|
|
||||||
te.assert_output(&["Foo"], "one/two/C.Foo2");
|
te.assert_output(&["Foo"], "one/two/C.Foo2");
|
||||||
|
|
||||||
|
// Only literal uppercase chars should trigger case sensitivity.
|
||||||
|
te.assert_output(
|
||||||
|
&["\\Ac"],
|
||||||
|
"one/two/c.foo
|
||||||
|
one/two/C.Foo2",
|
||||||
|
);
|
||||||
|
te.assert_output(&["\\AC"], "one/two/C.Foo2");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Case sensitivity (--case-sensitive)
|
/// Case sensitivity (--case-sensitive)
|
||||||
|
Loading…
Reference in New Issue
Block a user