summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter S Panov <peter@sipan.org>2017-06-29 00:57:33 +0000
committerAndrew Gallant <jamslam@gmail.com>2017-07-03 06:52:52 -0400
commit4047d9db710026b7f003243032f52d7c99c41ded (patch)
tree31a683ad965249ea5eabfe9052a6aa25d9a2badb
parent4683a325fae596db75176d188034c6623e91db79 (diff)
add --iglob flag
Working with Chris Stadler, implemented https://github.com/BurntSushi/ripgrep/issues/163#issuecomment-300012592
-rw-r--r--ignore/src/gitignore.rs30
-rw-r--r--ignore/src/overrides.rs33
-rw-r--r--src/app.rs10
-rw-r--r--src/args.rs8
-rw-r--r--tests/tests.rs15
5 files changed, 96 insertions, 0 deletions
diff --git a/ignore/src/gitignore.rs b/ignore/src/gitignore.rs
index 68655261..7ae91bf8 100644
--- a/ignore/src/gitignore.rs
+++ b/ignore/src/gitignore.rs
@@ -254,6 +254,7 @@ pub struct GitignoreBuilder {
builder: GlobSetBuilder,
root: PathBuf,
globs: Vec<Glob>,
+ case_insensitive: bool,
}
impl GitignoreBuilder {
@@ -269,6 +270,7 @@ impl GitignoreBuilder {
builder: GlobSetBuilder::new(),
root: strip_prefix("./", root).unwrap_or(root).to_path_buf(),
globs: vec![],
+ case_insensitive: false,
}
}
@@ -424,6 +426,7 @@ impl GitignoreBuilder {
let parsed = try!(
GlobBuilder::new(&glob.actual)
.literal_separator(literal_separator)
+ .case_insensitive(self.case_insensitive)
.build()
.map_err(|err| {
Error::Glob {
@@ -435,6 +438,16 @@ impl GitignoreBuilder {
self.globs.push(glob);
Ok(self)
}
+
+ /// Toggle whether the globs should be matched case insensitively or not.
+ ///
+ /// This is disabled by default.
+ pub fn case_insensitive(
+ &mut self, yes: bool
+ ) -> Result<&mut GitignoreBuilder, Error> {
+ self.case_insensitive = yes;
+ Ok(self)
+ }
}
/// Return the file path of the current environment's global gitignore file.
@@ -617,4 +630,21 @@ mod tests {
fn regression_106() {
gi_from_str("/", " ");
}
+
+ #[test]
+ fn case_insensitive() {
+ let gi = GitignoreBuilder::new(ROOT)
+ .case_insensitive(true).unwrap()
+ .add_str(None, "*.html").unwrap()
+ .build().unwrap();
+ assert!(gi.matched("foo.html", false).is_ignore());
+ assert!(gi.matched("foo.HTML", false).is_ignore());
+ assert!(!gi.matched("foo.htm", false).is_ignore());
+ assert!(!gi.matched("foo.HTM", false).is_ignore());
+ }
+
+ ignored!(cs1, ROOT, "*.html", "foo.html");
+ not_ignored!(cs2, ROOT, "*.html", "foo.HTML");
+ not_ignored!(cs3, ROOT, "*.html", "foo.htm");
+ not_ignored!(cs4, ROOT, "*.html", "foo.HTM");
}
diff --git a/ignore/src/overrides.rs b/ignore/src/overrides.rs
index faf05f31..453066f9 100644
--- a/ignore/src/overrides.rs
+++ b/ignore/src/overrides.rs
@@ -137,6 +137,16 @@ impl OverrideBuilder {
try!(self.builder.add_line(None, glob));
Ok(self)
}
+
+ /// Toggle whether the globs should be matched case insensitively or not.
+ ///
+ /// This is disabled by default.
+ pub fn case_insensitive(
+ &mut self, yes: bool
+ ) -> Result<&mut OverrideBuilder, Error> {
+ try!(self.builder.case_insensitive(yes));
+ Ok(self)
+ }
}
#[cfg(test)]
@@ -220,4 +230,27 @@ mod tests {
let ov = ov(&["!/bar"]);
assert!(ov.matched("./foo/bar", false).is_none());
}
+
+ #[test]
+ fn case_insensitive() {
+ let ov = OverrideBuilder::new(ROOT)
+ .case_insensitive(true).unwrap()
+ .add("*.html").unwrap()
+ .build().unwrap();
+ assert!(ov.matched("foo.html", false).is_whitelist());
+ assert!(ov.matched("foo.HTML", false).is_whitelist());
+ assert!(ov.matched("foo.htm", false).is_ignore());
+ assert!(ov.matched("foo.HTM", false).is_ignore());
+ }
+
+ #[test]
+ fn default_case_sensitive() {
+ let ov = OverrideBuilder::new(ROOT)
+ .add("*.html").unwrap()
+ .build().unwrap();
+ assert!(ov.matched("foo.html", false).is_whitelist());
+ assert!(ov.matched("foo.HTML", false).is_ignore());
+ assert!(ov.matched("foo.htm", false).is_ignore());
+ assert!(ov.matched("foo.HTM", false).is_ignore());
+ }
}
diff --git a/src/app.rs b/src/app.rs
index e43dc5ae..832ac6ea 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -90,6 +90,9 @@ pub fn app() -> App<'static, 'static> {
.arg(flag("glob").short("g")
.takes_value(true).multiple(true).number_of_values(1)
.value_name("GLOB"))
+ .arg(flag("iglob")
+ .takes_value(true).multiple(true).number_of_values(1)
+ .value_name("GLOB"))
.arg(flag("ignore-case").short("i"))
.arg(flag("line-number").short("n"))
.arg(flag("no-line-number").short("N").overrides_with("line-number"))
@@ -270,6 +273,13 @@ lazy_static! {
ignore logic. Multiple glob flags may be used. Globbing \
rules match .gitignore globs. Precede a glob with a ! \
to exclude it.");
+ doc!(h, "iglob",
+ "Include or exclude files/directories case insensitively.",
+ "Include or exclude files/directories for searching that \
+ match the given glob. This always overrides any other \
+ ignore logic. Multiple glob flags may be used. Globbing \
+ rules match .gitignore globs. Precede a glob with a ! \
+ to exclude it. Globs are matched case insensitively.");
doc!(h, "ignore-case",
"Case insensitive search.",
"Case insensitive search. This is overridden by \
diff --git a/src/args.rs b/src/args.rs
index b0e5d648..cd905b45 100644
--- a/src/args.rs
+++ b/src/args.rs
@@ -771,6 +771,14 @@ impl<'a> ArgMatches<'a> {
for glob in self.values_of_lossy_vec("glob") {
try!(ovr.add(&glob));
}
+ // this is smelly. In the long run it might make sense
+ // to change overridebuilder to be like globsetbuilder
+ // but this would be a breaking change to the ignore crate
+ // so it is being shelved for now...
+ try!(ovr.case_insensitive(true));
+ for glob in self.values_of_lossy_vec("iglob") {
+ try!(ovr.add(&glob));
+ }
ovr.build().map_err(From::from)
}
diff --git a/tests/tests.rs b/tests/tests.rs
index 95fecfd4..8e0c9e0b 100644
--- a/tests/tests.rs
+++ b/tests/tests.rs
@@ -336,6 +336,21 @@ sherlock!(glob_negate, "Sherlock", ".", |wd: WorkDir, mut cmd: Command| {
assert_eq!(lines, "file.py:Sherlock\n");
});
+sherlock!(iglob, "Sherlock", ".", |wd: WorkDir, mut cmd: Command| {
+ wd.create("file.HTML", "Sherlock");
+ cmd.arg("--iglob").arg("*.html");
+ let lines: String = wd.stdout(&mut cmd);
+ assert_eq!(lines, "file.HTML:Sherlock\n");
+});
+
+sherlock!(csglob, "Sherlock", ".", |wd: WorkDir, mut cmd: Command| {
+ wd.create("file1.HTML", "Sherlock");
+ wd.create("file2.html", "Sherlock");
+ cmd.arg("--glob").arg("*.html");
+ let lines: String = wd.stdout(&mut cmd);
+ assert_eq!(lines, "file2.html:Sherlock\n");
+});
+
sherlock!(count, "Sherlock", ".", |wd: WorkDir, mut cmd: Command| {
cmd.arg("--count");
let lines: String = wd.stdout(&mut cmd);