aboutsummaryrefslogtreecommitdiff
path: root/src/nix/search.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/nix/search.cc')
-rw-r--r--src/nix/search.cc59
1 files changed, 42 insertions, 17 deletions
diff --git a/src/nix/search.cc b/src/nix/search.cc
index e9307342c..bdd45cbed 100644
--- a/src/nix/search.cc
+++ b/src/nix/search.cc
@@ -9,7 +9,7 @@
#include "shared.hh"
#include "eval-cache.hh"
#include "attr-path.hh"
-#include "fmt.hh"
+#include "hilite.hh"
#include <regex>
#include <fstream>
@@ -18,16 +18,26 @@ using namespace nix;
std::string wrap(std::string prefix, std::string s)
{
- return prefix + s + ANSI_NORMAL;
+ return concatStrings(prefix, s, ANSI_NORMAL);
}
struct CmdSearch : InstallableCommand, MixJSON
{
std::vector<std::string> res;
+ std::vector<std::string> excludeRes;
CmdSearch()
{
expectArgs("regex", &res);
+ addFlag(Flag {
+ .longName = "exclude",
+ .shortName = 'e',
+ .description = "Hide packages whose attribute path, name or description contain *regex*.",
+ .labels = {"regex"},
+ .handler = {[this](std::string s) {
+ excludeRes.push_back(s);
+ }},
+ });
}
std::string description() override
@@ -62,11 +72,16 @@ struct CmdSearch : InstallableCommand, MixJSON
res.push_back("^");
std::vector<std::regex> regexes;
+ std::vector<std::regex> excludeRegexes;
regexes.reserve(res.size());
+ excludeRegexes.reserve(excludeRes.size());
for (auto & re : res)
regexes.push_back(std::regex(re, std::regex::extended | std::regex::icase));
+ for (auto & re : excludeRes)
+ excludeRegexes.emplace_back(re, std::regex::extended | std::regex::icase);
+
auto state = getEvalState();
auto jsonOut = json ? std::make_unique<JSONObject>(std::cout) : nullptr;
@@ -77,13 +92,15 @@ struct CmdSearch : InstallableCommand, MixJSON
visit = [&](eval_cache::AttrCursor & cursor, const std::vector<Symbol> & attrPath, bool initialRecurse)
{
+ auto attrPathS = state->symbols.resolve(attrPath);
+
Activity act(*logger, lvlInfo, actUnknown,
- fmt("evaluating '%s'", concatStringsSep(".", attrPath)));
+ fmt("evaluating '%s'", concatStringsSep(".", attrPathS)));
try {
auto recurse = [&]()
{
for (const auto & attr : cursor.getAttrs()) {
- auto cursor2 = cursor.getAttr(attr);
+ auto cursor2 = cursor.getAttr(state->symbols[attr]);
auto attrPath2(attrPath);
attrPath2.push_back(attr);
visit(*cursor2, attrPath2, false);
@@ -91,19 +108,27 @@ struct CmdSearch : InstallableCommand, MixJSON
};
if (cursor.isDerivation()) {
- DrvName name(cursor.getAttr("name")->getString());
+ DrvName name(cursor.getAttr(state->sName)->getString());
- auto aMeta = cursor.maybeGetAttr("meta");
- auto aDescription = aMeta ? aMeta->maybeGetAttr("description") : nullptr;
+ auto aMeta = cursor.maybeGetAttr(state->sMeta);
+ auto aDescription = aMeta ? aMeta->maybeGetAttr(state->sDescription) : nullptr;
auto description = aDescription ? aDescription->getString() : "";
std::replace(description.begin(), description.end(), '\n', ' ');
- auto attrPath2 = concatStringsSep(".", attrPath);
+ auto attrPath2 = concatStringsSep(".", attrPathS);
std::vector<std::smatch> attrPathMatches;
std::vector<std::smatch> descriptionMatches;
std::vector<std::smatch> nameMatches;
bool found = false;
+ for (auto & regex : excludeRegexes) {
+ if (
+ std::regex_search(attrPath2, regex)
+ || std::regex_search(name.name, regex)
+ || std::regex_search(description, regex))
+ return;
+ }
+
for (auto & regex : regexes) {
found = false;
auto addAll = [&found](std::sregex_iterator it, std::vector<std::smatch> & vec) {
@@ -131,42 +156,42 @@ struct CmdSearch : InstallableCommand, MixJSON
jsonElem.attr("version", name.version);
jsonElem.attr("description", description);
} else {
- auto name2 = hiliteMatches(name.name, std::move(nameMatches), ANSI_GREEN, "\e[0;2m");
+ auto name2 = hiliteMatches(name.name, nameMatches, ANSI_GREEN, "\e[0;2m");
if (results > 1) logger->cout("");
logger->cout(
"* %s%s",
- wrap("\e[0;1m", hiliteMatches(attrPath2, std::move(attrPathMatches), ANSI_GREEN, "\e[0;1m")),
+ wrap("\e[0;1m", hiliteMatches(attrPath2, attrPathMatches, ANSI_GREEN, "\e[0;1m")),
name.version != "" ? " (" + name.version + ")" : "");
if (description != "")
logger->cout(
- " %s", hiliteMatches(description, std::move(descriptionMatches), ANSI_GREEN, ANSI_NORMAL));
+ " %s", hiliteMatches(description, descriptionMatches, ANSI_GREEN, ANSI_NORMAL));
}
}
}
else if (
attrPath.size() == 0
- || (attrPath[0] == "legacyPackages" && attrPath.size() <= 2)
- || (attrPath[0] == "packages" && attrPath.size() <= 2))
+ || (attrPathS[0] == "legacyPackages" && attrPath.size() <= 2)
+ || (attrPathS[0] == "packages" && attrPath.size() <= 2))
recurse();
else if (initialRecurse)
recurse();
- else if (attrPath[0] == "legacyPackages" && attrPath.size() > 2) {
+ else if (attrPathS[0] == "legacyPackages" && attrPath.size() > 2) {
auto attr = cursor.maybeGetAttr(state->sRecurseForDerivations);
if (attr && attr->getBool())
recurse();
}
} catch (EvalError & e) {
- if (!(attrPath.size() > 0 && attrPath[0] == "legacyPackages"))
+ if (!(attrPath.size() > 0 && attrPathS[0] == "legacyPackages"))
throw;
}
};
- for (auto & [cursor, prefix] : installable->getCursors(*state))
- visit(*cursor, parseAttrPath(*state, prefix), true);
+ for (auto & cursor : installable->getCursors(*state))
+ visit(*cursor, cursor->getAttrPath(), true);
if (!json && !results)
throw Error("no results for the given search term(s)!");