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}