aboutsummaryrefslogtreecommitdiff
path: root/src/nix
diff options
context:
space:
mode:
Diffstat (limited to 'src/nix')
-rw-r--r--src/nix/add-to-store.cc8
-rw-r--r--src/nix/command.cc13
-rw-r--r--src/nix/command.hh7
-rw-r--r--src/nix/flake.cc7
-rw-r--r--src/nix/installables.cc6
-rw-r--r--src/nix/local.mk2
-rw-r--r--src/nix/main.cc30
-rw-r--r--src/nix/markdown.cc50
-rw-r--r--src/nix/markdown.hh7
-rw-r--r--src/nix/profile.cc7
-rw-r--r--src/nix/registry.cc7
-rw-r--r--src/nix/repl.cc29
-rw-r--r--src/nix/show-config.cc6
13 files changed, 152 insertions, 27 deletions
diff --git a/src/nix/add-to-store.cc b/src/nix/add-to-store.cc
index 713155840..023ffa4ed 100644
--- a/src/nix/add-to-store.cc
+++ b/src/nix/add-to-store.cc
@@ -36,6 +36,14 @@ struct CmdAddToStore : MixDryRun, StoreCommand
return "add a path to the Nix store";
}
+ std::string doc() override
+ {
+ return R"(
+ Copy the file or directory *path* to the Nix store, and
+ print the resulting store path on standard output.
+ )";
+ }
+
Examples examples() override
{
return {
diff --git a/src/nix/command.cc b/src/nix/command.cc
index da32819da..2f1fbded1 100644
--- a/src/nix/command.cc
+++ b/src/nix/command.cc
@@ -4,12 +4,25 @@
#include "nixexpr.hh"
#include "profiles.hh"
+#include <nlohmann/json.hpp>
+
extern char * * environ __attribute__((weak));
namespace nix {
Commands * RegisterCommand::commands = nullptr;
+void NixMultiCommand::printHelp(const string & programName, std::ostream & out)
+{
+ MultiCommand::printHelp(programName, out);
+}
+
+nlohmann::json NixMultiCommand::toJSON()
+{
+ // FIXME: use Command::toJSON() as well.
+ return MultiCommand::toJSON();
+}
+
StoreCommand::StoreCommand()
{
}
diff --git a/src/nix/command.hh b/src/nix/command.hh
index bc46a2028..d60c8aeb6 100644
--- a/src/nix/command.hh
+++ b/src/nix/command.hh
@@ -21,6 +21,13 @@ static constexpr Command::Category catSecondary = 100;
static constexpr Command::Category catUtility = 101;
static constexpr Command::Category catNixInstallation = 102;
+struct NixMultiCommand : virtual MultiCommand, virtual Command
+{
+ void printHelp(const string & programName, std::ostream & out) override;
+
+ nlohmann::json toJSON() override;
+};
+
/* A command that requires a Nix store. */
struct StoreCommand : virtual Command
{
diff --git a/src/nix/flake.cc b/src/nix/flake.cc
index 653f8db1b..ae6f4c5f9 100644
--- a/src/nix/flake.cc
+++ b/src/nix/flake.cc
@@ -933,7 +933,7 @@ struct CmdFlakeShow : FlakeCommand
}
};
-struct CmdFlake : virtual MultiCommand, virtual Command
+struct CmdFlake : NixMultiCommand
{
CmdFlake()
: MultiCommand({
@@ -963,11 +963,6 @@ struct CmdFlake : virtual MultiCommand, virtual Command
command->second->prepare();
command->second->run();
}
-
- void printHelp(const string & programName, std::ostream & out) override
- {
- MultiCommand::printHelp(programName, out);
- }
};
static auto r1 = registerCommand<CmdFlake>("flake");
diff --git a/src/nix/installables.cc b/src/nix/installables.cc
index d34f87982..1f1ed680f 100644
--- a/src/nix/installables.cc
+++ b/src/nix/installables.cc
@@ -76,7 +76,7 @@ MixFlakeOptions::MixFlakeOptions()
addFlag({
.longName = "override-input",
- .description = "override a specific flake input (e.g. 'dwarffs/nixpkgs')",
+ .description = "override a specific flake input (e.g. `dwarffs/nixpkgs`)",
.labels = {"input-path", "flake-url"},
.handler = {[&](std::string inputPath, std::string flakeRef) {
lockFlags.inputOverrides.insert_or_assign(
@@ -116,7 +116,7 @@ SourceExprCommand::SourceExprCommand()
addFlag({
.longName = "file",
.shortName = 'f',
- .description = "evaluate FILE rather than the default",
+ .description = "evaluate *file* rather than the default",
.labels = {"file"},
.handler = {&file},
.completer = completePath
@@ -124,7 +124,7 @@ SourceExprCommand::SourceExprCommand()
addFlag({
.longName ="expr",
- .description = "evaluate attributes from EXPR",
+ .description = "evaluate attributes from *expr*",
.labels = {"expr"},
.handler = {&expr}
});
diff --git a/src/nix/local.mk b/src/nix/local.mk
index b057b7cc6..e96200685 100644
--- a/src/nix/local.mk
+++ b/src/nix/local.mk
@@ -19,7 +19,7 @@ nix_CXXFLAGS += -I src/libutil -I src/libstore -I src/libfetchers -I src/libexpr
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, \
diff --git a/src/nix/main.cc b/src/nix/main.cc
index e62657e95..e9479f564 100644
--- a/src/nix/main.cc
+++ b/src/nix/main.cc
@@ -17,6 +17,8 @@
#include <netdb.h>
#include <netinet/in.h>
+#include <nlohmann/json.hpp>
+
extern std::string chrootHelperName;
void chrootHelper(int argc, char * * argv);
@@ -140,6 +142,11 @@ struct NixArgs : virtual MultiCommand, virtual MixCommonArgs
printHelp(programName, std::cout);
throw Exit();
}
+
+ std::string description() override
+ {
+ return "a tool for reproducible and declarative configuration management";
+ }
};
void mainWrapped(int argc, char * * argv)
@@ -172,6 +179,29 @@ void mainWrapped(int argc, char * * argv)
NixArgs args;
+ if (argc == 2 && std::string(argv[1]) == "__dump-args") {
+ std::cout << args.toJSON().dump() << "\n";
+ return;
+ }
+
+ if (argc == 2 && std::string(argv[1]) == "__dump-builtins") {
+ EvalState state({}, openStore("dummy://"));
+ auto res = nlohmann::json::object();
+ auto builtins = state.baseEnv.values[0]->attrs;
+ for (auto & builtin : *builtins) {
+ auto b = nlohmann::json::object();
+ if (builtin.value->type != tPrimOp) continue;
+ auto primOp = builtin.value->primOp;
+ if (!primOp->doc) continue;
+ b["arity"] = primOp->arity;
+ b["args"] = primOp->args;
+ b["doc"] = trim(stripIndentation(primOp->doc));
+ res[(std::string) builtin.name] = std::move(b);
+ }
+ std::cout << res.dump() << "\n";
+ return;
+ }
+
Finally printCompletions([&]()
{
if (completions) {
diff --git a/src/nix/markdown.cc b/src/nix/markdown.cc
new file mode 100644
index 000000000..40788a42f
--- /dev/null
+++ b/src/nix/markdown.cc
@@ -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);
+}
+
+}
diff --git a/src/nix/markdown.hh b/src/nix/markdown.hh
new file mode 100644
index 000000000..78320fcf5
--- /dev/null
+++ b/src/nix/markdown.hh
@@ -0,0 +1,7 @@
+#include "types.hh"
+
+namespace nix {
+
+std::string renderMarkdownToTerminal(std::string_view markdown);
+
+}
diff --git a/src/nix/profile.cc b/src/nix/profile.cc
index cffc9ee44..9241931e9 100644
--- a/src/nix/profile.cc
+++ b/src/nix/profile.cc
@@ -437,7 +437,7 @@ struct CmdProfileDiffClosures : virtual StoreCommand, MixDefaultProfile
}
};
-struct CmdProfile : virtual MultiCommand, virtual Command
+struct CmdProfile : NixMultiCommand
{
CmdProfile()
: MultiCommand({
@@ -461,11 +461,6 @@ struct CmdProfile : virtual MultiCommand, virtual Command
command->second->prepare();
command->second->run();
}
-
- void printHelp(const string & programName, std::ostream & out) override
- {
- MultiCommand::printHelp(programName, out);
- }
};
static auto r1 = registerCommand<CmdProfile>("profile");
diff --git a/src/nix/registry.cc b/src/nix/registry.cc
index ebee4545c..367268683 100644
--- a/src/nix/registry.cc
+++ b/src/nix/registry.cc
@@ -115,7 +115,7 @@ struct CmdRegistryPin : virtual Args, EvalCommand
}
};
-struct CmdRegistry : virtual MultiCommand, virtual Command
+struct CmdRegistry : virtual NixMultiCommand
{
CmdRegistry()
: MultiCommand({
@@ -141,11 +141,6 @@ struct CmdRegistry : virtual MultiCommand, virtual Command
command->second->prepare();
command->second->run();
}
-
- void printHelp(const string & programName, std::ostream & out) override
- {
- MultiCommand::printHelp(programName, out);
- }
};
static auto r1 = registerCommand<CmdRegistry>("registry");
diff --git a/src/nix/repl.cc b/src/nix/repl.cc
index a3e92b966..50d9b2568 100644
--- a/src/nix/repl.cc
+++ b/src/nix/repl.cc
@@ -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
@@ -419,7 +420,8 @@ bool NixRepl::processLine(string line)
<< " :r Reload all files\n"
<< " :s <expr> Build dependencies of derivation, then start nix-shell\n"
<< " :t <expr> Describe result of evaluation\n"
- << " :u <expr> Build derivation, then start nix-shell\n";
+ << " :u <expr> Build derivation, then start nix-shell\n"
+ << " :doc <expr> Show documentation of a builtin function\n";
}
else if (command == ":a" || command == ":add") {
@@ -513,6 +515,29 @@ bool NixRepl::processLine(string line)
else if (command == ":q" || command == ":quit")
return false;
+ else if (command == ":doc") {
+ Value v;
+ evalString(arg, v);
+ 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 + "*";
+
+ markdown +=
+ "**Synopsis:** `builtins." + (std::string) (*doc->name) + "` "
+ + concatStringsSep(" ", args) + "\n\n";
+ }
+
+ markdown += trim(stripIndentation(doc->doc));
+
+ std::cout << renderMarkdownToTerminal(markdown);
+ } else
+ throw Error("value does not have documentation");
+ }
+
else if (command != "")
throw Error("unknown command '%1%'", command);
@@ -786,7 +811,7 @@ struct CmdRepl : StoreCommand, MixEvalArgs
return {
Example{
"Display all special commands within the REPL:",
- "nix repl\n nix-repl> :?"
+ "nix repl\nnix-repl> :?"
}
};
}
diff --git a/src/nix/show-config.cc b/src/nix/show-config.cc
index 4fd8886de..3ed1ad2aa 100644
--- a/src/nix/show-config.cc
+++ b/src/nix/show-config.cc
@@ -2,7 +2,8 @@
#include "common-args.hh"
#include "shared.hh"
#include "store-api.hh"
-#include "json.hh"
+
+#include <nlohmann/json.hpp>
using namespace nix;
@@ -19,8 +20,7 @@ struct CmdShowConfig : Command, MixJSON
{
if (json) {
// FIXME: use appropriate JSON types (bool, ints, etc).
- JSONObject jsonObj(std::cout);
- globalConfig.toJSON(jsonObj);
+ logger->stdout("%s", globalConfig.toJSON().dump());
} else {
std::map<std::string, Config::SettingInfo> settings;
globalConfig.getSettings(settings);