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 let mut docs: Vec<CommandDoc> = handlers::SAFE_CMDS
52 .iter()
53 .map(|&name| CommandDoc {
54 name,
55 kind: DocKind::AlwaysSafe,
56 description: safe_cmd_description(name),
57 })
58 .collect();
59 docs.sort_by_key(|d| d.name);
60 docs
61}
62
63fn safe_cmd_description(name: &str) -> &'static str {
64 match name {
65 "arch" => "Print machine architecture",
66 "b2sum" => "BLAKE2 checksum",
67 "base64" => "Base64 encode/decode",
68 "basename" => "Strip directory from path",
69 "bc" => "Calculator",
70 "branchdiff" => "Branch diff tool",
71 "cal" => "Display calendar",
72 "cat" => "Print file contents",
73 "cd" => "Change directory",
74 "cksum" => "File checksum",
75 "cloc" => "Count lines of code",
76 "colordiff" => "Colorized diff",
77 "column" => "Format into columns",
78 "comm" => "Compare sorted files",
79 "command" => "Run command or check existence",
80 "cucumber" => "BDD test runner",
81 "cut" => "Extract fields from lines",
82 "date" => "Display date and time",
83 "df" => "Disk free space",
84 "diff" => "Compare files",
85 "dig" => "DNS lookup",
86 "dirname" => "Strip filename from path",
87 "du" => "Disk usage",
88 "echo" => "Print text",
89 "expand" => "Convert tabs to spaces",
90 "expr" => "Evaluate expression",
91 "factor" => "Print prime factors",
92 "false" => "Return failure exit code",
93 "fd" => "Find files",
94 "file" => "Detect file type",
95 "fmt" => "Reformat text",
96 "fold" => "Wrap lines",
97 "getconf" => "Get system configuration values",
98 "grep" => "Search file contents",
99 "groups" => "Print group memberships",
100 "head" => "Print first lines",
101 "hexdump" => "Display file in hex",
102 "host" => "DNS lookup",
103 "hostname" => "Print hostname",
104 "iconv" => "Convert character encoding",
105 "id" => "Print user/group IDs",
106 "identify" => "ImageMagick identify",
107 "jq" => "JSON processor",
108 "locale" => "Print locale info",
109 "lsof" => "List open files",
110 "ls" => "List directory",
111 "md5" => "MD5 checksum (macOS)",
112 "md5sum" => "MD5 checksum",
113 "mdfind" => "Spotlight search (macOS)",
114 "mdls" => "File metadata (macOS)",
115 "nl" => "Number lines",
116 "nm" => "List object file symbols",
117 "nproc" => "Print number of CPUs",
118 "nslookup" => "DNS lookup",
119 "od" => "Octal dump",
120 "otool" => "Object file tool (macOS)",
121 "paste" => "Merge lines of files",
122 "pgrep" => "Search for processes",
123 "printenv" => "Print environment variables",
124 "printf" => "Format and print text",
125 "ps" => "List processes",
126 "pwd" => "Print working directory",
127 "readlink" => "Resolve symlink",
128 "realpath" => "Resolve path",
129 "rev" => "Reverse lines",
130 "rg" => "Ripgrep search",
131 "seq" => "Print number sequence",
132 "sha1sum" => "SHA-1 checksum",
133 "sha256sum" => "SHA-256 checksum",
134 "sha512sum" => "SHA-512 checksum",
135 "shasum" => "SHA checksum",
136 "shellcheck" => "Shell script linter",
137 "size" => "Object file section sizes",
138 "sleep" => "Pause execution",
139 "stat" => "File status",
140 "strings" => "Find printable strings in binary",
141 "sum" => "File checksum",
142 "sw_vers" => "macOS version info",
143 "tac" => "Print file in reverse",
144 "tail" => "Print last lines",
145 "test" => "Evaluate conditional expression",
146 "tokei" => "Code statistics",
147 "tr" => "Translate characters",
148 "tree" => "Directory tree",
149 "true" => "Return success exit code",
150 "tty" => "Print terminal name",
151 "unexpand" => "Convert spaces to tabs",
152 "uniq" => "Filter duplicate lines",
153 "uname" => "System information",
154 "uptime" => "System uptime",
155 "uuidgen" => "Generate UUID",
156 "wc" => "Count lines/words/bytes",
157 "which" => "Locate command",
158 "whois" => "Domain registration lookup",
159 "whoami" => "Print current user",
160 "xxd" => "Hex dump",
161 _ => "Safe read-only utility",
162 }
163}