Skip to main content

argot_cmd/model/
example.rs

1use serde::{Deserialize, Serialize};
2
3/// A usage example for a command.
4///
5/// Examples are rendered in help output and Markdown documentation pages. Each
6/// example has a short human-readable description, the command string as it
7/// would be typed, and an optional expected output snippet.
8///
9/// # Examples
10///
11/// ```
12/// # use argot_cmd::Example;
13/// let ex = Example::new("list all items", "myapp list")
14///     .with_output("item1\nitem2");
15///
16/// assert_eq!(ex.description, "list all items");
17/// assert_eq!(ex.command, "myapp list");
18/// assert_eq!(ex.output.as_deref(), Some("item1\nitem2"));
19/// ```
20#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
21pub struct Example {
22    /// Short description of what the example demonstrates.
23    pub description: String,
24    /// The full command string as it would be typed by the user.
25    pub command: String,
26    /// Optional expected output shown below the command in help and documentation.
27    pub output: Option<String>,
28}
29
30impl Example {
31    /// Create a new [`Example`] with a description and command string.
32    ///
33    /// The `output` field is `None` by default; use [`Example::with_output`]
34    /// to attach expected output.
35    ///
36    /// # Arguments
37    ///
38    /// - `description` — Short explanation of what the example shows.
39    /// - `command` — The command string as typed (including the program name).
40    ///
41    /// # Examples
42    ///
43    /// ```
44    /// # use argot_cmd::Example;
45    /// let ex = Example::new("deploy to staging", "myapp deploy staging");
46    /// assert_eq!(ex.command, "myapp deploy staging");
47    /// assert!(ex.output.is_none());
48    /// ```
49    pub fn new(description: impl Into<String>, command: impl Into<String>) -> Self {
50        Self {
51            description: description.into(),
52            command: command.into(),
53            output: None,
54        }
55    }
56
57    /// Attach an expected output snippet to this example.
58    ///
59    /// The output is rendered as a comment in plain-text help and as a code
60    /// block annotation in Markdown documentation.
61    ///
62    /// # Examples
63    ///
64    /// ```
65    /// # use argot_cmd::Example;
66    /// let ex = Example::new("check version", "myapp --version")
67    ///     .with_output("myapp 1.0.0");
68    ///
69    /// assert_eq!(ex.output.as_deref(), Some("myapp 1.0.0"));
70    /// ```
71    pub fn with_output(mut self, output: impl Into<String>) -> Self {
72        self.output = Some(output.into());
73        self
74    }
75}
76
77#[cfg(test)]
78mod tests {
79    use super::*;
80
81    #[test]
82    fn test_example_new() {
83        let ex = Example::new("run it", "mycmd run");
84        assert_eq!(ex.description, "run it");
85        assert_eq!(ex.command, "mycmd run");
86        assert!(ex.output.is_none());
87    }
88
89    #[test]
90    fn test_example_with_output() {
91        let ex = Example::new("run it", "mycmd run").with_output("done");
92        assert_eq!(ex.output.as_deref(), Some("done"));
93    }
94
95    #[test]
96    fn test_example_serde_round_trip() {
97        let ex = Example::new("desc", "cmd").with_output("out");
98        let json = serde_json::to_string(&ex).unwrap();
99        let de: Example = serde_json::from_str(&json).unwrap();
100        assert_eq!(ex, de);
101    }
102}