aboutsummaryrefslogtreecommitdiff
path: root/src/nix/search.cc
diff options
context:
space:
mode:
authorDaniel Poelzleithner <poelzleithner@b1-systems.de>2018-04-18 21:08:35 +0200
committerDaniel Poelzleithner <poelzleithner@b1-systems.de>2018-04-18 21:08:35 +0200
commitb712d4674bb18dd8c449c97b02e99b3e78bd6dd0 (patch)
tree3f01eda5872cc5b26296d3b8a3a0ffe330f35b88 /src/nix/search.cc
parentb37f5ae31dc0a0cbfa7e5bbf6b199e7e39c287ac (diff)
Allow multiple search experssions in nix search
The common use case is to search for packages containing multiple words like a "git" "frontend". Having only one expressions makes this simple regular use case very complicated. Instead, search accepts multiple regular epressions which all need to match. nix search git 'gui|frontend' returns a list of all git uis for example
Diffstat (limited to 'src/nix/search.cc')
-rw-r--r--src/nix/search.cc56
1 files changed, 38 insertions, 18 deletions
diff --git a/src/nix/search.cc b/src/nix/search.cc
index 5ccf1b7cf..539676698 100644
--- a/src/nix/search.cc
+++ b/src/nix/search.cc
@@ -25,14 +25,14 @@ std::string hilite(const std::string & s, const std::smatch & m)
struct CmdSearch : SourceExprCommand, MixJSON
{
- std::string re;
+ std::vector<std::string> res;
bool writeCache = true;
bool useCache = true;
CmdSearch()
{
- expectArg("regex", &re, true);
+ expectArgs("regex", &res);
mkFlag()
.longName("update-cache")
@@ -68,9 +68,13 @@ struct CmdSearch : SourceExprCommand, MixJSON
"nix search blender"
},
Example{
- "To search for Firefox and Chromium:",
+ "To search for Firefox or Chromium:",
"nix search 'firefox|chromium'"
},
+ Example{
+ "To search for git and frontend or gui:",
+ "nix search git 'frontend|gui'"
+ },
};
}
@@ -81,9 +85,16 @@ struct CmdSearch : SourceExprCommand, MixJSON
// Empty search string should match all packages
// Use "^" here instead of ".*" due to differences in resulting highlighting
// (see #1893 -- libc++ claims empty search string is not in POSIX grammar)
- if (re.empty()) re = "^";
+ if (res.empty()) {
+ res.push_back("^");
+ }
- std::regex regex(re, std::regex::extended | std::regex::icase);
+ std::vector<std::regex> regexes;
+ regexes.reserve(res.size());
+
+ for (auto &re : res) {
+ regexes.push_back(std::regex(re, std::regex::extended | std::regex::icase));
+ }
auto state = getEvalState();
@@ -102,6 +113,7 @@ struct CmdSearch : SourceExprCommand, MixJSON
debug("at attribute '%s'", attrPath);
try {
+ uint found = 0;
state->forceValue(*v);
@@ -115,25 +127,33 @@ struct CmdSearch : SourceExprCommand, MixJSON
if (state->isDerivation(*v)) {
DrvInfo drv(*state, attrPath, v->attrs);
+ std::string description;
+ std::smatch attrPathMatch;
+ std::smatch descriptionMatch;
+ std::smatch nameMatch;
+ std::string name;
DrvName parsed(drv.queryName());
- std::smatch attrPathMatch;
- std::regex_search(attrPath, attrPathMatch, regex);
+ for (auto &regex : regexes) {
+ std::regex_search(attrPath, attrPathMatch, regex);
- auto name = parsed.name;
- std::smatch nameMatch;
- std::regex_search(name, nameMatch, regex);
+ name = parsed.name;
+ std::regex_search(name, nameMatch, regex);
- std::string description = drv.queryMetaString("description");
- std::replace(description.begin(), description.end(), '\n', ' ');
- std::smatch descriptionMatch;
- std::regex_search(description, descriptionMatch, regex);
+ description = drv.queryMetaString("description");
+ std::replace(description.begin(), description.end(), '\n', ' ');
+ std::regex_search(description, descriptionMatch, regex);
+
+ if (!attrPathMatch.empty()
+ || !nameMatch.empty()
+ || !descriptionMatch.empty())
+ {
+ found++;
+ }
+ }
- if (!attrPathMatch.empty()
- || !nameMatch.empty()
- || !descriptionMatch.empty())
- {
+ if (found == res.size()) {
if (json) {
auto jsonElem = jsonOut->object(attrPath);