"""
Browse command for CLI.
"""
from typing import Annotated
import typer
from rich.console import Console
from rich.progress import Progress, SpinnerColumn, TextColumn
from ra_mcp_browse.operations import BrowseOperations
from ra_mcp_common.telemetry import get_tracer
from ra_mcp_common.utils.http_client import get_http_client
from .formatting import RichConsoleFormatter
_tracer = get_tracer("ra_mcp.cli.browse")
console = Console()
def _print_renderables(renderables, console: Console) -> None:
for item in renderables:
console.print(item)
def browse(
reference_code: Annotated[str, typer.Argument(help="Document reference code from search results (e.g., 'SE/RA/420422/01')")],
pages: Annotated[
str | None,
typer.Option(help='Page specification: single ("5"), range ("1-10"), or list ("5,7,9"). Alias: --page'),
] = None,
page: Annotated[
str | None,
typer.Option(help='Page specification: single ("5"), range ("1-10"), or list ("5,7,9"). Shorthand for --pages'),
] = None,
search_term: Annotated[str | None, typer.Option("--search-term", help="Highlight keyword in transcribed text (case-insensitive)")] = None,
max_display: Annotated[int, typer.Option("--max-display", help="Maximum number of pages to display in output")] = 20,
log: Annotated[bool, typer.Option("--log", help="Enable detailed API request/response logging to ra_mcp_api.log file")] = False,
show_links: Annotated[
bool,
typer.Option("--show-links", help="Display direct links to ALTO XML, IIIF images, and Bildvisaren viewer"),
] = False,
) -> None:
"""Browse pages by reference code.
You can specify pages using either --pages or --page (they work the same way).
If both are provided, --page takes precedence.
Examples:
ra browse "SE/RA/123" --page 5
ra browse "SE/RA/123" --pages "1-10"
ra browse "SE/RA/123" --page "5,7,9"
ra browse "SE/RA/123" --page 1 --log # With API logging
"""
http_client = get_http_client(log)
browse_operations = BrowseOperations(http_client=http_client)
formatter = RichConsoleFormatter(console)
console.print(f"\n[bold cyan]📖 Browsing document: {reference_code}[/bold cyan]\n")
if log:
console.print("[dim]API logging enabled - check ra_mcp_api.log[/dim]")
requested_pages = page if page is not None else pages
with _tracer.start_as_current_span(
"cli.browse",
attributes={
"browse.reference_code": reference_code,
"browse.pages": requested_pages or "1-20",
},
):
try:
with Progress(
SpinnerColumn(),
TextColumn("[progress.description]{task.description}"),
console=console,
) as progress:
progress.add_task("Loading document...", total=None)
browse_result = browse_operations.browse_document(
reference_code=reference_code,
pages=requested_pages or "1-20",
highlight_term=search_term,
max_pages=max_display,
)
if not browse_result.contexts and not browse_result.oai_metadata:
console.print(f"[yellow]No pages found for '{reference_code}'[/yellow]")
console.print("\n[dim]Suggestions:[/dim]")
console.print("[dim]- Check the reference code format[/dim]")
console.print("[dim]- Verify the document has transcribed pages[/dim]")
console.print("[dim]- Try different page numbers[/dim]")
raise typer.Exit(code=1)
has_pages = bool(browse_result.contexts)
renderables = formatter.format_browse_results(
browse_result,
highlight_term=search_term,
show_links=show_links,
show_success_message=has_pages,
)
_print_renderables(renderables, console)
except typer.Exit:
raise
except Exception as error:
console.print(f"[red]Browse failed: {error}[/red]")
raise typer.Exit(code=1) from error