""" scripts/extract_hyphenation.py Extrait les points de cesure depuis les logs de compilation TeX. Deux formats geres, tous deux valides par execution reelle (pdfTeX/LuaTeX, TeX Live 2023, 2026-09-02) : 1. \\showhyphens{mot} (pdfTeX ou LuaTeX) -> une ligne par mot : [] \\tenrm mot-avec-ti-rets Fiable pour les tests mot-par-mot (test/words.tex). 2. Callback LuaTeX post_linebreak_filter -> une ligne par ligne de paragraphe composee : LINE: Ny ma-ha-fi-na-ri-tra dia Necessaire pour les tests en contexte (test/sentences_lua.tex) -- l'approche pdfTeX via les messages Overfull/Underfull a un angle mort confirme : les lignes "Loose" (badness finie, pas de depassement) n'impriment pas leur contenu meme avec \\hbadness=0. Voir docs/methodology.md section 3. """ from __future__ import annotations import re from pathlib import Path SHOWHYPHENS_LINE = re.compile(r"^\[\]\s+\\\w+\s+(\S+)$", re.MULTILINE) LUA_CALLBACK_LINE = re.compile(r"^LINE: (.+)$", re.MULTILINE) PARAGRAPH_OVERFULL_LINE = re.compile(r"^\\\w+\s+(.+?)\s*\|$", re.MULTILINE) def extract_hyphenated_words(log_content: str) -> list[str]: return [m.group(1) for m in SHOWHYPHENS_LINE.finditer(log_content)] def extract_lua_lines(log_content: str) -> list[str]: results = [] for m in LUA_CALLBACK_LINE.finditer(log_content): line = re.split(r"\s*\[\d+\{", m.group(1))[0] results.append(line.rstrip()) return results def extract_broken_lines_overfull(log_content: str) -> list[str]: return [m.group(1) for m in PARAGRAPH_OVERFULL_LINE.finditer(log_content)] def main() -> None: import argparse parser = argparse.ArgumentParser() parser.add_argument("log_path", type=Path) parser.add_argument("output_path", type=Path) parser.add_argument( "--mode", choices=["showhyphens", "lua", "overfull"], default="showhyphens", ) args = parser.parse_args() content = args.log_path.read_text(encoding="utf-8", errors="replace") extractors = { "showhyphens": extract_hyphenated_words, "lua": extract_lua_lines, "overfull": extract_broken_lines_overfull, } results = extractors[args.mode](content) args.output_path.write_text("\n".join(results) + "\n", encoding="utf-8") print(f"{len(results)} entree(s) extraite(s) -> {args.output_path}") if __name__ == "__main__": main()