pynotes-cli 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,8 @@
1
+ Metadata-Version: 2.4
2
+ Name: pynotes-cli
3
+ Version: 0.1.0
4
+ Summary: A terminal Markdown personal journal and notes tool.
5
+ Requires-Python: >=3.9
6
+ Requires-Dist: typer>=0.9.0
7
+ Requires-Dist: rich>=13.0.0
8
+ Requires-Dist: questionary>=2.0.0
@@ -0,0 +1,84 @@
1
+ # Pynotes
2
+
3
+ Pynotes is a lightning-fast terminal-based Markdown personal journal and notes tool. It allows you to seamlessly create, read, list, and filter your notes directly from the command line, while storing everything locally in a lightweight SQLite database.
4
+
5
+ ## What it Does
6
+
7
+ - **Create & Edit**: Interactively create notes with titles, tags, and Markdown content. Edit existing notes smoothly.
8
+ - **List & Filter**: View all your notes in a beautifully formatted table or filter them down by specific tags.
9
+ - **View Notes**: Render your notes with full Markdown syntax highlighting right in your terminal.
10
+ - **Local Storage**: Keeps all your data secure and accessible on your local machine (`~/.pynotes.db`).
11
+
12
+ ## Project Structure
13
+
14
+ ```text
15
+ pynotes/
16
+ ├── pyproject.toml # Project metadata and dependencies configuration
17
+ ├── README.md # Project documentation and instructions
18
+ └── pynotes/ # Main application package
19
+ ├── __init__.py # Marks the directory as a Python package
20
+ ├── main.py # Entry point defining the CLI commands using Typer
21
+ ├── db.py # Handles SQLite database connection and queries
22
+ ├── ui.py # Manages terminal output rendering using Rich
23
+ └── prompts.py # Handles interactive user inputs using Questionary
24
+ ```
25
+
26
+ ## Tech Stack
27
+
28
+ - **[Python 3.10+](https://www.python.org/)**
29
+ - **[Typer](https://typer.tiangolo.com/)**: For building the powerful command-line interface.
30
+ - **[Rich](https://rich.readthedocs.io/)**: For beautiful terminal formatting, tables, and Markdown rendering.
31
+ - **[Questionary](https://questionary.readthedocs.io/)**: For interactive and user-friendly CLI prompts.
32
+ - **[SQLite3](https://docs.python.org/3/library/sqlite3.html)**: For local database storage (built-in).
33
+
34
+ ## Instructions to Run
35
+
36
+ ### 1. Installation
37
+
38
+ It is recommended to install `pynotes` in editable mode so that you can easily access the CLI from anywhere in your terminal.
39
+
40
+ ```bash
41
+ # Clone the repository and navigate to the directory
42
+ cd path/to/pynotes
43
+
44
+ # Install the package and its dependencies
45
+ pip install -e .
46
+ ```
47
+
48
+ ### 2. Usage
49
+
50
+ Once installed, the `pynotes` command will be globally available in your terminal environment.
51
+
52
+ **Initialize the Database:**
53
+ Initialize your local database at `~/.pynotes.db`.
54
+ ```bash
55
+ pynotes init
56
+ ```
57
+
58
+ **Create a New Note:**
59
+ ```bash
60
+ pynotes new
61
+ ```
62
+ Follow the interactive prompts to add your title, tags, and Markdown content. Press `Alt+Enter` (or `Esc` then `Enter` on Mac) to save the content.
63
+
64
+ **List All Notes:**
65
+ ```bash
66
+ pynotes list
67
+ ```
68
+
69
+ **Filter Notes by Tag:**
70
+ ```bash
71
+ pynotes list --tag <your-tag>
72
+ ```
73
+
74
+ **View a Specific Note:**
75
+ View the full rendered Markdown of a note by providing its ID.
76
+ ```bash
77
+ pynotes view <note_id>
78
+ ```
79
+
80
+ **Edit a Note:**
81
+ Edit the title, tags, or content of an existing note.
82
+ ```bash
83
+ pynotes edit <note_id>
84
+ ```
File without changes
@@ -0,0 +1,50 @@
1
+ import sqlite3
2
+ from pathlib import Path
3
+
4
+ DB_PATH = Path.home() / ".pynotes.db"
5
+
6
+ def get_connection():
7
+ return sqlite3.connect(DB_PATH)
8
+
9
+ def init_db():
10
+ with get_connection() as conn:
11
+ conn.execute("""
12
+ CREATE TABLE IF NOT EXISTS notes (
13
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
14
+ title TEXT NOT NULL,
15
+ tags TEXT NOT NULL,
16
+ content TEXT NOT NULL,
17
+ created_at DATE DEFAULT CURRENT_DATE
18
+ )
19
+ """)
20
+
21
+ def add_note(title: str, tags: str, content: str):
22
+ with get_connection() as conn:
23
+ conn.execute(
24
+ "INSERT INTO notes (title, tags, content) VALUES (?, ?, ?)",
25
+ (title, tags, content)
26
+ )
27
+
28
+ def get_notes(tag: str = None):
29
+ with get_connection() as conn:
30
+ if tag:
31
+ # Simple wildcard search for tags
32
+ return conn.execute(
33
+ "SELECT id, title, tags, created_at FROM notes WHERE tags LIKE ?",
34
+ (f"%{tag}%",)
35
+ ).fetchall()
36
+ return conn.execute("SELECT id, title, tags, created_at FROM notes").fetchall()
37
+
38
+ def get_note(note_id: int):
39
+ with get_connection() as conn:
40
+ return conn.execute(
41
+ "SELECT title, tags, content FROM notes WHERE id = ?",
42
+ (note_id,)
43
+ ).fetchone()
44
+
45
+ def update_note(note_id: int, title: str, tags: str, content: str):
46
+ with get_connection() as conn:
47
+ conn.execute(
48
+ "UPDATE notes SET title = ?, tags = ?, content = ? WHERE id = ?",
49
+ (title, tags, content, note_id)
50
+ )
@@ -0,0 +1,57 @@
1
+ import typer
2
+ from pynotes import db, ui, prompts
3
+
4
+ app = typer.Typer(help="A lightning-fast terminal Markdown journal.")
5
+
6
+ @app.callback()
7
+ def main_callback():
8
+ db.init_db()
9
+
10
+ @app.command()
11
+ def init():
12
+ ui.display_success("Knowledge base initialized at ~/.pynotes.db")
13
+
14
+ @app.command()
15
+ def new():
16
+ note_data = prompts.prompt_new_note()
17
+
18
+ if note_data and note_data["title"]:
19
+ db.add_note(note_data["title"], note_data["tags"], note_data["content"])
20
+ ui.display_success("Note saved successfully!")
21
+ else:
22
+ ui.display_error("Note creation cancelled.")
23
+
24
+ @app.command(name="list")
25
+ def list_notes(tag: str = typer.Option(None, help="Filter notes by tag")):
26
+ #list notes ( and filter tag)
27
+ notes = db.get_notes(tag)
28
+ ui.display_notes_table(notes)
29
+
30
+ @app.command()
31
+ def view(note_id: int):
32
+ note = db.get_note(note_id)
33
+
34
+ #view note w/ id
35
+ if note:
36
+ ui.display_note(title=note[0], content=note[2])
37
+ else:
38
+ ui.display_error(f"Note with ID {note_id} not found.")
39
+
40
+ @app.command()
41
+ def edit(note_id: int):
42
+ note = db.get_note(note_id)
43
+ if not note:
44
+ ui.display_error(f"Note with ID {note_id} not found.")
45
+ return
46
+
47
+ ui.display_success(f"Editing note: {note[0]}")
48
+ note_data = prompts.prompt_edit_note(existing_title=note[0], existing_tags=note[1], existing_content=note[2])
49
+
50
+ if note_data and note_data["title"]:
51
+ db.update_note(note_id, note_data["title"], note_data["tags"], note_data["content"])
52
+ ui.display_success("Note updated successfully!")
53
+ else:
54
+ ui.display_error("Note edit cancelled.")
55
+
56
+ if __name__ == "__main__":
57
+ app()
@@ -0,0 +1,59 @@
1
+ import questionary
2
+
3
+ def prompt_new_note():
4
+ title = questionary.text("Enter note title:").ask()
5
+ if not title:
6
+ return None
7
+
8
+ tags = questionary.text("Enter tags (comma separated):").ask()
9
+
10
+ # multiline=True allows hitting Enter for new lines.
11
+ # The user presses Alt+Enter (or Esc then Enter on Mac) to submit.
12
+ content = questionary.text(
13
+ "Content (Markdown supported - Press Alt+Enter to save):",
14
+ multiline=True
15
+ ).ask()
16
+
17
+ return {
18
+ "title": title,
19
+ "tags": tags,
20
+ "content": content
21
+ }
22
+
23
+ def prompt_edit_note(existing_title: str, existing_tags: str, existing_content: str):
24
+ title = questionary.text("Edit note title:", default=existing_title).ask()
25
+ if not title:
26
+ return None
27
+
28
+ tags = questionary.text("Edit tags (comma separated):", default=existing_tags).ask()
29
+
30
+ content = questionary.text(
31
+ "Edit Content (Markdown supported - Press Alt+Enter to save):",
32
+ default=existing_content,
33
+ multiline=True
34
+ ).ask()
35
+
36
+ return {
37
+ "title": title,
38
+ "tags": tags,
39
+ "content": content
40
+ }
41
+
42
+ def prompt_edit_note(existing_title: str, existing_tags: str, existing_content: str):
43
+ title = questionary.text("Edit note title:", default=existing_title).ask()
44
+ if not title:
45
+ return None
46
+
47
+ tags = questionary.text("Edit tags (comma separated):", default=existing_tags).ask()
48
+
49
+ content = questionary.text(
50
+ "Edit Content (Markdown supported - Press Alt+Enter to save):",
51
+ default=existing_content,
52
+ multiline=True
53
+ ).ask()
54
+
55
+ return {
56
+ "title": title,
57
+ "tags": tags,
58
+ "content": content
59
+ }
@@ -0,0 +1,35 @@
1
+ from rich.console import Console
2
+ from rich.table import Table
3
+ from rich.markdown import Markdown
4
+ from rich import box
5
+
6
+ console = Console()
7
+
8
+ def display_notes_table(notes):
9
+ if not notes:
10
+ console.print("[yellow]No notes found.[/yellow]")
11
+ return
12
+
13
+ table = Table(title="Pynotes", box=box.SIMPLE)
14
+ table.add_column("ID", justify="right", style="cyan", no_wrap=True)
15
+ table.add_column("Title", style="magenta")
16
+ table.add_column("Tags", style="green")
17
+ table.add_column("Date", style="dim")
18
+
19
+ for note in notes:
20
+ table.add_row(str(note[0]), note[1], note[2], note[3])
21
+
22
+ console.print(table)
23
+
24
+ def display_note(title: str, content: str):
25
+ console.print(f"\n[magenta]# {title}[/magenta]")
26
+ console.print("-" * 50)
27
+ # Renders the text as actual markdown (bolding, code blocks, etc.)
28
+ console.print(Markdown(content))
29
+ console.print("\n")
30
+
31
+ def display_success(message: str):
32
+ console.print(f"[green]✔ {message}[/green]")
33
+
34
+ def display_error(message: str):
35
+ console.print(f"[red]✖ {message}[/red]")
@@ -0,0 +1,8 @@
1
+ Metadata-Version: 2.4
2
+ Name: pynotes-cli
3
+ Version: 0.1.0
4
+ Summary: A terminal Markdown personal journal and notes tool.
5
+ Requires-Python: >=3.9
6
+ Requires-Dist: typer>=0.9.0
7
+ Requires-Dist: rich>=13.0.0
8
+ Requires-Dist: questionary>=2.0.0
@@ -0,0 +1,13 @@
1
+ README.md
2
+ pyproject.toml
3
+ pynotes/__init__.py
4
+ pynotes/db.py
5
+ pynotes/main.py
6
+ pynotes/prompts.py
7
+ pynotes/ui.py
8
+ pynotes_cli.egg-info/PKG-INFO
9
+ pynotes_cli.egg-info/SOURCES.txt
10
+ pynotes_cli.egg-info/dependency_links.txt
11
+ pynotes_cli.egg-info/entry_points.txt
12
+ pynotes_cli.egg-info/requires.txt
13
+ pynotes_cli.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ pynotes = pynotes.main:app
@@ -0,0 +1,3 @@
1
+ typer>=0.9.0
2
+ rich>=13.0.0
3
+ questionary>=2.0.0
@@ -0,0 +1 @@
1
+ pynotes
@@ -0,0 +1,17 @@
1
+ [project]
2
+ name = "pynotes-cli"
3
+ version = "0.1.0"
4
+ description = "A terminal Markdown personal journal and notes tool."
5
+ requires-python = ">=3.9"
6
+ dependencies = [
7
+ "typer>=0.9.0",
8
+ "rich>=13.0.0",
9
+ "questionary>=2.0.0"
10
+ ]
11
+
12
+ [project.scripts]
13
+ pynotes = "pynotes.main:app"
14
+
15
+ [build-system]
16
+ requires = ["setuptools>=61.0"]
17
+ build-backend = "setuptools.build_meta"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+