Add getDoc() function

This commit is contained in:
Eelco Dolstra 2020-08-25 13:31:11 +02:00
parent 2a2121d264
commit f53b5f1058
No known key found for this signature in database
GPG key ID: 8170B4726D7198DE
3 changed files with 42 additions and 13 deletions

View file

@ -563,6 +563,25 @@ Value & EvalState::getBuiltin(const string & name)
}
std::optional<EvalState::Doc> EvalState::getDoc(Value & v)
{
if (v.type == tPrimOp || v.type == tPrimOpApp) {
auto v2 = &v;
while (v2->type == tPrimOpApp)
v2 = v2->primOpApp.left;
if (v2->primOp->doc)
return Doc {
.pos = noPos,
.name = v2->primOp->name,
.arity = v2->primOp->arity,
.args = v2->primOp->args,
.doc = v2->primOp->doc,
};
}
return {};
}
/* Every "format" object (even temporary) takes up a few hundred bytes
of stack space, which is a real killer in the recursive
evaluator. So here are some helper functions for throwing

View file

@ -248,6 +248,17 @@ public:
Value & getBuiltin(const string & name);
struct Doc
{
Pos pos;
std::optional<Symbol> name;
size_t arity;
std::vector<std::string> args;
const char * doc;
};
std::optional<Doc> getDoc(Value & v);
private:
inline Value * lookupVar(Env * env, const ExprVar & var, bool noEval);

View file

@ -514,23 +514,22 @@ bool NixRepl::processLine(string line)
else if (command == ":doc") {
Value v;
evalString(arg, v);
if (v.type == tPrimOp || v.type == tPrimOpApp) {
auto v2 = &v;
while (v2->type == tPrimOpApp)
v2 = v2->primOpApp.left;
if (v2->primOp->doc) {
auto args = v2->primOp->args;
if (auto doc = state->getDoc(v)) {
std::string markdown;
if (!doc->args.empty() && doc->name) {
auto args = doc->args;
for (auto & arg : args)
arg = "*" + arg + "*";
auto markdown =
"**Synopsis:** `builtins." + (std::string) v2->primOp->name + "` "
+ concatStringsSep(" ", args) + "\n\n"
+ trim(stripIndentation(v2->primOp->doc));
markdown +=
"**Synopsis:** `builtins." + (std::string) (*doc->name) + "` "
+ concatStringsSep(" ", args) + "\n\n";
}
std::cout << renderMarkdownToTerminal(markdown);
} else
throw Error("builtin function '%s' does not have documentation", v2->primOp->name);
markdown += trim(stripIndentation(doc->doc));
std::cout << renderMarkdownToTerminal(markdown);
} else
throw Error("value does not have documentation");
}