#!/usr/bin/env python3 """ DReader E-Book Reader - Main Entry Point This script launches the DReader application with a Pygame-based desktop HAL for testing and development. Usage: python run_dreader.py [library_path] python run_dreader.py ~/Books python run_dreader.py tests/data/library-epub Options: --width WIDTH Window width (default: 800) --height HEIGHT Window height (default: 1200) --fullscreen Run in fullscreen mode --log-level LEVEL Logging level: DEBUG, INFO, WARNING, ERROR (default: INFO) Examples: # Run with default library path python run_dreader.py # Run with custom library python run_dreader.py ~/Documents/Books # Run in fullscreen python run_dreader.py --fullscreen # Run with debug logging python run_dreader.py --log-level DEBUG """ import sys import asyncio import argparse import logging from pathlib import Path # Add parent directory to path sys.path.insert(0, str(Path(__file__).parent)) from dreader.main import DReaderApplication, AppConfig from dreader.hal_pygame import PygameDisplayHAL def parse_args(): """Parse command line arguments.""" parser = argparse.ArgumentParser( description="DReader E-Book Reader Application", formatter_class=argparse.RawDescriptionHelpFormatter, epilog=""" Examples: %(prog)s # Use default library path %(prog)s ~/Books # Custom library path %(prog)s --width 1200 --height 1600 # Custom window size %(prog)s --fullscreen # Fullscreen mode %(prog)s --log-level DEBUG # Debug logging """ ) parser.add_argument( 'library_path', nargs='?', default=None, help='Path to directory containing EPUB files (default: tests/data/library-epub)' ) parser.add_argument( '--width', type=int, default=800, help='Window width in pixels (default: 800)' ) parser.add_argument( '--height', type=int, default=1200, help='Window height in pixels (default: 1200)' ) parser.add_argument( '--fullscreen', action='store_true', help='Run in fullscreen mode' ) parser.add_argument( '--library', action='store_true', help='Always start in library mode (ignore saved state)' ) parser.add_argument( '--log-level', choices=['DEBUG', 'INFO', 'WARNING', 'ERROR'], default='INFO', help='Logging level (default: INFO)' ) return parser.parse_args() def main(): """Main entry point.""" args = parse_args() # Set up logging log_level = getattr(logging, args.log_level) logging.basicConfig( level=log_level, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' ) logger = logging.getLogger(__name__) logger.info("Starting DReader E-Book Reader") # Determine library path if args.library_path: library_path = Path(args.library_path).expanduser().resolve() else: # Default to test library library_path = Path(__file__).parent / "tests" / "data" / "library-epub" # Verify library path exists if not library_path.exists(): logger.error(f"Library path does not exist: {library_path}") print(f"\nError: Library directory not found: {library_path}") print("\nPlease provide a valid path to a directory containing EPUB files.") print("Example:") print(f" python {sys.argv[0]} ~/Documents/Books") sys.exit(1) if not library_path.is_dir(): logger.error(f"Library path is not a directory: {library_path}") print(f"\nError: Not a directory: {library_path}") sys.exit(1) logger.info(f"Library path: {library_path}") logger.info(f"Window size: {args.width}x{args.height}") logger.info(f"Fullscreen: {args.fullscreen}") logger.info(f"Force library mode: {args.library}") # Create HAL try: hal = PygameDisplayHAL( width=args.width, height=args.height, fullscreen=args.fullscreen ) except RuntimeError as e: logger.error(f"Failed to initialize Pygame HAL: {e}") print(f"\nError: {e}") print("\nTo install Pygame, run:") print(" pip install pygame") sys.exit(1) # Create application config config = AppConfig( display_hal=hal, library_path=str(library_path), page_size=(args.width, args.height), force_library_mode=args.library, log_level=log_level ) # Create application app = DReaderApplication(config) # Run event loop try: logger.info("Starting event loop") asyncio.run(hal.run_event_loop(app)) logger.info("Application exited normally") except KeyboardInterrupt: logger.info("Interrupted by user") print("\nShutting down...") except Exception as e: logger.error(f"Application error: {e}", exc_info=True) print(f"\nError: {e}") print("\nFor more details, run with --log-level DEBUG") sys.exit(1) if __name__ == "__main__": main()