diff --git a/src/nix/profile.cc b/src/nix/profile.cc index 53fac7d2454..25a4110b89c 100644 --- a/src/nix/profile.cc +++ b/src/nix/profile.cc @@ -561,10 +561,24 @@ struct AllMatcher final : public Matcher AllMatcher all; -class MixProfileElementMatchers : virtual Args, virtual StoreCommand +class MixProfileElementMatchers : virtual Args, virtual StoreCommand, public virtual MixDefaultProfile { std::vector> _matchers; + void completeProfileElements(AddCompletions & completions, std::string_view prefix) + { + auto * evalCmd = dynamic_cast(this); + if (!evalCmd) + return; + + auto evalState = evalCmd->getEvalState(); + ProfileManifest manifest(*evalState, *profile); + + for (auto & [name, element] : manifest.elements) + if (name.starts_with(prefix)) + completions.add(name, element.identifier()); + } + public: MixProfileElementMatchers() @@ -595,6 +609,9 @@ class MixProfileElementMatchers : virtual Args, virtual StoreCommand _matchers.push_back(make_ref(arg)); } } + }}, + .completer = {[this](AddCompletions & completions, size_t, std::string_view prefix) { + completeProfileElements(completions, prefix); }}}); } @@ -635,7 +652,7 @@ class MixProfileElementMatchers : virtual Args, virtual StoreCommand } }; -struct CmdProfileRemove : virtual EvalCommand, MixDefaultProfile, MixProfileElementMatchers +struct CmdProfileRemove : virtual EvalCommand, MixProfileElementMatchers { std::string description() override { @@ -675,7 +692,7 @@ struct CmdProfileRemove : virtual EvalCommand, MixDefaultProfile, MixProfileElem } }; -struct CmdProfileUpgrade : virtual SourceExprCommand, MixDefaultProfile, MixProfileElementMatchers +struct CmdProfileUpgrade : virtual SourceExprCommand, MixProfileElementMatchers { std::string description() override { diff --git a/tests/functional/nix-profile.sh b/tests/functional/nix-profile.sh index a27a32c6efd..df9a8e0f4b6 100755 --- a/tests/functional/nix-profile.sh +++ b/tests/functional/nix-profile.sh @@ -78,6 +78,25 @@ unset NIX_CONFIG # Test conflicting package add. nix profile add "$flake1Dir" 2>&1 | grep "warning: 'flake1' is already added" +# Test tab completion of profile elements +# The profile should have 'foo' and 'flake1' installed at this point +completion_output=$(NIX_GET_COMPLETIONS=3 nix profile remove '' 2>&1) +echo "$completion_output" | grep -q "^normal$" +echo "$completion_output" | grep -q "^flake1" +echo "$completion_output" | grep -q "^foo" + +# Test prefix matching - should only complete 'flake1' when prefix is 'fl' +completion_output=$(NIX_GET_COMPLETIONS=3 nix profile remove 'fl' 2>&1) +echo "$completion_output" | grep -q "^normal$" +echo "$completion_output" | grep -q "^flake1" +echo "$completion_output" | grepQuietInverse "^foo" + +# Test completion with upgrade command +completion_output=$(NIX_GET_COMPLETIONS=3 nix profile upgrade '' 2>&1) +echo "$completion_output" | grep -q "^normal$" +echo "$completion_output" | grep -q "^flake1" +echo "$completion_output" | grep -q "^foo" + # Test upgrading a package. printf NixOS > "$flake1Dir"/who printf 2.0 > "$flake1Dir"/version