Created
September 19, 2025 17:25
-
-
Save Vaibhavs10/4467cd28e53d0c0f0bbdc85d9ae59b50 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| """ | |
| Simple journaling CLI tool. | |
| Features: | |
| - Add a journal entry for today (or a specific date). | |
| - View entry for a given date (default: today). | |
| - List all dates with entries. | |
| Entries are stored in a JSON file at ``~/.journal.json``. | |
| """ | |
| import argparse | |
| import json | |
| import os | |
| import sys | |
| from datetime import datetime | |
| from pathlib import Path | |
| from rich.console import Console | |
| from rich.table import Table | |
| from rich.panel import Panel | |
| from rich.prompt import Prompt | |
| from rich.theme import Theme | |
| from rich.markdown import Markdown | |
| JOURNAL_PATH = Path.home() / ".journal.json" | |
| # Define a zen theme | |
| zen_theme = Theme({ | |
| "info": "dim cyan", | |
| "warning": "magenta", | |
| "danger": "bold red", | |
| "success": "bold green", | |
| "header": "bold bright_blue", | |
| }) | |
| console = Console(theme=zen_theme) | |
| def load_journal(): | |
| if JOURNAL_PATH.exists(): | |
| with open(JOURNAL_PATH, "r", encoding="utf-8") as f: | |
| try: | |
| return json.load(f) | |
| except json.JSONDecodeError: | |
| return {} | |
| return {} | |
| def save_journal(data): | |
| with open(JOURNAL_PATH, "w", encoding="utf-8") as f: | |
| json.dump(data, f, ensure_ascii=False, indent=2) | |
| def add_entry(args): | |
| journal = load_journal() | |
| date_str = args.date or datetime.now().strftime("%Y-%m-%d") | |
| entry_text = args.text | |
| if not entry_text: | |
| # Use a daily template with three reflective questions | |
| console.print("[bold cyan]Please answer the following prompts (press Enter after each line).[/]") | |
| did = Prompt.ask("[green]What did you do today?[/]") | |
| better = Prompt.ask("[green]What could be better?[/]") | |
| wrong = Prompt.ask("[green]What went wrong?[/]") | |
| entry_text = f"## What did I do today?\n{did}\n\n## What could be better?\n{better}\n\n## What went wrong?\n{wrong}" | |
| timestamp = datetime.now().isoformat(timespec="seconds") | |
| journal[date_str] = {"timestamp": timestamp, "text": entry_text} | |
| save_journal(journal) | |
| console.print(f"[bright_green]Entry saved for {date_str}.[/]") | |
| def view_entry(args): | |
| journal = load_journal() | |
| date_str = args.date or datetime.now().strftime("%Y-%m-%d") | |
| entry = journal.get(date_str) | |
| if entry: | |
| md = Markdown(entry["text"], style="info") | |
| console.print(f"[header]{date_str}[/header]") | |
| console.print(md) | |
| console.print(f"[dim]Recorded at: {entry['timestamp']}[/]") | |
| else: | |
| console.print(f"[danger]No entry found for {date_str}.[/]") | |
| def list_entries(_): | |
| journal = load_journal() | |
| if not journal: | |
| console.print("[yellow]No journal entries found.[/]") | |
| return | |
| table = Table(title="Journal entries") | |
| table.add_column("Date", style="cyan", no_wrap=True) | |
| table.add_column("Timestamp", style="magenta") | |
| for d in sorted(journal.keys()): | |
| ts = journal[d]["timestamp"] | |
| table.add_row(d, ts) | |
| console.print(table) | |
| def print_banner(): | |
| banner = r""" | |
| ____ _ _ _ _ | |
| | _ \ __ _(_) |_ _ | | ___ _ _ _ __ _ __ | | | |
| | | | |/ _` | | | | | | |/ _ \| | | | '__| '_ \ | | | |
| | |_| | (_| | | | |_| | | (_) | |_| | | | | | ||_| | |
| |____/ \__,_|_|_|\__, |_|\___/ \__,_|_| |_| |_|(_) | |
| |___/ | |
| """ | |
| console.print(banner, style="header") | |
| def main(): | |
| print_banner() | |
| parser = argparse.ArgumentParser(description="Simple journaling CLI") | |
| subparsers = parser.add_subparsers(dest="command", required=True) | |
| # add command | |
| parser_add = subparsers.add_parser("add", help="Add a journal entry") | |
| parser_add.add_argument("-t", "--text", type=str, help="Entry text (if omitted, read from stdin)") | |
| parser_add.add_argument("-d", "--date", type=str, help="Date for the entry (YYYY-MM-DD), default today") | |
| parser_add.set_defaults(func=add_entry) | |
| # view command | |
| parser_view = subparsers.add_parser("view", help="View an entry for a date") | |
| parser_view.add_argument("-d", "--date", type=str, help="Date to view (YYYY-MM-DD), default today") | |
| parser_view.set_defaults(func=view_entry) | |
| # list command | |
| parser_list = subparsers.add_parser("list", help="List all entry dates") | |
| parser_list.set_defaults(func=list_entries) | |
| args = parser.parse_args() | |
| args.func(args) | |
| if __name__ == "__main__": | |
| main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment