diff options
author | Daniel Poelzleithner <poelzleithner@b1-systems.de> | 2018-04-18T19·08+0200 |
---|---|---|
committer | Daniel Poelzleithner <poelzleithner@b1-systems.de> | 2018-04-18T19·08+0200 |
commit | b712d4674bb18dd8c449c97b02e99b3e78bd6dd0 (patch) | |
tree | 3f01eda5872cc5b26296d3b8a3a0ffe330f35b88 | |
parent | b37f5ae31dc0a0cbfa7e5bbf6b199e7e39c287ac (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
-rw-r--r-- | src/nix/search.cc | 56 |
1 files changed, 38 insertions, 18 deletions
diff --git a/src/nix/search.cc b/src/nix/search.cc index 5ccf1b7cf529..539676698086 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 ®ex : 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); |