Pair Programming IDE Rust

👤 Sharing: AI
```rust
use std::io;

// Define a struct to represent a task
#[derive(Debug)]
struct Task {
    description: String,
    completed: bool,
}

impl Task {
    // Constructor for a new task
    fn new(description: String) -> Task {
        Task {
            description,
            completed: false,
        }
    }

    // Method to mark a task as completed
    fn mark_completed(&mut self) {
        self.completed = true;
    }
}

fn main() {
    // Initialize a vector to store tasks
    let mut tasks: Vec<Task> = Vec::new();

    loop {
        // Display the menu
        println!("\nTask Manager");
        println!("1. Add task");
        println!("2. List tasks");
        println!("3. Mark task as completed");
        println!("4. Exit");

        // Get user input
        let mut choice = String::new();
        println!("Enter your choice: ");
        io::stdin()
            .read_line(&mut choice)
            .expect("Failed to read line");

        // Parse the user's choice
        let choice: u32 = match choice.trim().parse() {
            Ok(num) => num,
            Err(_) => {
                println!("Invalid input. Please enter a number.");
                continue;
            }
        };

        // Process the user's choice
        match choice {
            1 => {
                // Add a new task
                println!("Enter task description: ");
                let mut description = String::new();
                io::stdin()
                    .read_line(&mut description)
                    .expect("Failed to read line");

                let description = description.trim().to_string(); // Remove leading/trailing whitespace
                let new_task = Task::new(description);
                tasks.push(new_task);
                println!("Task added!");
            }
            2 => {
                // List tasks
                if tasks.is_empty() {
                    println!("No tasks yet!");
                } else {
                    println!("Tasks:");
                    for (index, task) in tasks.iter().enumerate() {
                        println!(
                            "{}. {} (Completed: {})",
                            index + 1,
                            task.description,
                            task.completed
                        );
                    }
                }
            }
            3 => {
                // Mark a task as completed
                println!("Enter the task number to mark as completed: ");
                let mut task_number = String::new();
                io::stdin()
                    .read_line(&mut task_number)
                    .expect("Failed to read line");

                let task_number: usize = match task_number.trim().parse() {
                    Ok(num) => num,
                    Err(_) => {
                        println!("Invalid input. Please enter a number.");
                        continue;
                    }
                };

                // Check if the task number is valid
                if task_number > 0 && task_number <= tasks.len() {
                    let task_index = task_number - 1;
                    tasks[task_index].mark_completed();
                    println!("Task marked as completed!");
                } else {
                    println!("Invalid task number.");
                }
            }
            4 => {
                // Exit the program
                println!("Exiting...");
                break;
            }
            _ => {
                println!("Invalid choice. Please enter a number between 1 and 4.");
            }
        }
    }
}
```

**Explanation:**

1. **`use std::io;`**: This line imports the `io` module from the standard library, which is needed for input/output operations (like reading from the console).

2. **`struct Task`**: This defines a `struct` called `Task`. A `struct` is a custom data type that groups related data together. In this case, each `Task` has:
   - `description`: A `String` representing the task's description (e.g., "Buy groceries").
   - `completed`: A `bool` indicating whether the task has been completed (true) or not (false).

3. **`impl Task`**:  This block implements methods for the `Task` struct.  Methods are functions associated with a particular type.
   - **`fn new(description: String) -> Task`**: This is a constructor function. It takes a task description as input and returns a new `Task` instance.  It initializes the `completed` field to `false` by default.
   - **`fn mark_completed(&mut self)`**: This method allows you to mark a task as completed.  The `&mut self` parameter means it takes a mutable reference to the `Task` instance, allowing it to modify the `completed` field.

4. **`fn main()`**: This is the main function, the entry point of the program.

5. **`let mut tasks: Vec<Task> = Vec::new();`**: This line creates a mutable vector (a dynamically sized array) called `tasks`.  It will store `Task` structs.  `Vec::new()` initializes an empty vector.  The `mut` keyword is crucial because we'll be adding, removing, and modifying tasks in the vector.

