Rust
Reading commands
Read command-line arguments with std::env::args.
Reading commands
In a real CLI, commands come from the program arguments: cargo run -- ekle "Süt al". std::env::args() gives the program path as its first element:
let args: Vec<String> = std::env::args().collect();
match args.get(1).map(|s| s.as_str()) {
Some("ekle") => { /* args[2] */ }
Some("liste") => { /* ... */ }
_ => println!("Kullanım: todo <ekle|liste|bitir>"),
}
In the exercise we'll give the commands in an array and split each command into a name and an argument with split_once(' ').
Matching commands
Commands without arguments, like "liste", have no space; with unwrap_or((k, "")) we take the whole text as the name and the argument as empty. Then a match on the name:
for k in komutlar {
let (ad, arg) = k.split_once(' ').unwrap_or((k, ""));
match ad {
"ekle" => { liste.ekle(arg); }
"bitir" => { /* arg.parse() */ }
"liste" => liste.listele(),
_ => println!("Bilinmeyen komut: {ad}"),
}
}
Exercise Command handler
Process the commands ["ekle Süt al", "ekle Kod yaz", "bitir 1", "liste", "sil 3"] in order. Run ekle, bitir (parse the id) and liste with the methods you support; for anything else print Bilinmeyen komut: AD.
Show example solution
struct Gorev {
id: u32,
metin: String,
bitti: bool,
}
struct Liste {
gorevler: Vec<Gorev>,
sonraki_id: u32,
}
impl Liste {
fn ekle(&mut self, metin: &str) -> u32 {
self.sonraki_id += 1;
self.gorevler.push(Gorev {
id: self.sonraki_id,
metin: metin.to_string(),
bitti: false,
});
self.sonraki_id
}
fn tamamla(&mut self, id: u32) -> bool {
match self.gorevler.iter_mut().find(|g| g.id == id) {
Some(g) => {
g.bitti = true;
true
}
None => false,
}
}
fn listele(&self) {
for g in &self.gorevler {
let isaret = if g.bitti { "x" } else { " " };
println!("[{}] {}: {}", isaret, g.id, g.metin);
}
}
}
fn main() {
let mut liste = Liste {
gorevler: Vec::new(),
sonraki_id: 0,
};
let komutlar = ["ekle Süt al", "ekle Kod yaz", "bitir 1", "liste", "sil 3"];
for k in komutlar {
let (ad, arg) = k.split_once(' ').unwrap_or((k, ""));
match ad {
"ekle" => {
liste.ekle(arg);
}
"bitir" => {
let tamam = arg.parse().map(|id| liste.tamamla(id)).unwrap_or(false);
if !tamam {
println!("Görev yok: {}", arg);
}
}
"liste" => liste.listele(),
_ => println!("Bilinmeyen komut: {}", ad),
}
}
}
Test yourself
-
What does <code>"bitir 1".split_once(' ')</code> return?
- ("bitir", "1")
- None
- Some(("bitir", "1"))
- ["bitir", "1"]
Show answer
Some(("bitir", "1")) — split_once splits at the first separator and returns a pair inside an Option; None if there is no separator.
-
Name and argument
let (ad, arg) = k.____(' ').unwrap_or((k, ""));
Show answer
let (ad, arg) = k.split_once(' ').unwrap_or((k, ""));
-
Command and action
- ekle Süt al
- Adds a task
- bitir 1
- Marks number 1
- liste
- Prints the list
- sil 3
- Unknown command
Next lesson: Vec<T>