Skip to content

Commit efb9ed3

Browse files
committed
Brand new implementation of the keyboard layout translator. This new
version looks into the Xorg database when searching for a possible match for a given KBD-style keyboard layout.
1 parent 2b27977 commit efb9ed3

File tree

1 file changed

+263
-62
lines changed

1 file changed

+263
-62
lines changed

bin/ModifyXinitrc

Lines changed: 263 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,269 @@
11
#!/usr/bin/env python
22
# -*- coding: utf-8 -*-
33

4-
# Quick and dirty keyboard configurator for ~/.xinitrc
4+
# loadkeys to setxkbmap helper
5+
#
6+
# Given a keyboard.map file, finds an associated Xorg keyboard model,
7+
# layout, and variant, and writes it down to the user's .xinitrc file.
8+
#
9+
# Written by Lucas C. Villa Real <lucasvr@gobolinux.org>
10+
#
11+
# Released under the GNU GPL version 2 or above
512

613
import os
14+
import sys
15+
import libxml2
16+
import subprocess
717

8-
if len(os.sys.argv) != 2 :
9-
print "Syntax: %s <KeymapLayout>" %os.sys.argv[0]
10-
os.sys.exit(1)
11-
12-
KeymapLayout = os.sys.argv[1]
13-
14-
xinitrc = os.getenv("HOME") + "/.xinitrc"
15-
if not os.path.exists(xinitrc) :
16-
print "Error: %s does not exist." %xinitrc
17-
os.sys.exit(1)
18-
19-
20-
def getKeyboardSettings() :
21-
XkbModel = "default"
22-
XkbLayout = "us"
23-
XkbVariant = "basic"
24-
if KeymapLayout == "be-latin1" :
25-
XkbModel = "pc104"
26-
XkbLayout = "be"
27-
elif KeymapLayout == "br-abnt2" :
28-
XkbModel = "abnt2"
29-
XkbLayout = "br"
30-
elif KeymapLayout == "br-abnt" :
31-
XkbModel = "abnt"
32-
XkbLayout = "br"
33-
elif KeymapLayout == "fr-latin9" :
34-
XkbModel = "pc105"
35-
XkbVariant = "latin9"
36-
XkbLayout = "fr"
37-
elif KeymapLayout == "us-acentos" :
38-
XkbModel = "pc105"
39-
XkbLayout = "us_intl"
40-
elif KeymapLayout == "sv-latin1" :
41-
XkbModel = "pc105"
42-
XkbLayout = "se"
43-
elif KeymapLayout == "us" :
44-
XkbModel = "pc104"
45-
XkbLayout = "us"
46-
elif KeymapLayout == "dvorak" :
47-
XkbModel = "pc105"
48-
XkbLayout = "dvorak"
49-
else :
50-
XkbModel = "pc104"
51-
XkbLayout = KeymapLayout
52-
return XkbModel, XkbLayout, XkbVariant
53-
54-
55-
XkbModel, XkbLayout, XkbVariant = getKeyboardSettings()
56-
kbd_settings = "-model %s -layout %s" %(XkbModel, XkbLayout)
57-
if XkbVariant != "basic":
58-
kbd_settings += " -variant %s" %XkbVariant
59-
60-
oldFile = open(xinitrc)
61-
newFile = open(xinitrc + ".new", "w")
62-
newFile.write("setxkbmap %s\n" %kbd_settings)
63-
for line in oldFile.readlines() :
64-
newFile.write(line)
65-
oldFile.close()
66-
newFile.close()
67-
os.unlink(xinitrc)
68-
os.rename(xinitrc+".new", xinitrc)
18+
19+
class KeyboardSettings:
20+
def __init__(self, keymap=None, x11_layout=None, x11_variant=None):
21+
self.keymap = keymap
22+
self.x11_model = "pc104"
23+
self.x11_layout = "us" if x11_layout is None else x11_layout
24+
self.x11_variant = x11_variant
25+
26+
if keymap == "be-latin1" :
27+
self.x11_model = "pc104"
28+
self.x11_layout = "be"
29+
elif keymap == "br-abnt2" :
30+
self.x11_model = "abnt2"
31+
self.x11_layout = "br"
32+
elif keymap == "br-abnt" :
33+
self.x11_model = "abnt"
34+
self.x11_layout = "br"
35+
elif keymap == "fr-latin9" :
36+
self.x11_model = "pc105"
37+
self.x11_layout = "fr"
38+
elif keymap == "us-acentos" :
39+
self.x11_model = "pc105"
40+
self.x11_layout = "us_intl"
41+
elif keymap == "sv-latin1" :
42+
self.x11_model = "pc105"
43+
self.x11_layout = "se"
44+
elif keymap == "us" :
45+
self.x11_model = "pc104"
46+
self.x11_layout = "us"
47+
elif keymap == "dvorak" :
48+
self.x11_model = "pc105"
49+
self.x11_layout = "dvorak"
50+
51+
def __getkbmap(self):
52+
cmd = "setxkbmap -model {0} -layout {1}".format(self.x11_model, self.x11_layout)
53+
if self.x11_variant:
54+
cmd += " -variant {0}".format(self.x11_variant)
55+
return cmd
56+
57+
def write(self, xinitrc):
58+
oldFile = open(xinitrc)
59+
newFile = open(xinitrc + ".new", "w")
60+
newFile.write(self.__getkbmap() + "\n")
61+
for line in oldFile.readlines() :
62+
newFile.write(line)
63+
oldFile.close()
64+
newFile.close()
65+
os.unlink(xinitrc)
66+
os.rename(xinitrc+".new", xinitrc)
67+
68+
def test(self):
69+
if subprocess.call(self.__getkbmap().split()) != 0:
70+
print("Error evaluating '{0}', please check.".format(cmd))
71+
72+
73+
class XKB:
74+
def __init__(self):
75+
self.rulesfile = "/usr/share/X11/xkb/rules/base.xml"
76+
self.layouts = {}
77+
78+
def parseRules(self):
79+
doc = libxml2.parseFile(self.rulesfile)
80+
ctxt = doc.xpathNewContext()
81+
layouts = ctxt.xpathEval("/xkbConfigRegistry/layoutList/layout/configItem/name")
82+
self.layouts = dict((x.content, x) for x in layouts)
83+
for layout in self.layouts.keys():
84+
configitem = self.layouts[layout].get_parent()
85+
variants = configitem.xpathEval("../variantList/variant/configItem/name")
86+
self.layouts[layout] = [x.content for x in variants]
87+
return self.layouts
88+
89+
def x11Layout(self, keymap):
90+
if self.layouts.has_key(keymap):
91+
return keymap
92+
keymap_two = "-".join(keymap.split("-")[0:2])
93+
if self.layouts.has_key(keymap_two):
94+
return keymap_two
95+
keymap_one = keymap.split("-")[0]
96+
if self.layouts.has_key(keymap_one):
97+
return keymap_one
98+
return None
99+
100+
def x11Variant(self, keymap, layout):
101+
if layout is None:
102+
return None
103+
keymap = keymap[len(layout):].strip("-")
104+
for variant in self.layouts[layout]:
105+
if keymap in self.layouts[layout]:
106+
return keymap
107+
keymap_two = "-".join(keymap.split("-")[-2:])
108+
if keymap_two in self.layouts[layout]:
109+
return keymap_two
110+
keymap_one = keymap.split("-")[-1]
111+
if keymap_one in self.layouts[layout]:
112+
return keymap_one
113+
return None
114+
115+
116+
def main():
117+
if len(sys.argv) != 2:
118+
print("Syntax: {0} <KeymapLayout>".format(sys.argv[0]))
119+
sys.exit(1)
120+
121+
xinitrc = os.getenv("HOME") + "/.xinitrc"
122+
if not os.path.exists(xinitrc) :
123+
print("Error: {0} does not exist.".format(xinitrc))
124+
sys.exit(1)
125+
126+
rules = XKB()
127+
rules.parseRules()
128+
keymap = sys.argv[1]
129+
130+
x11_layout = rules.x11Layout(keymap)
131+
x11_variant = rules.x11Variant(keymap, x11_layout)
132+
settings = KeyboardSettings(keymap, x11_layout, x11_variant)
133+
settings.write(xinitrc)
134+
135+
136+
def main_debug_all():
137+
loadkeys_keymaps = '''
138+
dvorak.map
139+
azerty.map
140+
be-latin1.map
141+
fr-latin1.map
142+
fr-latin9.map
143+
fr-pc.map
144+
fr.map
145+
wangbe.map
146+
wangbe2.map
147+
ANSI-dvorak.map
148+
dvorak-l.map
149+
dvorak-r.map
150+
dvorak.map
151+
tr_f-latin5.map
152+
trf.map
153+
bg-cp1251.map
154+
bg-cp855.map
155+
bg_bds-cp1251.map
156+
bg_bds-utf8.map
157+
bg_pho-cp1251.map
158+
bg_pho-utf8.map
159+
br-abnt.map
160+
br-abnt2.map
161+
br-latin1-abnt2.map
162+
br-latin1-us.map
163+
by.map
164+
cf.map
165+
cz-cp1250.map
166+
cz-lat2-prog.map
167+
cz-lat2.map
168+
cz.map
169+
defkeymap.map
170+
defkeymap_V1.0.map
171+
dk-latin1.map
172+
dk.map
173+
emacs.map
174+
emacs2.map
175+
es-cp850.map
176+
es.map
177+
et-nodeadkeys.map
178+
et.map
179+
fi-latin1.map
180+
fi-latin9.map
181+
fi.map
182+
gr-pc.map
183+
gr.map
184+
hu101.map
185+
il-heb.map
186+
il-phonetic.map
187+
il.map
188+
is-latin1-us.map
189+
is-latin1.map
190+
it-ibm.map
191+
it.map
192+
it2.map
193+
jp106.map
194+
la-latin1.map
195+
lt.baltic.map
196+
lt.l4.map
197+
lt.map
198+
mk-cp1251.map
199+
mk-utf.map
200+
mk.map
201+
mk0.map
202+
nl.map
203+
nl2.map
204+
no-latin1.map
205+
no.map
206+
pc110.map
207+
pl.map
208+
pl2.map
209+
pt-latin1.map
210+
pt-latin9.map
211+
ro_win.map
212+
ru-cp1251.map
213+
ru-ms.map
214+
ru-yawerty.map
215+
ru.map
216+
ru1.map
217+
ru2.map
218+
ru3.map
219+
ru4.map
220+
ru_win.map
221+
se-fi-ir209.map
222+
se-fi-lat6.map
223+
se-ir209.map
224+
se-lat6.map
225+
sk-prog-qwerty.map
226+
sk-qwerty.map
227+
sr-cy.map
228+
sv-latin1.map
229+
tr_q-latin5.map
230+
tralt.map
231+
trq.map
232+
ua-utf-ws.map
233+
ua-utf.map
234+
ua-ws.map
235+
ua.map
236+
uk.map
237+
us-acentos.map
238+
us.map
239+
croat.map
240+
cz-us-qwertz.map
241+
de-latin1-nodeadkeys.map
242+
de-latin1.map
243+
de.map
244+
de_CH-latin1.map
245+
fr_CH-latin1.map
246+
fr_CH.map
247+
hu.map
248+
sg-latin1-lk450.map
249+
sg-latin1.map
250+
sg.map
251+
sk-prog-qwertz.map
252+
sk-qwertz.map
253+
slovene.map
254+
'''
255+
256+
rules = XKB()
257+
rules.parseRules()
258+
259+
# create translation rules
260+
mappings = {}
261+
keymaps = [x.strip().split(".")[0] for x in loadkeys_keymaps.strip().split("\n")]
262+
for keymap in keymaps:
263+
x11_layout = rules.x11Layout(keymap)
264+
x11_variant = rules.x11Variant(keymap, x11_layout)
265+
mappings[keymap] = KeyboardSettings(keymap, x11_layout, x11_variant)
266+
mappings[keymap].test()
267+
268+
if __name__ == "__main__":
269+
main()

0 commit comments

Comments
 (0)