Allow 'nix' subcommands to provide docs in Markdown format
This commit is contained in:
parent
3c4f8c9175
commit
dc2f278c95
|
@ -12,7 +12,7 @@ def show_flags:
|
||||||
;
|
;
|
||||||
|
|
||||||
def show_synopsis:
|
def show_synopsis:
|
||||||
"`" + .command + "` " + (.args | map("*" + .label + "*" + (if has("arity") then "" else "..." end)) | join(" ")) + "\n\n"
|
"`" + .command + "` [*flags*...] " + (.args | map("*" + .label + "*" + (if has("arity") then "" else "..." end)) | join(" ")) + "\n\n"
|
||||||
;
|
;
|
||||||
|
|
||||||
def show_command:
|
def show_command:
|
||||||
|
@ -21,6 +21,10 @@ def show_command:
|
||||||
+ "`" + .command + "` - " + .def.description + "\n\n"
|
+ "`" + .command + "` - " + .def.description + "\n\n"
|
||||||
+ .section + " Synopsis\n\n"
|
+ .section + " Synopsis\n\n"
|
||||||
+ ({"command": .command, "args": .def.args} | show_synopsis)
|
+ ({"command": .command, "args": .def.args} | show_synopsis)
|
||||||
|
+ (if .def | has("doc")
|
||||||
|
then .section + " Description\n\n" + .def.doc + "\n\n"
|
||||||
|
else ""
|
||||||
|
end)
|
||||||
+ (if (.def.flags | length) > 0 then
|
+ (if (.def.flags | length) > 0 then
|
||||||
.section + " Flags\n\n"
|
.section + " Flags\n\n"
|
||||||
+ (.def | show_flags)
|
+ (.def | show_flags)
|
||||||
|
|
|
@ -359,12 +359,14 @@ nlohmann::json Command::toJSON()
|
||||||
for (auto & example : examples()) {
|
for (auto & example : examples()) {
|
||||||
auto ex = nlohmann::json::object();
|
auto ex = nlohmann::json::object();
|
||||||
ex["description"] = example.description;
|
ex["description"] = example.description;
|
||||||
ex["command"] = example.command;
|
ex["command"] = chomp(stripIndentation(example.command));
|
||||||
exs.push_back(std::move(ex));
|
exs.push_back(std::move(ex));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto res = Args::toJSON();
|
auto res = Args::toJSON();
|
||||||
res["examples"] = std::move(exs);
|
res["examples"] = std::move(exs);
|
||||||
|
auto s = doc();
|
||||||
|
if (s != "") res.emplace("doc", stripIndentation(s));
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ public:
|
||||||
|
|
||||||
virtual void printHelp(const string & programName, std::ostream & out);
|
virtual void printHelp(const string & programName, std::ostream & out);
|
||||||
|
|
||||||
|
/* Return a short one-line description of the command. */
|
||||||
virtual std::string description() { return ""; }
|
virtual std::string description() { return ""; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -221,6 +222,9 @@ struct Command : virtual Args
|
||||||
virtual void prepare() { };
|
virtual void prepare() { };
|
||||||
virtual void run() = 0;
|
virtual void run() = 0;
|
||||||
|
|
||||||
|
/* Return documentation about this command, in Markdown format. */
|
||||||
|
virtual std::string doc() { return ""; }
|
||||||
|
|
||||||
struct Example
|
struct Example
|
||||||
{
|
{
|
||||||
std::string description;
|
std::string description;
|
||||||
|
|
|
@ -153,43 +153,6 @@ void Config::convertToArgs(Args & args, const std::string & category)
|
||||||
s.second.setting->convertToArg(args, category);
|
s.second.setting->convertToArg(args, category);
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string stripIndentation(std::string_view s)
|
|
||||||
{
|
|
||||||
size_t minIndent = 10000;
|
|
||||||
size_t curIndent = 0;
|
|
||||||
bool atStartOfLine = true;
|
|
||||||
|
|
||||||
for (auto & c : s) {
|
|
||||||
if (atStartOfLine && c == ' ')
|
|
||||||
curIndent++;
|
|
||||||
else if (c == '\n') {
|
|
||||||
if (atStartOfLine)
|
|
||||||
minIndent = std::max(minIndent, curIndent);
|
|
||||||
curIndent = 0;
|
|
||||||
atStartOfLine = true;
|
|
||||||
} else {
|
|
||||||
if (atStartOfLine) {
|
|
||||||
minIndent = std::min(minIndent, curIndent);
|
|
||||||
atStartOfLine = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string res;
|
|
||||||
|
|
||||||
size_t pos = 0;
|
|
||||||
while (pos < s.size()) {
|
|
||||||
auto eol = s.find('\n', pos);
|
|
||||||
if (eol == s.npos) eol = s.size();
|
|
||||||
if (eol - pos > minIndent)
|
|
||||||
res.append(s.substr(pos + minIndent, eol - pos - minIndent));
|
|
||||||
res.push_back('\n');
|
|
||||||
pos = eol + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
AbstractSetting::AbstractSetting(
|
AbstractSetting::AbstractSetting(
|
||||||
const std::string & name,
|
const std::string & name,
|
||||||
const std::string & description,
|
const std::string & description,
|
||||||
|
|
|
@ -1464,6 +1464,47 @@ string base64Decode(std::string_view s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string stripIndentation(std::string_view s)
|
||||||
|
{
|
||||||
|
size_t minIndent = 10000;
|
||||||
|
size_t curIndent = 0;
|
||||||
|
bool atStartOfLine = true;
|
||||||
|
|
||||||
|
for (auto & c : s) {
|
||||||
|
if (atStartOfLine && c == ' ')
|
||||||
|
curIndent++;
|
||||||
|
else if (c == '\n') {
|
||||||
|
if (atStartOfLine)
|
||||||
|
minIndent = std::max(minIndent, curIndent);
|
||||||
|
curIndent = 0;
|
||||||
|
atStartOfLine = true;
|
||||||
|
} else {
|
||||||
|
if (atStartOfLine) {
|
||||||
|
minIndent = std::min(minIndent, curIndent);
|
||||||
|
atStartOfLine = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string res;
|
||||||
|
|
||||||
|
size_t pos = 0;
|
||||||
|
while (pos < s.size()) {
|
||||||
|
auto eol = s.find('\n', pos);
|
||||||
|
if (eol == s.npos) eol = s.size();
|
||||||
|
if (eol - pos > minIndent)
|
||||||
|
res.append(s.substr(pos + minIndent, eol - pos - minIndent));
|
||||||
|
res.push_back('\n');
|
||||||
|
pos = eol + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
static Sync<std::pair<unsigned short, unsigned short>> windowSize{{0, 0}};
|
static Sync<std::pair<unsigned short, unsigned short>> windowSize{{0, 0}};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -464,6 +464,12 @@ string base64Encode(std::string_view s);
|
||||||
string base64Decode(std::string_view s);
|
string base64Decode(std::string_view s);
|
||||||
|
|
||||||
|
|
||||||
|
/* Remove common leading whitespace from the lines in the string
|
||||||
|
's'. For example, if every line is indented by at least 3 spaces,
|
||||||
|
then we remove 3 spaces from the start of every line. */
|
||||||
|
std::string stripIndentation(std::string_view s);
|
||||||
|
|
||||||
|
|
||||||
/* Get a value for the specified key from an associate container. */
|
/* Get a value for the specified key from an associate container. */
|
||||||
template <class T>
|
template <class T>
|
||||||
std::optional<typename T::mapped_type> get(const T & map, const typename T::key_type & key)
|
std::optional<typename T::mapped_type> get(const T & map, const typename T::key_type & key)
|
||||||
|
|
|
@ -36,6 +36,14 @@ struct CmdAddToStore : MixDryRun, StoreCommand
|
||||||
return "add a path to the Nix store";
|
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
|
Examples examples() override
|
||||||
{
|
{
|
||||||
return {
|
return {
|
||||||
|
|
Loading…
Reference in a new issue