From 32a8a1d4ad575df569acc2f4d7f840de8e538b44 Mon Sep 17 00:00:00 2001 From: Yunxiao Xu Date: Wed, 1 Apr 2026 21:06:34 -0700 Subject: [PATCH] Improve documentation and modernize type hints --- AGENTS.md | 11 ++++++----- src/rp/__init__.py | 4 +++- src/rp/cli.py | 30 ++++++++++++++++++++++-------- src/rp/detect.py | 17 +++++++++++++++++ src/rp/pager.py | 13 +++++++++++++ src/rp/render.py | 23 +++++++++++++++++++++-- 6 files changed, 82 insertions(+), 16 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 7723979..0e127d6 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -162,11 +162,12 @@ rich-viewer/ ├── AGENTS.md # This file └── src/ └── rp/ - ├── __init__.py # Version metadata - ├── cli.py # Typer CLI entry point - ├── detect.py # File type detection - ├── render.py # Rendering logic - └── py.typed # PEP 561 marker + ├── __init__.py # Version metadata + ├── cli.py # Typer CLI entry point + ├── detect.py # File type detection + ├── render.py # Rendering logic + ├── pager.py # Pager integration + └── py.typed # PEP 561 marker ``` ## Dependencies diff --git a/src/rp/__init__.py b/src/rp/__init__.py index f18f86c..06b6c7c 100644 --- a/src/rp/__init__.py +++ b/src/rp/__init__.py @@ -1,4 +1,6 @@ -"""rp — Rich print files beautifully in your terminal.""" +"""Project metadata for rp.""" + +from __future__ import annotations __version__ = "0.2.0" __author__ = "Yunxiao Xu" diff --git a/src/rp/cli.py b/src/rp/cli.py index 3a8d24f..c29b593 100644 --- a/src/rp/cli.py +++ b/src/rp/cli.py @@ -1,10 +1,10 @@ -"""CLI entry point for rp — rich print files beautifully.""" +"""CLI entry point for rp.""" from __future__ import annotations import sys from pathlib import Path -from typing import Annotated, Optional +from typing import Annotated import typer from rich.console import Console @@ -22,6 +22,11 @@ app = typer.Typer( def version_callback(value: bool) -> None: + """Print version information and exit. + + Args: + value: Flag value from typer callback. + """ if value: console = Console() console.print(f"Rich Print (rp) {__version__}") @@ -33,11 +38,11 @@ def version_callback(value: bool) -> None: @app.command() def main( file: Annotated[ - Optional[Path], + Path | None, typer.Argument(help="File to rich-print. Use '-' or omit to read from stdin."), ] = None, file_type: Annotated[ - Optional[str], + str | None, typer.Option( "--type", "-t", help="Force file type (e.g. json, python, markdown)." ), @@ -47,21 +52,21 @@ def main( typer.Option("--theme", help="Pygments color theme."), ] = "monokai", line_numbers: Annotated[ - Optional[bool], + bool | None, typer.Option( "--line-numbers/--no-line-numbers", help="Show line numbers. Default: auto.", ), ] = None, pager: Annotated[ - Optional[bool], + bool | None, typer.Option( "--pager/--no-pager", help="Use pager for output. Default: auto-detect.", ), ] = None, version: Annotated[ - Optional[bool], + bool | None, typer.Option( "--version", "-v", @@ -71,7 +76,16 @@ def main( ), ] = None, ) -> None: - """Rich print files beautifully in your terminal.""" + """Render a file or stdin input in the terminal. + + Args: + file: File to rich-print. Use '-' or omit to read from stdin. + file_type: Force file type (e.g. json, python, markdown). + theme: Pygments color theme. + line_numbers: Show line numbers. Default: auto. + pager: Use pager for output. Default: auto-detect. + version: Show version and exit. + """ console = Console() if file is None or str(file) == "-": diff --git a/src/rp/detect.py b/src/rp/detect.py index ca5e811..e439c16 100644 --- a/src/rp/detect.py +++ b/src/rp/detect.py @@ -60,6 +60,23 @@ def detect_type( content: str | None = None, explicit_type: str | None = None, ) -> str: + """Detect the file type for syntax highlighting. + + Detection priority: + 1. Explicit type if provided + 2. Filename-based mapping (for example, Dockerfile) + 3. Extension-based mapping + 4. JSON if content starts with '{' or '[' and parses successfully + 5. Fallback to 'text' + + Args: + path: File path for filename and extension detection. + content: File content for JSON detection. + explicit_type: Override auto-detection with explicit type. + + Returns: + Pygments lexer name for the detected file type. + """ if explicit_type is not None: return explicit_type diff --git a/src/rp/pager.py b/src/rp/pager.py index 3cd1142..f2aa2b1 100644 --- a/src/rp/pager.py +++ b/src/rp/pager.py @@ -9,6 +9,11 @@ from rich.pager import Pager, SystemPager def _is_mouse_capable_less() -> bool: + """Check whether the system has a usable ``less`` executable. + + Returns: + True if ``less`` is installed and responds to ``--version``. + """ less = shutil.which("less") if less is None: return False @@ -26,6 +31,14 @@ class MousePager(Pager): """Pager that prefers ``less --mouse`` and falls back to the system pager.""" def show(self, content: str) -> None: + """Display content with mouse-scroll support when available. + + Uses ``less --mouse`` when available; otherwise falls back to the system + pager. + + Args: + content: Content to display in pager. + """ if _is_mouse_capable_less(): try: subprocess.run( diff --git a/src/rp/render.py b/src/rp/render.py index d2e3037..a910f2e 100644 --- a/src/rp/render.py +++ b/src/rp/render.py @@ -14,18 +14,37 @@ from rp.pager import MousePager @dataclass class RenderOptions: + """Rendering options for file display. + + Attributes: + theme: Pygments color theme name. + line_numbers: Show line numbers. ``None`` enables them for code only. + pager: Use pager for output. ``None`` auto-detects terminal output. + """ + theme: str = "monokai" line_numbers: bool | None = None pager: bool | None = None -_MARKDOWN_TYPES = {"markdown", "md"} -_JSON_TYPES = {"json"} +_MARKDOWN_TYPES: set[str] = {"markdown", "md"} +_JSON_TYPES: set[str] = {"json"} def render( content: str, file_type: str, console: Console, options: RenderOptions ) -> None: + """Render content to the console with syntax highlighting. + + Renders Markdown with Rich Markdown, JSON with Rich JSON with a Syntax + fallback, and all other types with Pygments Syntax highlighting. + + Args: + content: File content to render. + file_type: Pygments lexer name. + console: Rich console to render to. + options: Rendering options (theme, line numbers, pager). + """ line_numbers = options.line_numbers if line_numbers is None: line_numbers = file_type not in _MARKDOWN_TYPES and file_type not in _JSON_TYPES