From 47f5d658a554676edb4b5a20fe73dabff5483de8 Mon Sep 17 00:00:00 2001 From: Max Date: Mon, 21 Feb 2022 23:03:31 +0100 Subject: [PATCH] patch: nix-dram --- src/libcmd/installables.cc | 32 +++++++++++++++++++++++++++----- src/nix/search.cc | 25 +++++++++++++++++++++++-- tests/flakes.sh | 2 +- tests/search.sh | 16 ++++++++-------- 4 files changed, 59 insertions(+), 16 deletions(-) diff --git a/src/libcmd/installables.cc b/src/libcmd/installables.cc index e3489db68..8b13627b6 100644 --- a/src/libcmd/installables.cc +++ b/src/libcmd/installables.cc @@ -20,6 +20,10 @@ namespace nix { +const static std::regex attrPathRegex( + R"((?:[a-zA-Z0-9_"-][a-zA-Z0-9_".-]*))", + std::regex::ECMAScript); + void completeFlakeInputPath( ref evalState, const FlakeRef & flakeRef, @@ -234,12 +238,21 @@ void completeFlakeRefWithFragment( /* Look for flake output attributes that match the prefix. */ try { + bool isAttrPath = std::regex_match(prefix.begin(), prefix.end(), attrPathRegex); auto hash = prefix.find('#'); - if (hash == std::string::npos) { + if (!isAttrPath && hash == std::string::npos) { completeFlakeRef(evalState->store, prefix); } else { - auto fragment = prefix.substr(hash + 1); - auto flakeRefS = std::string(prefix.substr(0, hash)); + auto fragment = + isAttrPath + ? prefix + : prefix.substr(hash + 1); + + auto flakeRefS = + isAttrPath + ? std::string("flake:default") + : std::string(prefix.substr(0, hash)); + // FIXME: do tilde expansion. auto flakeRef = parseFlakeRef(flakeRefS, absPath(".")); @@ -274,7 +287,10 @@ void completeFlakeRefWithFragment( auto attrPath2 = attr->getAttrPath(attr2); /* Strip the attrpath prefix. */ attrPath2.erase(attrPath2.begin(), attrPath2.begin() + attrPathPrefix.size()); - completions->add(flakeRefS + "#" + concatStringsSep(".", attrPath2)); + if (isAttrPath) + completions->add(concatStringsSep(".", attrPath2)); + else + completions->add(flakeRefS + "#" + concatStringsSep(".", attrPath2)); } } } @@ -749,7 +765,13 @@ std::vector> SourceExprCommand::parseInstallables( } try { - auto [flakeRef, fragment] = parseFlakeRefWithFragment(s, absPath(".")); + bool isAttrPath = std::regex_match(s, attrPathRegex); + + auto [flakeRef, fragment] = + isAttrPath + ? std::make_pair(parseFlakeRef("flake:default", absPath(".")), s) + : parseFlakeRefWithFragment(s, absPath(".")); + result.push_back(std::make_shared( this, getEvalState(), diff --git a/src/nix/search.cc b/src/nix/search.cc index e9307342c..8e114716d 100644 --- a/src/nix/search.cc +++ b/src/nix/search.cc @@ -21,13 +21,32 @@ std::string wrap(std::string prefix, std::string s) return prefix + s + ANSI_NORMAL; } -struct CmdSearch : InstallableCommand, MixJSON +struct CmdSearch : SourceExprCommand, MixJSON { + std::string _installable{"flake:default"}; std::vector res; CmdSearch() { - expectArgs("regex", &res); + bool hasInstallable = false; + + addFlag({ + .longName = "installable", + .shortName = 'i', + .description = "Search within this installable", + .labels = {"installable"}, + .handler = {[this, &hasInstallable](std::string ss) { + hasInstallable = true; + _installable = ss; + }}, + .completer = completePath + }); + + if (hasInstallable && (file || expr)) { + throw UsageError("'--installable' cannot be used together with '--file' or '--expr'"); + } + + expectArgs("args", &res); } std::string description() override @@ -55,6 +74,8 @@ struct CmdSearch : InstallableCommand, MixJSON settings.readOnlyMode = true; evalSettings.enableImportFromDerivation.setDefault(false); + auto installable = parseInstallable(store, (file || expr) ? "" : _installable); + // 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) diff --git a/tests/flakes.sh b/tests/flakes.sh index db178967f..f41a25a31 100644 --- a/tests/flakes.sh +++ b/tests/flakes.sh @@ -129,7 +129,7 @@ nix build -o $TEST_ROOT/result flake1#foo [[ -e $TEST_ROOT/result/hello ]] # Test defaultPackage. -nix build -o $TEST_ROOT/result flake1 +nix build -o $TEST_ROOT/result flake1# [[ -e $TEST_ROOT/result/hello ]] nix build -o $TEST_ROOT/result $flake1Dir diff --git a/tests/search.sh b/tests/search.sh index 52e12f381..d749eeb32 100644 --- a/tests/search.sh +++ b/tests/search.sh @@ -3,26 +3,26 @@ source common.sh clearStore clearCache -(( $(nix search -f search.nix '' hello | wc -l) > 0 )) +(( $(nix search -f search.nix hello | wc -l) > 0 )) # Check descriptions are searched -(( $(nix search -f search.nix '' broken | wc -l) > 0 )) +(( $(nix search -f search.nix broken | wc -l) > 0 )) # Check search that matches nothing -(( $(nix search -f search.nix '' nosuchpackageexists | wc -l) == 0 )) +(( $(nix search -f search.nix nosuchpackageexists | wc -l) == 0 )) # Search for multiple arguments -(( $(nix search -f search.nix '' hello empty | wc -l) == 2 )) +(( $(nix search -f search.nix hello empty | wc -l) == 2 )) # Multiple arguments will not exist -(( $(nix search -f search.nix '' hello broken | wc -l) == 0 )) +(( $(nix search -f search.nix hello broken | wc -l) == 0 )) ## Search expressions # Check that empty search string matches all -nix search -f search.nix '' |grep -q foo -nix search -f search.nix '' |grep -q bar -nix search -f search.nix '' |grep -q hello +nix search -f search.nix |grep -q foo +nix search -f search.nix |grep -q bar +nix search -f search.nix |grep -q hello ## Tests for multiple regex/match highlighting