-
-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add --include/--exclude flags, with correct precedence #809
Comments
This is a limitation of ripgrep's argv parser. It is the same reason why ripgrep doesn't have traditional --include and --exclude flags for example. I would love to fix this, but I don't know the optimal route. |
Could you expand on that, as it might be in my sphere of influence to change? The way I understand it, it's currently set up so that excludes always override includes, no? The way I imagine in the simple case is just using normal overrides in whichever flag is last "wins" (or overrides the prior). However, I'm assuming in ripgrep's case this is complicated by having multiple includes/excludes? i.e. what do I mean:
In ripgrep's help message for Edit: So keeping the current functionality as is (perhaps just adding overrides?) seems fine, with the ability to also add more traditional include/excludes. As there may be times I do want to be able to say, "ripgrep, ONLY search this one file type" which wouldn't be possible with traditional includes/excludes. So I see them (current type system with traditional include/exclude) as not mutually exclusive ideas. From a implementation standpoint traditional include/excludes are much harder to implement than just, " If what I've said is true so far, there are a few ways I could actually tackle this on my end. The easiest would be to provide something like i.e. assume we had an argv (after config parse) that was roughly The other way would involve something I've been thinking about, which is to provide companions to the validators, namely the ability to provide functions to Apologies for the length! As I began typing it was mainly me talking myself through the problem at hand 😜 Edit: Added some words about current |
Exactly. Basically, you want
I think whatever the docs say today was my attempt at documenting ripgrep's behavior, and not necessarily the ideal behavior. I'm pretty sure I was aware of this issue when I added the Lines 873 to 878 in 361698b
You can see for example that we add all positive selections followed by all negative selections. This means negative selections will always override positive selections, regardless of where they come. This is likely the source of this specific bug reported. We could swap the positive/negative and that would fix this particular bug, but it would just create another one (negative overrides that came after positive overrides would not override the positives). The docs on the
That is interesting. I might argue that this would be better solve by dropping your default ignore rules into a
I'm not sure I quite grok this, but from ripgrep's perspective, basically what I'd need is the ability to couple two or more flags together, and then have a way to ask clap for the list of values given to any of those flags in the order they were received. Each value I get would then need to be tagged with its corresponding flag (whether that's an associative list or corresponding lists or whatever doesn't really matter). That would be enough information on my end to load them into globsets, which will handle the actual precedence rules.
What do you think of my idea above in lieu of this? Is it simpler to implement? It definitely implies new API items to |
@pikeas As a note, you can work around this by not putting |
Also, @kbknapp, I admire your zeal. :) ripgrep has had this bug since day 1 (even in the docopt days), so there is no real urgency to get this fixed, and there are usually pretty easy workarounds on the user's end although it is somewhat exacerbated by the config file feature. With enough effort, I could probably fix this on ripgrep's end with some light parsing of the argv itself. I would only need to look at flags I think. For example, given:
I could pretty easily get a list of |
I actually wrote up two versions of my comment above, and deleted the original because I thought the suggestion was too much work on your end (which I'm still slightly inclined to believe), but it entailed being able to query new information from clap about the position an argument came in. At first glance it appeared to me like it'd be a quick win and easy to implement this feature (include/exclude) with this new information. And since clap already knows all this info, its super simple for me to add on that side of things. It's also quite general purpose because it doesn't assume a particular use case (like An example would look something like this:
Which clap reports as
With just two overlapping values this is simple, but even so based off just what clap reports we can't actually know what the user wanted because there's two truths. So back to including position information which would look something like this (using that original argv as an example). matches.positions_of("include"); // [1, 4]
matches.positions_of("exclude"); // [2, 3]
matches.position_of("include"); // [1]
matches.position_of("exclude"); // [2]
matches.values_of("include").unwrap().with_positions(); // An iterator that provides [(1, A), (4, B)]
matches.values_of("exclude").unwrap().with_positions(); // An iterator that provides [(2, B), (3, C)] That could be used to get a final list for your globset via // Collect up chained values
let mut combined = matches.values_of("include").unwrap()
.with_positions()
.chain(matches.values_of("exclude").unwrap()
.with_positions()
.collect();
// Sorting by position
combined.sort_by_key(|tup| tup.0);
// Remove "overrides"
let mut overrides = vec![];
for (i, a) in combined.iter().enumerate() {
if combined[i+1..].iter().any(|tup| tup.1 == a.1) {
overrides.push(i);
}
}
for &i in overrides.iter().rev() {
combined.swap_remove(i);
}
// swap back out into separate fields
let mut includes = Vec::new();
let mut excludes = Vec::new();
let inc_p: Vec<_> = matches.positions_of("include").unwrap().collect();
for (p, val) in combined.into_iter() {
if inc_p.contains(p) {
includes.push(val);
} else {
excludes.push(val);
}
}
// From our original argv, we now have
// include = ["A", "B"]
// exclude = ["C"] I'm sure there's far more clean ways to do this (and more efficient), but this was just off the top of my head. |
Since the |
I think there's no need for quite so much custom argv parsing, at least not anymore. I think that, as this is done, I think that with these two proposals, the user could accomplish most things they might want to do with |
Turns out that clap now was archived in Github. Any direction for now? |
clap is not archived and as of ripgrep 14, ripgrep no longer uses clap. |
Sorry, my bad. I was confuse with an older Github repo: https://github.com/epage/clapng
So it means that the blocker for this issue is irrelevant, and this issue may be solved? |
From a narrow technical perspective, sure, it is now very easy to implement But, I am currently in the (long) process of overhauling how globbing is implemented. And then I plan to move into figuring out how to make ripgrep's filtering story crisper. A sizeable fraction of extant open issues are related to filtering in one form or another. So I'd rather add these flags as part of figuring out the grander filtering story. |
thanks |
On rg 0.8.0 / OS X 10.12.6
When using
rg -Tfiletype -tfiletype foo
, the exclude takes precedence over the include. Is this intentional behavior?My use case is a
.ripgreprc
which excludes minified files by default, which I do occasionally need to search. I can dorg --type-add=minified:*.min.{css,js} -tminified --no-config foo
in this case, but this is pretty clunky. I would much rather dorg -tminified foo
and have my include clobber my config file's default exclude.The text was updated successfully, but these errors were encountered: