mirror of https://github.com/sharkdp/fd.git
Implement -F/--fixed-strings/--literal
This commit is contained in:
parent
089c183d30
commit
814d37030e
|
@ -211,6 +211,7 @@ FLAGS:
|
||||||
--no-ignore-vcs Do not respect .gitignore files
|
--no-ignore-vcs Do not respect .gitignore files
|
||||||
-s, --case-sensitive Case-sensitive search (default: smart case)
|
-s, --case-sensitive Case-sensitive search (default: smart case)
|
||||||
-i, --ignore-case Case-insensitive 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
|
-a, --absolute-path Show absolute instead of relative paths
|
||||||
-L, --follow Follow symbolic links
|
-L, --follow Follow symbolic links
|
||||||
-p, --full-path Search full path (default: file-/dirname only)
|
-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)
|
-d, --max-depth <depth> Set maximum search depth (default: none)
|
||||||
-t, --type <filetype>... Filter by type: f(ile), d(irectory), (sym)l(ink)
|
-t, --type <filetype>... Filter by type: f(ile), d(irectory), (sym)l(ink)
|
||||||
-e, --extension <ext>... Filter by file extension
|
-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
|
-E, --exclude <pattern>... Exclude entries that match the given glob pattern
|
||||||
-c, --color <when> When to use colors: never, *auto*, always
|
-c, --color <when> When to use colors: never, *auto*, always
|
||||||
-j, --threads <num> Set number of threads to use for searching & executing
|
-j, --threads <num> Set number of threads to use for searching & executing
|
||||||
|
|
3
doc/fd.1
3
doc/fd.1
|
@ -47,6 +47,9 @@ Perform a case-sensitive search (default: smart case).
|
||||||
.B \-i, \-\-ignore\-case
|
.B \-i, \-\-ignore\-case
|
||||||
Perform a case-insensitive search (default: smart case).
|
Perform a case-insensitive search (default: smart case).
|
||||||
.TP
|
.TP
|
||||||
|
.B \-F, \-\-fixed\-strings
|
||||||
|
Treat the pattern as a literal string instead of a regular expression.
|
||||||
|
.TP
|
||||||
.B \-a, \-\-absolute\-path
|
.B \-a, \-\-absolute\-path
|
||||||
Show absolute instead of relative paths.
|
Show absolute instead of relative paths.
|
||||||
.TP
|
.TP
|
||||||
|
|
|
@ -61,6 +61,12 @@ pub fn build_app() -> App<'static, 'static> {
|
||||||
.short("i")
|
.short("i")
|
||||||
.overrides_with("case-sensitive"),
|
.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("absolute-path").long("absolute-path").short("a"))
|
||||||
.arg(arg("follow").long("follow").short("L").alias("dereference"))
|
.arg(arg("follow").long("follow").short("L").alias("dereference"))
|
||||||
.arg(arg("full-path").long("full-path").short("p"))
|
.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)"
|
, "Case-insensitive search (default: smart case)"
|
||||||
, "Perform a case-insensitive search. By default, fd uses case-insensitive searches, \
|
, "Perform a case-insensitive search. By default, fd uses case-insensitive searches, \
|
||||||
unless the pattern contains an uppercase character (smart case).");
|
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"
|
doc!(h, "absolute-path"
|
||||||
, "Show absolute instead of relative paths"
|
, "Show absolute instead of relative paths"
|
||||||
, "Shows the full path starting from the root as opposed to relative paths.");
|
, "Shows the full path starting from the root as opposed to relative paths.");
|
||||||
|
|
11
src/main.rs
11
src/main.rs
|
@ -81,10 +81,17 @@ fn main() {
|
||||||
.collect();
|
.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
|
// 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 = !matches.is_present("ignore-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") {
|
let colored_output = match matches.value_of("color") {
|
||||||
Some("always") => true,
|
Some("always") => true,
|
||||||
|
@ -169,7 +176,7 @@ fn main() {
|
||||||
.unwrap_or_else(|| vec![]),
|
.unwrap_or_else(|| vec![]),
|
||||||
};
|
};
|
||||||
|
|
||||||
match RegexBuilder::new(pattern)
|
match RegexBuilder::new(&pattern_regex)
|
||||||
.case_insensitive(!config.case_sensitive)
|
.case_insensitive(!config.case_sensitive)
|
||||||
.dot_matches_new_line(true)
|
.dot_matches_new_line(true)
|
||||||
.build()
|
.build()
|
||||||
|
|
|
@ -791,3 +791,33 @@ fn assert_exec_output(exec_style: &str) {
|
||||||
te.assert_output(&["e1", exec_style, "printf", "%s.%s\n"], "e1 e2.");
|
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)"], "");
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue