CodeBlanks Logo Icon CodeBlanks

Özet - clap ile CLI

Derive, flag ve subcommand'ı birleştirerek bir dosya CLI'sı yazarsın.

clap ile CLI özeti

clap derive arayüzünde struct'lar argüman şemasıdır: #[derive(Parser)], alan türleri dönüşümü belirler. #[arg(short, long)] bayrak adlarını, default_value_t varsayılanı verir; bool değersiz bayrak, Option<T> isteğe bağlı, Vec<T> çoklu pozisyoneldir. Alt komutlar #[derive(Subcommand)] enum'larıdır. Yardım, sürüm ve hata mesajları otomatik üretilir.

Genel bayrak ve alt komut

Üst düzey seçenekler ve alt komut birlikte tek bir yapı oluşturur:

#[derive(Debug)]
struct Cli {
    sessiz: bool,
    komut: Komut,
}

fn cli_ayristir(args: &[&str]) -> Result<Cli, String> {
    let sessiz = args.contains(&"--sessiz");
    let kalan: Vec<&str> = args.iter().copied().filter(|a| *a != "--sessiz").collect();
    Ok(Cli { sessiz, komut: komut_ayristir(&kalan)? })
}

Uygulama Tam CLI

Önceki dersteki Komut ve komut_ayristir ile yukarıdaki Cli ve cli_ayristir kodunu yaz. ["--sessiz", "sil", "2"] sonucunu {:?} ile yazdır.

Başlangıç kodu

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

#[derive(Debug)]
struct Cli {
    sessiz: bool,
    komut: Komut,
}

fn cli_ayristir(args: &[&str]) -> Result<Cli, String> {
    let sessiz = args.contains(&"--sessiz");
    let kalan: Vec<&str> = args.iter().copied().filter(|a| *a != "--sessiz").collect();
    Ok(Cli {
        sessiz,
        komut: komut_ayristir(&kalan)?,
    })
}

fn main() {
    println!("{:?}", cli_ayristir(&["--sessiz", "sil", "2"]));
}

Beklenen çıktı

Ok(Cli { sessiz: true, komut: Sil { no: 2 } })

Soru ve cevaplar

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

1 Tüm alt komutlarda geçerli bir <code>--sessiz</code> bayrağı nereye konur?

  • Üst düzey Cli struct'ına (#[arg(global = true)] ile) Doğru cevap
  • Her variant'a ayrı ayrı
  • Komut enum'ının dışında bir static'e
  • Konamaz

Açıklama: global = true, bayrağın alt komuttan önce ya da sonra yazılabilmesini sağlar.

2 Alt komut türet

Soru
#[derive(____)]
enum Komut {
    Ekle { metin: String },
    Liste,
}
Cevap
#[derive(Subcommand)]
enum Komut {
    Ekle { metin: String },
    Liste,
}

Açıklama: Alt komut enum'ları Subcommand türetir.

3 Grubun özeti

Kavram Anlamı
#[derive(Parser)] Argüman şeması
bool alan Değersiz bayrak
Option<T> alan İsteğe bağlı
#[derive(Subcommand)] Alt komutlar

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