mirror of
https://github.com/YosysHQ/yosys
synced 2025-07-28 15:07:58 +00:00
Docs: Proto doc_string approach for cmd help
Add `doc_string` field to `Pass` constructor Add `docs/util/newcmdref.py` to contain command domain Update `docs/util/cmdref.py` with `cmd:usage` and `cmd:optiongroup` for describing commands. Functional, but WIP.
This commit is contained in:
parent
5ce097ed3d
commit
714790c70b
5 changed files with 635 additions and 43 deletions
|
@ -29,30 +29,6 @@
|
|||
|
||||
YOSYS_NAMESPACE_BEGIN
|
||||
|
||||
#define MAX_LINE_LEN 80
|
||||
void log_pass_str(const std::string &pass_str, int indent=0, bool leading_newline=false) {
|
||||
if (pass_str.empty())
|
||||
return;
|
||||
std::string indent_str(indent*4, ' ');
|
||||
std::istringstream iss(pass_str);
|
||||
if (leading_newline)
|
||||
log("\n");
|
||||
for (std::string line; std::getline(iss, line);) {
|
||||
log("%s", indent_str.c_str());
|
||||
auto curr_len = indent_str.length();
|
||||
std::istringstream lss(line);
|
||||
for (std::string word; std::getline(lss, word, ' ');) {
|
||||
if (curr_len + word.length() >= MAX_LINE_LEN) {
|
||||
curr_len = 0;
|
||||
log("\n%s", indent_str.c_str());
|
||||
}
|
||||
log("%s ", word.c_str());
|
||||
curr_len += word.length() + 1;
|
||||
}
|
||||
log("\n");
|
||||
}
|
||||
}
|
||||
|
||||
#define MAX_REG_COUNT 1000
|
||||
|
||||
bool echo_mode = false;
|
||||
|
@ -65,7 +41,7 @@ std::map<std::string, Backend*> backend_register;
|
|||
|
||||
std::vector<std::string> Frontend::next_args;
|
||||
|
||||
Pass::Pass(std::string name, std::string short_help, const vector<PassUsageBlock> usages) : pass_name(name), short_help(short_help), pass_usages(usages)
|
||||
Pass::Pass(std::string name, std::string short_help, const vector<std::string> doc_string, const vector<PassUsageBlock> usages) : pass_name(name), short_help(short_help), doc_string(doc_string), pass_usages(usages)
|
||||
{
|
||||
next_queued_pass = first_queued_pass;
|
||||
first_queued_pass = this;
|
||||
|
@ -138,6 +114,37 @@ void Pass::post_execute(Pass::pre_post_exec_state_t state)
|
|||
current_pass->runtime_ns -= time_ns;
|
||||
}
|
||||
|
||||
#define MAX_LINE_LEN 80
|
||||
void log_pass_str(const std::string &pass_str, std::string indent_str, bool leading_newline=false) {
|
||||
if (pass_str.empty())
|
||||
return;
|
||||
std::istringstream iss(pass_str);
|
||||
if (leading_newline)
|
||||
log("\n");
|
||||
for (std::string line; std::getline(iss, line);) {
|
||||
log("%s", indent_str.c_str());
|
||||
auto curr_len = indent_str.length();
|
||||
std::istringstream lss(line);
|
||||
for (std::string word; std::getline(lss, word, ' ');) {
|
||||
while (word[0] == '`' && word.back() == '`')
|
||||
word = word.substr(1, word.length()-2);
|
||||
if (curr_len + word.length() >= MAX_LINE_LEN-1) {
|
||||
curr_len = 0;
|
||||
log("\n%s", indent_str.c_str());
|
||||
}
|
||||
if (word.length()) {
|
||||
log("%s ", word.c_str());
|
||||
curr_len += word.length() + 1;
|
||||
}
|
||||
}
|
||||
log("\n");
|
||||
}
|
||||
}
|
||||
void log_pass_str(const std::string &pass_str, int indent=0, bool leading_newline=false) {
|
||||
std::string indent_str(indent*4, ' ');
|
||||
log_pass_str(pass_str, indent_str, leading_newline);
|
||||
}
|
||||
|
||||
void Pass::help()
|
||||
{
|
||||
if (HasUsages()) {
|
||||
|
@ -151,6 +158,28 @@ void Pass::help()
|
|||
log_pass_str(usage.postscript, 0, true);
|
||||
}
|
||||
log("\n");
|
||||
} else if (HasDocstring()) {
|
||||
log("\n");
|
||||
auto print_empty = true;
|
||||
for (auto doc_line : doc_string) {
|
||||
if (doc_line.find("..") == 0 && doc_line.find(":: ") != std::string::npos) {
|
||||
auto command_pos = doc_line.find(":: ");
|
||||
auto command_str = doc_line.substr(0, command_pos);
|
||||
if (command_str.compare(".. cmd:usage") == 0) {
|
||||
log_pass_str(doc_line.substr(command_pos+3), 1);
|
||||
} else {
|
||||
print_empty = false;
|
||||
}
|
||||
} else if (doc_line.length()) {
|
||||
std::size_t first_pos = doc_line.find_first_not_of(" \t");
|
||||
auto indent_str = doc_line.substr(0, first_pos);
|
||||
log_pass_str(doc_line, indent_str);
|
||||
print_empty = true;
|
||||
} else if (print_empty) {
|
||||
log("\n");
|
||||
}
|
||||
}
|
||||
log("\n");
|
||||
} else {
|
||||
log("\n");
|
||||
log("No help message for command `%s'.\n", pass_name.c_str());
|
||||
|
@ -852,7 +881,7 @@ struct HelpPass : public Pass {
|
|||
vector<PassUsageBlock> usages;
|
||||
auto experimental_flag = pass->experimental_flag;
|
||||
|
||||
if (pass->HasUsages()) {
|
||||
if (pass->HasUsages() || pass->HasDocstring()) {
|
||||
for (auto usage : pass->pass_usages)
|
||||
usages.push_back(usage);
|
||||
} else {
|
||||
|
@ -949,23 +978,28 @@ struct HelpPass : public Pass {
|
|||
// write to json
|
||||
json.name(name.c_str()); json.begin_object();
|
||||
json.entry("title", title);
|
||||
json.name("usages"); json.begin_array();
|
||||
for (auto usage : usages) {
|
||||
json.begin_object();
|
||||
json.entry("signature", usage.signature);
|
||||
json.entry("description", usage.description);
|
||||
json.name("options"); json.begin_array();
|
||||
for (auto option : usage.options) {
|
||||
json.begin_array();
|
||||
json.value(option.keyword);
|
||||
json.value(option.description);
|
||||
if (pass->HasDocstring()) {
|
||||
json.entry("content", pass->doc_string);
|
||||
}
|
||||
if (usages.size()) {
|
||||
json.name("usages"); json.begin_array();
|
||||
for (auto usage : usages) {
|
||||
json.begin_object();
|
||||
json.entry("signature", usage.signature);
|
||||
json.entry("description", usage.description);
|
||||
json.name("options"); json.begin_array();
|
||||
for (auto option : usage.options) {
|
||||
json.begin_array();
|
||||
json.value(option.keyword);
|
||||
json.value(option.description);
|
||||
json.end_array();
|
||||
}
|
||||
json.end_array();
|
||||
json.entry("postscript", usage.postscript);
|
||||
json.end_object();
|
||||
}
|
||||
json.end_array();
|
||||
json.entry("postscript", usage.postscript);
|
||||
json.end_object();
|
||||
}
|
||||
json.end_array();
|
||||
json.entry("experimental_flag", experimental_flag);
|
||||
json.end_object();
|
||||
}
|
||||
|
|
|
@ -40,8 +40,10 @@ struct PassUsageBlock {
|
|||
struct Pass
|
||||
{
|
||||
std::string pass_name, short_help;
|
||||
const vector<std::string> doc_string;
|
||||
const vector<PassUsageBlock> pass_usages;
|
||||
Pass(std::string name, std::string short_help = "** document me **",
|
||||
const vector<std::string> doc_string = {},
|
||||
const vector<PassUsageBlock> usages = {});
|
||||
// Prefer overriding 'Pass::on_shutdown()' if possible
|
||||
virtual ~Pass();
|
||||
|
@ -62,6 +64,10 @@ struct Pass
|
|||
return !pass_usages.empty();
|
||||
}
|
||||
|
||||
bool HasDocstring() {
|
||||
return !doc_string.empty();
|
||||
}
|
||||
|
||||
struct pre_post_exec_state_t {
|
||||
Pass *parent_pass;
|
||||
int64_t begin_ns;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue