1pub fn assert_sorted(cmd: &clap::Command) {
30 let subcommands: Vec<_> = cmd.get_subcommands().map(|s| s.get_name()).collect();
31
32 if subcommands.is_empty() {
33 return;
34 }
35
36 let mut sorted = subcommands.clone();
37 sorted.sort();
38
39 if subcommands != sorted {
40 panic!(
41 "Subcommands are not sorted alphabetically!\nActual order: {:?}\nExpected order: {:?}",
42 subcommands, sorted
43 );
44 }
45}
46
47pub fn is_sorted(cmd: &clap::Command) -> Result<(), String> {
61 let subcommands: Vec<_> = cmd.get_subcommands().map(|s| s.get_name()).collect();
62
63 if subcommands.is_empty() {
64 return Ok(());
65 }
66
67 let mut sorted = subcommands.clone();
68 sorted.sort();
69
70 if subcommands != sorted {
71 Err(format!(
72 "Subcommands are not sorted alphabetically!\nActual order: {:?}\nExpected order: {:?}",
73 subcommands, sorted
74 ))
75 } else {
76 Ok(())
77 }
78}
79
80#[cfg(test)]
81mod tests {
82 use super::*;
83 use clap::{Command, CommandFactory, Parser, Subcommand};
84
85 #[test]
86 fn test_sorted_subcommands() {
87 let cmd = Command::new("test")
88 .subcommand(Command::new("add"))
89 .subcommand(Command::new("delete"))
90 .subcommand(Command::new("list"));
91
92 assert_sorted(&cmd);
93 }
94
95 #[test]
96 #[should_panic(expected = "Subcommands are not sorted")]
97 fn test_unsorted_subcommands() {
98 let cmd = Command::new("test")
99 .subcommand(Command::new("list"))
100 .subcommand(Command::new("add"))
101 .subcommand(Command::new("delete"));
102
103 assert_sorted(&cmd);
104 }
105
106 #[test]
107 fn test_is_sorted_ok() {
108 let cmd = Command::new("test")
109 .subcommand(Command::new("add"))
110 .subcommand(Command::new("delete"))
111 .subcommand(Command::new("list"));
112
113 assert!(is_sorted(&cmd).is_ok());
114 }
115
116 #[test]
117 fn test_is_sorted_err() {
118 let cmd = Command::new("test")
119 .subcommand(Command::new("list"))
120 .subcommand(Command::new("add"));
121
122 assert!(is_sorted(&cmd).is_err());
123 }
124
125 #[test]
126 fn test_no_subcommands() {
127 let cmd = Command::new("test");
128 assert_sorted(&cmd);
129 assert!(is_sorted(&cmd).is_ok());
130 }
131
132 #[test]
133 fn test_with_derive_sorted() {
134 #[derive(Parser)]
135 struct Cli {
136 #[command(subcommand)]
137 command: Commands,
138 }
139
140 #[derive(Subcommand)]
141 enum Commands {
142 Add,
143 Delete,
144 List,
145 }
146
147 let cmd = Cli::command();
148 assert_sorted(&cmd);
149 }
150
151 #[test]
152 #[should_panic(expected = "Subcommands are not sorted")]
153 fn test_with_derive_unsorted() {
154 #[derive(Parser)]
155 struct Cli {
156 #[command(subcommand)]
157 command: Commands,
158 }
159
160 #[derive(Subcommand)]
161 enum Commands {
162 List,
163 Add,
164 Delete,
165 }
166
167 let cmd = Cli::command();
168 assert_sorted(&cmd);
169 }
170}