nix repl ':doc': Render using lowdown

This commit is contained in:
Eelco Dolstra 2020-08-24 18:10:33 +02:00
parent 0f314f3c25
commit d0690bc311
No known key found for this signature in database
GPG key ID: 8170B4726D7198DE
4 changed files with 71 additions and 6 deletions

View file

@ -15,11 +15,12 @@ nix_SOURCES := \
$(wildcard src/nix-prefetch-url/*.cc) \
$(wildcard src/nix-store/*.cc) \
nix_CXXFLAGS += -I src/libutil -I src/libstore -I src/libfetchers -I src/libexpr -I src/libmain
# -fpermissive is needed by lowdown.
nix_CXXFLAGS += -I src/libutil -I src/libstore -I src/libfetchers -I src/libexpr -I src/libmain -fpermissive
nix_LIBS = libexpr libmain libfetchers libstore libutil
nix_LDFLAGS = -pthread $(SODIUM_LIBS) $(EDITLINE_LIBS) $(BOOST_LDFLAGS) -lboost_context -lboost_thread -lboost_system
nix_LDFLAGS = -pthread $(SODIUM_LIBS) $(EDITLINE_LIBS) $(BOOST_LDFLAGS) -lboost_context -lboost_thread -lboost_system -llowdown
$(foreach name, \
nix-build nix-channel nix-collect-garbage nix-copy-closure nix-daemon nix-env nix-hash nix-instantiate nix-prefetch-url nix-shell nix-store, \

50
src/nix/markdown.cc Normal file
View file

@ -0,0 +1,50 @@
#include "markdown.hh"
#include "util.hh"
#include "finally.hh"
#include <sys/queue.h>
extern "C" {
#include <lowdown.h>
}
namespace nix {
std::string renderMarkdownToTerminal(std::string_view markdown)
{
struct lowdown_opts opts {
.type = LOWDOWN_TERM,
.maxdepth = 20,
.cols = std::min(getWindowSize().second, (unsigned short) 80),
.hmargin = 0,
.vmargin = 0,
.feat = LOWDOWN_COMMONMARK | LOWDOWN_FENCED | LOWDOWN_DEFLIST | LOWDOWN_TABLES,
.oflags = 0,
};
auto doc = lowdown_doc_new(&opts);
if (!doc)
throw Error("cannot allocate Markdown document");
Finally freeDoc([&]() { lowdown_doc_free(doc); });
size_t maxn = 0;
auto node = lowdown_doc_parse(doc, &maxn, markdown.data(), markdown.size());
if (!node)
throw Error("cannot parse Markdown document");
Finally freeNode([&]() { lowdown_node_free(node); });
auto renderer = lowdown_term_new(&opts);
if (!renderer)
throw Error("cannot allocate Markdown renderer");
Finally freeRenderer([&]() { lowdown_term_free(renderer); });
auto buf = lowdown_buf_new(16384);
if (!buf)
throw Error("cannot allocate Markdown output buffer");
Finally freeBuffer([&]() { lowdown_buf_free(buf); });
lowdown_term_rndr(buf, nullptr, renderer, node);
return std::string(buf->data, buf->size);
}
}

7
src/nix/markdown.hh Normal file
View file

@ -0,0 +1,7 @@
#include "types.hh"
namespace nix {
std::string renderMarkdownToTerminal(std::string_view markdown);
}

View file

@ -32,6 +32,7 @@ extern "C" {
#include "globals.hh"
#include "command.hh"
#include "finally.hh"
#include "markdown.hh"
#if HAVE_BOEHMGC
#define GC_INCLUDE_NEW
@ -518,10 +519,16 @@ bool NixRepl::processLine(string line)
while (v2->type == tPrimOpApp)
v2 = v2->primOpApp.left;
if (v2->primOp->doc) {
// FIXME: format markdown.
if (!v2->primOp->args.empty())
std::cout << fmt("Arguments: %s\n\n", concatStringsSep(" ", v2->primOp->args));
std::cout << trim(stripIndentation(v2->primOp->doc)) << "\n";
auto args = v2->primOp->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));
std::cout << renderMarkdownToTerminal(markdown);
} else
throw Error("builtin function '%s' does not have documentation", v2->primOp->name);
} else