From d1d544e23caef571f578996c6bdae9233d0ff7d2 Mon Sep 17 00:00:00 2001 From: Hendrik Eeckhaut Date: Fri, 6 Sep 2024 21:35:12 +0200 Subject: [PATCH] Create CLI documentation with a Rust script (instead of Python) + style improvement (#10680) --- .github/workflows/lint.yml | 1 + book/cli/SUMMARY.md | 1 - book/cli/help.py | 294 --------------- book/cli/help.rs | 374 ++++++++++++++++++++ book/cli/reth.md | 2 + book/cli/reth/config.md | 2 + book/cli/reth/db.md | 2 + book/cli/reth/db/checksum.md | 2 + book/cli/reth/db/clear.md | 2 + book/cli/reth/db/clear/mdbx.md | 2 + book/cli/reth/db/clear/static-file.md | 2 + book/cli/reth/db/diff.md | 2 + book/cli/reth/db/drop.md | 2 + book/cli/reth/db/get.md | 2 + book/cli/reth/db/get/mdbx.md | 2 + book/cli/reth/db/get/static-file.md | 2 + book/cli/reth/db/list.md | 2 + book/cli/reth/db/path.md | 2 + book/cli/reth/db/stats.md | 2 + book/cli/reth/db/version.md | 2 + book/cli/reth/debug.md | 2 + book/cli/reth/debug/build-block.md | 2 + book/cli/reth/debug/execution.md | 2 + book/cli/reth/debug/in-memory-merkle.md | 2 + book/cli/reth/debug/merkle.md | 2 + book/cli/reth/debug/replay-engine.md | 2 + book/cli/reth/dump-genesis.md | 2 + book/cli/reth/import.md | 2 + book/cli/reth/init-state.md | 2 + book/cli/reth/init.md | 2 + book/cli/reth/node.md | 2 + book/cli/reth/p2p.md | 2 + book/cli/reth/p2p/body.md | 2 + book/cli/reth/p2p/header.md | 2 + book/cli/reth/p2p/rlpx.md | 2 + book/cli/reth/p2p/rlpx/ping.md | 2 + book/cli/reth/prune.md | 2 + book/cli/reth/recover.md | 2 + book/cli/reth/recover/storage-tries.md | 2 + book/cli/reth/stage.md | 2 + book/cli/reth/stage/drop.md | 2 + book/cli/reth/stage/dump.md | 2 + book/cli/reth/stage/dump/account-hashing.md | 2 + book/cli/reth/stage/dump/execution.md | 2 + book/cli/reth/stage/dump/merkle.md | 2 + book/cli/reth/stage/dump/storage-hashing.md | 2 + book/cli/reth/stage/run.md | 2 + book/cli/reth/stage/unwind.md | 2 + book/cli/reth/stage/unwind/num-blocks.md | 2 + book/cli/reth/stage/unwind/to-block.md | 2 + book/cli/update.sh | 2 +- 51 files changed, 468 insertions(+), 296 deletions(-) delete mode 100755 book/cli/help.py create mode 100755 book/cli/help.rs diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 47fc54071ee5..6f6042f0cd41 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -130,6 +130,7 @@ jobs: timeout-minutes: 30 steps: - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@nightly - uses: dtolnay/rust-toolchain@master with: toolchain: "1.81" # MSRV diff --git a/book/cli/SUMMARY.md b/book/cli/SUMMARY.md index 4cc86c7a3649..5f338a0d1ec7 100644 --- a/book/cli/SUMMARY.md +++ b/book/cli/SUMMARY.md @@ -44,4 +44,3 @@ - [`reth recover`](./reth/recover.md) - [`reth recover storage-tries`](./reth/recover/storage-tries.md) - [`reth prune`](./reth/prune.md) - diff --git a/book/cli/help.py b/book/cli/help.py deleted file mode 100755 index 3f40a5e0b566..000000000000 --- a/book/cli/help.py +++ /dev/null @@ -1,294 +0,0 @@ -#!/usr/bin/env python3 - -import argparse -import os -import re -import subprocess -import sys -from os import makedirs, path - -HELP_KEY = "help" -SECTION_START = "" -SECTION_END = "" -SECTION_RE = rf"\s*{SECTION_START}.*?{SECTION_END}" - -README = """\ -# CLI Reference - - - -Automatically-generated CLI reference from `--help` output. - -{{#include ./SUMMARY.md}} -""" - - -def write_file(file_path, content): - content = "\n".join([line.rstrip() for line in content.split("\n")]) - with open(file_path, "w") as f: - f.write(content) - - -def main(): - args = parse_args(sys.argv[1:]) - for cmd in args.commands: - if cmd.find(" ") >= 0: - raise Exception(f"subcommands are not allowed: {cmd}") - makedirs(args.out_dir, exist_ok=True) - - output = {} - - # Iterate over all commands and their subcommands. - cmd_iter = [[cmd] for cmd in args.commands] - for cmd in cmd_iter: - subcmds, stdout = get_entry(cmd) - if args.verbose and len(subcmds) > 0: - eprint(f"Found subcommands for \"{' '.join(cmd)}\": {subcmds}") - - # Add entry to output map, e.g. `output["cmd"]["subcmd"]["help"] = "..."`. - e = output - for arg in cmd: - tmp = e.get(arg) - if not tmp: - e[arg] = {} - tmp = e[arg] - e = tmp - e[HELP_KEY] = stdout - - # Append subcommands. - for subcmd in subcmds: - cmd_iter.append(cmd + [subcmd]) - - # Generate markdown files. - summary = "" - root_summary = "" - for cmd, obj in output.items(): - cmd_markdown(args.out_dir, cmd, obj) - - root_path = path.relpath(args.out_dir, args.root_dir) - summary += cmd_summary("", cmd, obj, 0) - summary += "\n" - - root_summary += cmd_summary(root_path, cmd, obj, args.root_indentation) - root_summary += "\n" - write_file(path.join(args.out_dir, "SUMMARY.md"), summary) - - # Generate README.md. - if args.readme: - write_file(path.join(args.out_dir, "README.md"), README) - - if args.root_summary: - update_root_summary(args.root_dir, root_summary) - - -def parse_args(args: list[str]): - """Parses command line arguments.""" - parser = argparse.ArgumentParser( - description="Generate markdown files from help output of commands" - ) - parser.add_argument("--root-dir", default=".", help="Root directory") - parser.add_argument( - "--root-indentation", - default=0, - type=int, - help="Indentation for the root SUMMARY.md file", - ) - parser.add_argument("--out-dir", help="Output directory") - parser.add_argument( - "--readme", - action="store_true", - help="Whether to add a README.md file", - ) - parser.add_argument( - "--root-summary", - action="store_true", - help="Whether to update the root SUMMARY.md file", - ) - parser.add_argument( - "commands", - nargs="+", - help="Command to generate markdown for. Can be a subcommand.", - ) - parser.add_argument( - "--verbose", "-v", action="store_true", help="Print verbose output" - ) - return parser.parse_known_args(args)[0] - - -def get_entry(cmd: list[str]): - """Returns the subcommands and help output for a command.""" - env = os.environ.copy() - env["NO_COLOR"] = "1" - env["COLUMNS"] = "100" - env["LINES"] = "10000" - output = subprocess.run(cmd + ["--help"], capture_output=True, env=env) - if output.returncode != 0: - stderr = output.stderr.decode("utf-8") - raise Exception(f"Command \"{' '.join(cmd)}\" failed:\n{stderr}") - stdout = output.stdout.decode("utf-8") - subcmds = parse_sub_commands(stdout) - return subcmds, stdout - - -def parse_sub_commands(s: str): - """Returns a list of subcommands from the help output of a command.""" - idx = s.find("Commands:") - if idx < 0: - return [] - s = s[idx:] - - idx = s.find("Options:") - if idx < 0: - return [] - s = s[:idx] - - idx = s.find("Arguments:") - if idx >= 0: - s = s[:idx] - - subcmds = s.splitlines()[1:] - subcmds = filter( - lambda x: x.strip() != "" and x.startswith(" ") and x[2] != " ", subcmds - ) - subcmds = map(lambda x: x.strip().split(" ")[0], subcmds) - subcmds = filter(lambda x: x != "help", subcmds) - return list(subcmds) - - -def cmd_markdown(out_dir: str, cmd: str, obj: object): - """Writes the markdown for a command and its subcommands to out_dir.""" - - def rec(cmd: list[str], obj: object): - out = "" - out += f"# {' '.join(cmd)}\n\n" - out += help_markdown(cmd, obj[HELP_KEY]) - out_path = out_dir - for arg in cmd: - out_path = path.join(out_path, arg) - makedirs(path.dirname(out_path), exist_ok=True) - write_file(f"{out_path}.md", out) - - for k, v in obj.items(): - if k == HELP_KEY: - continue - rec(cmd + [k], v) - - rec([command_name(cmd)], obj) - - -def help_markdown(cmd: list[str], s: str): - """Returns the markdown for a command's help output.""" - cmd[0] = command_name(cmd[0]) - description, s = parse_description(s) - return f"""\ -{description} - -```bash -$ {' '.join(cmd)} --help -{preprocess_help(s.strip())} -```""" - - -def parse_description(s: str): - """Splits the help output into a description and the rest.""" - idx = s.find("Usage:") - if idx < 0: - return "", s - return s[:idx].strip().splitlines()[0].strip(), s[idx:] - - -def cmd_summary(md_root: str, cmd: str, obj: object, indent: int): - """Returns the summary for a command and its subcommands.""" - - def rec(cmd: list[str], obj: object, indent: int): - nonlocal out - cmd_s = " ".join(cmd) - cmd_path = cmd_s.replace(" ", "/") - if md_root != "": - cmd_path = f"{md_root}/{cmd_path}" - out += f"{' ' * indent}- [`{cmd_s}`](./{cmd_path}.md)\n" - - for k, v in obj.items(): - if k == HELP_KEY: - continue - rec(cmd + [k], v, indent + 2) - - out = "" - rec([command_name(cmd)], obj, indent) - return out - - -def update_root_summary(root_dir: str, root_summary: str): - """Replaces the CLI_REFERENCE section in the root SUMMARY.md file.""" - summary_file = path.join(root_dir, "SUMMARY.md") - - with open(summary_file, "r") as f: - real_root_summary = f.read() - - if not re.search(SECTION_RE, real_root_summary, flags=re.DOTALL): - raise Exception( - f"Could not find CLI_REFERENCE section in {summary_file}. " - "Please add the following section to the file:\n" - f"{SECTION_START}\n{SECTION_END}" - ) - - last_line = re.findall(f".*{SECTION_END}", real_root_summary)[0] - root_summary_s = root_summary.rstrip().replace("\n\n", "\n") - replace_with = f" {SECTION_START}\n{root_summary_s}\n{last_line}" - - real_root_summary = re.sub( - SECTION_RE, replace_with, real_root_summary, flags=re.DOTALL - ) - root_summary_file = path.join(root_dir, "SUMMARY.md") - with open(root_summary_file, "w") as f: - f.write(real_root_summary) - - -def eprint(*args, **kwargs): - """Prints to stderr.""" - print(*args, file=sys.stderr, **kwargs) - - -def command_name(cmd: str): - """Returns the name of a command.""" - return cmd.split("/")[-1] - - -def preprocess_help(s: str): - """Preprocesses the help output of a command.""" - # Remove the user-specific paths. - s = re.sub( - r"default: /.*/reth", - "default: ", - s, - ) - # Remove the commit SHA and target architecture triple or fourth - # rustup available targets: - # aarch64-apple-darwin - # x86_64-unknown-linux-gnu - # x86_64-pc-windows-gnu - s = re.sub( - r"default: reth/.*-[0-9A-Fa-f]{6,10}/([_\w]+)-(\w+)-(\w+)(-\w+)?", - "default: reth/-/", - s, - ) - # Remove the OS - s = re.sub( - r"default: reth/.*/\w+", - "default: reth//", - s, - ) - - # Remove rpc.max-tracing-requests default value - s = re.sub( - r"(rpc.max-tracing-requests \n.*\n.*\n.*)\[default: \d+\]", - r"\1[default: ]", - s, - flags=re.MULTILINE, - ) - - return s - - -if __name__ == "__main__": - main() diff --git a/book/cli/help.rs b/book/cli/help.rs new file mode 100755 index 000000000000..e347e1ea5db6 --- /dev/null +++ b/book/cli/help.rs @@ -0,0 +1,374 @@ +#!/usr/bin/env -S cargo +nightly -Zscript +--- +[package] +edition = "2021" + +[dependencies] +clap = { version = "4", features = ["derive"] } +pathdiff = "0.2" +regex = "1" +--- +use clap::Parser; +use regex::Regex; +use std::borrow::Cow; +use std::fs::{self, File}; +use std::io::{self, Write}; +use std::iter::once; +use std::path::{Path, PathBuf}; +use std::process::{Command, Stdio}; +use std::str; +use std::sync::LazyLock; +use std::{fmt, process}; + +const SECTION_START: &str = ""; +const SECTION_END: &str = ""; +const README: &str = r#"# CLI Reference + + + +Automatically-generated CLI reference from `--help` output. + +{{#include ./SUMMARY.md}} +"#; +const TRIM_LINE_END_MARKDOWN: bool = true; + +/// Lazy static regex to avoid recompiling the same regex pattern multiple times. +macro_rules! regex { + ($re:expr) => {{ + static RE: LazyLock = + LazyLock::new(|| Regex::new($re).expect("Failed to compile regex pattern")); + &*RE + }}; +} + +/// Generate markdown files from help output of commands +#[derive(Parser, Debug)] +#[command(about, long_about = None)] +struct Args { + /// Root directory + #[arg(long, default_value_t = String::from("."))] + root_dir: String, + + /// Indentation for the root SUMMARY.md file + #[arg(long, default_value_t = 2)] + root_indentation: usize, + + /// Output directory + #[arg(long)] + out_dir: PathBuf, + + /// Whether to add a README.md file + #[arg(long)] + readme: bool, + + /// Whether to update the root SUMMARY.md file + #[arg(long)] + root_summary: bool, + + /// Print verbose output + #[arg(short, long)] + verbose: bool, + + /// Commands to generate markdown for. + #[arg(required = true, num_args = 1..)] + commands: Vec, +} + +fn write_file(file_path: &Path, content: &str) -> io::Result<()> { + let content = if TRIM_LINE_END_MARKDOWN { + content + .lines() + .map(|line| line.trim_end()) + .collect::>() + .join("\n") + } else { + content.to_string() + }; + fs::write(file_path, content) +} + +fn main() -> io::Result<()> { + let args = Args::parse(); + debug_assert!(args.commands.len() >= 1); + + let out_dir = args.out_dir; + fs::create_dir_all(&out_dir)?; + + let mut todo_iter: Vec = args + .commands + .iter() + .rev() // reverse to keep the order (pop) + .map(Cmd::new) + .collect(); + let mut output = Vec::new(); + + // Iterate over all commands and their subcommands. + while let Some(cmd) = todo_iter.pop() { + let (new_subcmds, stdout) = get_entry(&cmd)?; + if args.verbose && !new_subcmds.is_empty() { + println!( + "Found subcommands for \"{}\": {:?}", + cmd.command_name(), + new_subcmds + ); + } + // Add new subcommands to todo_iter (so that they are processed in the correct order). + for subcmd in new_subcmds.into_iter().rev() { + let new_subcmds: Vec<_> = cmd + .subcommands + .iter() + .cloned() + .chain(once(subcmd)) + .collect(); + + todo_iter.push(Cmd { + cmd: cmd.cmd, + subcommands: new_subcmds, + }); + } + output.push((cmd, stdout)); + } + + // Generate markdown files. + for (cmd, stdout) in &output { + cmd_markdown(&out_dir, cmd, stdout)?; + } + + // Generate SUMMARY.md. + let summary: String = output + .iter() + .map(|(cmd, _)| cmd_summary(None, cmd, 0)) + .chain(once("\n".to_string())) + .collect(); + + write_file(&out_dir.clone().join("SUMMARY.md"), &summary)?; + + // Generate README.md. + if args.readme { + let path = &out_dir.join("README.md"); + if args.verbose { + println!("Writing README.md to \"{}\"", path.to_string_lossy()); + } + write_file(path, README)?; + } + + // Generate root SUMMARY.md. + if args.root_summary { + let root_summary: String = output + .iter() + .map(|(cmd, _)| { + let root_path = pathdiff::diff_paths(&out_dir, &args.root_dir); + cmd_summary(root_path, cmd, args.root_indentation) + }) + .collect(); + + let path = Path::new(args.root_dir.as_str()); + if args.verbose { + println!("Updating root summary in \"{}\"", path.to_string_lossy()); + } + update_root_summary(path, &root_summary)?; + } + + Ok(()) +} + +/// Returns the subcommands and help output for a command. +fn get_entry(cmd: &Cmd) -> io::Result<(Vec, String)> { + let output = Command::new(cmd.cmd) + .args(&cmd.subcommands) + .arg("--help") + .env("NO_COLOR", "1") + .env("COLUMNS", "100") + .env("LINES", "10000") + .stdout(Stdio::piped()) + .output()?; + + if !output.status.success() { + let stderr = str::from_utf8(&output.stderr).unwrap_or("Failed to parse stderr as UTF-8"); + return Err(io::Error::new( + io::ErrorKind::Other, + format!("Command \"{}\" failed:\n{}", cmd, stderr), + )); + } + + let stdout = str::from_utf8(&output.stdout) + .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))? + .to_string(); + + // Parse subcommands from the help output + let subcmds = parse_sub_commands(&stdout); + + Ok((subcmds, stdout)) +} + +/// Returns a list of subcommands from the help output of a command. +fn parse_sub_commands(s: &str) -> Vec { + // This regex matches lines starting with two spaces, followed by the subcommand name. + let re = regex!(r"^ (\S+)"); + + s.split("Commands:") + .nth(1) // Get the part after "Commands:" + .map(|commands_section| { + commands_section + .lines() + .take_while(|line| !line.starts_with("Options:") && !line.starts_with("Arguments:")) + .filter_map(|line| { + re.captures(line) + .and_then(|cap| cap.get(1).map(|m| m.as_str().to_string())) + }) + .filter(|cmd| cmd != "help") + .map(String::from) + .collect() + }) + .unwrap_or_default() // Return an empty Vec if "Commands:" was not found +} + +/// Writes the markdown for a command to out_dir. +fn cmd_markdown(out_dir: &Path, cmd: &Cmd, stdout: &str) -> io::Result<()> { + let out = format!("# {}\n\n{}", cmd, help_markdown(cmd, stdout)); + + let out_path = out_dir.join(cmd.to_string().replace(" ", "/")); + fs::create_dir_all(out_path.parent().unwrap())?; + write_file(&out_path.with_extension("md"), &out)?; + + Ok(()) +} + +/// Returns the markdown for a command's help output. +fn help_markdown(cmd: &Cmd, stdout: &str) -> String { + let (description, s) = parse_description(stdout); + format!( + "{}\n\n```bash\n$ {} --help\n```\n```txt\n{}\n```", + description, + cmd, + preprocess_help(s.trim()) + ) +} + +/// Splits the help output into a description and the rest. +fn parse_description(s: &str) -> (&str, &str) { + match s.find("Usage:") { + Some(idx) => { + let description = s[..idx].trim().lines().next().unwrap_or(""); + (description, &s[idx..]) + } + None => ("", s), + } +} + +/// Returns the summary for a command and its subcommands. +fn cmd_summary(md_root: Option, cmd: &Cmd, indent: usize) -> String { + let cmd_s = cmd.to_string(); + let cmd_path = cmd_s.replace(" ", "/"); + let full_cmd_path = match md_root { + None => cmd_path, + Some(md_root) => format!("{}/{}", md_root.to_string_lossy(), cmd_path), + }; + let indent_string = " ".repeat(indent + (cmd.subcommands.len() * 2)); + format!("{}- [`{}`](./{}.md)\n", indent_string, cmd_s, full_cmd_path) +} + +/// Replaces the CLI_REFERENCE section in the root SUMMARY.md file. +fn update_root_summary(root_dir: &Path, root_summary: &str) -> io::Result<()> { + let summary_file = root_dir.join("SUMMARY.md"); + let original_summary_content = fs::read_to_string(&summary_file)?; + + let section_re = regex!(&format!(r"(?s)\s*{SECTION_START}.*?{SECTION_END}")); + if !section_re.is_match(&original_summary_content) { + eprintln!( + "Could not find CLI_REFERENCE section in {}. Please add the following section to the file:\n{}\n... CLI Reference goes here ...\n\n{}", + summary_file.display(), + SECTION_START, + SECTION_END + ); + process::exit(1); + } + + let section_end_re = regex!(&format!(r".*{SECTION_END}")); + let last_line = section_end_re + .find(&original_summary_content) + .map(|m| m.as_str().to_string()) + .expect("Could not extract last line of CLI_REFERENCE section"); + + let root_summary_s = root_summary.trim_end().replace("\n\n", "\n"); + let replace_with = format!(" {}\n{}\n{}", SECTION_START, root_summary_s, last_line); + + let new_root_summary = section_re + .replace(&original_summary_content, replace_with.as_str()) + .to_string(); + + let mut root_summary_file = File::create(&summary_file)?; + root_summary_file.write_all(new_root_summary.as_bytes()) +} + +/// Preprocesses the help output of a command. +fn preprocess_help(s: &str) -> Cow<'_, str> { + static REPLACEMENTS: LazyLock> = LazyLock::new(|| { + let patterns: &[(&str, &str)] = &[ + // Remove the user-specific paths. + (r"default: /.*/reth", "default: "), + // Remove the commit SHA and target architecture triple or fourth + // rustup available targets: + // aarch64-apple-darwin + // x86_64-unknown-linux-gnu + // x86_64-pc-windows-gnu + ( + r"default: reth/.*-[0-9A-Fa-f]{6,10}/([_\w]+)-(\w+)-(\w+)(-\w+)?", + "default: reth/-/", + ), + // Remove the OS + (r"default: reth/.*/\w+", "default: reth//"), + // Remove rpc.max-tracing-requests default value + ( + r"(rpc.max-tracing-requests \n.*\n.*\n.*)\[default: \d+\]", + r"$1[default: ]", + ), + ]; + patterns + .iter() + .map(|&(re, replace_with)| (Regex::new(re).expect(re), replace_with)) + .collect() + }); + + let mut s = Cow::Borrowed(s); + for (re, replacement) in REPLACEMENTS.iter() { + if let Cow::Owned(result) = re.replace_all(&s, *replacement) { + s = Cow::Owned(result); + } + } + s +} + +#[derive(Hash, Debug, PartialEq, Eq)] +struct Cmd<'a> { + /// path to binary (e.g. ./target/debug/reth) + cmd: &'a Path, + /// subcommands (e.g. [db, stats]) + subcommands: Vec, +} + +impl<'a> Cmd<'a> { + fn command_name(&self) -> &str { + self.cmd + .file_name() + .and_then(|os_str| os_str.to_str()) + .expect("Expect valid command") + } + + fn new(cmd: &'a PathBuf) -> Self { + Self { + cmd, + subcommands: Vec::new(), + } + } +} + +impl<'a> fmt::Display for Cmd<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.command_name())?; + if !self.subcommands.is_empty() { + write!(f, " {}", self.subcommands.join(" "))?; + } + Ok(()) + } +} diff --git a/book/cli/reth.md b/book/cli/reth.md index cebeb44e2378..70a1dec4dace 100644 --- a/book/cli/reth.md +++ b/book/cli/reth.md @@ -4,6 +4,8 @@ Reth ```bash $ reth --help +``` +```txt Usage: reth [OPTIONS] Commands: diff --git a/book/cli/reth/config.md b/book/cli/reth/config.md index df0d261b07b1..ebf76fae372e 100644 --- a/book/cli/reth/config.md +++ b/book/cli/reth/config.md @@ -4,6 +4,8 @@ Write config to stdout ```bash $ reth config --help +``` +```txt Usage: reth config [OPTIONS] Options: diff --git a/book/cli/reth/db.md b/book/cli/reth/db.md index b867134a9d33..5bece3e31f73 100644 --- a/book/cli/reth/db.md +++ b/book/cli/reth/db.md @@ -4,6 +4,8 @@ Database debugging utilities ```bash $ reth db --help +``` +```txt Usage: reth db [OPTIONS] Commands: diff --git a/book/cli/reth/db/checksum.md b/book/cli/reth/db/checksum.md index 407630ed4143..a422454fd058 100644 --- a/book/cli/reth/db/checksum.md +++ b/book/cli/reth/db/checksum.md @@ -4,6 +4,8 @@ Calculates the content checksum of a table ```bash $ reth db checksum --help +``` +```txt Usage: reth db checksum [OPTIONS] Arguments: diff --git a/book/cli/reth/db/clear.md b/book/cli/reth/db/clear.md index 7abc54623b2f..554499a36d78 100644 --- a/book/cli/reth/db/clear.md +++ b/book/cli/reth/db/clear.md @@ -4,6 +4,8 @@ Deletes all table entries ```bash $ reth db clear --help +``` +```txt Usage: reth db clear [OPTIONS] Commands: diff --git a/book/cli/reth/db/clear/mdbx.md b/book/cli/reth/db/clear/mdbx.md index ad8ad761e8dc..50f373146702 100644 --- a/book/cli/reth/db/clear/mdbx.md +++ b/book/cli/reth/db/clear/mdbx.md @@ -4,6 +4,8 @@ Deletes all database table entries ```bash $ reth db clear mdbx --help +``` +```txt Usage: reth db clear mdbx [OPTIONS]
Arguments: diff --git a/book/cli/reth/db/clear/static-file.md b/book/cli/reth/db/clear/static-file.md index 9d1d25fa6ec8..c830af259c95 100644 --- a/book/cli/reth/db/clear/static-file.md +++ b/book/cli/reth/db/clear/static-file.md @@ -4,6 +4,8 @@ Deletes all static file segment entries ```bash $ reth db clear static-file --help +``` +```txt Usage: reth db clear static-file [OPTIONS] Arguments: diff --git a/book/cli/reth/db/diff.md b/book/cli/reth/db/diff.md index 88266901bb0c..ea4c29612ff7 100644 --- a/book/cli/reth/db/diff.md +++ b/book/cli/reth/db/diff.md @@ -4,6 +4,8 @@ Create a diff between two database tables or two entire databases ```bash $ reth db diff --help +``` +```txt Usage: reth db diff [OPTIONS] --secondary-datadir --output Options: diff --git a/book/cli/reth/db/drop.md b/book/cli/reth/db/drop.md index 4a8089f85ac4..c23f6d93c563 100644 --- a/book/cli/reth/db/drop.md +++ b/book/cli/reth/db/drop.md @@ -4,6 +4,8 @@ Deletes all database entries ```bash $ reth db drop --help +``` +```txt Usage: reth db drop [OPTIONS] Options: diff --git a/book/cli/reth/db/get.md b/book/cli/reth/db/get.md index 94081668add2..266e46e5ca62 100644 --- a/book/cli/reth/db/get.md +++ b/book/cli/reth/db/get.md @@ -4,6 +4,8 @@ Gets the content of a table for the given key ```bash $ reth db get --help +``` +```txt Usage: reth db get [OPTIONS] Commands: diff --git a/book/cli/reth/db/get/mdbx.md b/book/cli/reth/db/get/mdbx.md index 0921b79bf6a9..18fa76edaa8e 100644 --- a/book/cli/reth/db/get/mdbx.md +++ b/book/cli/reth/db/get/mdbx.md @@ -4,6 +4,8 @@ Gets the content of a database table for the given key ```bash $ reth db get mdbx --help +``` +```txt Usage: reth db get mdbx [OPTIONS]
[SUBKEY] Arguments: diff --git a/book/cli/reth/db/get/static-file.md b/book/cli/reth/db/get/static-file.md index 672df215948e..a50da0c0e45d 100644 --- a/book/cli/reth/db/get/static-file.md +++ b/book/cli/reth/db/get/static-file.md @@ -4,6 +4,8 @@ Gets the content of a static file segment for the given key ```bash $ reth db get static-file --help +``` +```txt Usage: reth db get static-file [OPTIONS] Arguments: diff --git a/book/cli/reth/db/list.md b/book/cli/reth/db/list.md index 68bc1d9c273c..9b64a70a07fb 100644 --- a/book/cli/reth/db/list.md +++ b/book/cli/reth/db/list.md @@ -4,6 +4,8 @@ Lists the contents of a table ```bash $ reth db list --help +``` +```txt Usage: reth db list [OPTIONS]
Arguments: diff --git a/book/cli/reth/db/path.md b/book/cli/reth/db/path.md index 591d8e150bde..a711acad0d88 100644 --- a/book/cli/reth/db/path.md +++ b/book/cli/reth/db/path.md @@ -4,6 +4,8 @@ Returns the full database path ```bash $ reth db path --help +``` +```txt Usage: reth db path [OPTIONS] Options: diff --git a/book/cli/reth/db/stats.md b/book/cli/reth/db/stats.md index 76b6c90ae91d..2ed087ae1c2d 100644 --- a/book/cli/reth/db/stats.md +++ b/book/cli/reth/db/stats.md @@ -4,6 +4,8 @@ Lists all the tables, their entry count and their size ```bash $ reth db stats --help +``` +```txt Usage: reth db stats [OPTIONS] Options: diff --git a/book/cli/reth/db/version.md b/book/cli/reth/db/version.md index 131dd6dc236a..549f9709170a 100644 --- a/book/cli/reth/db/version.md +++ b/book/cli/reth/db/version.md @@ -4,6 +4,8 @@ Lists current and local database versions ```bash $ reth db version --help +``` +```txt Usage: reth db version [OPTIONS] Options: diff --git a/book/cli/reth/debug.md b/book/cli/reth/debug.md index d61094834d39..ab016d631d61 100644 --- a/book/cli/reth/debug.md +++ b/book/cli/reth/debug.md @@ -4,6 +4,8 @@ Various debug routines ```bash $ reth debug --help +``` +```txt Usage: reth debug [OPTIONS] Commands: diff --git a/book/cli/reth/debug/build-block.md b/book/cli/reth/debug/build-block.md index e2103038933e..6676938d2dbe 100644 --- a/book/cli/reth/debug/build-block.md +++ b/book/cli/reth/debug/build-block.md @@ -4,6 +4,8 @@ Debug block building ```bash $ reth debug build-block --help +``` +```txt Usage: reth debug build-block [OPTIONS] --prev-randao --timestamp --suggested-fee-recipient Options: diff --git a/book/cli/reth/debug/execution.md b/book/cli/reth/debug/execution.md index 2f8732761fed..9935bd2d7193 100644 --- a/book/cli/reth/debug/execution.md +++ b/book/cli/reth/debug/execution.md @@ -4,6 +4,8 @@ Debug the roundtrip execution of blocks as well as the generated data ```bash $ reth debug execution --help +``` +```txt Usage: reth debug execution [OPTIONS] --to Options: diff --git a/book/cli/reth/debug/in-memory-merkle.md b/book/cli/reth/debug/in-memory-merkle.md index 112e9a9b0ef3..972abef59501 100644 --- a/book/cli/reth/debug/in-memory-merkle.md +++ b/book/cli/reth/debug/in-memory-merkle.md @@ -4,6 +4,8 @@ Debug in-memory state root calculation ```bash $ reth debug in-memory-merkle --help +``` +```txt Usage: reth debug in-memory-merkle [OPTIONS] Options: diff --git a/book/cli/reth/debug/merkle.md b/book/cli/reth/debug/merkle.md index c891cfc0e5be..322d180c20cc 100644 --- a/book/cli/reth/debug/merkle.md +++ b/book/cli/reth/debug/merkle.md @@ -4,6 +4,8 @@ Debug the clean & incremental state root calculations ```bash $ reth debug merkle --help +``` +```txt Usage: reth debug merkle [OPTIONS] --to Options: diff --git a/book/cli/reth/debug/replay-engine.md b/book/cli/reth/debug/replay-engine.md index 154f4464c441..5d21ac738cdd 100644 --- a/book/cli/reth/debug/replay-engine.md +++ b/book/cli/reth/debug/replay-engine.md @@ -4,6 +4,8 @@ Debug engine API by replaying stored messages ```bash $ reth debug replay-engine --help +``` +```txt Usage: reth debug replay-engine [OPTIONS] --engine-api-store Options: diff --git a/book/cli/reth/dump-genesis.md b/book/cli/reth/dump-genesis.md index 7197be305f26..0a45ffb328b6 100644 --- a/book/cli/reth/dump-genesis.md +++ b/book/cli/reth/dump-genesis.md @@ -4,6 +4,8 @@ Dumps genesis block JSON configuration to stdout ```bash $ reth dump-genesis --help +``` +```txt Usage: reth dump-genesis [OPTIONS] Options: diff --git a/book/cli/reth/import.md b/book/cli/reth/import.md index 29a67f181764..ec1b4e6489be 100644 --- a/book/cli/reth/import.md +++ b/book/cli/reth/import.md @@ -4,6 +4,8 @@ This syncs RLP encoded blocks from a file ```bash $ reth import --help +``` +```txt Usage: reth import [OPTIONS] Options: diff --git a/book/cli/reth/init-state.md b/book/cli/reth/init-state.md index d947baec376d..611f500198ed 100644 --- a/book/cli/reth/init-state.md +++ b/book/cli/reth/init-state.md @@ -4,6 +4,8 @@ Initialize the database from a state dump file ```bash $ reth init-state --help +``` +```txt Usage: reth init-state [OPTIONS] Options: diff --git a/book/cli/reth/init.md b/book/cli/reth/init.md index 5eb9d4d03ba4..c632a5d79feb 100644 --- a/book/cli/reth/init.md +++ b/book/cli/reth/init.md @@ -4,6 +4,8 @@ Initialize the database from a genesis file ```bash $ reth init --help +``` +```txt Usage: reth init [OPTIONS] Options: diff --git a/book/cli/reth/node.md b/book/cli/reth/node.md index 98f677c158e7..1ee2097eaa67 100644 --- a/book/cli/reth/node.md +++ b/book/cli/reth/node.md @@ -4,6 +4,8 @@ Start the node ```bash $ reth node --help +``` +```txt Usage: reth node [OPTIONS] Options: diff --git a/book/cli/reth/p2p.md b/book/cli/reth/p2p.md index 37bec56b8acf..48447cc1baf3 100644 --- a/book/cli/reth/p2p.md +++ b/book/cli/reth/p2p.md @@ -4,6 +4,8 @@ P2P Debugging utilities ```bash $ reth p2p --help +``` +```txt Usage: reth p2p [OPTIONS] Commands: diff --git a/book/cli/reth/p2p/body.md b/book/cli/reth/p2p/body.md index 3b6c6b1622a0..cb1a96d63dda 100644 --- a/book/cli/reth/p2p/body.md +++ b/book/cli/reth/p2p/body.md @@ -4,6 +4,8 @@ Download block body ```bash $ reth p2p body --help +``` +```txt Usage: reth p2p body [OPTIONS] Arguments: diff --git a/book/cli/reth/p2p/header.md b/book/cli/reth/p2p/header.md index c00b81ddbf3f..69557c523fe6 100644 --- a/book/cli/reth/p2p/header.md +++ b/book/cli/reth/p2p/header.md @@ -4,6 +4,8 @@ Download block header ```bash $ reth p2p header --help +``` +```txt Usage: reth p2p header [OPTIONS] Arguments: diff --git a/book/cli/reth/p2p/rlpx.md b/book/cli/reth/p2p/rlpx.md index dd73e437aa42..71a164c64383 100644 --- a/book/cli/reth/p2p/rlpx.md +++ b/book/cli/reth/p2p/rlpx.md @@ -4,6 +4,8 @@ RLPx commands ```bash $ reth p2p rlpx --help +``` +```txt Usage: reth p2p rlpx [OPTIONS] Commands: diff --git a/book/cli/reth/p2p/rlpx/ping.md b/book/cli/reth/p2p/rlpx/ping.md index 222b57735bc3..a7cef4bd33ef 100644 --- a/book/cli/reth/p2p/rlpx/ping.md +++ b/book/cli/reth/p2p/rlpx/ping.md @@ -4,6 +4,8 @@ ping node ```bash $ reth p2p rlpx ping --help +``` +```txt Usage: reth p2p rlpx ping [OPTIONS] Arguments: diff --git a/book/cli/reth/prune.md b/book/cli/reth/prune.md index 0b3e701f6b30..5a362d673211 100644 --- a/book/cli/reth/prune.md +++ b/book/cli/reth/prune.md @@ -4,6 +4,8 @@ Prune according to the configuration without any limits ```bash $ reth prune --help +``` +```txt Usage: reth prune [OPTIONS] Options: diff --git a/book/cli/reth/recover.md b/book/cli/reth/recover.md index 4fe28211db0b..dcb9c3c73c2f 100644 --- a/book/cli/reth/recover.md +++ b/book/cli/reth/recover.md @@ -4,6 +4,8 @@ Scripts for node recovery ```bash $ reth recover --help +``` +```txt Usage: reth recover [OPTIONS] Commands: diff --git a/book/cli/reth/recover/storage-tries.md b/book/cli/reth/recover/storage-tries.md index d5df358a711d..6fd6bba3cdca 100644 --- a/book/cli/reth/recover/storage-tries.md +++ b/book/cli/reth/recover/storage-tries.md @@ -4,6 +4,8 @@ Recover the node by deleting dangling storage tries ```bash $ reth recover storage-tries --help +``` +```txt Usage: reth recover storage-tries [OPTIONS] Options: diff --git a/book/cli/reth/stage.md b/book/cli/reth/stage.md index c9ff302c1aa0..928ee0639c3b 100644 --- a/book/cli/reth/stage.md +++ b/book/cli/reth/stage.md @@ -4,6 +4,8 @@ Manipulate individual stages ```bash $ reth stage --help +``` +```txt Usage: reth stage [OPTIONS] Commands: diff --git a/book/cli/reth/stage/drop.md b/book/cli/reth/stage/drop.md index b700519e1a87..3deb7f86d760 100644 --- a/book/cli/reth/stage/drop.md +++ b/book/cli/reth/stage/drop.md @@ -4,6 +4,8 @@ Drop a stage's tables from the database ```bash $ reth stage drop --help +``` +```txt Usage: reth stage drop [OPTIONS] Options: diff --git a/book/cli/reth/stage/dump.md b/book/cli/reth/stage/dump.md index a5fd3052c0b6..1614fcf4b1e7 100644 --- a/book/cli/reth/stage/dump.md +++ b/book/cli/reth/stage/dump.md @@ -4,6 +4,8 @@ Dumps a stage from a range into a new database ```bash $ reth stage dump --help +``` +```txt Usage: reth stage dump [OPTIONS] Commands: diff --git a/book/cli/reth/stage/dump/account-hashing.md b/book/cli/reth/stage/dump/account-hashing.md index 4c5030a55bdc..46145ed8d4c8 100644 --- a/book/cli/reth/stage/dump/account-hashing.md +++ b/book/cli/reth/stage/dump/account-hashing.md @@ -4,6 +4,8 @@ ```bash $ reth stage dump account-hashing --help +``` +```txt Usage: reth stage dump account-hashing [OPTIONS] --output-datadir --from --to Options: diff --git a/book/cli/reth/stage/dump/execution.md b/book/cli/reth/stage/dump/execution.md index 420602f8a676..836265a6f84b 100644 --- a/book/cli/reth/stage/dump/execution.md +++ b/book/cli/reth/stage/dump/execution.md @@ -4,6 +4,8 @@ Execution stage ```bash $ reth stage dump execution --help +``` +```txt Usage: reth stage dump execution [OPTIONS] --output-datadir --from --to Options: diff --git a/book/cli/reth/stage/dump/merkle.md b/book/cli/reth/stage/dump/merkle.md index aa32e5e32ce1..90fa0f0f5228 100644 --- a/book/cli/reth/stage/dump/merkle.md +++ b/book/cli/reth/stage/dump/merkle.md @@ -4,6 +4,8 @@ Merkle stage ```bash $ reth stage dump merkle --help +``` +```txt Usage: reth stage dump merkle [OPTIONS] --output-datadir --from --to Options: diff --git a/book/cli/reth/stage/dump/storage-hashing.md b/book/cli/reth/stage/dump/storage-hashing.md index 5ef1483de245..2b078570f576 100644 --- a/book/cli/reth/stage/dump/storage-hashing.md +++ b/book/cli/reth/stage/dump/storage-hashing.md @@ -4,6 +4,8 @@ ```bash $ reth stage dump storage-hashing --help +``` +```txt Usage: reth stage dump storage-hashing [OPTIONS] --output-datadir --from --to Options: diff --git a/book/cli/reth/stage/run.md b/book/cli/reth/stage/run.md index 8bc87fd97796..d50178ebf91f 100644 --- a/book/cli/reth/stage/run.md +++ b/book/cli/reth/stage/run.md @@ -4,6 +4,8 @@ Run a single stage. ```bash $ reth stage run --help +``` +```txt Usage: reth stage run [OPTIONS] --from --to Options: diff --git a/book/cli/reth/stage/unwind.md b/book/cli/reth/stage/unwind.md index 41b0a6640914..86c92ab70393 100644 --- a/book/cli/reth/stage/unwind.md +++ b/book/cli/reth/stage/unwind.md @@ -4,6 +4,8 @@ Unwinds a certain block range, deleting it from the database ```bash $ reth stage unwind --help +``` +```txt Usage: reth stage unwind [OPTIONS] Commands: diff --git a/book/cli/reth/stage/unwind/num-blocks.md b/book/cli/reth/stage/unwind/num-blocks.md index 2974b0841d5c..c74f75556f45 100644 --- a/book/cli/reth/stage/unwind/num-blocks.md +++ b/book/cli/reth/stage/unwind/num-blocks.md @@ -4,6 +4,8 @@ Unwinds the database from the latest block, until the given number of blocks hav ```bash $ reth stage unwind num-blocks --help +``` +```txt Usage: reth stage unwind num-blocks [OPTIONS] Arguments: diff --git a/book/cli/reth/stage/unwind/to-block.md b/book/cli/reth/stage/unwind/to-block.md index 98f8f34620f5..ea710b953ad9 100644 --- a/book/cli/reth/stage/unwind/to-block.md +++ b/book/cli/reth/stage/unwind/to-block.md @@ -4,6 +4,8 @@ Unwinds the database from the latest block, until the given block number or hash ```bash $ reth stage unwind to-block --help +``` +```txt Usage: reth stage unwind to-block [OPTIONS] Arguments: diff --git a/book/cli/update.sh b/book/cli/update.sh index bffacf287760..6e792df0f2bd 100755 --- a/book/cli/update.sh +++ b/book/cli/update.sh @@ -5,7 +5,7 @@ BOOK_ROOT="$(dirname "$(dirname "$0")")" RETH=${1:-"$(dirname "$BOOK_ROOT")/target/debug/reth"} cmd=( - "$(dirname "$0")/help.py" + "$(dirname "$0")/help.rs" --root-dir "$BOOK_ROOT/" --root-indentation 2 --root-summary