Implement -F/--fixed-strings/--literal

This commit is contained in:
sharkdp 2018-02-10 15:19:53 +01:00 committed by David Peter
parent 089c183d30
commit 814d37030e
5 changed files with 53 additions and 3 deletions

View File

@ -211,6 +211,7 @@ FLAGS:
--no-ignore-vcs Do not respect .gitignore files
-s, --case-sensitive Case-sensitive search (default: smart case)
-i, --ignore-case Case-insensitive search (default: smart case)
-F, --fixed-strings Treat the pattern as a literal string
-a, --absolute-path Show absolute instead of relative paths
-L, --follow Follow symbolic links
-p, --full-path Search full path (default: file-/dirname only)
@ -222,7 +223,7 @@ OPTIONS:
-d, --max-depth <depth> Set maximum search depth (default: none)
-t, --type <filetype>... Filter by type: f(ile), d(irectory), (sym)l(ink)
-e, --extension <ext>... Filter by file extension
-x, --exec <cmd>... Execute a command for each search result
-x, --exec <cmd> Execute a command for each search result
-E, --exclude <pattern>... Exclude entries that match the given glob pattern
-c, --color <when> When to use colors: never, *auto*, always
-j, --threads <num> Set number of threads to use for searching & executing

View File

@ -47,6 +47,9 @@ Perform a case-sensitive search (default: smart case).
.B \-i, \-\-ignore\-case
Perform a case-insensitive search (default: smart case).
.TP
.B \-F, \-\-fixed\-strings
Treat the pattern as a literal string instead of a regular expression.
.TP
.B \-a, \-\-absolute\-path
Show absolute instead of relative paths.
.TP

View File

@ -61,6 +61,12 @@ pub fn build_app() -> App<'static, 'static> {
.short("i")
.overrides_with("case-sensitive"),
)
.arg(
arg("fixed-strings")
.long("fixed-strings")
.short("F")
.alias("literal"),
)
.arg(arg("absolute-path").long("absolute-path").short("a"))
.arg(arg("follow").long("follow").short("L").alias("dereference"))
.arg(arg("full-path").long("full-path").short("p"))
@ -153,6 +159,9 @@ fn usage() -> HashMap<&'static str, Help> {
, "Case-insensitive search (default: smart case)"
, "Perform a case-insensitive search. By default, fd uses case-insensitive searches, \
unless the pattern contains an uppercase character (smart case).");
doc!(h, "fixed-strings"
, "Treat the pattern as a literal string"
, "Treat the pattern as a literal string instead of a regular expression.");
doc!(h, "absolute-path"
, "Show absolute instead of relative paths"
, "Shows the full path starting from the root as opposed to relative paths.");

View File

@ -81,10 +81,17 @@ fn main() {
.collect();
}
// Treat pattern as literal string if '--fixed-strings' is used
let pattern_regex = if matches.is_present("fixed-strings") {
regex::escape(pattern)
} else {
String::from(pattern)
};
// 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.is_present("ignore-case")
&& (matches.is_present("case-sensitive") || pattern_has_uppercase_char(pattern));
&& (matches.is_present("case-sensitive") || pattern_has_uppercase_char(&pattern_regex));
let colored_output = match matches.value_of("color") {
Some("always") => true,
@ -169,7 +176,7 @@ fn main() {
.unwrap_or_else(|| vec![]),
};
match RegexBuilder::new(pattern)
match RegexBuilder::new(&pattern_regex)
.case_insensitive(!config.case_sensitive)
.dot_matches_new_line(true)
.build()

View File

@ -791,3 +791,33 @@ fn assert_exec_output(exec_style: &str) {
te.assert_output(&["e1", exec_style, "printf", "%s.%s\n"], "e1 e2.");
}
}
/// Literal search (--fixed-strings)
#[test]
fn test_fixed_strings() {
let dirs = &["test1", "test2"];
let files = &["test1/a.foo", "test1/a_foo", "test2/Download (1).tar.gz"];
let te = TestEnv::new(dirs, files);
// Regex search, dot is treated as "any character"
te.assert_output(
&["a.foo"],
"test1/a.foo
test1/a_foo",
);
// Literal search, dot is treated as character
te.assert_output(&["--fixed-strings", "a.foo"], "test1/a.foo");
// Regex search, parens are treated as group
te.assert_output(&["download (1)"], "");
// Literal search, parens are treated as characters
te.assert_output(
&["--fixed-strings", "download (1)"],
"test2/Download (1).tar.gz",
);
// Combine with --case-sensitive
te.assert_output(&["--fixed-strings", "--case-sensitive", "download (1)"], "");
}