Skip to main content

usage/docs/markdown/
cmd.rs

1use crate::docs::markdown::renderer::MarkdownRenderer;
2use crate::docs::models::SpecCommand;
3use crate::error::UsageErr;
4
5impl MarkdownRenderer {
6    pub fn render_cmd(&self, cmd: &crate::SpecCommand) -> Result<String, UsageErr> {
7        let mut cmd = SpecCommand::from(cmd);
8        cmd.render_md(self);
9        let mut ctx = self.clone();
10        ctx.insert("cmd", &cmd);
11        ctx.render("cmd_template.md.tera")
12    }
13}
14
15#[cfg(test)]
16mod tests {
17    use crate::docs::markdown::renderer::MarkdownRenderer;
18    use crate::test::SPEC_KITCHEN_SINK;
19    use crate::Spec;
20    use insta::assert_snapshot;
21
22    #[test]
23    fn test_render_markdown_cmd() {
24        let ctx = MarkdownRenderer::new(SPEC_KITCHEN_SINK.clone())
25            .with_multi(true)
26            .with_replace_pre_with_code_fences(true);
27        assert_snapshot!(ctx.render_cmd(&SPEC_KITCHEN_SINK.cmd).unwrap(), @r"
28        # `mycli`
29
30        - **Usage**: `mycli [FLAGS] <ARGS>… <SUBCOMMAND>`
31
32        ## Arguments
33
34        ### `<arg1>`
35
36        arg1 description
37
38        ### `[arg2]`
39
40        arg2 description
41
42        **Choices:**
43
44        - `choice1`
45        - `choice2`
46        - `choice3`
47
48        **Default:** `default value`
49
50        ### `<arg3>`
51
52        arg3 long description
53
54        ### `<argrest>…`
55
56        ### `[with-default]`
57
58        **Default:** `default value`
59
60        ## Flags
61
62        ### `--flag1`
63
64        flag1 description
65
66        ### `--flag2`
67
68        flag2 long description
69
70        includes a code block:
71
72        ```
73        $ echo hello world
74        hello world
75
76        more code
77        ```
78
79        Examples:
80
81        ```
82        # run with no arguments to use the interactive selector
83        $ mise use
84
85        # set the current version of node to 20.x in mise.toml of current directory
86        # will write the fuzzy version (e.g.: 20)
87        ```
88
89        some docs
90
91        ```
92        $ echo hello world
93        hello world
94        ```
95
96        ### `--flag3`
97
98        flag3 description
99
100        ### `--with-default`
101
102        **Default:** `default value`
103
104        ### `--shell <shell>`
105
106        **Choices:**
107
108        - `bash`
109        - `zsh`
110        - `fish`
111
112        ## Subcommands
113
114        - [`mycli plugin <SUBCOMMAND>`](/plugin.md)
115        ");
116    }
117
118    #[test]
119    fn test_render_markdown_cmd_effect() {
120        let spec: Spec = r#"
121name "mise"
122bin "mise"
123cmd "ls" effect="read" help="List installed tools"
124cmd "use" effect="write" help="Install a tool"
125cmd "uninstall" effect="destructive" help="Remove a tool"
126cmd "version" help="Show the version"
127        "#
128        .parse()
129        .unwrap();
130        let ctx = MarkdownRenderer::new(spec.clone()).with_multi(true);
131        let rendered = spec
132            .cmd
133            .subcommands
134            .values()
135            .map(|cmd| ctx.render_cmd(cmd).unwrap())
136            .collect::<Vec<_>>()
137            .join("\n\n");
138
139        // Every effect value must render its own label, and a command without
140        // one must not render the line at all.
141        assert_snapshot!(rendered, @r"
142        # `mise ls`
143
144        - **Usage**: `mise ls`
145        - **Effect**: read-only
146
147        List installed tools
148
149        # `mise use`
150
151        - **Usage**: `mise use`
152        - **Effect**: modifies state
153
154        Install a tool
155
156        # `mise uninstall`
157
158        - **Usage**: `mise uninstall`
159        - **Effect**: destructive — may delete or irreversibly overwrite
160
161        Remove a tool
162
163        # `mise version`
164
165        - **Usage**: `mise version`
166
167        Show the version
168        ");
169    }
170}