AzLearn

تمرين إعادة البناء

Todo List Manager

أعد كتابة مدير مهام صغير يضيف ويعرض ويؤشر المهام في ملف نصي.

rust ~16 دقيقة مبتدئ
أعد بناء الكود Rebuild

هذا هو الكود. اكتبه بنفسك.

الكود المرجعي
use std::env;
use std::fs;
use std::io;
use std::path::Path;

const TODO_FILE: &str = "todos.txt";

fn main() -> io::Result<()> {
    let mut args = env::args().skip(1);
    let command = args.next().unwrap_or_else(|| "list".to_string());

    match command.as_str() {
        "add" => {
            let text = args.collect::<Vec<_>>().join(" ");
            if text.is_empty() {
                println!("Usage: todo add buy milk");
            } else {
                let mut tasks = load_tasks()?;
                tasks.push(Task { done: false, text });
                save_tasks(&tasks)?;
            }
        }
        "done" => {
            let number = args.next().and_then(|value| value.parse::<usize>().ok());
            if let Some(index) = number.and_then(|n| n.checked_sub(1)) {
                let mut tasks = load_tasks()?;
                if let Some(task) = tasks.get_mut(index) {
                    task.done = true;
                    save_tasks(&tasks)?;
                }
            }
        }
        "list" => print_tasks(&load_tasks()?),
        _ => println!("Commands: add, done, list"),
    }

    Ok(())
}

#[derive(Clone)]
struct Task {
    done: bool,
    text: String,
}

fn load_tasks() -> io::Result<Vec<Task>> {
    if !Path::new(TODO_FILE).exists() {
        return Ok(Vec::new());
    }

    let text = fs::read_to_string(TODO_FILE)?;
    let tasks = text
        .lines()
        .map(|line| Task {
            done: line.starts_with("[x] "),
            text: line.get(4..).unwrap_or("").to_string(),
        })
        .collect();

    Ok(tasks)
}

fn save_tasks(tasks: &[Task]) -> io::Result<()> {
    let mut text = String::new();

    for task in tasks {
        let mark = if task.done { "[x]" } else { "[ ]" };
        text.push_str(&format!("{mark} {}\n", task.text));
    }

    fs::write(TODO_FILE, text)
}

fn print_tasks(tasks: &[Task]) {
    for (index, task) in tasks.iter().enumerate() {
        let mark = if task.done { "x" } else { " " };
        println!("{}. [{mark}] {}", index + 1, task.text);
    }
}
اكتب هنا