Subcommand
- Rust course
- Intermediate
- Lesson 99/115
- 4 min
Build a subcommand structure.
Subcommands
Subcommands like git commit or cargo build are expressed in clap with an enum; each variant is a subcommand and its fields are its arguments:
#[derive(Parser)]
struct Cli {
#[command(subcommand)]
komut: Komut,
}
#[derive(Subcommand)]
enum Komut {
/// Not ekler
Ekle { metin: String },
/// Notları listeler
Liste,
/// Not siler
Sil { no: usize },
}Then each subcommand is handled separately with match cli.komut { .. }; the compiler won't let you forget a subcommand.
Parsing subcommands by hand
The same enum can be built by hand with slice patterns:
fn komut_ayristir(args: &[&str]) -> Result<Komut, String> {
match args {
["ekle", metin @ ..] if !metin.is_empty() => {
Ok(Komut::Ekle { metin: metin.join(" ") })
}
["liste"] => Ok(Komut::Liste),
["sil", n] => n.parse().map(|no| Komut::Sil { no })
.map_err(|_| format!("geçersiz numara: {n}")),
[k, ..] => Err(format!("bilinmeyen alt komut: {k}")),
[] => Err(String::from("alt komut gerekli")),
}
}Practice Subcommands
Write the Komut enum above (#[derive(Debug)]) and the komut_ayristir function. Print the results of ["ekle", "süt", "al"], ["liste"] and ["uç"] with {:?} on separate lines.
Starter code
fn main() {
// buraya yaz
}Sample solution
#[derive(Debug)]
enum Komut {
Ekle { metin: String },
Liste,
Sil { no: usize },
}
fn komut_ayristir(args: &[&str]) -> Result<Komut, String> {
match args {
["ekle", metin @ ..] if !metin.is_empty() => Ok(Komut::Ekle { metin: metin.join(" ") }),
["liste"] => Ok(Komut::Liste),
["sil", n] => n
.parse()
.map(|no| Komut::Sil { no })
.map_err(|_| format!("geçersiz numara: {n}")),
[k, ..] => Err(format!("bilinmeyen alt komut: {k}")),
[] => Err(String::from("alt komut gerekli")),
}
}
fn main() {
println!("{:?}", komut_ayristir(&["ekle", "süt", "al"]));
println!("{:?}", komut_ayristir(&["liste"]));
println!("{:?}", komut_ayristir(&["uç"]));
}Expected output
Ok(Ekle { metin: "süt al" })
Ok(Liste)
Err("bilinmeyen alt komut: uç")
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 What is the biggest benefit of modelling subcommands as an enum?
- No help text needed
- Thanks to match exhaustiveness, an unhandled subcommand is a compile error Correct answer
- Faster parsing
- Less memory
Explanation: When you add a new subcommand, every match that doesn't handle it is pointed out by the compiler.
2 Subcommand field
struct Cli {
#[command(____)]
komut: Komut,
}
struct Cli {
#[command(subcommand)]
komut: Komut,
}
Explanation: #[command(subcommand)] ties the field to subcommands via an enum.
3 Arguments and Komut
| Term | Meaning |
|---|---|
ekle süt al |
Ekle { metin: "süt al" } |
liste |
Liste |
sil 2 |
Sil { no: 2 } |
uç |
Error |