diff options
author | Eelco Dolstra <eelco.dolstra@logicblox.com> | 2013-09-09T10·00+0200 |
---|---|---|
committer | Eelco Dolstra <eelco.dolstra@logicblox.com> | 2013-09-09T10·00+0200 |
commit | e133e91410d9486e022a1bc0372b822152b6654e (patch) | |
tree | f1593b76a7389a3e153a70b74ebcd4948488cb29 | |
parent | 8e765b8876ff67879a6bd1a067bad526b14a4045 (diff) |
Support tab-completion on attribute sets
Example: $ nix-repl '<nixos>' > config.services.xserver.desktop<TAB> 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
-rw-r--r-- | nix-repl.cc | 39 |
1 files changed, 34 insertions, 5 deletions
diff --git a/nix-repl.cc b/nix-repl.cc index f7eb6ab5c0d7..9c22abbfacf6 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. + } } } |