aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libcmd/installables.cc86
-rw-r--r--src/libcmd/repl.cc4
-rw-r--r--tests/completions.sh6
3 files changed, 55 insertions, 41 deletions
diff --git a/src/libcmd/installables.cc b/src/libcmd/installables.cc
index e097f23b3..f63b9eeae 100644
--- a/src/libcmd/installables.cc
+++ b/src/libcmd/installables.cc
@@ -207,55 +207,59 @@ Strings SourceExprCommand::getDefaultFlakeAttrPathPrefixes()
void SourceExprCommand::completeInstallable(std::string_view prefix)
{
- if (file) {
- completionType = ctAttrs;
+ try {
+ if (file) {
+ completionType = ctAttrs;
- evalSettings.pureEval = false;
- auto state = getEvalState();
- Expr *e = state->parseExprFromFile(
- resolveExprPath(state->checkSourcePath(lookupFileArg(*state, *file)))
- );
+ evalSettings.pureEval = false;
+ auto state = getEvalState();
+ Expr *e = state->parseExprFromFile(
+ resolveExprPath(state->checkSourcePath(lookupFileArg(*state, *file)))
+ );
- Value root;
- state->eval(e, root);
+ Value root;
+ state->eval(e, root);
- auto autoArgs = getAutoArgs(*state);
+ auto autoArgs = getAutoArgs(*state);
- std::string prefix_ = std::string(prefix);
- auto sep = prefix_.rfind('.');
- std::string searchWord;
- if (sep != std::string::npos) {
- searchWord = prefix_.substr(sep + 1, std::string::npos);
- prefix_ = prefix_.substr(0, sep);
- } else {
- searchWord = prefix_;
- prefix_ = "";
- }
+ std::string prefix_ = std::string(prefix);
+ auto sep = prefix_.rfind('.');
+ std::string searchWord;
+ if (sep != std::string::npos) {
+ searchWord = prefix_.substr(sep + 1, std::string::npos);
+ prefix_ = prefix_.substr(0, sep);
+ } else {
+ searchWord = prefix_;
+ prefix_ = "";
+ }
- auto [v, pos] = findAlongAttrPath(*state, prefix_, *autoArgs, root);
- Value &v1(*v);
- state->forceValue(v1, pos);
- Value v2;
- state->autoCallFunction(*autoArgs, v1, v2);
-
- if (v2.type() == nAttrs) {
- for (auto & i : *v2.attrs) {
- std::string name = state->symbols[i.name];
- if (name.find(searchWord) == 0) {
- if (prefix_ == "")
- completions->add(name);
- else
- completions->add(prefix_ + "." + name);
+ auto [v, pos] = findAlongAttrPath(*state, prefix_, *autoArgs, root);
+ Value &v1(*v);
+ state->forceValue(v1, pos);
+ Value v2;
+ state->autoCallFunction(*autoArgs, v1, v2);
+
+ if (v2.type() == nAttrs) {
+ for (auto & i : *v2.attrs) {
+ std::string name = state->symbols[i.name];
+ if (name.find(searchWord) == 0) {
+ if (prefix_ == "")
+ completions->add(name);
+ else
+ completions->add(prefix_ + "." + name);
+ }
}
}
+ } else {
+ completeFlakeRefWithFragment(
+ getEvalState(),
+ lockFlags,
+ getDefaultFlakeAttrPathPrefixes(),
+ getDefaultFlakeAttrPaths(),
+ prefix);
}
- } else {
- completeFlakeRefWithFragment(
- getEvalState(),
- lockFlags,
- getDefaultFlakeAttrPathPrefixes(),
- getDefaultFlakeAttrPaths(),
- prefix);
+ } catch (EvalError&) {
+ // Don't want eval errors to mess-up with the completion engine, so let's just swallow them
}
}
diff --git a/src/libcmd/repl.cc b/src/libcmd/repl.cc
index df8932087..bb254ff8d 100644
--- a/src/libcmd/repl.cc
+++ b/src/libcmd/repl.cc
@@ -384,6 +384,10 @@ StringSet NixRepl::completePrefix(const std::string & prefix)
i++;
}
} else {
+ /* Temporarily disable the debugger, to avoid re-entering readline. */
+ auto debug_repl = state->debugRepl;
+ state->debugRepl = nullptr;
+ Finally restoreDebug([&]() { state->debugRepl = debug_repl; });
try {
/* This is an expression that should evaluate to an
attribute set. Evaluate it to get the names of the
diff --git a/tests/completions.sh b/tests/completions.sh
index 522aa1c86..19dc61098 100644
--- a/tests/completions.sh
+++ b/tests/completions.sh
@@ -28,6 +28,10 @@ cat <<EOF > bar/flake.nix
};
}
EOF
+mkdir -p err
+cat <<EOF > err/flake.nix
+throw "error"
+EOF
# Test the completion of a subcommand
[[ "$(NIX_GET_COMPLETIONS=1 nix buil)" == $'normal\nbuild\t' ]]
@@ -60,3 +64,5 @@ NIX_GET_COMPLETIONS=3 nix build --option allow-import-from | grep -- "allow-impo
# Attr path completions
[[ "$(NIX_GET_COMPLETIONS=2 nix eval ./foo\#sam)" == $'attrs\n./foo#sampleOutput\t' ]]
[[ "$(NIX_GET_COMPLETIONS=4 nix eval --file ./foo/flake.nix outp)" == $'attrs\noutputs\t' ]]
+[[ "$(NIX_GET_COMPLETIONS=4 nix eval --file ./err/flake.nix outp 2>&1)" == $'attrs' ]]
+[[ "$(NIX_GET_COMPLETIONS=2 nix eval ./err\# 2>&1)" == $'attrs' ]]