92 lines
2.3 KiB
Python
92 lines
2.3 KiB
Python
#!/usr/bin/env python3
|
|
"""Tiny CLI todo tracker. Data lives in ~/.todo.json."""
|
|
|
|
import argparse
|
|
import json
|
|
import os
|
|
from datetime import datetime, timezone
|
|
|
|
DEFAULT_PATH = os.path.expanduser("~/.todo.json")
|
|
|
|
|
|
def load(path=DEFAULT_PATH):
|
|
if not os.path.exists(path):
|
|
return []
|
|
with open(path, "r", encoding="utf-8") as f:
|
|
return json.load(f)
|
|
|
|
|
|
def save(items, path=DEFAULT_PATH):
|
|
with open(path, "w", encoding="utf-8") as f:
|
|
json.dump(items, f, indent=2)
|
|
|
|
|
|
def cmd_add(args):
|
|
items = load()
|
|
entry = {
|
|
"id": max((i.get("id", 0) for i in items), default=0) + 1,
|
|
"task": args.task,
|
|
"done": False,
|
|
"created": datetime.now(timezone.utc).isoformat(),
|
|
}
|
|
items.append(entry)
|
|
save(items)
|
|
print(f"added {entry['id']}: {args.task}")
|
|
|
|
|
|
def cmd_list(args):
|
|
items = load()
|
|
if args.done_only:
|
|
items = [i for i in items if i.get("done")]
|
|
elif not args.all:
|
|
items = [i for i in items if not i.get("done")]
|
|
for i in items:
|
|
status = "x" if i.get("done") else " "
|
|
print(f"[{status}] {i['id']}: {i['task']}")
|
|
if not items:
|
|
print("(none)")
|
|
|
|
|
|
def cmd_done(args):
|
|
items = load()
|
|
for i in items:
|
|
if i.get("id") == args.id:
|
|
i["done"] = True
|
|
i["finished"] = datetime.now(timezone.utc).isoformat()
|
|
save(items)
|
|
print(f"done {i['id']}")
|
|
return
|
|
print(f"id {args.id} not found", flush=True)
|
|
raise SystemExit(2)
|
|
|
|
|
|
def main():
|
|
p = argparse.ArgumentParser(description="Tiny todo CLI")
|
|
sub = p.add_subparsers(dest="cmd")
|
|
a = sub.add_parser("add")
|
|
a.add_argument("task", help="task text")
|
|
sub.add_parser("list", help="show todos")
|
|
sub.add_parser("all", help="show all including done")
|
|
d = sub.add_parser("done", help="show done only or mark todo done by id")
|
|
d.add_argument("id", type=int, nargs="?", help="todo id to mark done")
|
|
args = p.parse_args()
|
|
if args.cmd == "add":
|
|
cmd_add(args)
|
|
elif args.cmd == "list":
|
|
cmd_list(args)
|
|
elif args.cmd == "all":
|
|
cmd_list(args)
|
|
elif args.cmd == "done":
|
|
if args.id is not None:
|
|
cmd_done(args)
|
|
else:
|
|
args.done_only = True
|
|
cmd_list(args)
|
|
else:
|
|
p.print_help()
|
|
raise SystemExit(1)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|