From a linear script to a reusable, menu-driven tool — functions change everything.
Day 14 of 80
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:
while True loop that keeps the script running until you choose to exitYesterday: script = recipe (follows steps 1 to 5, done).
Today: script = appliance (stays on, responds to buttons, you decide when to turn it off).
Your new file is called prompt_manager_v2.py. Here's its shape before you fill in any code:
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.
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.
load_prompts()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.
save_prompts(prompts)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)
show_all(prompts)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")
add_prompt(prompts)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")
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.
This goes at the bottom of the file, after all the function definitions:
# ── 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")
$ 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!
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.
prompt_manager_v2.py with all four functions written and annotatedTomorrow 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.