"""CLI entry point for rp.""" from __future__ import annotations import sys from pathlib import Path from typing import Annotated import typer from rich.console import Console from rp import __author__, __license__, __version__ from rp.detect import detect_type from rp.render import RenderOptions, render app = typer.Typer( name="rp", help="Rich print files — markdown, JSON, code, and more — beautifully in your terminal.", no_args_is_help=False, rich_markup_mode="rich", ) 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__}") console.print(f"Copyright (c) 2026 {__author__}") console.print(f"License: {__license__}") raise typer.Exit() @app.command() def main( file: Annotated[ Path | None, typer.Argument(help="File to rich-print. Use '-' or omit to read from stdin."), ] = None, file_type: Annotated[ str | None, typer.Option( "--type", "-t", help="Force file type (e.g. json, python, markdown)." ), ] = None, theme: Annotated[ str, typer.Option("--theme", help="Pygments color theme."), ] = "monokai", line_numbers: Annotated[ bool | None, typer.Option( "--line-numbers/--no-line-numbers", help="Show line numbers. Default: auto.", ), ] = None, pager: Annotated[ bool | None, typer.Option( "--pager/--no-pager", help="Use pager for output. Default: auto-detect.", ), ] = None, guess_content: Annotated[ bool, typer.Option( "--guess-content/--no-guess-content", help="Use heuristic content-based type detection as a fallback.", ), ] = False, version: Annotated[ bool | None, typer.Option( "--version", "-v", help="Show version.", callback=version_callback, is_eager=True, ), ] = None, ) -> None: """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. guess_content: Use heuristic content-based type detection as a fallback. version: Show version and exit. """ console = Console() if file is None or str(file) == "-": if sys.stdin.isatty(): console.print("[dim]Reading from stdin. Press Ctrl+D to end.[/dim]") content = sys.stdin.read() file_path = None else: if not file.exists(): console.print(f"[red]Error:[/red] File not found: {file}") raise typer.Exit(code=1) if file.is_dir(): console.print(f"[red]Error:[/red] Is a directory: {file}") raise typer.Exit(code=1) try: content = file.read_text(encoding="utf-8") except UnicodeDecodeError: console.print(f"[red]Error:[/red] Cannot read binary file: {file}") raise typer.Exit(code=1) except (PermissionError, OSError) as e: console.print(f"[red]Error:[/red] {e}") raise typer.Exit(code=1) file_path = str(file) if not content: console.print("[dim]Empty input, nothing to display.[/dim]") raise typer.Exit() file_type = detect_type( path=file_path, content=content, explicit_type=file_type, guess_content=guess_content, ) options = RenderOptions( theme=theme, line_numbers=line_numbers, pager=pager, ) render(content, file_type, console, options) if __name__ == "__main__": app()