Week 3 of 16

Prompt Manager with Menu (Part 1)

From a linear script to a reusable, menu-driven tool — functions change everything.

Day 14 60 minutes Build

Day 14 of 80

What Changes Today

Yesterday's script ran top-to-bottom once and exited. That works for a quick one-off task, but a real tool needs to stick around and let you do multiple things — view prompts, add one, then view again without restarting the script.

Today you introduce two powerful ideas at once:

The Mental Model Shift

Yesterday: script = recipe (follows steps 1 to 5, done).
Today: script = appliance (stays on, responds to buttons, you decide when to turn it off).

The New Structure

Your new file is called prompt_manager_v2.py. Here's its shape before you fill in any code:

prompt_manager_v2.py — skeleton Python
import json

PROMPTS_FILE = "prompts.json"

# ── Four focused functions ────────────────────────────────────────────
def load_prompts():    # reads file → returns list
    ...

def save_prompts(prompts):  # takes list → writes file
    ...

def show_all(prompts):     # takes list → prints to screen
    ...

def add_prompt(prompts):   # takes list → asks user → appends → saves
    ...

# ── Menu loop ────────────────────────────────────────────────────────
while True:
    # show choices, read input, call the right function
    ...

Notice how each function does exactly one thing. This is the most important design principle you'll learn as a programmer.

Functions Are Reusable

Without functions, if you need to save the prompts list in three different places, you copy the with open... block three times. When you need to change it, you change it three times and probably miss one.

With a save_prompts() function, you write the save logic once. Every part of the script that needs to save calls save_prompts(prompts). Change the function once and it's fixed everywhere.

Rule of thumb: if you're about to write the same code twice, write a function instead.

Building the Functions

Function 1: load_prompts()

prompt_manager_v2.py Python
def load_prompts():
    """Load prompts from file. Return empty list if file doesn't exist."""
    # try/except handles the case where the file hasn't been created yet
    try:
        with open(PROMPTS_FILE, "r") as f:
            return json.load(f)   # return sends the value back to the caller
    except FileNotFoundError:
        return []               # caller gets an empty list — safe to work with

The triple-quoted string immediately after def is called a docstring. It documents what the function does. Get in the habit — your future self will thank you.

Function 2: save_prompts(prompts)

prompt_manager_v2.py Python
def save_prompts(prompts):
    """Save the prompts list back to the JSON file."""
    # "w" mode creates the file if it doesn't exist,
    # or overwrites it if it does — we want to replace the whole file
    with open(PROMPTS_FILE, "w") as f:
        json.dump(prompts, f, indent=2)
    # No return needed — this function's job is the side effect (writing the file)

Function 3: show_all(prompts)

prompt_manager_v2.py Python
def show_all(prompts):
    """Display every prompt in the library."""
    # Handle the empty-library case gracefully — no index errors
    if not prompts:
        print("\n  (empty — add some prompts first!)\n")
        return   # early return exits the function here — skips the loop below

    print(f"\n--- All Prompts ({len(prompts)}) ---\n")

    for i, p in enumerate(prompts):
        # Line 1: number, platform tag, shot name
        print(f"  {i + 1}. [{p['platform']}] {p['shot']}")
        # Line 2: first 60 chars of the prompt text, with "..." if longer
        # [:60] is a slice — it takes characters 0 through 59
        print(f"     {p['prompt'][:60]}...\n")

Function 4: add_prompt(prompts)

prompt_manager_v2.py Python
def add_prompt(prompts):
    """Ask the user for a new prompt and add it to the list."""
    print("\n--- Add New Prompt ---")
    platform = input("Platform (Kling / Runway / Veo): ")

    # Validate: check if the user typed a known platform
    # .lower() makes the check case-insensitive ("KLING" matches "kling")
    valid = ["kling", "runway", "veo"]
    if platform.lower() not in valid:
        print(f"  Unknown platform. Defaulting to Kling.")
        platform = "Kling"

    shot   = input("Shot description: ")
    prompt = input("Full prompt text: ")

    # Build the dictionary and add it to the in-memory list
    prompts.append({"platform": platform, "shot": shot, "prompt": prompt})

    # Save immediately so we never lose data
    save_prompts(prompts)
    print(f"\n  Saved! Library now has {len(prompts)} prompts.\n")
Why Pass prompts to Every Function?

Python functions don't automatically know about variables defined outside them. By passing prompts as an argument, each function works on the real list. When add_prompt calls prompts.append(), it modifies the same list the main loop is using — so the menu immediately reflects the change.

The Main Menu Loop

This goes at the bottom of the file, after all the function definitions:

prompt_manager_v2.py — menu loop Python
# ── Entry point ──────────────────────────────────────────────────────
# Load prompts once when the script starts
prompts = load_prompts()

# while True loops forever — the only exit is break or quit()
while True:
    print("\n========== Prompt Manager ==========")
    print("  1. View all prompts")
    print("  2. Add a prompt")
    print("  3. Search prompts")
    print("  4. Delete a prompt")
    print("  5. Export by platform")
    print("  6. Quit")
    print("===================================\n")

    choice = input("Choose (1-6): ").strip()
    # .strip() removes any accidental spaces or newlines

    if choice == "1":
        show_all(prompts)
    elif choice == "2":
        add_prompt(prompts)
    elif choice == "3":
        print("  (Search coming tomorrow!)")
    elif choice == "4":
        print("  (Delete coming tomorrow!)")
    elif choice == "5":
        print("  (Export coming tomorrow!)")
    elif choice == "6":
        print("\n  Bye!\n")
        break   # break exits the while loop → script ends
    else:
        print("  Invalid choice. Enter 1-6.\n")

Run It

Terminal
$ python prompt_manager_v2.py

========== Prompt Manager ==========
  1. View all prompts
  2. Add a prompt
  3. Search prompts
  4. Delete a prompt
  5. Export by platform
  6. Quit
===================================

Choose (1-6): 1

--- All Prompts (3) ---

  1. [Kling] Golf swing follow-through
     Slow-motion golf swing, camera tracks club head through i...

  2. [Runway] Ocean aerial
     Aerial drone shot over turquoise ocean, waves breaking on...

  3. [Veo] City timelapse at night
     City traffic timelapse, light trails, skyscrapers, neon r...

========== Prompt Manager ==========
  1. View all prompts
  2. Add a prompt
...
Choose (1-6): 6

  Bye!
Why Options 3, 4, 5 Say "Coming Tomorrow"

This is intentional. Stubbing out the menu now — with placeholder print statements — lets you test the menu loop and the two working functions without waiting until all six features are done. It's a real software development practice called incremental delivery. Finish tomorrow's lesson and all six options will work.

End of Day Checklist

Tomorrow

Tomorrow you complete the tool by implementing the three remaining functions: search_prompts, delete_prompt, and export_by_platform. You'll also do the Week 3 milestone check and review everything you've learned so far.