Merge branch 'nix-repl-e' of https://github.com/zimbatm/nix
This commit is contained in:
commit
852554bb16
6 changed files with 88 additions and 34 deletions
|
@ -93,4 +93,36 @@ Value * findAlongAttrPath(EvalState & state, const string & attrPath,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Pos findDerivationFilename(EvalState & state, Value & v, std::string what)
|
||||||
|
{
|
||||||
|
Value * v2;
|
||||||
|
try {
|
||||||
|
auto dummyArgs = state.allocBindings(0);
|
||||||
|
v2 = findAlongAttrPath(state, "meta.position", *dummyArgs, v);
|
||||||
|
} catch (Error &) {
|
||||||
|
throw Error("package '%s' has no source location information", what);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: is it possible to extract the Pos object instead of doing this
|
||||||
|
// toString + parsing?
|
||||||
|
auto pos = state.forceString(*v2);
|
||||||
|
|
||||||
|
auto colon = pos.rfind(':');
|
||||||
|
if (colon == std::string::npos)
|
||||||
|
throw Error("cannot parse meta.position attribute '%s'", pos);
|
||||||
|
|
||||||
|
std::string filename(pos, 0, colon);
|
||||||
|
unsigned int lineno;
|
||||||
|
try {
|
||||||
|
lineno = std::stoi(std::string(pos, colon + 1));
|
||||||
|
} catch (std::invalid_argument & e) {
|
||||||
|
throw Error("cannot parse line number '%s'", pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
Symbol file = state.symbols.create(filename);
|
||||||
|
|
||||||
|
return { file, lineno, 0 };
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,4 +10,7 @@ namespace nix {
|
||||||
Value * findAlongAttrPath(EvalState & state, const string & attrPath,
|
Value * findAlongAttrPath(EvalState & state, const string & attrPath,
|
||||||
Bindings & autoArgs, Value & vIn);
|
Bindings & autoArgs, Value & vIn);
|
||||||
|
|
||||||
|
/* Heuristic to find the filename and lineno or a nix value. */
|
||||||
|
Pos findDerivationFilename(EvalState & state, Value & v, std::string what);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -178,6 +178,19 @@ Strings argvToStrings(int argc, char * * argv)
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Strings editorFor(Pos pos)
|
||||||
|
{
|
||||||
|
auto editor = getEnv("EDITOR", "cat");
|
||||||
|
auto args = tokenizeString<Strings>(editor);
|
||||||
|
if (pos.line > 0 && (
|
||||||
|
editor.find("emacs") != std::string::npos ||
|
||||||
|
editor.find("nano") != std::string::npos ||
|
||||||
|
editor.find("vim") != std::string::npos))
|
||||||
|
args.push_back(fmt("+%d", pos.line));
|
||||||
|
args.push_back(pos.file);
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
std::string renderLabels(const Strings & labels)
|
std::string renderLabels(const Strings & labels)
|
||||||
{
|
{
|
||||||
std::string res;
|
std::string res;
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "util.hh"
|
#include "util.hh"
|
||||||
|
#include "nixexpr.hh"
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
|
@ -190,6 +191,9 @@ public:
|
||||||
|
|
||||||
Strings argvToStrings(int argc, char * * argv);
|
Strings argvToStrings(int argc, char * * argv);
|
||||||
|
|
||||||
|
/* Helper function to generate args that invoke $EDITOR on filename:lineno */
|
||||||
|
Strings editorFor(Pos pos);
|
||||||
|
|
||||||
/* Helper function for rendering argument labels. */
|
/* Helper function for rendering argument labels. */
|
||||||
std::string renderLabels(const Strings & labels);
|
std::string renderLabels(const Strings & labels);
|
||||||
|
|
||||||
|
|
|
@ -36,45 +36,17 @@ struct CmdEdit : InstallableCommand
|
||||||
|
|
||||||
auto v = installable->toValue(*state);
|
auto v = installable->toValue(*state);
|
||||||
|
|
||||||
Value * v2;
|
Pos pos = findDerivationFilename(*state, *v, installable->what());
|
||||||
try {
|
|
||||||
auto dummyArgs = state->allocBindings(0);
|
|
||||||
v2 = findAlongAttrPath(*state, "meta.position", *dummyArgs, *v);
|
|
||||||
} catch (Error &) {
|
|
||||||
throw Error("package '%s' has no source location information", installable->what());
|
|
||||||
}
|
|
||||||
|
|
||||||
auto pos = state->forceString(*v2);
|
|
||||||
debug("position is %s", pos);
|
|
||||||
|
|
||||||
auto colon = pos.rfind(':');
|
|
||||||
if (colon == std::string::npos)
|
|
||||||
throw Error("cannot parse meta.position attribute '%s'", pos);
|
|
||||||
|
|
||||||
std::string filename(pos, 0, colon);
|
|
||||||
int lineno;
|
|
||||||
try {
|
|
||||||
lineno = std::stoi(std::string(pos, colon + 1));
|
|
||||||
} catch (std::invalid_argument & e) {
|
|
||||||
throw Error("cannot parse line number '%s'", pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto editor = getEnv("EDITOR", "cat");
|
|
||||||
|
|
||||||
auto args = tokenizeString<Strings>(editor);
|
|
||||||
|
|
||||||
if (editor.find("emacs") != std::string::npos ||
|
|
||||||
editor.find("nano") != std::string::npos ||
|
|
||||||
editor.find("vim") != std::string::npos)
|
|
||||||
args.push_back(fmt("+%d", lineno));
|
|
||||||
|
|
||||||
args.push_back(filename);
|
|
||||||
|
|
||||||
stopProgressBar();
|
stopProgressBar();
|
||||||
|
|
||||||
|
auto args = editorFor(pos);
|
||||||
|
|
||||||
execvp(args.front().c_str(), stringsToCharPtrs(args).data());
|
execvp(args.front().c_str(), stringsToCharPtrs(args).data());
|
||||||
|
|
||||||
throw SysError("cannot run editor '%s'", editor);
|
std::string command;
|
||||||
|
for (const auto &arg : args) command += " '" + arg + "'";
|
||||||
|
throw SysError("cannot run command%s", command);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ extern "C" {
|
||||||
#include "shared.hh"
|
#include "shared.hh"
|
||||||
#include "eval.hh"
|
#include "eval.hh"
|
||||||
#include "eval-inline.hh"
|
#include "eval-inline.hh"
|
||||||
|
#include "attr-path.hh"
|
||||||
#include "store-api.hh"
|
#include "store-api.hh"
|
||||||
#include "common-eval-args.hh"
|
#include "common-eval-args.hh"
|
||||||
#include "get-drvs.hh"
|
#include "get-drvs.hh"
|
||||||
|
@ -440,6 +441,7 @@ bool NixRepl::processLine(string line)
|
||||||
<< " <x> = <expr> Bind expression to variable\n"
|
<< " <x> = <expr> Bind expression to variable\n"
|
||||||
<< " :a <expr> Add attributes from resulting set to scope\n"
|
<< " :a <expr> Add attributes from resulting set to scope\n"
|
||||||
<< " :b <expr> Build derivation\n"
|
<< " :b <expr> Build derivation\n"
|
||||||
|
<< " :e <expr> Open the derivation in $EDITOR\n"
|
||||||
<< " :i <expr> Build derivation, then install result into current profile\n"
|
<< " :i <expr> Build derivation, then install result into current profile\n"
|
||||||
<< " :l <path> Load Nix expression and add it to scope\n"
|
<< " :l <path> Load Nix expression and add it to scope\n"
|
||||||
<< " :p <expr> Evaluate and print expression recursively\n"
|
<< " :p <expr> Evaluate and print expression recursively\n"
|
||||||
|
@ -466,6 +468,34 @@ bool NixRepl::processLine(string line)
|
||||||
reloadFiles();
|
reloadFiles();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (command == ":e" || command == ":edit") {
|
||||||
|
Value v;
|
||||||
|
evalString(arg, v);
|
||||||
|
|
||||||
|
Pos pos;
|
||||||
|
|
||||||
|
if (v.type == tPath || v.type == tString) {
|
||||||
|
PathSet context;
|
||||||
|
auto filename = state.coerceToString(noPos, v, context);
|
||||||
|
pos.file = state.symbols.create(filename);
|
||||||
|
} else if (v.type == tLambda) {
|
||||||
|
pos = v.lambda.fun->pos;
|
||||||
|
} else {
|
||||||
|
// assume it's a derivation
|
||||||
|
pos = findDerivationFilename(state, v, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open in EDITOR
|
||||||
|
auto args = editorFor(pos);
|
||||||
|
auto editor = args.front();
|
||||||
|
args.pop_front();
|
||||||
|
runProgram(editor, args);
|
||||||
|
|
||||||
|
// Reload right after exiting the editor
|
||||||
|
state.resetFileCache();
|
||||||
|
reloadFiles();
|
||||||
|
}
|
||||||
|
|
||||||
else if (command == ":t") {
|
else if (command == ":t") {
|
||||||
Value v;
|
Value v;
|
||||||
evalString(arg, v);
|
evalString(arg, v);
|
||||||
|
|
Loading…
Reference in a new issue