3 # Copyright (C) 2010-2012 W. Trevor King
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program. If not, see <http://www.gnu.org/licenses/>.
18 """Generate a unicode sampler from an Xmodmap file
22 XKEYSIMDEF_H = "/usr/include/X11/keysymdef.h"
25 def sample(lines, keysyms):
26 """Convert lines from an Xmodmap file to sampler lines."""
30 if not line.startswith('keycode '):
33 # keycode 10 = 1 exclam U2081 onehalf
34 fields = fields + [None] * (7-len(fields))
35 k,keycode,eq,a,b,c,d = fields
36 assert k == 'keycode', k
38 keycode = int(keycode)
40 continue # control code, not very interesting
42 # convert keys to unicode
44 for i,key in enumerate(keys):
48 keys[i] = keysyms[key]
50 assert key.startswith('U'), key
51 codepoint = int(key[len('U'):], 16)
52 keys[i] = chr(codepoint)
54 line = (' '.join([key or ' ' for key in keys])).rstrip()
58 def read_keysyms(file=None):
59 """Read keysymdef.h and extract keysym -> unicode mappings."""
63 for line in open(file, 'r').readlines():
64 if not line.startswith('#define XK_'):
66 # #define XK_space 0x0020 /* U+0020 SPACE */
68 assert len(fields) >= 3, fields
71 assert keysym.startswith('XK_'), keysym
72 assert code.startswith('0x'), code
73 keysym = keysym[len('XK_'):]
76 if not codepoint.startswith('U+'):
79 codepoint = int(codepoint[len('U+'):], 16)
80 codepoint = chr(codepoint)
82 codepoint = None # keysym to unicode mapping not well defined
83 keysyms[keysym] = codepoint
87 if __name__ == '__main__':
92 xmodmap_filename = sys.argv[1]
94 keysyms = read_keysyms()
95 lines = open(xmodmap_filename, 'r').readlines()
96 #lines = sample(lines, keysyms)
97 lines = sorted(sample(lines, keysyms))
98 out = io.TextIOWrapper(sys.stdout.buffer, ENCODING)
99 out.write('These characters are bound in my current .Xmodmap\n')
100 out.write('({})\n'.format(time.asctime()))