#!/usr/bin/env python3 """Extract Hanja and symbol readings from libhangul data.""" import sys import unicodedata from pathlib import Path def ishangul(s): return s != "" and all(0xAC00 <= ord(c) <= 0xD7A3 for c in s) def isjamo(s): return len(s) == 1 and 0x3131 <= ord(s) <= 0x314E def ishanja(s): return s != "" and all(0x3400 <= ord(c) <= 0x4DBF or 0x4E00 <= ord(c) <= 0x9FFF or 0xF900 <= ord(c) <= 0xFAFF for c in s) def issymbol(s): """One rune the popup can draw and a candidate row can carry: not a space, which the row separates candidates with, and not a formatting character, which would leave a blank candidate to pick.""" return (len(s) == 1 and not s.isspace() and not ishanja(s) and not unicodedata.category(s).startswith("C")) def keeps(reading, value): """A syllable reading gives Hanja; a jamo reading gives a symbol.""" if ishangul(reading): return ishanja(value) return isjamo(reading) and issymbol(value) def extract(src, name): comments = [] entries = [] seen = set() leading = True for lineno, raw in enumerate(src, 1): line = raw.rstrip("\r\n") if not line: continue if line.startswith("#"): if leading: comments.append(line.rstrip()) continue leading = False fields = line.split(":") if len(fields) != 3: raise ValueError(f"{name}:{lineno}: need key:value:comment") reading, value, _ = fields if not keeps(reading, value): continue pair = (value, reading) if pair in seen: raise ValueError(f"{name}:{lineno}: duplicate reading") seen.add(pair) entries.append(pair) if not entries: raise ValueError(f"{name}: no readings") return comments, entries def main(): sys.stdin.reconfigure(encoding="utf-8") sys.stdout.reconfigure(encoding="utf-8") sys.stderr.reconfigure(encoding="utf-8") if len(sys.argv) > 2: print(f"usage: {sys.argv[0]} [libhangul-hanja.txt]", file=sys.stderr) return 2 src = sys.stdin name = "" try: if len(sys.argv) == 2: name = sys.argv[1] src = Path(name).open(encoding="utf-8") comments, entries = extract(src, name) for line in comments: print(line) if comments: print() for value, reading in entries: print(f"{value}\t{reading}") except (OSError, UnicodeError, ValueError) as error: print(error, file=sys.stderr) return 1 finally: if src is not sys.stdin: src.close() return 0 if __name__ == "__main__": sys.exit(main())