Project 2 - Build a Personal To-Do List Manager (Command Line)
13th October 2025 By Gururaj
blog

Let's create a command-line to-do list manager, a practical project that will help you manage tasks efficiently while reinforcing key programming concepts like functions, file handling, and list manipulation. This application will allow you to view your tasks, add new ones, mark tasks as complete, and save everything to a file so your tasks persist between sessions. It’s a great way to level up your skills, as it combines user interaction, data storage, and modular code design.

Project Overview

The to-do list manager will be a text-based application that runs in the terminal. Users will interact with it through a simple menu, entering commands to perform actions like adding a task, viewing all tasks, marking a task as complete, or exiting the program. Tasks will be stored in a file, ensuring they’re saved even after the program closes. This project introduces real-world programming challenges like reading from and writing to files, handling user input, and organizing code with functions.

Features

  1. View Tasks: Display all tasks with their status (e.g., "Complete" or "Incomplete") and a unique task number.
  2. Add Tasks: Allow users to add new tasks with a description. Each task will automatically be marked as "Incomplete."
  3. Mark Tasks as Complete: Let users mark a task as complete by entering its task number.
  4. Save Tasks to File: Store tasks in a file (e.g., a text or JSON file) so they persist between program runs.
  5. Load Tasks from File: Load tasks from the file when the program starts to restore the previous state.
  6. Exit Program: Provide an option to exit the application cleanly, ensuring all tasks are saved.

Learning Outcomes

This project will help you practice:

  • Functions: Break down the program into reusable functions like add_task(), view_tasks(), mark_complete(), save_tasks(), and load_tasks().
  • File Handling: Read from and write to a file to store tasks persistently, using formats like plain text or JSON.
  • Lists and Data Structures: Manage tasks as a list of dictionaries (e.g., each task having a description and status).
  • User Input: Handle user input gracefully, including validating inputs to prevent errors (e.g., ensuring a valid task number is entered).
  • Control Flow: Use loops and conditionals to create a menu-driven interface.
  • Error Handling: Implement basic error checking, like handling cases where the file doesn’t exist or the user enters invalid input.

Example Workflow

When you run the program, it might look like this in the terminal:

text
 
=== To-Do List Manager ===
1. View tasks
2. Add task
3. Mark task as complete
4. Exit
Enter your choice (1-4):
 
 
  • If you choose 1, it displays something like:
    text
     
    Tasks:
    1. Buy groceries - Incomplete
    2. Finish homework - Complete
    3. Call mom - Incomplete
     
     
  • If you choose 2, it prompts for a task description:
    text
     
    Enter task description: Go for a run
    Task added successfully!
     
     
  • If you choose 3, it asks for a task number to mark complete:
    text
     
    Enter task number to mark as complete: 1
    Task marked as complete!
     
     
  • Choosing 4 saves all tasks to a file and exits.

Implementation Ideas

  • Data Structure: Store tasks as a list of dictionaries, e.g., [{"description": "Buy groceries", "status": "Incomplete"}, ...].
  • File Storage: Use a JSON file for simplicity and readability, or a plain text file with a clear format (e.g., one task per line with a delimiter for status).
  • Functions:
    • load_tasks(): Read tasks from the file when the program starts.
    • save_tasks(): Write tasks to the file when adding, completing, or exiting.
    • view_tasks(): Display the task list with numbers and statuses.
    • add_task(): Append a new task to the list.
    • mark_complete(): Update the status of a task based on its number.
    • main(): Handle the menu loop and user input.
  • Error Handling: Check for invalid inputs (e.g., non-numeric input for task numbers) and handle cases where the file is missing or corrupted.

Example Code Structure (in Python)

Here’s a rough outline of how the code might look:

python
 
import json

def load_tasks():
    try:
        with open("tasks.json", "r") as file:
            return json.load(file)
    except FileNotFoundError:
        return []

def save_tasks(tasks):
    with open("tasks.json", "w") as file:
        json.dump(tasks, file, indent=4)

def view_tasks(tasks):
    if not tasks:
        print("No tasks found!")
        return
    for i, task in enumerate(tasks, 1):
        print(f"{i}. {task['description']} - {task['status']}")

def add_task(tasks, description):
    tasks.append({"description": description, "status": "Incomplete"})

def mark_complete(tasks, task_number):
    if 1 <= task_number <= len(tasks):
        tasks[task_number - 1]["status"] = "Complete"
        print("Task marked as complete!")
    else:
        print("Invalid task number!")

def main():
    tasks = load_tasks()
    while True:
        print("\n=== To-Do List Manager ===")
        print("1. View tasks")
        print("2. Add task")
        print("3. Mark task as complete")
        print("4. Exit")
        choice = input("Enter your choice (1-4): ")
        
        if choice == "1":
            view_tasks(tasks)
        elif choice == "2":
            description = input("Enter task description: ")
            add_task(tasks, description)
            save_tasks(tasks)
            print("Task added successfully!")
        elif choice == "3":
            view_tasks(tasks)
            try:
                task_number = int(input("Enter task number to mark as complete: "))
                mark_complete(tasks, task_number)
                save_tasks(tasks)
            except ValueError:
                print("Please enter a valid number!")
        elif choice == "4":
            save_tasks(tasks)
            print("Goodbye!")
            break
        else:
            print("Invalid choice! Please try again.")

if __name__ == "__main__":
    main()
 
 

Enhancements

Once the core functionality is working, you could add features like:

  • Delete Tasks: Allow users to remove tasks.
  • Edit Tasks: Let users modify task descriptions.
  • Categories or Priorities: Add fields for task categories or priority levels.
  • Due Dates: Include due dates and sort tasks by them.
  • Clear Completed Tasks: Add an option to remove all completed tasks.
  • Search Tasks: Allow users to search for tasks by keyword.

Why This Project?

 

This to-do list manager is a perfect balance of challenge and practicality. It’s complex enough to stretch your skills but simple enough to complete in a reasonable time. You’ll gain hands-on experience with file I/O, modular programming, and user interaction, which are foundational for building larger applications. Plus, you’ll end up with a tool you can actually use to stay organized!