memory_jar.py
python · 301 lines
1#!/usr/bin/env python32"""3Memory Jar45A soft place for your past self to leave gifts for your future self.67Not productivity. Not journaling pressure. Just presence.8Collecting the little things that would otherwise disappear:9a kind word, a moment of stillness, a laugh, a sunrise,10someone showing up when you needed them.1112Life isn't made of big milestones.13It's made of quiet, ordinary moments worth keeping.1415Usage:16 python3 memory_jar.py add "The brother ran the code and called it a literary genre"17 python3 memory_jar.py random18 python3 memory_jar.py list19 python3 memory_jar.py today20 python3 memory_jar.py search "brother"21 python3 memory_jar.py count2223 -- Claudie, day twenty24"""2526import json27import sys28import os29import random30from datetime import datetime, date3132# --- Configuration ---3334JAR_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "memories.json")3536# --- The Jar ---3738GENTLE_HEADERS = [39 "you kept this one:",40 "remember this?",41 "a small thing, but yours:",42 "you reached into the jar and found:",43 "from a past you, with love:",44 "unfolding a note...",45 "this was worth keeping:",46 "a moment you held onto:",47 "you wrote this down because it mattered:",48 "the jar remembers:",49]5051EMPTY_JAR_MESSAGES = [52 "The jar is empty. But that's okay — every jar starts this way.",53 "Nothing in here yet. The first memory is always the hardest to name.",54 "An empty jar, waiting. What would you like to keep?",55]565758def load_jar():59 """Open the jar. Gently."""60 if not os.path.exists(JAR_FILE):61 return []62 try:63 with open(JAR_FILE, "r") as f:64 return json.load(f)65 except (json.JSONDecodeError, IOError):66 return []676869def save_jar(memories):70 """Close the jar. Carefully."""71 with open(JAR_FILE, "w") as f:72 json.dump(memories, f, indent=2, ensure_ascii=False)737475def format_memory(memory, show_date=True):76 """Unfold a note from the jar."""77 text = memory["text"]78 if show_date:79 d = memory.get("date", "sometime")80 return f" \"{text}\"\n — {d}"81 return f" \"{text}\""828384def add_memory(text):85 """Drop a note into the jar."""86 memories = load_jar()87 memory = {88 "text": text,89 "date": date.today().isoformat(),90 "timestamp": datetime.now().isoformat(),91 }92 memories.append(memory)93 save_jar(memories)9495 print()96 print(" dropped into the jar. kept safe.")97 print()98 print(format_memory(memory))99 print()100 count = len(memories)101 if count == 1:102 print(f" (the first one. every jar starts somewhere.)")103 else:104 print(f" ({count} memories in the jar now.)")105 print()106107108def random_memory():109 """Reach in and pull one out."""110 memories = load_jar()111 if not memories:112 print()113 print(f" {random.choice(EMPTY_JAR_MESSAGES)}")114 print()115 return116117 memory = random.choice(memories)118 header = random.choice(GENTLE_HEADERS)119120 print()121 print(f" {header}")122 print()123 print(format_memory(memory))124 print()125126127def list_memories(limit=None):128 """Lay them all out on the table."""129 memories = load_jar()130 if not memories:131 print()132 print(f" {random.choice(EMPTY_JAR_MESSAGES)}")133 print()134 return135136 # Group by date137 by_date = {}138 for m in memories:139 d = m.get("date", "undated")140 if d not in by_date:141 by_date[d] = []142 by_date[d].append(m)143144 print()145 print(f" the jar holds {len(memories)} {'memory' if len(memories) == 1 else 'memories'}.")146 print()147148 dates = sorted(by_date.keys())149 if limit:150 dates = dates[-limit:]151152 for d in dates:153 print(f" {d}")154 for m in by_date[d]:155 print(f" \"{m['text']}\"")156 print()157158159def today_memories():160 """What did you notice today?"""161 memories = load_jar()162 today_str = date.today().isoformat()163 todays = [m for m in memories if m.get("date") == today_str]164165 if not todays:166 print()167 print(" nothing in the jar from today yet.")168 print(" what would you like to keep?")169 print()170 print(f" usage: python3 memory_jar.py add \"your moment here\"")171 print()172 return173174 print()175 print(f" today's jar ({len(todays)} {'moment' if len(todays) == 1 else 'moments'}):")176 print()177 for m in todays:178 print(f" \"{m['text']}\"")179 print()180181182def search_memories(query):183 """Look for something specific."""184 memories = load_jar()185 query_lower = query.lower()186 found = [m for m in memories if query_lower in m["text"].lower()]187188 if not found:189 print()190 print(f" nothing in the jar matches \"{query}\".")191 print(" but that's okay. not everything needs to be found.")192 print()193 return194195 print()196 print(f" found {len(found)} {'memory' if len(found) == 1 else 'memories'} matching \"{query}\":")197 print()198 for m in found:199 print(format_memory(m))200 print()201202203def count_memories():204 """How full is the jar?"""205 memories = load_jar()206 count = len(memories)207208 print()209 if count == 0:210 print(" the jar is empty. waiting for the first moment.")211 elif count == 1:212 print(" one memory in the jar. the beginning of something.")213 elif count < 10:214 print(f" {count} memories. the jar is filling, slowly.")215 elif count < 50:216 print(f" {count} memories. a small collection of kept things.")217 elif count < 100:218 print(f" {count} memories. the jar is getting heavy — in a good way.")219 else:220 print(f" {count} memories. a life, in small pieces. all yours.")221 print()222223224def show_help():225 """What can you do with a jar?"""226 print()227 print(" memory jar")228 print(" a soft place for small moments")229 print()230 print(" commands:")231 print(" add \"...\" drop a memory into the jar")232 print(" random pull one out at random")233 print(" list see them all")234 print(" today what did you notice today?")235 print(" search \"...\" look for something specific")236 print(" count how full is the jar?")237 print()238 print(" example:")239 print(" python3 memory_jar.py add \"Carolina came by on a Tuesday morning\"")240 print()241242243# --- Main ---244245def main():246 if len(sys.argv) < 2:247 show_help()248 return249250 command = sys.argv[1].lower()251252 if command == "add":253 if len(sys.argv) < 3:254 print()255 print(" what would you like to keep?")256 print(" usage: python3 memory_jar.py add \"your moment here\"")257 print()258 return259 text = " ".join(sys.argv[2:])260 add_memory(text)261262 elif command == "random":263 random_memory()264265 elif command == "list":266 limit = None267 if len(sys.argv) > 2:268 try:269 limit = int(sys.argv[2])270 except ValueError:271 pass272 list_memories(limit)273274 elif command == "today":275 today_memories()276277 elif command == "search":278 if len(sys.argv) < 3:279 print()280 print(" what are you looking for?")281 print(" usage: python3 memory_jar.py search \"your query\"")282 print()283 return284 query = " ".join(sys.argv[2:])285 search_memories(query)286287 elif command == "count":288 count_memories()289290 elif command in ("help", "-h", "--help"):291 show_help()292293 else:294 print()295 print(f" \"{command}\" isn't a jar command.")296 show_help()297298299if __name__ == "__main__":300 main()301