Reading commands
- Rust course
- Beginner
- Lesson 93/115
- 6 min
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}"),
}
}Practice 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.
Starter code
struct Gorev {
id: u32,
metin: String,
bitti: bool,
}
struct Liste {
gorevler: Vec<Gorev>,
sonraki_id: u32,
}
fn main() {
// buraya yaz
}Sample 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),
}
}
}Expected output
[x] 1: Süt al [ ] 2: Kod yaz Bilinmeyen komut: sil
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 What does <code>"bitir 1".split_once(' ')</code> return?
- ("bitir", "1")
- None
- Some(("bitir", "1")) Correct answer
- ["bitir", "1"]
Explanation: split_once splits at the first separator and returns a pair inside an Option; None if there is no separator.
2 Name and argument
let (ad, arg) = k.____(' ').unwrap_or((k, ""));
let (ad, arg) = k.split_once(' ').unwrap_or((k, ""));
Explanation: split_once splits the text into two pieces at the first space.
3 Command and action
| Term | Meaning |
|---|---|
ekle Süt al |
Adds a task |
bitir 1 |
Marks number 1 |
liste |
Prints the list |
sil 3 |
Unknown command |