#!/usr/bin/env python
#
# Copyright (C) 2015 by Intevation GmbH
# Author(s):
# Thomas Arendsen Hein <thomas@intevation.de>
#
# This program is free software under the GNU GPL (>=v2)

r"""
latex-unicodechar

Suggested usage of this script:
  latex file.tex </dev/null | latex-unicode

Parses the following LaTeX error message:
  Package inputenc Error: Unicode char \u8:X not set up for use with LaTeX.
and suggest possible solutions/workarounds.

Must be run with a UTF-8 locale!
Compatible with python versions >= 2.6 (including 3.x).
"""

import sys
import binascii
import unicodedata

def u8report(u8char):
    hex_ = binascii.hexlify(u8char).decode()
    hexbytes = [hex_[x:x+2] for x in range(0, len(hex_), 2)]
    try:
        unichar = u8char.decode('utf8')
    except UnicodeDecodeError as inst:
        return ("Can't decode byte sequence: %s\n"
                % ' '.join(hexbytes))

    if len(unichar) != 1:
        return ("Byte sequence is not a single Unicode character: %s\n"
                % ' '.join(hexbytes))

    values = {
        'char': unichar,
        'utf8hex': ' '.join(hexbytes),
        'unihex': "%04x" % ord(unichar),
        'uniname': unicodedata.name(unichar, "unknown"),
        'pcre': ''.join([r'\x{%s}' % x for x in hexbytes]),
        'vim': ''.join([r'\x%s' % x for x in hexbytes]),
    }
    return (
        'Original Character:   \"%(char)s\" (might be invisible)\n'
        'UTF-8 sequence (hex): %(utf8hex)s\n'
        'Unicode value (hex):  %(unihex)s\n'
        'Unicode name:         %(uniname)s\n'
        '\n'
        'To find affected files in the shell:\n'
        "  grep -lP '%(pcre)s' *.tex\n"
        'To type the character in vim:\n'
        '  <Ctrl-V>u%(unihex)s or <Ctrl-R>="%(vim)s"<Enter>\n'
        'To replace this character with "???" in the source file:\n'
        "  perl -pe 's/'%(pcre)s/???/g' -i file.tex\n"
        'To replace this character with "???" in the LaTeX output:\n'
        '  \\DeclareUnicodeCharacter{%(unihex)s}{???}\n'
        '\n'
    ) % values

def main():
    u8error = br'\u8:'
    try:
        stdin = sys.stdin.buffer
        stdout = sys.stdout.buffer
    except AttributeError:
        stdin = sys.stdin
        stdout = sys.stdout
    line = stdin.readline()
    while line:
        for word in line.split():
            if word.startswith(u8error):
                stdout.write(u8report(word[len(u8error):]).encode('utf-8'))
        line = stdin.readline()

if __name__ == "__main__":
    main()
