Building a To-Do App with vecless

In this tutorial, you’ll build a command-line To-Do list app using the vecless crate. This app will:

  • Accept tasks as command-line arguments
  • Support a --reverse flag to flip the order
  • Support a --filter <keyword> flag to show only matching tasks
  • Display tasks with line numbers

🧱 Step 1: Set Up Your Project

Create a new binary project:

cargo new vecless-todo --bin
cd vecless-todo

Add vecless to your Cargo.toml:

[dependencies]
vecless = "0.1"

✍️ Step 2: Write the App

Replace the contents of src/main.rs with the following:

use std::env;
use vecless::List;

fn main() {
    let mut args = env::args().skip(1).peekable();

    if args.peek().is_none() {
        println!("Usage: cargo run -- [--reverse] [--filter <keyword>] <task 1> <task 2> ...");
        return;
    }

    let mut reverse = false;
    let mut filter: Option<String> = None;
    let mut list = List::new();

    while let Some(arg) = args.next() {
        match arg.as_str() {
            "--reverse" => reverse = true,
            "--filter" => {
                if let Some(keyword) = args.next() {
                    filter = Some(keyword);
                } else {
                    eprintln!("Expected keyword after --filter");
                    return;
                }
            }
            task => list = list.push(task.to_string()),
        }
    }

    if !reverse {
        list = list.reverse();
    }

    if let Some(keyword) = filter {
        list = list
            .iter()
            .filter(|task| task.contains(&keyword))
            .cloned()
            .collect::<Vec<_>>()
            .into_iter()
            .fold(List::new(), |list, task| list.add([task]));
    }

    if list.is_empty() {
        println!("✅ No tasks to show.");
    } else {
        println!("📝 Your To-Do List:");
        for (i, task) in list.iter().enumerate() {
            println!("{}. {}", i + 1, task);
        }
    }
}

🧪 Step 3: Try It Out

Basic usage:

cargo run -- "Buy milk" "Read Rust book" "Walk the dog"

Reverse order:

cargo run -- --reverse "Buy milk" "Read Rust book" "Walk the dog"

Filter tasks:

cargo run -- --filter Rust "Buy milk" "Read Rust book" "Walk the dog"

🧠 How It Works

  • List::new() creates an empty list.
  • .push(...) adds tasks to the front (so we reverse at the end to preserve order).
  • .reverse() flips the list if --reverse is not passed.
  • .iter() gives us a reference-based iterator for filtering and printing.
  • We use .cloned() and .collect() to rebuild a filtered list.

🧩 Bonus Ideas

  • Add a --numbered flag to toggle line numbers
  • Save tasks to a file and load them later
  • Add task completion and removal