Skip to main content

safe_chains/
docs.rs

1use crate::handlers;
2
3pub struct CommandDoc {
4    pub name: &'static str,
5    pub kind: DocKind,
6    pub description: &'static str,
7}
8
9pub enum DocKind {
10    AlwaysSafe,
11    Handler,
12}
13
14pub fn all_command_docs() -> Vec<CommandDoc> {
15    let mut docs = safe_cmd_docs();
16    docs.extend(handlers::handler_docs());
17    docs.sort_by_key(|d| d.name);
18    docs
19}
20
21pub fn render_markdown(docs: &[CommandDoc]) -> String {
22    let mut out = String::from(
23        "# Supported Commands\n\
24         \n\
25         Auto-generated by `safe-chains --list-commands`.\n\
26         \n\
27         Any command with only `--version` or `--help` as its sole argument is always allowed.\n\
28         \n\
29         ## Unconditionally Safe\n\
30         \n\
31         These commands are allowed with any arguments.\n\
32         \n\
33         | Command | Description |\n\
34         |---------|-------------|\n",
35    );
36
37    for doc in docs.iter().filter(|d| matches!(d.kind, DocKind::AlwaysSafe)) {
38        out.push_str(&format!("| `{}` | {} |\n", doc.name, doc.description));
39    }
40
41    out.push_str("\n## Handled Commands\n\nThese commands are allowed with specific subcommands or flags.\n\n");
42
43    for doc in docs.iter().filter(|d| matches!(d.kind, DocKind::Handler)) {
44        out.push_str(&format!("### `{}`\n\n{}\n\n", doc.name, doc.description));
45    }
46
47    out
48}
49
50fn safe_cmd_docs() -> Vec<CommandDoc> {
51    handlers::SAFE_CMD_ENTRIES
52        .iter()
53        .map(|&(name, description)| CommandDoc {
54            name,
55            kind: DocKind::AlwaysSafe,
56            description,
57        })
58        .collect()
59}