todo_cli.py in Python
A complete CLI todo list persisting to JSON.
"""A tiny todo list that persists to a JSON file."""
import argparse
import json
from pathlib import Path
TODO_FILE = Path("todos.json")
def load_todos():
if TODO_FILE.exists():
return json.loads(TODO_FILE.read_text())
return []
def save_todos(todos):
TODO_FILE.write_text(json.dumps(todos, indent=2))
def main():
parser = argparse.ArgumentParser(description="minimal todo list")
sub = parser.add_subparsers(dest="command", required=True)
add = sub.add_parser("add")
add.add_argument("text")
done = sub.add_parser("done")
done.add_argument("number", type=int)
sub.add_parser("list")
args = parser.parse_args()
todos = load_todos()
if args.command == "add":
todos.append({"text": args.text, "done": False})
save_todos(todos)
print(f"added: {args.text}")
elif args.command == "done":
todos[args.number - 1]["done"] = True
save_todos(todos)
print(f"completed #{args.number}")
else:
for i, todo in enumerate(todos, start=1):
mark = "x" if todo["done"] else " "
print(f"[{mark}] {i}. {todo['text']}")
if __name__ == "__main__":
main()
How it works
argparsesubcommands give it add, done, and list verbs.- State round-trips through a JSON file with
pathlib. - Each command edits the list and saves it back.
Keywords and builtins used here
defelifelseenumerateforifintload_todosmainprintreturnsave_todostype
The run, in numbers
- Lines
- 45
- Characters to type
- 1039
- Tokens
- 306
- Three-star pace
- 105 tpm
At the three-star pace of 105 tokens a minute, this run takes about 175 seconds.
Step 3 of 5 in Encore, step 70 of 72 in Language basics.