Finish the tool. Lock in the week. Three functions to go.
Day 15 of 80
Yesterday you built the menu loop and four foundational functions. Options 3, 4, and 5 were stubbed out. Today you replace those stubs with real code:
| Menu Option | Function | What It Does |
|---|---|---|
| 3 — Search | search_prompts() |
Filter by keyword across all three fields |
| 4 — Delete | delete_prompt() |
Show list, ask for number, remove it, save |
| 5 — Export | export_by_platform() |
Group prompts by platform, write one file per platform |
After writing the three functions, you'll swap out the placeholder print() lines in the menu loop and run a full test of all six options.
Search works by checking if the user's keyword appears in any of the three text fields of each prompt. The key tool here is a list comprehension — a concise way to filter a list.
def search_prompts(prompts):
"""Filter the library by a keyword and display matching prompts."""
query = input("\nSearch (keyword or platform name): ").lower()
# .lower() means searching "kling" and "Kling" both match
# List comprehension — reads as:
# "Give me each p from prompts WHERE the query appears in any field"
# This replaces a for loop + if + append pattern in one readable line
results = [
p for p in prompts
if query in p["platform"].lower()
or query in p["shot"].lower()
or query in p["prompt"].lower()
]
if not results:
print(f"\n No prompts matching '{query}'.\n")
return
print(f"\n--- Found {len(results)} match(es) ---\n")
# Display results the same way show_all() does
for i, p in enumerate(results):
print(f" {i + 1}. [{p['platform']}] {p['shot']}")
print(f" {p['prompt'][:60]}...\n")
The long way to search would be:
results = []
for p in prompts:
if query in p["platform"].lower():
results.append(p)
The list comprehension does the same thing in one line: [p for p in prompts if query in p["platform"].lower()]. It's not shorter just for style — it's a standard Python pattern that every programmer will recognize immediately.
Delete shows the list, asks for a number, converts the input string to an integer, validates it, then uses .pop() to remove that item from the list.
def delete_prompt(prompts):
"""Show the full list, ask which number to delete, remove it."""
if not prompts:
print("\n Nothing to delete.\n")
return
# Show the numbered list so the user knows what to type
show_all(prompts)
choice = input("Delete which number? (or 'cancel'): ")
if choice.lower() == "cancel":
return
# try/except here because int("abc") raises ValueError
# We never trust raw user input when we need a number
try:
# Subtract 1 because the menu shows 1-based numbers,
# but Python lists are 0-based
index = int(choice) - 1
# Guard against negative numbers and numbers beyond list length
if index < 0 or index >= len(prompts):
print(" Invalid number.\n")
return
# .pop(index) removes the item at that position AND returns it
# so we can tell the user what was deleted
removed = prompts.pop(index)
save_prompts(prompts)
print(f"\n Deleted: [{removed['platform']}] {removed['shot']}\n")
except ValueError:
# int("abc") → ValueError, caught here instead of crashing
print(" Please enter a number.\n")
try/except ValueError?If the user types "two" instead of "2", calling int("two") raises a ValueError and the script would crash without try/except. The except block catches that specific error and prints a friendly message. This pattern — validate numeric input with try/except ValueError — is one you'll use in almost every script that takes user input.
Export groups prompts by platform and writes a separate JSON file for each platform. The trick is building a dictionary of lists — one key per platform, each key holding a list of that platform's prompts.
def export_by_platform(prompts):
"""Group prompts by platform and write one JSON file per platform."""
if not prompts:
print("\n Nothing to export.\n")
return
# Build a dict like: {"Kling": [...], "Runway": [...], "Veo": [...]}
# We start with an empty dict and add keys as we encounter new platforms
grouped = {}
for p in prompts:
platform = p["platform"]
if platform not in grouped:
# First time we see this platform — create an empty list for it
grouped[platform] = []
grouped[platform].append(p)
# Now write one file per platform
# .items() gives us (key, value) pairs from the dictionary
for platform, platform_prompts in grouped.items():
# Build a safe filename: "prompts_kling.json", "prompts_runway.json", etc.
filename = f"prompts_{platform.lower()}.json"
with open(filename, "w") as f:
json.dump(platform_prompts, f, indent=2)
print(f" Exported {len(platform_prompts)} prompts to {filename}")
print()
Update the menu loop at the bottom of prompt_manager_v2.py — replace the three placeholder print() lines with real function calls:
prompts = load_prompts()
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()
if choice == "1": show_all(prompts)
elif choice == "2": add_prompt(prompts)
elif choice == "3": search_prompts(prompts) # was placeholder
elif choice == "4": delete_prompt(prompts) # was placeholder
elif choice == "5": export_by_platform(prompts) # was placeholder
elif choice == "6":
print("\n Bye!\n")
break
else:
print(" Invalid choice. Enter 1-6.\n")
$ python prompt_manager_v2.py
========== Prompt Manager ==========
1. View all prompts ...
Choose (1-6): 3
Search (keyword or platform name): kling
--- Found 1 match(es) ---
1. [Kling] Golf swing follow-through
Slow-motion golf swing, camera tracks club head through i...
Choose (1-6): 4
--- All Prompts (3) ---
1. [Kling] Golf swing follow-through ...
2. [Runway] Ocean aerial ...
3. [Veo] City timelapse at night ...
Delete which number? (or 'cancel'): 2
Deleted: [Runway] Ocean aerial
Choose (1-6): 5
Exported 1 prompts to prompts_kling.json
Exported 1 prompts to prompts_veo.json
Choose (1-6): 6
Bye!
By the end of Week 3, you can:
json.load(), json.dump(), open() with "r" and "w" modesFileNotFoundError, ValueError) and handle them gracefully instead of crashingwhile True loop with branching logic, functions that each do one thing, and a clean exit pathThat's a real, useful, production-relevant set of skills. You've built something you could actually hand to another person to use.
search_prompts, delete_prompt, export_by_platformprompts_kling.json / prompts_veo.json files appeared in the folderWeek 4 starts Monday with APIs. You'll watch a short lesson on what an API actually is, then spend the rest of the week making real calls to the Claude API and building a tool that auto-generates video prompts for you.