From e133e91410d9486e022a1bc0372b822152b6654e Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 9 Sep 2013 12:00:33 +0200 Subject: [PATCH] Support tab-completion on attribute sets Example: $ nix-repl '' > config.services.xserver.desktop comletes to > config.services.xserver.desktopManager You also get suggestions if there are multiple matches: > config.services.xserver.desktopManager.kde4 config.services.xserver.desktopManager.kde4.enable config.services.xserver.desktopManager.kde4.phononBackends --- nix-repl.cc | 39 ++++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/nix-repl.cc b/nix-repl.cc index f7eb6ab5c..9c22abbfa 100644 --- a/nix-repl.cc +++ b/nix-repl.cc @@ -183,11 +183,40 @@ void NixRepl::completePrefix(string prefix) { completions.clear(); - StringSet::iterator i = varNames.lower_bound(prefix); - while (i != varNames.end()) { - if (string(*i, 0, prefix.size()) != prefix) break; - completions.insert(*i); - i++; + size_t dot = prefix.rfind('.'); + + if (dot == string::npos) { + /* This is a variable name; look it up in the current scope. */ + StringSet::iterator i = varNames.lower_bound(prefix); + while (i != varNames.end()) { + if (string(*i, 0, prefix.size()) != prefix) break; + completions.insert(*i); + i++; + } + } else { + try { + /* This is an expression that should evaluate to an + attribute set. Evaluate it to get the names of the + attributes. */ + string expr(prefix, 0, dot); + string prefix2 = string(prefix, dot + 1); + + Expr * e = parseString(expr); + Value v; + e->eval(state, *env, v); + state.forceAttrs(v); + + foreach (Bindings::iterator, i, *v.attrs) { + string name = i->name; + if (string(name, 0, prefix2.size()) != prefix2) continue; + completions.insert(expr + "." + name); + } + + } catch (ParseError & e) { + // Quietly ignore parse errors. + }catch (EvalError & e) { + // Quietly ignore evaluation errors. + } } }