mirror of
https://github.com/BurntSushi/ripgrep.git
synced 2025-03-03 14:32:22 +02:00
Add -s/--case-sensitive flag.
This flag overrides both --smart-case and --ignore-case. Closes #124.
This commit is contained in:
parent
316ffd87b3
commit
925d0db9f0
14
doc/rg.1
14
doc/rg.1
@ -70,6 +70,7 @@ Show this usage message.
|
||||
.TP
|
||||
.B \-i, \-\-ignore\-case
|
||||
Case insensitive search.
|
||||
Overridden by \-\-case\-sensitive.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
@ -209,6 +210,12 @@ Follow symlinks.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-\-maxdepth \f[I]NUM\f[]
|
||||
Descend at most NUM directories below the command line arguments.
|
||||
A value of zero searches only the starting\-points themselves.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-\-mmap
|
||||
Search using memory maps when possible.
|
||||
This is enabled by default when ripgrep thinks it will be faster.
|
||||
@ -252,9 +259,16 @@ Alias for \-\-color=always \-\-heading \-n.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-s, \-\-case\-sensitive
|
||||
Search case sensitively.
|
||||
This overrides \-\-ignore\-case and \-\-smart\-case.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
.B \-S, \-\-smart\-case
|
||||
Search case insensitively if the pattern is all lowercase.
|
||||
Search case sensitively otherwise.
|
||||
This is overridden by either \-\-case\-sensitive or \-\-ignore\-case.
|
||||
.RS
|
||||
.RE
|
||||
.TP
|
||||
|
@ -49,7 +49,7 @@ the raw speed of grep.
|
||||
: Show this usage message.
|
||||
|
||||
-i, --ignore-case
|
||||
: Case insensitive search.
|
||||
: Case insensitive search. Overridden by --case-sensitive.
|
||||
|
||||
-n, --line-number
|
||||
: Show line numbers (1-based). This is enabled by default at a tty.
|
||||
@ -168,9 +168,13 @@ the raw speed of grep.
|
||||
-p, --pretty
|
||||
: Alias for --color=always --heading -n.
|
||||
|
||||
-s, --case-sensitive
|
||||
: Search case sensitively. This overrides --ignore-case and --smart-case.
|
||||
|
||||
-S, --smart-case
|
||||
: Search case insensitively if the pattern is all lowercase.
|
||||
Search case sensitively otherwise.
|
||||
Search case sensitively otherwise. This is overridden by either
|
||||
--case-sensitive or --ignore-case.
|
||||
|
||||
-j, --threads *ARG*
|
||||
: The number of threads to use. Defaults to the number of logical CPUs
|
||||
|
68
src/args.rs
68
src/args.rs
@ -62,6 +62,7 @@ Common options:
|
||||
Precede a glob with a '!' to exclude it.
|
||||
-h, --help Show this usage message.
|
||||
-i, --ignore-case Case insensitive search.
|
||||
Overridden by --case-sensitive.
|
||||
-n, --line-number Show line numbers (1-based). This is enabled
|
||||
by default at a tty.
|
||||
-N, --no-line-number Suppress line numbers.
|
||||
@ -168,9 +169,13 @@ Less common options:
|
||||
-p, --pretty
|
||||
Alias for --color=always --heading -n.
|
||||
|
||||
-s, --case-sensitive
|
||||
Search case sensitively. This overrides --ignore-case and --smart-case.
|
||||
|
||||
-S, --smart-case
|
||||
Search case insensitively if the pattern is all lowercase.
|
||||
Search case sensitively otherwise.
|
||||
Search case sensitively otherwise. This is overridden by
|
||||
either --case-sensitive or --ignore-case.
|
||||
|
||||
-j, --threads ARG
|
||||
The number of threads to use. Defaults to the number of logical CPUs
|
||||
@ -210,6 +215,7 @@ pub struct RawArgs {
|
||||
arg_path: Vec<String>,
|
||||
flag_after_context: usize,
|
||||
flag_before_context: usize,
|
||||
flag_case_sensitive: bool,
|
||||
flag_color: String,
|
||||
flag_column: bool,
|
||||
flag_context: usize,
|
||||
@ -257,7 +263,6 @@ pub struct RawArgs {
|
||||
/// Args are transformed/normalized from RawArgs.
|
||||
#[derive(Debug)]
|
||||
pub struct Args {
|
||||
pattern: String,
|
||||
paths: Vec<PathBuf>,
|
||||
after_context: usize,
|
||||
before_context: usize,
|
||||
@ -287,7 +292,6 @@ pub struct Args {
|
||||
replace: Option<Vec<u8>>,
|
||||
text: bool,
|
||||
threads: usize,
|
||||
type_defs: Vec<FileTypeDef>,
|
||||
type_list: bool,
|
||||
types: Types,
|
||||
with_filename: bool,
|
||||
@ -296,7 +300,6 @@ pub struct Args {
|
||||
impl RawArgs {
|
||||
/// Convert arguments parsed into a configuration used by ripgrep.
|
||||
fn to_args(&self) -> Result<Args> {
|
||||
let pattern = self.pattern();
|
||||
let paths =
|
||||
if self.arg_path.is_empty() {
|
||||
if atty::on_stdin()
|
||||
@ -362,7 +365,6 @@ impl RawArgs {
|
||||
} else {
|
||||
self.flag_color == "always"
|
||||
};
|
||||
let eol = b'\n';
|
||||
|
||||
let mut with_filename = self.flag_with_filename;
|
||||
if !with_filename {
|
||||
@ -370,22 +372,10 @@ impl RawArgs {
|
||||
}
|
||||
with_filename = with_filename && !self.flag_no_filename;
|
||||
|
||||
let mut btypes = TypesBuilder::new();
|
||||
btypes.add_defaults();
|
||||
try!(self.add_types(&mut btypes));
|
||||
let types = try!(btypes.build());
|
||||
let grep = try!(
|
||||
GrepBuilder::new(&pattern)
|
||||
.case_smart(self.flag_smart_case)
|
||||
.case_insensitive(self.flag_ignore_case)
|
||||
.line_terminator(eol)
|
||||
.build()
|
||||
);
|
||||
let no_ignore = self.flag_no_ignore || self.flag_unrestricted >= 1;
|
||||
let hidden = self.flag_hidden || self.flag_unrestricted >= 2;
|
||||
let text = self.flag_text || self.flag_unrestricted >= 3;
|
||||
let mut args = Args {
|
||||
pattern: pattern,
|
||||
paths: paths,
|
||||
after_context: after_context,
|
||||
before_context: before_context,
|
||||
@ -394,11 +384,11 @@ impl RawArgs {
|
||||
context_separator: unescape(&self.flag_context_separator),
|
||||
count: self.flag_count,
|
||||
files_with_matches: self.flag_files_with_matches,
|
||||
eol: eol,
|
||||
eol: self.eol(),
|
||||
files: self.flag_files,
|
||||
follow: self.flag_follow,
|
||||
glob_overrides: glob_overrides,
|
||||
grep: grep,
|
||||
grep: try!(self.grep()),
|
||||
heading: !self.flag_no_heading && self.flag_heading,
|
||||
hidden: hidden,
|
||||
ignore_case: self.flag_ignore_case,
|
||||
@ -419,9 +409,8 @@ impl RawArgs {
|
||||
replace: self.flag_replace.clone().map(|s| s.into_bytes()),
|
||||
text: text,
|
||||
threads: threads,
|
||||
type_defs: btypes.definitions(),
|
||||
type_list: self.flag_type_list,
|
||||
types: types,
|
||||
types: try!(self.types()),
|
||||
with_filename: with_filename,
|
||||
};
|
||||
// If stdout is a tty, then apply some special default options.
|
||||
@ -440,20 +429,22 @@ impl RawArgs {
|
||||
Ok(args)
|
||||
}
|
||||
|
||||
fn add_types(&self, types: &mut TypesBuilder) -> Result<()> {
|
||||
fn types(&self) -> Result<Types> {
|
||||
let mut btypes = TypesBuilder::new();
|
||||
btypes.add_defaults();
|
||||
for ty in &self.flag_type_clear {
|
||||
types.clear(ty);
|
||||
btypes.clear(ty);
|
||||
}
|
||||
for def in &self.flag_type_add {
|
||||
try!(types.add_def(def));
|
||||
try!(btypes.add_def(def));
|
||||
}
|
||||
for ty in &self.flag_type {
|
||||
types.select(ty);
|
||||
btypes.select(ty);
|
||||
}
|
||||
for ty in &self.flag_type_not {
|
||||
types.negate(ty);
|
||||
btypes.negate(ty);
|
||||
}
|
||||
Ok(())
|
||||
btypes.build().map_err(From::from)
|
||||
}
|
||||
|
||||
fn pattern(&self) -> String {
|
||||
@ -483,6 +474,27 @@ impl RawArgs {
|
||||
s
|
||||
}
|
||||
}
|
||||
|
||||
fn eol(&self) -> u8 {
|
||||
// We might want to make this configurable.
|
||||
b'\n'
|
||||
}
|
||||
|
||||
fn grep(&self) -> Result<Grep> {
|
||||
let smart =
|
||||
self.flag_smart_case
|
||||
&& !self.flag_ignore_case
|
||||
&& !self.flag_case_sensitive;
|
||||
let casei =
|
||||
self.flag_ignore_case
|
||||
&& !self.flag_case_sensitive;
|
||||
GrepBuilder::new(&self.pattern())
|
||||
.case_smart(smart)
|
||||
.case_insensitive(casei)
|
||||
.line_terminator(self.eol())
|
||||
.build()
|
||||
.map_err(From::from)
|
||||
}
|
||||
}
|
||||
|
||||
impl Args {
|
||||
@ -677,7 +689,7 @@ impl Args {
|
||||
|
||||
/// Returns a list of type definitions currently loaded.
|
||||
pub fn type_defs(&self) -> &[FileTypeDef] {
|
||||
&self.type_defs
|
||||
self.types.definitions()
|
||||
}
|
||||
|
||||
/// Returns true if ripgrep should print the type definitions currently
|
||||
|
16
src/types.rs
16
src/types.rs
@ -159,6 +159,7 @@ impl FileTypeDef {
|
||||
/// Types is a file type matcher.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Types {
|
||||
defs: Vec<FileTypeDef>,
|
||||
selected: Option<glob::SetYesNo>,
|
||||
negated: Option<glob::SetYesNo>,
|
||||
has_selected: bool,
|
||||
@ -176,8 +177,10 @@ impl Types {
|
||||
selected: Option<glob::SetYesNo>,
|
||||
negated: Option<glob::SetYesNo>,
|
||||
has_selected: bool,
|
||||
defs: Vec<FileTypeDef>,
|
||||
) -> Types {
|
||||
Types {
|
||||
defs: defs,
|
||||
selected: selected,
|
||||
negated: negated,
|
||||
has_selected: has_selected,
|
||||
@ -193,7 +196,7 @@ impl Types {
|
||||
|
||||
/// Creates a new file type matcher that never matches.
|
||||
pub fn empty() -> Types {
|
||||
Types::new(None, None, false)
|
||||
Types::new(None, None, false, vec![])
|
||||
}
|
||||
|
||||
/// Returns a match for the given path against this file type matcher.
|
||||
@ -233,6 +236,11 @@ impl Types {
|
||||
Match::None
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the set of current file type definitions.
|
||||
pub fn definitions(&self) -> &[FileTypeDef] {
|
||||
&self.defs
|
||||
}
|
||||
}
|
||||
|
||||
/// TypesBuilder builds a type matcher from a set of file type definitions and
|
||||
@ -298,7 +306,11 @@ impl TypesBuilder {
|
||||
Some(try!(bset.build_yesno()))
|
||||
};
|
||||
Ok(Types::new(
|
||||
selected_globs, negated_globs, !self.selected.is_empty()))
|
||||
selected_globs,
|
||||
negated_globs,
|
||||
!self.selected.is_empty(),
|
||||
self.definitions(),
|
||||
))
|
||||
}
|
||||
|
||||
/// Return the set of current file type definitions.
|
||||
|
@ -754,7 +754,8 @@ clean!(regression_105_part2, "test", ".", |wd: WorkDir, mut cmd: Command| {
|
||||
});
|
||||
|
||||
// See: https://github.com/BurntSushi/ripgrep/issues/20
|
||||
sherlock!(feature_20, "Sherlock", ".", |wd: WorkDir, mut cmd: Command| {
|
||||
sherlock!(feature_20_no_filename, "Sherlock", ".",
|
||||
|wd: WorkDir, mut cmd: Command| {
|
||||
cmd.arg("--no-filename");
|
||||
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
@ -766,7 +767,7 @@ be, to a very large extent, the result of luck. Sherlock Holmes
|
||||
});
|
||||
|
||||
// See: https://github.com/BurntSushi/ripgrep/issues/68
|
||||
clean!(feature_68, "test", ".", |wd: WorkDir, mut cmd: Command| {
|
||||
clean!(feature_68_no_ignore_vcs, "test", ".", |wd: WorkDir, mut cmd: Command| {
|
||||
wd.create(".gitignore", "foo");
|
||||
wd.create(".ignore", "bar");
|
||||
wd.create("foo", "test");
|
||||
@ -778,7 +779,8 @@ clean!(feature_68, "test", ".", |wd: WorkDir, mut cmd: Command| {
|
||||
});
|
||||
|
||||
// See: https://github.com/BurntSushi/ripgrep/issues/70
|
||||
sherlock!(feature_70, "sherlock", ".", |wd: WorkDir, mut cmd: Command| {
|
||||
sherlock!(feature_70_smart_case, "sherlock", ".",
|
||||
|wd: WorkDir, mut cmd: Command| {
|
||||
cmd.arg("--smart-case");
|
||||
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
@ -832,7 +834,7 @@ sherlock\x00can extract a clew from a wisp of straw or a flake of cigar ash;
|
||||
});
|
||||
|
||||
// See: https://github.com/BurntSushi/ripgrep/issues/109
|
||||
clean!(max_depth, "far", ".", |wd: WorkDir, mut cmd: Command| {
|
||||
clean!(feature_109_max_depth, "far", ".", |wd: WorkDir, mut cmd: Command| {
|
||||
wd.create_dir("one");
|
||||
wd.create("one/pass", "far");
|
||||
wd.create_dir("one/too");
|
||||
@ -842,10 +844,25 @@ clean!(max_depth, "far", ".", |wd: WorkDir, mut cmd: Command| {
|
||||
|
||||
let lines: String = wd.stdout(&mut cmd);
|
||||
let expected = path("one/pass:far\n");
|
||||
|
||||
assert_eq!(lines, expected);
|
||||
});
|
||||
|
||||
// See: https://github.com/BurntSushi/ripgrep/issues/124
|
||||
clean!(feature_109_case_sensitive_part1, "test", ".",
|
||||
|wd: WorkDir, mut cmd: Command| {
|
||||
wd.create("foo", "tEsT");
|
||||
cmd.arg("--smart-case").arg("--case-sensitive");
|
||||
wd.assert_err(&mut cmd);
|
||||
});
|
||||
|
||||
// See: https://github.com/BurntSushi/ripgrep/issues/124
|
||||
clean!(feature_109_case_sensitive_part2, "test", ".",
|
||||
|wd: WorkDir, mut cmd: Command| {
|
||||
wd.create("foo", "tEsT");
|
||||
cmd.arg("--ignore-case").arg("--case-sensitive");
|
||||
wd.assert_err(&mut cmd);
|
||||
});
|
||||
|
||||
#[test]
|
||||
fn binary_nosearch() {
|
||||
let wd = WorkDir::new("binary_nosearch");
|
||||
|
Loading…
x
Reference in New Issue
Block a user