Skip to content

Commit

Permalink
Render fetcher info in primop again
Browse files Browse the repository at this point in the history
  • Loading branch information
Ericson2314 committed Jan 12, 2024
1 parent 10d663b commit 23476d8
Show file tree
Hide file tree
Showing 9 changed files with 143 additions and 10 deletions.
2 changes: 1 addition & 1 deletion src/libcmd/local.mk
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ libcmd_SOURCES := $(wildcard $(d)/*.cc)

libcmd_CXXFLAGS += -I src/libutil -I src/libstore -I src/libexpr -I src/libmain -I src/libfetchers

libcmd_LDFLAGS = $(EDITLINE_LIBS) $(LOWDOWN_LIBS) $(THREAD_LDFLAGS)
libcmd_LDFLAGS = $(EDITLINE_LIBS) $(THREAD_LDFLAGS)

libcmd_LIBS = libstore libutil libexpr libmain libfetchers

Expand Down
7 changes: 4 additions & 3 deletions src/libexpr/eval.cc
Original file line number Diff line number Diff line change
Expand Up @@ -657,7 +657,7 @@ Value * EvalState::addPrimOp(PrimOp && primOp)
v.mkApp(vPrimOp, vPrimOp);
return addConstant(primOp.name, v, {
.type = nThunk, // FIXME
.doc = primOp.doc,
.doc = primOp.doc.c_str(),
});
}

Expand All @@ -684,13 +684,14 @@ std::optional<EvalState::Doc> EvalState::getDoc(Value & v)
{
if (v.isPrimOp()) {
auto v2 = &v;
if (auto * doc = v2->primOp->doc)
auto & doc = v2->primOp->doc;
if (doc != "")
return Doc {
.pos = {},
.name = v2->primOp->name,
.arity = v2->primOp->arity,
.args = v2->primOp->args,
.doc = doc,
.doc = doc.c_str(),
};
}
return {};
Expand Down
2 changes: 1 addition & 1 deletion src/libexpr/eval.hh
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ struct PrimOp
/**
* Optional free-form documentation about the primop.
*/
const char * doc = nullptr;
const std::string doc = "";

/**
* Implementation of the primop.
Expand Down
2 changes: 1 addition & 1 deletion src/libexpr/local.mk
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ libexpr_CXXFLAGS += -I src/libutil -I src/libstore -I src/libfetchers -I src/lib

libexpr_LIBS = libutil libstore libfetchers

libexpr_LDFLAGS += -lboost_context $(THREAD_LDFLAGS)
libexpr_LDFLAGS += -lboost_context $(THREAD_LDFLAGS) $(LOWDOWN_LIBS)
ifdef HOST_LINUX
libexpr_LDFLAGS += -ldl
endif
Expand Down
136 changes: 134 additions & 2 deletions src/libexpr/primops/fetchTree.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
#include "url.hh"
#include "value-to-json.hh"

#if HAVE_LOWDOWN
# include "markdown.hh"
# include "terminal.hh"
#endif

#include <ctime>
#include <iomanip>
#include <regex>
Expand Down Expand Up @@ -186,7 +191,7 @@ static void prim_fetchTree(EvalState & state, const PosIdx pos, Value * * args,
static RegisterPrimOp primop_fetchTree({
.name = "fetchTree",
.args = {"input"},
.doc = R"(
.doc = stripIndentation(R"(
Fetch a file system tree or a plain file using one of the supported backends and return an attribute set with:
- the resulting fixed-output [store path](@docroot@/glossary.md#gloss-store-path)
Expand Down Expand Up @@ -227,6 +232,133 @@ static RegisterPrimOp primop_fetchTree({
document) if `fetchTree` was a curried call with the first paramter for
`type` or an attribute like `builtins.fetchTree.git`! -->
)") + []() -> std::string {
#if HAVE_LOWDOWN
struct lowdown_opts opts {
.type = LOWDOWN_TERM,
.maxdepth = SIZE_MAX,
.cols = SIZE_MAX,
.hmargin = 0,
.vmargin = 0,
.feat = LOWDOWN_COMMONMARK | LOWDOWN_FENCED | LOWDOWN_DEFLIST | LOWDOWN_TABLES,
//.oflags = LOWDOWN_TERM_NOLINK,
};

auto doc = LowdownUniquePtr<struct lowdown_doc> {
lowdown_doc_new(&opts),
};
assert(doc);

auto makeNode = [](enum lowdown_rndrt type) {
LowdownUniquePtr<struct lowdown_node> node {
(struct lowdown_node *) calloc(1, sizeof(struct lowdown_node))
};
assert(node);
node->type = type;
TAILQ_INIT(&node->children);
return node;
};

auto makeBuf = []{
return LowdownUniquePtr<struct lowdown_buf> {
lowdown_buf_new(16384),
};
};

auto setParent = [](struct lowdown_node & parent, struct lowdown_node & child) {
TAILQ_INSERT_TAIL(&parent.children, &child, entries);
++parent.rndr_list.items;
child.parent = &parent;
};

auto createBuffer = [](std::string_view str) -> struct lowdown_buf {
auto size = str.size();
auto * data = (char *) malloc(size);
assert(data);
memcpy(data, str.data(), size);
data[size] = '\0';
return {
.data = data,
.size = size,
.maxsize = size + 1,
.unit = 0,
.buffer_free = (int) true,
};
};

auto root = makeNode(LOWDOWN_ROOT);
auto & schemes = *makeNode(LOWDOWN_LIST).release();
setParent(*root, schemes);
schemes.rndr_list.flags = (enum hlist_fl) 0;

for (const auto & [schemeName, scheme] : fetchers::getAllInputSchemes()) {
auto & s = *makeNode(LOWDOWN_LISTITEM).release();
setParent(schemes, s);
s.rndr_listitem.flags = HLIST_FL_BLOCK;
{
auto & name_p = *makeNode(LOWDOWN_PARAGRAPH).release();
setParent(s, name_p);
auto & name = *makeNode(LOWDOWN_NORMAL_TEXT).release();
setParent(name_p, name);
name.rndr_normal_text.text = createBuffer(schemeName);
}
{
auto & desc_p = *makeNode(LOWDOWN_PARAGRAPH).release();
setParent(s, desc_p);
auto markdown = scheme->schemeDescription();
size_t maxn = 0;
auto * desc = lowdown_doc_parse(&*doc, &maxn, markdown.data(), markdown.size(), nullptr);
assert(desc);
setParent(desc_p, *desc);
}
auto & attrs = *makeNode(LOWDOWN_LIST).release();
setParent(s, attrs);
schemes.rndr_list.flags = (enum hlist_fl) 0;
for (const auto & [attrName, attribute] : scheme->allowedAttrs()) {
auto & a = *makeNode(LOWDOWN_LISTITEM).release();
setParent(attrs, a);
a.rndr_listitem.flags = HLIST_FL_BLOCK;
{
auto & name_p = *makeNode(LOWDOWN_PARAGRAPH).release();
setParent(a, name_p);
auto & name = *makeNode(LOWDOWN_NORMAL_TEXT).release();
setParent(name_p, name);
std::string header = attrName
+ " (" + attribute.type
+ ", " + (attribute.required ? "required" : "optional")
+ ")";
name.rndr_normal_text.text = createBuffer(std::string_view(header));
}
{
auto & doc_p = *makeNode(LOWDOWN_PARAGRAPH).release();
setParent(s, doc_p);
auto * markdown = attribute.doc;
size_t maxn = 0;
auto * doc_s = lowdown_doc_parse(&*doc, &maxn, markdown, strlen(markdown), nullptr);
assert(doc_s);
setParent(doc_p, *doc_s);
}
}
}

auto renderer = LowdownUniquePtr<struct lowdown_term> {
(struct lowdown_term *) lowdown_term_new(&opts),
};
assert(renderer);

auto buf = makeBuf();
assert(buf);

int rndr_res = lowdown_term_rndr(&*buf, &*renderer, &*root);
assert(rndr_res);

return filterANSIEscapes(std::string { buf->data, buf->size }, true);
#else
return {};
#endif
}()
+ stripIndentation(R"(
The following input types are still subject to change:
- `"path"`
Expand Down Expand Up @@ -271,7 +403,7 @@ static RegisterPrimOp primop_fetchTree({
> ```nix
> builtins.fetchTree "github:NixOS/nixpkgs/ae2e6b3958682513d28f7d633734571fb18285dd"
> ```
)",
)"),
.fun = prim_fetchTree,
.experimentalFeature = Xp::FetchTree,
});
Expand Down
2 changes: 1 addition & 1 deletion src/libutil/local.mk
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ libutil_SOURCES := $(wildcard $(d)/*.cc $(d)/signature/*.cc)

libutil_CXXFLAGS += -I src/libutil

libutil_LDFLAGS += $(THREAD_LDFLAGS) $(LIBCURL_LIBS) $(SODIUM_LIBS) $(OPENSSL_LIBS) $(LIBBROTLI_LIBS) $(LIBARCHIVE_LIBS) $(BOOST_LDFLAGS) -lboost_context
libutil_LDFLAGS += $(THREAD_LDFLAGS) $(LOWDOWN_LIBS) $(LIBCURL_LIBS) $(SODIUM_LIBS) $(OPENSSL_LIBS) $(LIBBROTLI_LIBS) $(LIBARCHIVE_LIBS) $(BOOST_LDFLAGS) -lboost_context

$(foreach i, $(wildcard $(d)/args/*.hh), \
$(eval $(call install-file-in, $(i), $(includedir)/nix/args, 0644)))
Expand Down
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion src/nix/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,7 @@ void mainWrapped(int argc, char * * argv)
auto b = nlohmann::json::object();
if (!builtin.value->isPrimOp()) continue;
auto primOp = builtin.value->primOp;
if (!primOp->doc) continue;
if (primOp->doc == "") continue;
b["arity"] = primOp->arity;
b["args"] = primOp->args;
b["doc"] = trim(stripIndentation(primOp->doc));
Expand Down

0 comments on commit 23476d8

Please sign in to comment.