#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# File: src/scitex_writer/_utils/_watch.py
"""
Watch mode for auto-recompilation.
Monitors file changes and triggers automatic recompilation.
"""
from __future__ import annotations
import subprocess
from logging import getLogger
from pathlib import Path
from typing import Callable, Optional
logger = getLogger(__name__)
def watch_manuscript(
project_dir: Path,
interval: int = 2,
on_compile: Optional[Callable] = None,
timeout: Optional[int] = None,
) -> None:
"""
Watch and auto-recompile manuscript on file changes.
Args:
project_dir: Path to writer project directory
interval: Check interval in seconds
on_compile: Callback function called after each compilation
timeout: Optional timeout in seconds (None = infinite)
Examples:
>>> from pathlib import Path
>>> def on_change():
... print("Recompiled!")
>>> watch_manuscript(Path("/path/to/project"), on_compile=on_change)
"""
# Get compile script from project directory
compile_script = project_dir / "compile"
if not compile_script.exists():
logger.error(f"compile script not found: {compile_script}")
return
# Build watch command
cmd = [str(compile_script), "-m", "-w"]
logger.info(f"Starting watch mode for {project_dir}")
logger.info("Press Ctrl+C to stop")
process = None
try:
# Run watch script
process = subprocess.Popen(
cmd,
cwd=project_dir,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
text=True,
bufsize=1, # Line-buffered
)
# Stream output
for line in iter(process.stdout.readline, ""):
if line:
print(line.rstrip())
# Call callback on compilation events
if on_compile and "Compilation" in line:
try:
on_compile()
except Exception as e:
logger.error(f"Callback error: {e}")
process.wait(timeout=timeout)
except KeyboardInterrupt:
logger.info("\nWatch mode stopped by user")
if process:
process.terminate()
try:
process.wait(timeout=5)
except subprocess.TimeoutExpired:
process.kill()
except Exception as e:
logger.error(f"Watch mode error: {e}")
if process:
process.terminate()
__all__ = ["watch_manuscript"]
# EOF