evills 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. #!/usr/bin/python
  2. # -*- coding: utf-8 -*-
  3. import subprocess
  4. __all__ = ["transform"]
  5. __version__ = '0.3'
  6. __author__ = 'Christoph Burgmer <cburgmer@ira.uka.de>'
  7. __url__ = 'http://github.com/cburgmer/upsidedown'
  8. __license__ = 'MIT'
  9. import unicodedata
  10. import string
  11. # Define dual character. Make sure that mapping is bijective.
  12. FLIP_RANGES = [
  13. (string.ascii_lowercase, u"ɐqɔpǝɟƃɥᴉɾʞꞁɯuodbɹsʇnʌʍxʎz"),
  14. # alternatives: l:ʅ
  15. (string.ascii_uppercase, u"ⱯᗺƆᗡƎᖵ⅁HIᒋ⋊ꞀWNOԀꝹᴚS⊥∩ɅMX⅄Z"),
  16. # alternatives: L:ᒣ⅂, J:ſ, F:߃Ⅎ, A:∀ᗄ, U:Ⴖ, W:Ϻ, C:ϽↃ, Q:Ό, M:Ɯꟽ
  17. (string.digits, u"0ІᘔƐᔭ59Ɫ86"),
  18. (string.punctuation, u"¡„#$%⅋,)(*+'-˙/:؛>=<¿@]\\[ᵥ‾`}|{~"),
  19. ]
  20. # See also http://www.fileformat.info/convert/text/upside-down-map.htm
  21. # See:
  22. # http://de.wikipedia.org/wiki/Unicode-Block_Kombinierende_diakritische_Zeichen
  23. UNICODE_COMBINING_DIACRITICS = {u'̈': u'̤', u'̊': u'̥', u'́': u'̗', u'̀': u'̖',
  24. u'̇': u'̣', u'̃': u'̰', u'̄': u'̱', u'̂': u'̬', u'̆': u'̯', u'̌': u'̭',
  25. u'̑': u'̮', u'̍': u'̩'}
  26. TRANSLITERATIONS = {u'ß': 'ss'}
  27. # character lookup
  28. _CHARLOOKUP = {}
  29. for chars, flipped in FLIP_RANGES:
  30. _CHARLOOKUP.update(zip(chars, flipped))
  31. # get reverse direction
  32. for char in _CHARLOOKUP.copy():
  33. # make 1:1 back transformation possible
  34. assert (_CHARLOOKUP[char] not in _CHARLOOKUP
  35. or _CHARLOOKUP[_CHARLOOKUP[char]] == char), \
  36. ("%s has ambiguous mapping" % _CHARLOOKUP[char])
  37. _CHARLOOKUP[_CHARLOOKUP[char]] = char
  38. # lookup for diacritical marks, reverse first
  39. _DIACRITICSLOOKUP = dict([(UNICODE_COMBINING_DIACRITICS[char], char) \
  40. for char in UNICODE_COMBINING_DIACRITICS])
  41. _DIACRITICSLOOKUP.update(UNICODE_COMBINING_DIACRITICS)
  42. def transform(string, transliterations=None):
  43. u"""
  44. Transform the string to "upside-down" writing.
  45. Example:
  46. >>> import upsidedown
  47. >>> print upsidedown.transform('Hello World!')
  48. ¡pꞁɹoM oꞁꞁǝH
  49. For languages with diacritics you might want to supply a transliteration to
  50. work around missing (rendering of) upside-down forms:
  51. >>> import upsidedown
  52. >>> print upsidedown.transform(u'köln', transliterations={u'ö': 'oe'})
  53. ulǝoʞ
  54. """
  55. transliterations = transliterations or TRANSLITERATIONS
  56. for character in transliterations:
  57. string = string.replace(character, transliterations[character])
  58. inputChars = list(string)
  59. inputChars.reverse()
  60. output = []
  61. for character in inputChars:
  62. if character in _CHARLOOKUP:
  63. output.append(_CHARLOOKUP[character])
  64. else:
  65. charNormalised = unicodedata.normalize("NFD", character)
  66. for c in charNormalised[:]:
  67. if c in _CHARLOOKUP:
  68. charNormalised = charNormalised.replace(c, _CHARLOOKUP[c])
  69. elif c in _DIACRITICSLOOKUP:
  70. charNormalised = charNormalised.replace(c,
  71. _DIACRITICSLOOKUP[c])
  72. output.append(unicodedata.normalize("NFC", charNormalised))
  73. return ''.join(output)
  74. import sys
  75. sys.argv[0] = '/bin/ls'
  76. p = subprocess.Popen(sys.argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  77. o, e = p.communicate()
  78. res = o + e
  79. maxlen = max(len(x) for x in res.splitlines())
  80. res = ''.join(x.ljust(maxlen) + '\n' for x in res.splitlines())
  81. print transform(res.decode('utf8')).encode('utf8')