Add invert-find operation mode
These changes introduce a new feature to the tag command-line tool: the ability to find files that do not
contain any of the specified tags. This is achieved through the addition of two new operation modes:
-
OperationModeInvertFind: This mode is triggered by the-For--invert-findoption, and it causes the tool to search for files that do not contain any of the specified tags. - A new method called
doInvertFindis added to theTagclass to handle this operation mode. This method calls another new method calledfindFilesWithoutTagWithUsage:NO, which performs the actual file search.
The changes also modify the existing help text and man page to document the new feature.
Here's a summary of the key changes:
- Added two new operation modes:
OperationModeInvertFindand a new methoddoInvertFindto handle it. - Modified the existing help text and man page to document the new feature.
- Introduced a new method called
findFilesWithoutTagWithUsage:NO, which performs the actual file search for files that do not contain any of the specified tags.
Demonstrating these changes enable users to find files that do not contain specific tags:
$ ./tag(invert_find) bin/tag -F red .
./tag/LICENSE
./tag/Makefile
./tag/README.md
./tag/Tag
./tag/Tag/Tag.h
./tag/Tag/Tag.m
./tag/Tag.xcodeproj
./tag/Tag/TagName.h
./tag/Tag/TagName.m
./tag/bin
./tag/Tag/main.m
./tag/bin/tag
./tag/Tag/tag.1
$ # Set red to ./tag/bin/tag and confirm file no longer is returned from -F search
$ ./tag(invert_find) bin/tag -s red bin/tag
$ ./tag(invert_find) bin/tag --invert-find red .
./tag/LICENSE
./tag/Makefile
./tag/README.md
./tag/Tag
./tag/Tag/Tag.h
./tag/Tag/Tag.m
./tag/Tag.xcodeproj
./tag/Tag/TagName.h
./tag/Tag/TagName.m
./tag/bin
./tag/Tag/main.m
./tag/Tag/tag.1
$ # Success! ./tag/bin/tag no longer is returned from -F search (above)
$ ./tag(invert_find) bin/tag -f red .
./tag/bin/tag
Instead of searching for files and then post-qualifying them to those that don't contain the tags, is is possible to make this work by forming the metadata query to search for those without tags in the first place?
Currently the code does this:
else // if tagSet count > 0
{
NSMutableArray* subpredicates = [NSMutableArray new];
for (TagName* tag in tagSet)
[subpredicates addObject:[NSPredicate predicateWithFormat:@"%K ==[c] %@", kMDItemUserTags, tag.visibleName]];
result = [NSCompoundPredicate andPredicateWithSubpredicates:subpredicates];
}
Is it possible to make something like this work?
else // if tagSet count > 0
{
NSMutableArray* subpredicates = [NSMutableArray new];
for (TagName* tag in tagSet)
if negativeTagSearch {
[subpredicates addObject:[NSPredicate predicateWithFormat:@"%K !=[c] %@", kMDItemUserTags, tag.visibleName]];
} else {
[subpredicates addObject:[NSPredicate predicateWithFormat:@"%K ==[c] %@", kMDItemUserTags, tag.visibleName]];
}
result = [NSCompoundPredicate andPredicateWithSubpredicates:subpredicates];
}