Blog Post #57: Mini-Project: Building a Command-Line To-Do List Application

It’s time for another project! We’ve spent the last several posts exploring Python’s most versatile data structure, the list. We’ve learned how to create them, add to them, remove from them, and loop through them like a pro. Now, we will combine all of that knowledge to build a useful, interactive program: a command-line to-do list application.

Our program will be able to view all current tasks, add new tasks, remove completed tasks, and exit. It’s a perfect example of how the concepts we’ve learned can come together to create something functional.

Step 1: The Setup

Let’s start by creating a new file named todo.py. The core of our application will be a while loop that keeps the program running and a list that stores our tasks. We’ll start with an empty list.

# Our list to store the to-do items
tasks = []

print("--- Welcome to your To-Do List ---")

# The main application loop
while True:
    # Display the menu and get user input
    print("\n--- To-Do List Menu ---")
    print("1. View all tasks")
    print("2. Add a task")
    print("3. Remove a task")
    print("4. Exit")
    
    choice = input("Enter your choice (1-4): ")

    # We will add the logic for our choices here

    if choice == '4':
        break

print("Goodbye!")

This code sets up our main application loop using the while True and break pattern from Post #38. Now, let’s fill in the logic for our other choices.

Step 2: Implementing the Menu Choices

We will use an if-elif-else chain (from Post #27) inside our while loop to handle the user’s input.

Choice 1: View Tasks

If the user chooses “1”, we should show them all their tasks in a numbered list. We’ll use enumerate() (from Post #56) to make this easy. We should also handle the case where the list is empty.

        if choice == '1':
            print("\n--- Your Tasks ---")
            if not tasks: # A Falsy check from Post #24
                print("Your to-do list is empty.")
            else:
                for index, task in enumerate(tasks, start=1):
                    print(f"{index}. {task}")

Choice 2: Add a Task

If the user chooses “2”, we need to ask them for the task and use .append() (from Post #50) to add it to our list.

        elif choice == '2':
            new_task = input("What task would you like to add? ")
            tasks.append(new_task)
            print(f"'{new_task}' has been added to your list.")

Choice 3: Remove a Task

This is our most complex step. We need to show the user the tasks, ask which one to remove by number, and then use .pop() (from Post #51) to remove it. We must also validate their input to make sure the number is in a valid range.

        elif choice == '3':
            if not tasks:
                print("Your to-do list is empty, nothing to remove.")
            else:
                print("\n--- Current Tasks ---")
                for index, task in enumerate(tasks, start=1):
                    print(f"{index}. {task}")
                
                task_num_str = input("Enter the number of the task to remove: ")
                task_num = int(task_num_str)

                # Check if the number is valid
                if 1 <= task_num <= len(tasks):
                    # Adjust for zero-based indexing
                    removed_task = tasks.pop(task_num - 1)
                    print(f"Removed task: '{removed_task}'")
                else:
                    print("Invalid task number.")

Handling Invalid Input

Finally, we add an else block to catch any input that isn’t one of our valid choices.

        else:
            print("Invalid choice. Please enter a number between 1 and 4.")

The Complete Program

Here is the full, commented script for our to-do list application.

# Our list to store the to-do items
tasks = []

print("--- Welcome to your To-Do List ---")

# The main application loop
while True:
    # Display the menu and get user input
    print("\n--- To-Do List Menu ---")
    print("1. View all tasks")
    print("2. Add a task")
    print("3. Remove a task")
    print("4. Exit")
    
    choice = input("Enter your choice (1-4): ")

    if choice == '1': # View Tasks
        print("\n--- Your Tasks ---")
        if not tasks:
            print("Your to-do list is empty.")
        else:
            for index, task in enumerate(tasks, start=1):
                print(f"{index}. {task}")

    elif choice == '2': # Add Task
        new_task = input("What task would you like to add? ")
        tasks.append(new_task)
        print(f"'{new_task}' has been added to your list.")

    elif choice == '3': # Remove Task
        if not tasks:
            print("Your to-do list is empty, nothing to remove.")
        else:
            print("\n--- Current Tasks ---")
            for index, task in enumerate(tasks, start=1):
                print(f"{index}. {task}")
            
            task_num_str = input("Enter the number of the task to remove: ")
            task_num = int(task_num_str)

            if 1 <= task_num <= len(tasks):
                removed_task = tasks.pop(task_num - 1)
                print(f"Removed task: '{removed_task}'")
            else:
                print("Invalid task number.")

    elif choice == '4': # Exit
        break

    else: # Handle invalid menu choices
        print("Invalid choice. Please enter a number between 1 and 4.")

print("Goodbye!")

What’s Next?

You’ve successfully built a functional to-do list manager! This project combines loops, conditionals, user input, and a wide array of list methods. You are now able to create interactive command-line applications that manage collections of data.

Our to-do list is a great example of using a mutable, or changeable, collection of data. But sometimes, you need a collection of items that should never change after it’s created. For this, Python provides an immutable version of a list. In Post #58, we will be introduced to tuples.

Author

Debjeet Bhowmik

Experienced Cloud & DevOps Engineer with hands-on experience in AWS, GCP, Terraform, Ansible, ELK, Docker, Git, GitLab, Python, PowerShell, Shell, and theoretical knowledge on Azure, Kubernetes & Jenkins. In my free time, I write blogs on ckdbtech.com

Leave a Comment