Implement rp CLI: rich-print markdown, JSON, code, and more
- Add typer CLI with auto file-type detection by extension - Support markdown (rich.Markdown), JSON (rich.JSON), and 30+ code languages via Pygments syntax highlighting - Features: line numbers toggle, pager support, stdin input, configurable color themes - Project metadata: MIT license, author, classifiers, entry point
This commit is contained in:
119
src/rp/cli.py
Normal file
119
src/rp/cli.py
Normal file
@@ -0,0 +1,119 @@
|
||||
"""CLI entry point for rp — rich print files beautifully."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Annotated, Optional
|
||||
|
||||
import typer
|
||||
from rich.console import Console
|
||||
|
||||
from rp import __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",
|
||||
)
|
||||
|
||||
_THEMES = [
|
||||
"monokai",
|
||||
"github-dark",
|
||||
"one-dark",
|
||||
"vim",
|
||||
"vs",
|
||||
"nord",
|
||||
"dracula",
|
||||
"solarized-dark",
|
||||
"solarized-light",
|
||||
"default",
|
||||
"friendly",
|
||||
"native",
|
||||
"emacs",
|
||||
]
|
||||
|
||||
|
||||
def version_callback(value: bool) -> None:
|
||||
if value:
|
||||
console = Console()
|
||||
console.print(f"rp {__version__}")
|
||||
raise typer.Exit()
|
||||
|
||||
|
||||
@app.command()
|
||||
def main(
|
||||
file: Annotated[
|
||||
Optional[Path],
|
||||
typer.Argument(help="File to rich-print. Use '-' or omit to read from stdin."),
|
||||
] = None,
|
||||
type: Annotated[
|
||||
Optional[str],
|
||||
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[
|
||||
Optional[bool],
|
||||
typer.Option(
|
||||
"--line-numbers/--no-line-numbers",
|
||||
help="Show line numbers. Default: auto.",
|
||||
),
|
||||
] = None,
|
||||
pager: Annotated[
|
||||
Optional[bool],
|
||||
typer.Option(
|
||||
"--pager/--no-pager",
|
||||
help="Use pager for output. Default: auto-detect.",
|
||||
),
|
||||
] = None,
|
||||
version: Annotated[
|
||||
Optional[bool],
|
||||
typer.Option(
|
||||
"--version",
|
||||
"-v",
|
||||
help="Show version.",
|
||||
callback=version_callback,
|
||||
is_eager=True,
|
||||
),
|
||||
] = None,
|
||||
) -> None:
|
||||
"""Rich print files beautifully in your terminal."""
|
||||
console = Console()
|
||||
|
||||
if file is None or str(file) == "-":
|
||||
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)
|
||||
content = file.read_text(encoding="utf-8")
|
||||
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=type)
|
||||
|
||||
options = RenderOptions(
|
||||
theme=theme,
|
||||
line_numbers=line_numbers,
|
||||
pager=pager,
|
||||
)
|
||||
render(content, file_type, console, options)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app()
|
||||
Reference in New Issue
Block a user