6. **`loop { ... }`**: This creates an infinite loop that continues until the user chooses to exit.

7. **Menu Display**: Inside the loop, the program displays a menu with options for adding, listing, marking completed, and exiting.

8. **User Input**:
   - `io::stdin().read_line(&mut choice)`: This reads a line of text from the standard input (the console) and stores it in the `choice` string.  The `&mut choice` part passes a mutable reference to the `choice` string, so the `read_line` function can modify it.
   - **Error Handling**: `expect("Failed to read line")`: This handles potential errors during the input process. If `read_line` fails (e.g., due to an unexpected error), the program will panic and display the error message.
   - **Parsing Input**:  `choice.trim().parse()`:  This part converts the user's input (which is a string) into a number (u32).
      - `trim()`: Removes any leading or trailing whitespace from the input string.
      - `parse()`: Attempts to parse the string as a `u32` (unsigned 32-bit integer).  The `parse()` method returns a `Result` type, which can be either `Ok(value)` if the parsing was successful or `Err(error)` if it failed.
   - **Matching the Result**:  `match choice.trim().parse() { ... }`: This uses a `match` expression to handle the result of the parsing operation.
      - `Ok(num) => num`: If the parsing was successful, the `Ok` variant contains the parsed number (num), which is then assigned to the `choice` variable.
      - `Err(_) => { ... }`: If the parsing failed (e.g., the user entered text that wasn't a number), the `Err` variant is matched. The `_` is a wildcard pattern that matches any error value.  An error message is printed, and the `continue` statement skips to the next iteration of the loop.

9. **Processing User Choice**:  The `match choice { ... }` expression processes the user's choice.

10. **Adding a Task (Choice 1)**:
    - Prompts the user for the task description.
    - Reads the description from the console.
    - Creates a new `Task` instance using `Task::new()`.
    - Adds the new task to the `tasks` vector using `tasks.push()`.

11. **Listing Tasks (Choice 2)**:
    - Checks if the `tasks` vector is empty. If so, it prints a message saying "No tasks yet!".
    - If there are tasks, it iterates through the `tasks` vector using a `for` loop with `enumerate()`. `enumerate()` provides both the index and the value of each element in the vector.
    - Prints the task number (index + 1), description, and completion status for each task.

12. **Marking a Task as Completed (Choice 3)**:
    - Prompts the user to enter the task number to mark as completed.
    - Reads the task number from the console.
    - Parses the input as a `usize` (unsigned integer, suitable for indexing).
    - **Input Validation**:  Checks if the entered task number is valid (i.e., within the range of valid task indices).
    - Accesses the task at the specified index using `tasks[task_index]`.
    - Calls the `mark_completed()` method on the task to set its `completed` field to `true`.

13. **Exiting (Choice 4)**:
    - Prints an "Exiting..." message.
    - `break;` exits the loop, ending the program.

14. **Invalid Choice**: If the user enters an invalid choice (other than 1-4), an error message is printed.

**How to Compile and Run:**

1. **Install Rust:** If you haven't already, install Rust from [https://www.rust-lang.org/tools/install](https://www.rust-lang.org/tools/install).
2. **Save the Code:** Save the code as a `.rs` file (e.g., `task_manager.rs`).
3. **Compile:** Open a terminal or command prompt and navigate to the directory where you saved the file. Then, compile the code using the Rust compiler:

   ```bash
   rustc task_manager.rs
   ```

4. **Run:** After successful compilation, an executable file will be created (e.g., `task_manager` on Linux/macOS or `task_manager.exe` on Windows). Run the executable:

   ```bash
   ./task_manager  # Linux/macOS
   task_manager.exe # Windows
   ```

Now you can interact with the task manager program in your terminal.
👁️ Viewed: 5

Comments