-
Notifications
You must be signed in to change notification settings - Fork 1
/
InsertUnicode.py
124 lines (90 loc) · 3.39 KB
/
InsertUnicode.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import sublime
import sublime_plugin
import collections
import os
from os.path import dirname, realpath
PACKAGE_NAME = 'InsertUnicode'
PACKAGE_DIR = dirname(realpath(__file__))
UNICODEDATA_FILENAME = os.path.join(PACKAGE_DIR, 'UnicodeData.txt')
BLOCKS_FILENAME = os.path.join(PACKAGE_DIR, 'Blocks.txt')
SETTINGS_FILENAME = 'InsertUnicode.sublime-settings'
UnicodeBlock = collections.namedtuple('UnicodeBlock', 'min max name')
def _read_block(line):
minmax, name = line.split('; ')
min_code, max_code = minmax.split('..')
min_code = int(min_code, 16)
max_code = int(max_code, 16)
return UnicodeBlock(min=min_code, max=max_code, name=name)
def _read_blocks(lines):
for line in lines:
line = line.strip()
if not line:
continue
if line.startswith('#'):
continue
yield _read_block(line)
def _read_unicodedata_names(lines):
for line in lines:
line = line.strip()
if not line:
continue
data = line.split(';')
code = data[0]
name = data[1]
oldname = data[10]
if name == '<control>':
name = '<control>: {0}'.format(oldname)
code = int(code, 16)
yield (code, name)
_BLOCKS = list(_read_blocks(open(BLOCKS_FILENAME).readlines()))
_NAMES = dict(_read_unicodedata_names(open(UNICODEDATA_FILENAME).readlines()))
def _get_label(codeunit, fallback):
"""
Returns a pretty label for the given code unit.
Uses a fallback name if not found in data
"""
name = _NAMES.get(codeunit, fallback)
char = chr(codeunit)
code = hex(codeunit)
return '[{code}] {char} {name}'.format(name=name, char=char, code=code)
def _insert_char(view, codeunits, code):
if code == -1:
return
else:
codeunit = codeunits[code]
insertion = chr(codeunit)
view.run_command('insert', {'characters': insertion})
class InsertUnicodeShowBlockListCommand(sublime_plugin.TextCommand):
def _show_block_list(self):
block_names = [b.name for b in _BLOCKS]
def show_block(block):
if block == -1:
return
else:
codeunits = range(_BLOCKS[block].min, _BLOCKS[block].max - 1)
block_names = [_get_label(codeunit, fallback='(unknown)')
for codeunit in codeunits]
sublime.set_timeout(
lambda: self.view.window().show_quick_panel(
block_names,
lambda code: _insert_char(self.view, codeunits, code),
0),
10)
self.view.window().show_quick_panel(block_names, show_block, 0)
def run(self, edit):
if _BLOCKS is None:
sublime.status_message('{0}: Unicode _blocks not loaded'.format(
PACKAGE_NAME))
return
else:
self._show_block_list()
_SETTINGS = sublime.load_settings(SETTINGS_FILENAME)
_USER_CHARS = [int(char, 16) for char in _SETTINGS.get('user_characters')]
class InsertUnicodeShowUserListCommand(sublime_plugin.TextCommand):
def run (self, edit):
block_names = [_get_label(codeunit, fallback='(unknown)')
for codeunit in _USER_CHARS]
self.view.window().show_quick_panel(
block_names,
lambda code: _insert_char(self.view, _USER_CHARS, code),
0)