Skip to content

Instantly share code, notes, and snippets.

@muellerzr
Last active May 6, 2025 13:58
Show Gist options
  • Select an option

  • Save muellerzr/4c805515e0d66ee95bca87b4de3aebe2 to your computer and use it in GitHub Desktop.

Select an option

Save muellerzr/4c805515e0d66ee95bca87b4de3aebe2 to your computer and use it in GitHub Desktop.

Revisions

  1. muellerzr revised this gist May 6, 2025. 1 changed file with 17 additions and 21 deletions.
    38 changes: 17 additions & 21 deletions journal.py
    Original file line number Diff line number Diff line change
    @@ -9,9 +9,9 @@
    Specialized for ML experiment tracking with predefined fields.
    To use:
    python journal.py write -c "experiment"
    python journal.py list -c "experiment"
    python journal.py search -q "good results" -c "experiment"
    python journal.py write -c "experiment_name"
    python journal.py list -c "experiment_name"
    python journal.py search -q "good results" -c "experiment_name"
    python journal.py export -f "txt"
    Note: Press Ctrl+D to save your entry
    @@ -47,7 +47,7 @@ def save_entries(self, filepath: str, entries: List[Dict]) -> None:
    with open(filepath, 'w') as f:
    json.dump(entries, f, indent=2)

    def write_entry(self, content: Dict[str, str], category: str = "general") -> None:
    def write_entry(self, content: Dict[str, str], category: str) -> None:
    filepath = self.get_current_file()
    now = datetime.now()
    date_str = now.strftime("%Y-%m-%d")
    @@ -67,6 +67,7 @@ def write_entry(self, content: Dict[str, str], category: str = "general") -> Non
    print(f"\nEntry saved successfully!")
    print(f"Date: {date_str}")
    print(f"Time: {time_str}")
    print(f"Experiment: {category}")

    def get_all_entries(self) -> List[Dict]:
    all_entries = []
    @@ -101,7 +102,7 @@ def export_journal(self, format_type: str = "txt") -> None:
    for entry in entries:
    f.write(f"Date: {entry['date']}\n")
    f.write(f"Time: {entry['time']}\n")
    f.write(f"Category: {entry['category']}\n")
    f.write(f"Experiment: {entry['category']}\n")
    f.write(f"W&B Run: {entry.get('wandb_run', 'N/A')}\n")
    f.write(f"\nResults:\n{entry.get('results', 'N/A')}\n")
    f.write(f"\nWhat Went Right:\n{entry.get('what_went_right', 'N/A')}\n")
    @@ -120,18 +121,13 @@ def display_entries(entries: List[Dict]) -> None:
    print("\n" + "="*50)
    print(f"Date: {entry['date']}")
    print(f"Time: {entry['time']}")
    print(f"Category: {entry['category']}")
    print(f"Experiment: {entry['category']}")
    print("-"*50)

    if entry['category'] == "experiment":
    print(f"W&B Run: {entry.get('wandb_run', 'N/A')}")
    print(f"\nResults:\n{entry.get('results', 'N/A')}")
    print(f"\nWhat Went Right:\n{entry.get('what_went_right', 'N/A')}")
    print(f"\nWhat Went Wrong:\n{entry.get('what_went_wrong', 'N/A')}")
    print(f"\nNext Steps:\n{entry.get('next_steps', 'N/A')}")
    else:
    print(entry.get('content', ''))

    print(f"W&B Run: {entry.get('wandb_run', 'N/A')}")
    print(f"\nResults:\n{entry.get('results', 'N/A')}")
    print(f"\nWhat Went Right:\n{entry.get('what_went_right', 'N/A')}")
    print(f"\nWhat Went Wrong:\n{entry.get('what_went_wrong', 'N/A')}")
    print(f"\nNext Steps:\n{entry.get('next_steps', 'N/A')}")
    print("="*50)

    def prompt_experiment_entry() -> Dict[str, str]:
    @@ -199,16 +195,16 @@ def main():

    # Write command
    write_parser = subparsers.add_parser("write", help="Write a new journal entry")
    write_parser.add_argument("-c", "--category", default="general", help="Entry category (general or experiment)")
    write_parser.add_argument("-c", "--category", required=True, help="Experiment name")

    # List command
    list_parser = subparsers.add_parser("list", help="List journal entries")
    list_parser.add_argument("-c", "--category", help="Filter by category")
    list_parser.add_argument("-c", "--category", help="Filter by experiment name")

    # Search command
    search_parser = subparsers.add_parser("search", help="Search journal entries")
    search_parser.add_argument("-q", "--query", help="Search text")
    search_parser.add_argument("-c", "--category", help="Filter by category")
    search_parser.add_argument("-c", "--category", help="Filter by experiment name")

    # Export command
    export_parser = subparsers.add_parser("export", help="Export journal entries")
    @@ -219,11 +215,11 @@ def main():

    if args.command == "write":
    now = datetime.now()
    print("\nQuick Journal - Experiment Entry")
    print(f"\nQuick Journal - Experiment: {args.category}")
    print(f"Date: {now.strftime('%Y-%m-%d')}")
    print(f"Time: {now.strftime('%H:%M')}")
    content = prompt_experiment_entry()
    journal.write_entry(content, "experiment")
    journal.write_entry(content, args.category)

    elif args.command == "list":
    entries = journal.search_entries(category=args.category)
  2. muellerzr revised this gist May 6, 2025. 1 changed file with 36 additions and 28 deletions.
    64 changes: 36 additions & 28 deletions journal.py
    Original file line number Diff line number Diff line change
    @@ -144,44 +144,52 @@ def prompt_experiment_entry() -> Dict[str, str]:
    content['wandb_run'] = wandb_run

    # Results
    print("\nResults (press Ctrl+D when done):")
    print("\nResults (press Enter twice when done):")
    lines = []
    try:
    while True:
    line = input("> ")
    lines.append(line)
    except EOFError:
    content['results'] = "\n".join(lines[:-1]) # Remove the last empty line
    while True:
    line = input("> ")
    if line.strip() == "" and (not lines or lines[-1].strip() == ""):
    if lines:
    lines.pop() # Remove the last empty line
    break
    lines.append(line)
    content['results'] = "\n".join(lines)

    # What Went Right
    print("\nWhat Went Right (press Ctrl+D when done):")
    print("\nWhat Went Right (press Enter twice when done):")
    lines = []
    try:
    while True:
    line = input("> ")
    lines.append(line)
    except EOFError:
    content['what_went_right'] = "\n".join(lines[:-1])
    while True:
    line = input("> ")
    if line.strip() == "" and (not lines or lines[-1].strip() == ""):
    if lines:
    lines.pop() # Remove the last empty line
    break
    lines.append(line)
    content['what_went_right'] = "\n".join(lines)

    # What Went Wrong
    print("\nWhat Went Wrong (press Ctrl+D when done):")
    print("\nWhat Went Wrong (press Enter twice when done):")
    lines = []
    try:
    while True:
    line = input("> ")
    lines.append(line)
    except EOFError:
    content['what_went_wrong'] = "\n".join(lines[:-1])
    while True:
    line = input("> ")
    if line.strip() == "" and (not lines or lines[-1].strip() == ""):
    if lines:
    lines.pop() # Remove the last empty line
    break
    lines.append(line)
    content['what_went_wrong'] = "\n".join(lines)

    # Next Steps
    print("\nNext Steps (press Ctrl+D when done):")
    print("\nNext Steps (press Enter twice when done):")
    lines = []
    try:
    while True:
    line = input("> ")
    lines.append(line)
    except EOFError:
    content['next_steps'] = "\n".join(lines[:-1])
    while True:
    line = input("> ")
    if line.strip() == "" and (not lines or lines[-1].strip() == ""):
    if lines:
    lines.pop() # Remove the last empty line
    break
    lines.append(line)
    content['next_steps'] = "\n".join(lines)

    return content

  3. muellerzr revised this gist May 6, 2025. 1 changed file with 48 additions and 57 deletions.
    105 changes: 48 additions & 57 deletions journal.py
    Original file line number Diff line number Diff line change
    @@ -99,18 +99,14 @@ def export_journal(self, format_type: str = "txt") -> None:
    filepath = os.path.join(self.journal_dir, f"{export_filename}.txt")
    with open(filepath, 'w') as f:
    for entry in entries:
    if entry['category'] == 'experiment':
    f.write(f"Date: {entry['date']}\n")
    f.write(f"Time: {entry['time']}\n")
    f.write(f"Category: {entry['category']}\n")
    f.write(f"W&B Run: {entry.get('wandb_run', 'N/A')}\n")
    f.write(f"\nResults:\n{entry.get('results', 'N/A')}\n")
    f.write(f"\nWhat Went Right:\n{entry.get('what_went_right', 'N/A')}\n")
    f.write(f"\nWhat Went Wrong:\n{entry.get('what_went_wrong', 'N/A')}\n")
    f.write(f"\nNext Steps:\n{entry.get('next_steps', 'N/A')}\n")
    else:
    f.write(f"[{entry['timestamp']}] ({entry['category']})\n")
    f.write(f"{entry.get('content', '')}\n")
    f.write(f"Date: {entry['date']}\n")
    f.write(f"Time: {entry['time']}\n")
    f.write(f"Category: {entry['category']}\n")
    f.write(f"W&B Run: {entry.get('wandb_run', 'N/A')}\n")
    f.write(f"\nResults:\n{entry.get('results', 'N/A')}\n")
    f.write(f"\nWhat Went Right:\n{entry.get('what_went_right', 'N/A')}\n")
    f.write(f"\nWhat Went Wrong:\n{entry.get('what_went_wrong', 'N/A')}\n")
    f.write(f"\nNext Steps:\n{entry.get('next_steps', 'N/A')}\n")
    f.write("\n---\n\n")

    print(f"Exported journal to {filepath}")
    @@ -140,43 +136,53 @@ def display_entries(entries: List[Dict]) -> None:

    def prompt_experiment_entry() -> Dict[str, str]:
    content = {}
    print("\nEnter experiment details:")

    # W&B Run
    wandb_run = input("\nW&B Run Name: ").strip()
    print("\nW&B Run Name (press Enter when done):")
    wandb_run = input("> ").strip()
    content['wandb_run'] = wandb_run

    # Results
    print("\nResults:")
    results = input("> ").strip()
    content['results'] = results
    print("\nResults (press Ctrl+D when done):")
    lines = []
    try:
    while True:
    line = input("> ")
    lines.append(line)
    except EOFError:
    content['results'] = "\n".join(lines[:-1]) # Remove the last empty line

    # What Went Right
    print("\nWhat Went Right:")
    went_right = input("> ").strip()
    content['what_went_right'] = went_right
    print("\nWhat Went Right (press Ctrl+D when done):")
    lines = []
    try:
    while True:
    line = input("> ")
    lines.append(line)
    except EOFError:
    content['what_went_right'] = "\n".join(lines[:-1])

    # What Went Wrong
    print("\nWhat Went Wrong:")
    went_wrong = input("> ").strip()
    content['what_went_wrong'] = went_wrong
    print("\nWhat Went Wrong (press Ctrl+D when done):")
    lines = []
    try:
    while True:
    line = input("> ")
    lines.append(line)
    except EOFError:
    content['what_went_wrong'] = "\n".join(lines[:-1])

    # Next Steps
    print("\nNext Steps:")
    next_steps = input("> ").strip()
    content['next_steps'] = next_steps
    print("\nNext Steps (press Ctrl+D when done):")
    lines = []
    try:
    while True:
    line = input("> ")
    lines.append(line)
    except EOFError:
    content['next_steps'] = "\n".join(lines[:-1])

    # Show summary before saving
    print("\nSummary of your entry:")
    print(f"W&B Run: {wandb_run}")
    print(f"Results: {results}")
    print(f"What Went Right: {went_right}")
    print(f"What Went Wrong: {went_wrong}")
    print(f"Next Steps: {next_steps}")

    confirm = input("\nSave this entry? (y/n): ").lower().strip()
    if confirm != 'y':
    raise EOFError("Entry cancelled by user")

    return content

    def main():
    @@ -205,26 +211,11 @@ def main():

    if args.command == "write":
    now = datetime.now()
    if args.category == "experiment":
    print("\nQuick Journal - Experiment Entry")
    print(f"Date: {now.strftime('%Y-%m-%d')}")
    print(f"Time: {now.strftime('%H:%M')}")
    content = prompt_experiment_entry()
    journal.write_entry(content, "experiment")
    else:
    print("\nQuick Journal - Enter your thoughts (press Ctrl+D to save)")
    print(f"Date: {now.strftime('%Y-%m-%d')}")
    print(f"Time: {now.strftime('%H:%M')}")
    print(f"Category: {args.category}")
    print("\nStart writing:")
    content_lines = []
    try:
    while True:
    line = input("> ")
    content_lines.append(line)
    except EOFError:
    if content_lines:
    journal.write_entry({"content": "\n".join(content_lines)}, args.category)
    print("\nQuick Journal - Experiment Entry")
    print(f"Date: {now.strftime('%Y-%m-%d')}")
    print(f"Time: {now.strftime('%H:%M')}")
    content = prompt_experiment_entry()
    journal.write_entry(content, "experiment")

    elif args.command == "list":
    entries = journal.search_entries(category=args.category)
  4. muellerzr revised this gist May 6, 2025. 1 changed file with 25 additions and 35 deletions.
    60 changes: 25 additions & 35 deletions journal.py
    Original file line number Diff line number Diff line change
    @@ -140,53 +140,43 @@ def display_entries(entries: List[Dict]) -> None:

    def prompt_experiment_entry() -> Dict[str, str]:
    content = {}
    print("\nEnter experiment details:")

    # W&B Run
    print("\nW&B Run Name (press Enter when done):")
    wandb_run = input("> ").strip()
    wandb_run = input("\nW&B Run Name: ").strip()
    content['wandb_run'] = wandb_run

    # Results
    print("\nResults (press Ctrl+D when done):")
    lines = []
    try:
    while True:
    line = input("> ")
    lines.append(line)
    except EOFError:
    content['results'] = "\n".join(lines[:-1]) # Remove the last empty line
    print("\nResults:")
    results = input("> ").strip()
    content['results'] = results

    # What Went Right
    print("\nWhat Went Right (press Ctrl+D when done):")
    lines = []
    try:
    while True:
    line = input("> ")
    lines.append(line)
    except EOFError:
    content['what_went_right'] = "\n".join(lines[:-1])
    print("\nWhat Went Right:")
    went_right = input("> ").strip()
    content['what_went_right'] = went_right

    # What Went Wrong
    print("\nWhat Went Wrong (press Ctrl+D when done):")
    lines = []
    try:
    while True:
    line = input("> ")
    lines.append(line)
    except EOFError:
    content['what_went_wrong'] = "\n".join(lines[:-1])
    print("\nWhat Went Wrong:")
    went_wrong = input("> ").strip()
    content['what_went_wrong'] = went_wrong

    # Next Steps
    print("\nNext Steps (press Ctrl+D when done):")
    lines = []
    try:
    while True:
    line = input("> ")
    lines.append(line)
    except EOFError:
    content['next_steps'] = "\n".join(lines[:-1])
    print("\nNext Steps:")
    next_steps = input("> ").strip()
    content['next_steps'] = next_steps

    # Show summary before saving
    print("\nSummary of your entry:")
    print(f"W&B Run: {wandb_run}")
    print(f"Results: {results}")
    print(f"What Went Right: {went_right}")
    print(f"What Went Wrong: {went_wrong}")
    print(f"Next Steps: {next_steps}")

    confirm = input("\nSave this entry? (y/n): ").lower().strip()
    if confirm != 'y':
    raise EOFError("Entry cancelled by user")

    return content

    def main():
  5. muellerzr revised this gist May 6, 2025. 1 changed file with 25 additions and 16 deletions.
    41 changes: 25 additions & 16 deletions journal.py
    Original file line number Diff line number Diff line change
    @@ -81,7 +81,7 @@ def search_entries(self, query: Optional[str] = None, category: Optional[str] =
    entries = self.get_all_entries()

    if query:
    entries = [e for e in entries if query.lower() in e['content'].lower()]
    entries = [e for e in entries if query.lower() in str(e).lower()]
    if category:
    entries = [e for e in entries if e['category'] == category]

    @@ -99,11 +99,19 @@ def export_journal(self, format_type: str = "txt") -> None:
    filepath = os.path.join(self.journal_dir, f"{export_filename}.txt")
    with open(filepath, 'w') as f:
    for entry in entries:
    f.write(f"Date: {entry['date']}\n")
    f.write(f"Time: {entry['time']}\n")
    f.write(f"Category: {entry['category']}\n")
    f.write(f"{entry['content']}\n")
    f.write("---\n\n")
    if entry['category'] == 'experiment':
    f.write(f"Date: {entry['date']}\n")
    f.write(f"Time: {entry['time']}\n")
    f.write(f"Category: {entry['category']}\n")
    f.write(f"W&B Run: {entry.get('wandb_run', 'N/A')}\n")
    f.write(f"\nResults:\n{entry.get('results', 'N/A')}\n")
    f.write(f"\nWhat Went Right:\n{entry.get('what_went_right', 'N/A')}\n")
    f.write(f"\nWhat Went Wrong:\n{entry.get('what_went_wrong', 'N/A')}\n")
    f.write(f"\nNext Steps:\n{entry.get('next_steps', 'N/A')}\n")
    else:
    f.write(f"[{entry['timestamp']}] ({entry['category']})\n")
    f.write(f"{entry.get('content', '')}\n")
    f.write("\n---\n\n")

    print(f"Exported journal to {filepath}")

    @@ -132,51 +140,52 @@ def display_entries(entries: List[Dict]) -> None:

    def prompt_experiment_entry() -> Dict[str, str]:
    content = {}
    print("\nEnter experiment details (press Ctrl+D to finish each section):")
    print("\nEnter experiment details:")

    # W&B Run
    wandb_run = input("W&B Run Name: ").strip()
    print("\nW&B Run Name (press Enter when done):")
    wandb_run = input("> ").strip()
    content['wandb_run'] = wandb_run

    # Results
    print("\nResults (Ctrl+D to finish):")
    print("\nResults (press Ctrl+D when done):")
    lines = []
    try:
    while True:
    line = input("> ")
    lines.append(line)
    except EOFError:
    content['results'] = "\n".join(lines)
    content['results'] = "\n".join(lines[:-1]) # Remove the last empty line

    # What Went Right
    print("\nWhat Went Right (Ctrl+D to finish):")
    print("\nWhat Went Right (press Ctrl+D when done):")
    lines = []
    try:
    while True:
    line = input("> ")
    lines.append(line)
    except EOFError:
    content['what_went_right'] = "\n".join(lines)
    content['what_went_right'] = "\n".join(lines[:-1])

    # What Went Wrong
    print("\nWhat Went Wrong (Ctrl+D to finish):")
    print("\nWhat Went Wrong (press Ctrl+D when done):")
    lines = []
    try:
    while True:
    line = input("> ")
    lines.append(line)
    except EOFError:
    content['what_went_wrong'] = "\n".join(lines)
    content['what_went_wrong'] = "\n".join(lines[:-1])

    # Next Steps
    print("\nNext Steps (Ctrl+D to finish):")
    print("\nNext Steps (press Ctrl+D when done):")
    lines = []
    try:
    while True:
    line = input("> ")
    lines.append(line)
    except EOFError:
    content['next_steps'] = "\n".join(lines)
    content['next_steps'] = "\n".join(lines[:-1])

    return content

  6. muellerzr revised this gist May 6, 2025. 1 changed file with 99 additions and 24 deletions.
    123 changes: 99 additions & 24 deletions journal.py
    Original file line number Diff line number Diff line change
    @@ -6,20 +6,28 @@

    """
    Quick Journal is a simple CLI journal that allows you to write, search, and export journal entries.
    Specialized for ML experiment tracking with predefined fields.
    To use:
    python journal.py write -c "personal"
    python journal.py list -c "personal"
    python journal.py search -q "happy" -c "personal"
    python journal.py write -c "experiment"
    python journal.py list -c "experiment"
    python journal.py search -q "good results" -c "experiment"
    python journal.py export -f "txt"
    Note: Press Ctrl+D to save your entry
    """

    class Journal:
    def __init__(self):
    self.journal_dir = os.path.join(os.path.expanduser("~"), ".quick-journal")
    self.ensure_journal_directory()
    self.experiment_fields = [
    "wandb_run",
    "results",
    "what_went_right",
    "what_went_wrong",
    "next_steps"
    ]

    def ensure_journal_directory(self) -> None:
    if not os.path.exists(self.journal_dir):
    @@ -39,21 +47,22 @@ def save_entries(self, filepath: str, entries: List[Dict]) -> None:
    with open(filepath, 'w') as f:
    json.dump(entries, f, indent=2)

    def write_entry(self, content: str, category: str = "general") -> None:
    def write_entry(self, content: Dict[str, str], category: str = "general") -> None:
    filepath = self.get_current_file()
    now = datetime.now()
    date_str = now.strftime("%Y-%m-%d")
    time_str = now.strftime("%H:%M")

    entries = self.load_entries(filepath)
    entries.append({
    entry = {
    "timestamp": f"{date_str} {time_str}",
    "date": date_str,
    "time": time_str,
    "content": content,
    "category": category
    })
    "category": category,
    **content
    }

    entries.append(entry)
    self.save_entries(filepath, entries)
    print(f"\nEntry saved successfully!")
    print(f"Date: {date_str}")
    @@ -109,16 +118,75 @@ def display_entries(entries: List[Dict]) -> None:
    print(f"Time: {entry['time']}")
    print(f"Category: {entry['category']}")
    print("-"*50)
    print(entry['content'])

    if entry['category'] == "experiment":
    print(f"W&B Run: {entry.get('wandb_run', 'N/A')}")
    print(f"\nResults:\n{entry.get('results', 'N/A')}")
    print(f"\nWhat Went Right:\n{entry.get('what_went_right', 'N/A')}")
    print(f"\nWhat Went Wrong:\n{entry.get('what_went_wrong', 'N/A')}")
    print(f"\nNext Steps:\n{entry.get('next_steps', 'N/A')}")
    else:
    print(entry.get('content', ''))

    print("="*50)

    def prompt_experiment_entry() -> Dict[str, str]:
    content = {}
    print("\nEnter experiment details (press Ctrl+D to finish each section):")

    # W&B Run
    wandb_run = input("W&B Run Name: ").strip()
    content['wandb_run'] = wandb_run

    # Results
    print("\nResults (Ctrl+D to finish):")
    lines = []
    try:
    while True:
    line = input("> ")
    lines.append(line)
    except EOFError:
    content['results'] = "\n".join(lines)

    # What Went Right
    print("\nWhat Went Right (Ctrl+D to finish):")
    lines = []
    try:
    while True:
    line = input("> ")
    lines.append(line)
    except EOFError:
    content['what_went_right'] = "\n".join(lines)

    # What Went Wrong
    print("\nWhat Went Wrong (Ctrl+D to finish):")
    lines = []
    try:
    while True:
    line = input("> ")
    lines.append(line)
    except EOFError:
    content['what_went_wrong'] = "\n".join(lines)

    # Next Steps
    print("\nNext Steps (Ctrl+D to finish):")
    lines = []
    try:
    while True:
    line = input("> ")
    lines.append(line)
    except EOFError:
    content['next_steps'] = "\n".join(lines)

    return content

    def main():
    parser = argparse.ArgumentParser(description="Quick Journal - A simple CLI journal")
    subparsers = parser.add_subparsers(dest="command", help="Commands")

    # Write command
    write_parser = subparsers.add_parser("write", help="Write a new journal entry")
    write_parser.add_argument("-c", "--category", default="general", help="Entry category")
    write_parser.add_argument("-c", "--category", default="general", help="Entry category (general or experiment)")

    # List command
    list_parser = subparsers.add_parser("list", help="List journal entries")
    @@ -138,19 +206,26 @@ def main():

    if args.command == "write":
    now = datetime.now()
    print("\nQuick Journal - Enter your thoughts (press Ctrl+D or Ctrl+Z to finish)")
    print(f"Date: {now.strftime('%Y-%m-%d')}")
    print(f"Time: {now.strftime('%H:%M')}")
    print(f"Category: {args.category}")
    print("\nStart writing:")
    content = []
    try:
    while True:
    line = input("> ")
    content.append(line)
    except (EOFError, KeyboardInterrupt):
    if content:
    journal.write_entry("\n".join(content), args.category)
    if args.category == "experiment":
    print("\nQuick Journal - Experiment Entry")
    print(f"Date: {now.strftime('%Y-%m-%d')}")
    print(f"Time: {now.strftime('%H:%M')}")
    content = prompt_experiment_entry()
    journal.write_entry(content, "experiment")
    else:
    print("\nQuick Journal - Enter your thoughts (press Ctrl+D to save)")
    print(f"Date: {now.strftime('%Y-%m-%d')}")
    print(f"Time: {now.strftime('%H:%M')}")
    print(f"Category: {args.category}")
    print("\nStart writing:")
    content_lines = []
    try:
    while True:
    line = input("> ")
    content_lines.append(line)
    except EOFError:
    if content_lines:
    journal.write_entry({"content": "\n".join(content_lines)}, args.category)

    elif args.command == "list":
    entries = journal.search_entries(category=args.category)
  7. muellerzr revised this gist May 6, 2025. 1 changed file with 25 additions and 8 deletions.
    33 changes: 25 additions & 8 deletions journal.py
    Original file line number Diff line number Diff line change
    @@ -41,17 +41,23 @@ def save_entries(self, filepath: str, entries: List[Dict]) -> None:

    def write_entry(self, content: str, category: str = "general") -> None:
    filepath = self.get_current_file()
    timestamp = datetime.now().strftime("%Y-%m-%d %H:%M")
    now = datetime.now()
    date_str = now.strftime("%Y-%m-%d")
    time_str = now.strftime("%H:%M")

    entries = self.load_entries(filepath)
    entries.append({
    "timestamp": timestamp,
    "timestamp": f"{date_str} {time_str}",
    "date": date_str,
    "time": time_str,
    "content": content,
    "category": category
    })

    self.save_entries(filepath, entries)
    print("Entry saved successfully!")
    print(f"\nEntry saved successfully!")
    print(f"Date: {date_str}")
    print(f"Time: {time_str}")

    def get_all_entries(self) -> List[Dict]:
    all_entries = []
    @@ -74,7 +80,8 @@ def search_entries(self, query: Optional[str] = None, category: Optional[str] =

    def export_journal(self, format_type: str = "txt") -> None:
    entries = self.get_all_entries()
    export_filename = f"journal-export-{datetime.now().strftime('%Y-%m-%d')}"
    now = datetime.now()
    export_filename = f"journal-export-{now.strftime('%Y-%m-%d')}"

    if format_type == "json":
    filepath = os.path.join(self.journal_dir, f"{export_filename}.json")
    @@ -83,7 +90,9 @@ def export_journal(self, format_type: str = "txt") -> None:
    filepath = os.path.join(self.journal_dir, f"{export_filename}.txt")
    with open(filepath, 'w') as f:
    for entry in entries:
    f.write(f"[{entry['timestamp']}] ({entry['category']})\n")
    f.write(f"Date: {entry['date']}\n")
    f.write(f"Time: {entry['time']}\n")
    f.write(f"Category: {entry['category']}\n")
    f.write(f"{entry['content']}\n")
    f.write("---\n\n")

    @@ -95,9 +104,13 @@ def display_entries(entries: List[Dict]) -> None:
    return

    for entry in entries:
    print(f"\n[{entry['timestamp']}] ({entry['category']})")
    print("\n" + "="*50)
    print(f"Date: {entry['date']}")
    print(f"Time: {entry['time']}")
    print(f"Category: {entry['category']}")
    print("-"*50)
    print(entry['content'])
    print("---")
    print("="*50)

    def main():
    parser = argparse.ArgumentParser(description="Quick Journal - A simple CLI journal")
    @@ -124,8 +137,12 @@ def main():
    journal = Journal()

    if args.command == "write":
    now = datetime.now()
    print("\nQuick Journal - Enter your thoughts (press Ctrl+D or Ctrl+Z to finish)")
    print(f"Current time: {datetime.now().strftime('%H:%M')}")
    print(f"Date: {now.strftime('%Y-%m-%d')}")
    print(f"Time: {now.strftime('%H:%M')}")
    print(f"Category: {args.category}")
    print("\nStart writing:")
    content = []
    try:
    while True:
  8. muellerzr created this gist May 6, 2025.
    153 changes: 153 additions & 0 deletions journal.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,153 @@
    import json
    import os
    from datetime import datetime
    import argparse
    from typing import Dict, List, Optional

    """
    Quick Journal is a simple CLI journal that allows you to write, search, and export journal entries.
    To use:
    python journal.py write -c "personal"
    python journal.py list -c "personal"
    python journal.py search -q "happy" -c "personal"
    python journal.py export -f "txt"
    """

    class Journal:
    def __init__(self):
    self.journal_dir = os.path.join(os.path.expanduser("~"), ".quick-journal")
    self.ensure_journal_directory()

    def ensure_journal_directory(self) -> None:
    if not os.path.exists(self.journal_dir):
    os.makedirs(self.journal_dir)

    def get_current_file(self) -> str:
    current_month = datetime.now().strftime("%Y-%m")
    return os.path.join(self.journal_dir, f"{current_month}.json")

    def load_entries(self, filepath: str) -> List[Dict]:
    if os.path.exists(filepath):
    with open(filepath, 'r') as f:
    return json.load(f)
    return []

    def save_entries(self, filepath: str, entries: List[Dict]) -> None:
    with open(filepath, 'w') as f:
    json.dump(entries, f, indent=2)

    def write_entry(self, content: str, category: str = "general") -> None:
    filepath = self.get_current_file()
    timestamp = datetime.now().strftime("%Y-%m-%d %H:%M")

    entries = self.load_entries(filepath)
    entries.append({
    "timestamp": timestamp,
    "content": content,
    "category": category
    })

    self.save_entries(filepath, entries)
    print("Entry saved successfully!")

    def get_all_entries(self) -> List[Dict]:
    all_entries = []
    for filename in os.listdir(self.journal_dir):
    if filename.endswith('.json'):
    filepath = os.path.join(self.journal_dir, filename)
    all_entries.extend(self.load_entries(filepath))

    return sorted(all_entries, key=lambda x: x['timestamp'], reverse=True)

    def search_entries(self, query: Optional[str] = None, category: Optional[str] = None) -> List[Dict]:
    entries = self.get_all_entries()

    if query:
    entries = [e for e in entries if query.lower() in e['content'].lower()]
    if category:
    entries = [e for e in entries if e['category'] == category]

    return entries

    def export_journal(self, format_type: str = "txt") -> None:
    entries = self.get_all_entries()
    export_filename = f"journal-export-{datetime.now().strftime('%Y-%m-%d')}"

    if format_type == "json":
    filepath = os.path.join(self.journal_dir, f"{export_filename}.json")
    self.save_entries(filepath, entries)
    else:
    filepath = os.path.join(self.journal_dir, f"{export_filename}.txt")
    with open(filepath, 'w') as f:
    for entry in entries:
    f.write(f"[{entry['timestamp']}] ({entry['category']})\n")
    f.write(f"{entry['content']}\n")
    f.write("---\n\n")

    print(f"Exported journal to {filepath}")

    def display_entries(entries: List[Dict]) -> None:
    if not entries:
    print("No entries found.")
    return

    for entry in entries:
    print(f"\n[{entry['timestamp']}] ({entry['category']})")
    print(entry['content'])
    print("---")

    def main():
    parser = argparse.ArgumentParser(description="Quick Journal - A simple CLI journal")
    subparsers = parser.add_subparsers(dest="command", help="Commands")

    # Write command
    write_parser = subparsers.add_parser("write", help="Write a new journal entry")
    write_parser.add_argument("-c", "--category", default="general", help="Entry category")

    # List command
    list_parser = subparsers.add_parser("list", help="List journal entries")
    list_parser.add_argument("-c", "--category", help="Filter by category")

    # Search command
    search_parser = subparsers.add_parser("search", help="Search journal entries")
    search_parser.add_argument("-q", "--query", help="Search text")
    search_parser.add_argument("-c", "--category", help="Filter by category")

    # Export command
    export_parser = subparsers.add_parser("export", help="Export journal entries")
    export_parser.add_argument("-f", "--format", choices=["txt", "json"], default="txt", help="Export format")

    args = parser.parse_args()
    journal = Journal()

    if args.command == "write":
    print("\nQuick Journal - Enter your thoughts (press Ctrl+D or Ctrl+Z to finish)")
    print(f"Current time: {datetime.now().strftime('%H:%M')}")
    content = []
    try:
    while True:
    line = input("> ")
    content.append(line)
    except (EOFError, KeyboardInterrupt):
    if content:
    journal.write_entry("\n".join(content), args.category)

    elif args.command == "list":
    entries = journal.search_entries(category=args.category)
    display_entries(entries)

    elif args.command == "search":
    entries = journal.search_entries(args.query, args.category)
    display_entries(entries)

    elif args.command == "export":
    journal.export_journal(args.format)

    else:
    parser.print_help()

    if __name__ == "__main__":
    main()