CodeBlanks Logo Icon CodeBlanks

Subcommand

Subcommand ile alt komut yapısı kurarsın.

Subcommand

git commit, cargo build gibi alt komutlar clap'te bir enum ile ifade edilir; her variant bir alt komut, alanları onun argümanlarıdır:

#[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 },
}

Ardından match cli.komut { .. } ile her alt komut ayrı ele alınır; derleyici bir alt komutu unutmana izin vermez.

Elle alt komut ayrıştırma

Dilim kalıpları ile aynı enum elle kurulabilir:

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")),
    }
}

Uygulama Alt komutlar

Yukarıdaki Komut enum'ını (#[derive(Debug)]) ve komut_ayristir fonksiyonunu yaz. ["ekle", "süt", "al"], ["liste"] ve ["uç"] sonuçlarını {:?} ile ayrı satırlara yazdır.

Başlangıç kodu

main.rs
fn main() {
    // buraya yaz
}

Örnek çözüm

main.rs
#[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ç"]));
}

Beklenen çıktı

Ok(Ekle { metin: "süt al" })
Ok(Liste)
Err("bilinmeyen alt komut: uç")

Soru ve cevaplar

Dersin sorularını cevaplarıyla birlikte inceleyebilirsin. Kendini denemek istersen dersi interaktif olarak çöz.

1 Alt komutları enum olarak modellemenin en büyük yararı nedir?

  • Yardım metni gerekmez
  • match kapsayıcılığı sayesinde ele alınmayan alt komut derleme hatasıdır Doğru cevap
  • Daha hızlı ayrıştırma
  • Daha az bellek

Açıklama: Yeni bir alt komut eklediğinde, onu işlemeyen her match derleyici tarafından gösterilir.

2 Alt komut alanı

Soru
struct Cli {
    #[command(____)]
    komut: Komut,
}
Cevap
struct Cli {
    #[command(subcommand)]
    komut: Komut,
}

Açıklama: #[command(subcommand)] alanı enum ile alt komutlara bağlar.

3 Argümanlar ve Komut

Kavram Anlamı
ekle süt al Ekle { metin: "süt al" }
liste Liste
sil 2 Sil { no: 2 }
uç Hata

Orta seviye bölümündeki tüm dersler