Skip to content

Instantly share code, notes, and snippets.

@puhitaku
Last active February 12, 2021 13:52
Show Gist options
  • Save puhitaku/fd36f76d9f1780e4c9cea678c7924fca to your computer and use it in GitHub Desktop.
Save puhitaku/fd36f76d9f1780e4c9cea678c7924fca to your computer and use it in GitHub Desktop.
Unicode special character converter

This Python script converts a plain text into a 𝐑𝐢𝐜𝐡 and 𝓖𝓸𝓻𝓰𝓮𝓸𝓾𝓼 text. Python 3.7+ is required.

Usage: /Users/takumi/dev/rcs/scripts/fontify STYLE [TEXT]
TEXT is ignored if stdin is piped.
Available styles:
 - serif-b
    𝐓𝐇𝐄 𝐐𝐔𝐈𝐂𝐊 𝐁𝐑𝐎𝐖𝐍 𝐅𝐎𝐗 𝐉𝐔𝐌𝐏𝐒 𝐎𝐕𝐄𝐑 𝐓𝐇𝐄 𝐋𝐀𝐙𝐘 𝐃𝐎𝐆. 𝟎𝟏𝟐𝟑𝟒
    𝐭𝐡𝐞 𝐪𝐮𝐢𝐜𝐤 𝐛𝐫𝐨𝐰𝐧 𝐟𝐨𝐱 𝐣𝐮𝐦𝐩𝐬 𝐨𝐯𝐞𝐫 𝐭𝐡𝐞 𝐥𝐚𝐳𝐲 𝐝𝐨𝐠. 𝟎𝟏𝟐𝟑𝟒
 - serif-i
    𝑇𝐻𝐸 𝑄𝑈𝐼𝐶𝐾 𝐵𝑅𝑂𝑊𝑁 𝐹𝑂𝑋 𝐽𝑈𝑀𝑃𝑆 𝑂𝑉𝐸𝑅 𝑇𝐻𝐸 𝐿𝐴𝑍𝑌 𝐷𝑂𝐺. 01234
    𝑡ℎ𝑒 𝑞𝑢𝑖𝑐𝑘 𝑏𝑟𝑜𝑤𝑛 𝑓𝑜𝑥 𝑗𝑢𝑚𝑝𝑠 𝑜𝑣𝑒𝑟 𝑡ℎ𝑒 𝑙𝑎𝑧𝑦 𝑑𝑜𝑔. 01234
 - serif-bi
    𝑻𝑯𝑬 𝑸𝑼𝑰𝑪𝑲 𝑩𝑹𝑶𝑾𝑵 𝑭𝑶𝑿 𝑱𝑼𝑴𝑷𝑺 𝑶𝑽𝑬𝑹 𝑻𝑯𝑬 𝑳𝑨𝒁𝒀 𝑫𝑶𝑮. 01234
    𝒕𝒉𝒆 𝒒𝒖𝒊𝒄𝒌 𝒃𝒓𝒐𝒘𝒏 𝒇𝒐𝒙 𝒋𝒖𝒎𝒑𝒔 𝒐𝒗𝒆𝒓 𝒕𝒉𝒆 𝒍𝒂𝒛𝒚 𝒅𝒐𝒈. 01234
 - sans-serif-n
    𝖳𝖧𝖤 𝖰𝖴𝖨𝖢𝖪 𝖡𝖱𝖮𝖶𝖭 𝖥𝖮𝖷 𝖩𝖴𝖬𝖯𝖲 𝖮𝖵𝖤𝖱 𝖳𝖧𝖤 𝖫𝖠𝖹𝖸 𝖣𝖮𝖦. 𝟢𝟣𝟤𝟥𝟦
    𝗍𝗁𝖾 𝗊𝗎𝗂𝖼𝗄 𝖻𝗋𝗈𝗐𝗇 𝖿𝗈𝗑 𝗃𝗎𝗆𝗉𝗌 𝗈𝗏𝖾𝗋 𝗍𝗁𝖾 𝗅𝖺𝗓𝗒 𝖽𝗈𝗀. 𝟢𝟣𝟤𝟥𝟦
 - sans-serif-b
    𝗧𝗛𝗘 𝗤𝗨𝗜𝗖𝗞 𝗕𝗥𝗢𝗪𝗡 𝗙𝗢𝗫 𝗝𝗨𝗠𝗣𝗦 𝗢𝗩𝗘𝗥 𝗧𝗛𝗘 𝗟𝗔𝗭𝗬 𝗗𝗢𝗚. 𝟬𝟭𝟮𝟯𝟰
    𝘁𝗵𝗲 𝗾𝘂𝗶𝗰𝗸 𝗯𝗿𝗼𝘄𝗻 𝗳𝗼𝘅 𝗷𝘂𝗺𝗽𝘀 𝗼𝘃𝗲𝗿 𝘁𝗵𝗲 𝗹𝗮𝘇𝘆 𝗱𝗼𝗴. 𝟬𝟭𝟮𝟯𝟰
 - sans-serif-i
    𝘛𝘏𝘌 𝘘𝘜𝘐𝘊𝘒 𝘉𝘙𝘖𝘞𝘕 𝘍𝘖𝘟 𝘑𝘜𝘔𝘗𝘚 𝘖𝘝𝘌𝘙 𝘛𝘏𝘌 𝘓𝘈𝘡𝘠 𝘋𝘖𝘎. 01234
    𝘵𝘩𝘦 𝘲𝘶𝘪𝘤𝘬 𝘣𝘳𝘰𝘸𝘯 𝘧𝘰𝘹 𝘫𝘶𝘮𝘱𝘴 𝘰𝘷𝘦𝘳 𝘵𝘩𝘦 𝘭𝘢𝘻𝘺 𝘥𝘰𝘨. 01234
 - sans-serif-bi
    𝙏𝙃𝙀 𝙌𝙐𝙄𝘾𝙆 𝘽𝙍𝙊𝙒𝙉 𝙁𝙊𝙓 𝙅𝙐𝙈𝙋𝙎 𝙊𝙑𝙀𝙍 𝙏𝙃𝙀 𝙇𝘼𝙕𝙔 𝘿𝙊𝙂. 01234
    𝙩𝙝𝙚 𝙦𝙪𝙞𝙘𝙠 𝙗𝙧𝙤𝙬𝙣 𝙛𝙤𝙭 𝙟𝙪𝙢𝙥𝙨 𝙤𝙫𝙚𝙧 𝙩𝙝𝙚 𝙡𝙖𝙯𝙮 𝙙𝙤𝙜. 01234
 - script-n
    𝒯ℋℰ 𝒬𝒰ℐ𝒞𝒦 ℬℛ𝒪𝒲𝒩 ℱ𝒪𝒳 𝒥𝒰ℳ𝒫𝒮 𝒪𝒱ℰℛ 𝒯ℋℰ ℒ𝒜𝒵𝒴 𝒟𝒪𝒢. 01234
    𝓉𝒽ℯ 𝓆𝓊𝒾𝒸𝓀 𝒷𝓇ℴ𝓌𝓃 𝒻ℴ𝓍 𝒿𝓊𝓂𝓅𝓈 ℴ𝓋ℯ𝓇 𝓉𝒽ℯ 𝓁𝒶𝓏𝓎 𝒹ℴℊ. 01234
 - script-b
    𝓣𝓗𝓔 𝓠𝓤𝓘𝓒𝓚 𝓑𝓡𝓞𝓦𝓝 𝓕𝓞𝓧 𝓙𝓤𝓜𝓟𝓢 𝓞𝓥𝓔𝓡 𝓣𝓗𝓔 𝓛𝓐𝓩𝓨 𝓓𝓞𝓖. 01234
    𝓽𝓱𝓮 𝓺𝓾𝓲𝓬𝓴 𝓫𝓻𝓸𝔀𝓷 𝓯𝓸𝔁 𝓳𝓾𝓶𝓹𝓼 𝓸𝓿𝓮𝓻 𝓽𝓱𝓮 𝓵𝓪𝔃𝔂 𝓭𝓸𝓰. 01234
 - fraktur-n
    𝔗ℌ𝔈 𝔔𝔘ℑ ℭ𝔎 𝔅ℜ𝔒𝔚𝔑 𝔉𝔒𝔛 𝔍𝔘𝔐𝔓𝔖 𝔒𝔙𝔈ℜ 𝔗ℌ𝔈 𝔏𝔄ℨ𝔜 𝔇𝔒𝔊. 01234
    𝔱𝔥𝔢 𝔮𝔲𝔦𝔠𝔨 𝔟𝔯𝔬𝔴𝔫 𝔣𝔬𝔵 𝔧𝔲𝔪𝔭𝔰 𝔬𝔳𝔢𝔯 𝔱𝔥𝔢 𝔩𝔞𝔷𝔶 𝔡𝔬𝔤. 01234
 - fraktur-b
    𝕿𝕳𝕰 𝕼𝖀𝕴𝕮𝕶 𝕭𝕽𝕺𝖂𝕹 𝕱𝕺𝖃 𝕵𝖀𝕸𝕻𝕾 𝕺𝖁𝕰𝕽 𝕿𝕳𝕰 𝕷𝕬𝖅𝖄 𝕯𝕺𝕲. 01234
    𝖙𝖍𝖊 𝖖𝖚𝖎𝖈𝖐 𝖇𝖗𝖔𝖜𝖓 𝖋𝖔𝖝 𝖏𝖚𝖒𝖕𝖘 𝖔𝖛𝖊𝖗 𝖙𝖍𝖊 𝖑𝖆𝖟𝖞 𝖉𝖔𝖌. 01234
 - monospace
    𝚃𝙷𝙴 𝚀𝚄𝙸𝙲𝙺 𝙱𝚁𝙾𝚆𝙽 𝙵𝙾𝚇 𝙹𝚄𝙼𝙿𝚂 𝙾𝚅𝙴𝚁 𝚃𝙷𝙴 𝙻𝙰𝚉𝚈 𝙳𝙾𝙶. 𝟶𝟷𝟸𝟹𝟺
    𝚝𝚑𝚎 𝚚𝚞𝚒𝚌𝚔 𝚋𝚛𝚘𝚠𝚗 𝚏𝚘𝚡 𝚓𝚞𝚖𝚙𝚜 𝚘𝚟𝚎𝚛 𝚝𝚑𝚎 𝚕𝚊𝚣𝚢 𝚍𝚘𝚐. 𝟶𝟷𝟸𝟹𝟺
 - double-struck
    𝕋ℍ𝔼 ℚ𝕌𝕀ℂ𝕂 𝔹ℝ𝕆𝕎ℕ 𝔽𝕆𝕏 𝕁𝕌𝕄ℙ𝕊 𝕆𝕍𝔼ℝ 𝕋ℍ𝔼 𝕃𝔸ℤ𝕐 𝔻𝕆𝔾. 𝟘𝟙𝟚𝟛𝟜
    𝕥𝕙𝕖 𝕢𝕦𝕚𝕔𝕜 𝕓𝕣𝕠𝕨𝕟 𝕗𝕠𝕩 𝕛𝕦𝕞𝕡𝕤 𝕠𝕧𝕖𝕣 𝕥𝕙𝕖 𝕝𝕒𝕫𝕪 𝕕𝕠𝕘. 𝟘𝟙𝟚𝟛𝟜
