33 — Todo: a growing project
Guide 31 saved a list of dicts with json_save; 23
moved code into modules. This guide grows both into a todo list project.
Steps
Storage lives in a module,
store.nme, exportingload()andsave(todos):
run it →# store.nme — file storage for the todo list. import os use file latest def load(): if os.path.exists("todos.json"): return json_load("todos.json") return [] def save(todos): json_save("todos.json", todos)The whole project. Save
todo.nmenext tostore.nme:# todo.nme — a todo list that survives between runs. # Run: nme r todo from "store.nme" import load, save todos = load() while True: show "" show "Commands: add, done, list, quit" ask command, "? " if command == "add": ask text, "Todo? " todos.append({"text": text, "done": False}) save(todos) show f"Added: {text}" elif command == "done": ask num, "Number? " i = int(num) if i >= 0 and i < len(todos): todos[i]["done"] = True save(todos) show f"Done: {todos[i]['text']}" else: show f"No todo number {i}" elif command == "list": show f"{len(todos)} todos" for i in range(len(todos)): if todos[i]["done"]: show f"{i}: [x] {todos[i]['text']}" else: show f"{i}: [ ] {todos[i]['text']}" elif command == "quit": show "Bye!" break else: show "Unknown command"addappends a dict and saves immediately;donemarks a todo by number with anandrange check.Run it and feed the commands through a pipe:
printf 'add\nbuy milk\ndone\n0\nlist\nquit\n' | nme r todoCommands: add, done, list, quit ? Todo? Added: buy milk Commands: add, done, list, quit ? Number? Done: buy milk Commands: add, done, list, quit ? 1 todos 0: [x] buy milk Commands: add, done, list, quit ? Bye!The todo is saved to
todos.json, so the next run loads it back. Korean writes the same menu with물어봐and말해; the full pair is in the Korean guide.
Try it yourself
Add a clear command that resets todos to [] and saves — one elif branch. Then make list count the open items.
What you learned
- A project splits into a main program and a storage module with a clear interface.
json_savepersists a list of dicts;load()restores it on the next run.int(num)and theandrange check keep a number command safe.