#!/usr/bin/env python3
import fileinput, sys
from dataclasses import dataclass
@dataclass
class Style:
start: int
patch: dict
have_digits: bool
digits_start: int
styles = {
'serif-b': Style(
0x1D400,
dict(),
True,
0x1D7CE,
),
'serif-i': Style(
0x1D434,
{'h': 'ℎ'},
False,
0,
),
'serif-bi': Style(
0x1D468,
dict(),
False,
0,
),
'sans-serif-n': Style(
0x1D5A0,
dict(),
True,
0x1D7E2,
),
'sans-serif-b': Style(
0x1D5D4,
dict(),
True,
0x1D7EC,
),
'sans-serif-i': Style(
0x1D608,
dict(),
False,
0,
),
'sans-serif-bi': Style(
0x1D63C,
dict(),
False,
0,
),
'script-n': Style(
0x1D49C,
{
'B': 'ℬ',
'E': 'ℰ',
'F': 'ℱ',
'H': 'ℋ',
'I': 'ℐ',
'L': 'ℒ',
'M': 'ℳ',
'R': 'ℛ',
'e': 'ℯ',
'g': 'ℊ',
'o': 'ℴ',
},
False,
0,
),
'script-b': Style(
0x1D4D0,
dict(),
False,
0,
),
'fraktur-n': Style(
0x1D504,
{
'C': 'ℭ',
'H': 'ℌ',
'I': 'ℑ ',
'R': 'ℜ',
'Z': 'ℨ',
},
False,
0,
),
'fraktur-b': Style(
0x1D56C,
dict(),
False,
0,
),
'monospace': Style(
0x1D670,
dict(),
True,
0x1D7F6,
),
'double-struck': Style(
0x1D538,
{
'C': 'ℂ',
'H': 'ℍ',
'N': 'ℕ',
'P': 'ℙ',
'Q': 'ℚ',
'R': 'ℝ',
'Z': 'ℤ',
},
True,
0x1D7D8,
),
}
def convert(style, text):
out = []
for c in text:
if c in style.patch:
out.append(style.patch[c])
continue
if ord(c) in range(ord('A'), ord('Z') + 1):
start = style.start
offset = ord('A')
elif ord(c) in range(ord('a'), ord('z') + 1):
start = style.start
offset = ord('a') - 26
elif ord(c) in range(ord('0'), ord('9') + 1):
if not style.have_digits:
out.append(c)
continue
start = style.digits_start
offset = ord('0')
else:
out.append(c)
continue
c = start + ord(c) - offset
out.append(eval(f'"\\U{c:08x}"'))
return ''.join(out)
def main():
tty = sys.stdin.isatty()
argv = sys.argv
sufficient_args = (tty and len(argv) >= 3) or (not tty and len(argv) >= 2)
if '-h' in argv or '--help' in argv or not sufficient_args:
usage()
if argv[1] not in styles:
print(f'Style "{argv[1]}" was not found', file=sys.stderr)
sys.exit(1)
style = styles[argv[1]]
if tty:
print(convert(style, argv[-1]), end='')
else:
print(convert(style, sys.stdin.read()), end='')
def usage():
print(f'Usage: {sys.argv[0]} STYLE [TEXT]')
print(f'TEXT is ignored if stdin is piped.')
print(f'Available styles:')
for name, style in styles.items():
sample1 = convert(
style, 'THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG. 01234'
)
sample2 = convert(
style, 'the quick brown fox jumps over the lazy dog. 01234'
)
print(f' - {name}')
print(f' {sample1}')
print(f' {sample2}')
print()
if '-h' in sys.argv or '--help' in sys.argv:
sys.exit(0)
else:
sys.exit(1)
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment