--- keymapper-0.5.3.orig/gen_keymap
+++ keymapper-0.5.3/gen_keymap
@@ -22,12 +22,13 @@
from keymapper.script import Script
from keymapper.fakequery import FakeQuery
from keymapper.parse.linux import parse_file as parse_linux
-from keymapper.parse.linux import FileProblem
+from keymapper.parse.linux import FileProblem, add_dir
+from keymapper.fakequery import FakeQuery
import sys
import codecs
from optparse import OptionParser, OptParseError
-from subprocess import Popen,PIPE
+#from subprocess import Popen,PIPE
try:
from cStringIO import StringIO
except ImportError:
@@ -39,42 +40,78 @@
parser.add_option("-?","--help", action="help", help="show this help text")
parser.add_option("-v","--verbose", action="count", dest="verbose", help="be more verbose")
parser.add_option("-m","--minlen", action="store", dest="minlen", type="int", default=30, help="Too-short Keymaps are skipped (default: 30 entries)")
-parser.add_option("-g","--graph", action="store_const", dest="format", const="graphviz",
- help="generate a hopefully-nice-looking .dot file")
-parser.add_option("--maps", action="store_const", dest="format", const="mapdump",
- help="print the to-be-processed keymaps")
+parser.add_option("-g","--graph", action="store_const", dest="format",
+ const="graphviz", help="generate a hopefully-nice-looking .dot file")
+parser.add_option("--maps", action="store_const", dest="format",
+ const="mapdump", help="print the to-be-processed keymaps")
+parser.add_option("-i","--installer", action="store_const", dest="iformat",
+ const="d-i", help="Input files are in d-i map form")
+parser.add_option("-I","--inc","--include", action="append", dest="dirs",
+ help="add a directory to the search path")
parser.add_option("-o","--output", action="store", dest="filename",
help="output file (default: stdout)")
+parser.add_option("-f","--filter", action="store", dest="filter",
+ help="Include only the branches leading to these keymaps")
+parser.add_option("-u","--useonly", action="store", dest="useonly",
+ help="Start generating the tree based only on these keymaps")
+parser.add_option("-s","--skip", action="store", dest="skip",
+ help="keymaps to skip")
+parser.add_option("-t","--test", action="store_true", dest="test",
+ help="Test the generated maps")
+parser.add_option("--interactive", action="store_true", dest="interactive",
+ help="Ask user to choose among indistinguishable keymaps")
+parser.add_option("--no-altgr", action="store_false", dest="altgr",
+ help="Do not consider AltGr keys", default=True)
(opts, args) = parser.parse_args()
if not args:
parser.error("no arguments supplied")
sys.exit(1)
+if opts.test and opts.format:
+ parser.error("You can only test scripts")
+ sys.exit(1)
+if opts.test and not opts.filename:
+ parser.error("You can only test scripts if you write them to a file")
+ sys.exit(1)
t = Tree()
keymapper.tree.trace = opts.verbose
+keymapper.tree.interactive = opts.interactive
+
+if opts.dirs:
+ for d in opts.dirs:
+ add_dir(d)
if opts.filename:
- out=open(opts.filename,"w")
+ out = open(opts.filename,"w")
else:
- out=sys.stdout
+ out = sys.stdout
if opts.format == "graphviz":
out = codecs.getwriter("latin1")(out,"replace")
else:
out = codecs.getwriter("utf-8")(out)
+known={}
for f in args:
for l in open(f):
comment = l.find('#')
if comment > -1: l = l[:comment]
l = l.strip()
if l == "": continue
- if " " in l or "\t" in l:
- (name,code) = l.split()
+ name = l.split()
+ if opts.iformat == "d-i":
+ name = name[1]
else:
- name = l
- code = "utf-8"
+ name = name[0]
+ if opts.useonly and name not in opts.useonly.split(","):
+ continue
+ if opts.skip and name in opts.skip.split(","):
+ continue
+ if name in known:
+ continue
+ known[name]=1
+
# code = codecs.getreader(code)
# pipe = Popen(("loadkeys","-q","-M",name), stdout=PIPE).stdout
# pipe = code(pipe)
@@ -83,8 +120,8 @@
try:
if opts.verbose:
print "Parsing:",name
-# map = parse_map(name,pipe)
- map = parse_linux(name)
+# map = parse_map(name,pipe,opts.altgr)
+ map = parse_linux(name,opts.altgr)
except EmptyMapError:
print >>sys.stderr,"Map '%s' skipped: empty" % name
except MapInputError,exc:
@@ -107,11 +144,32 @@
if opts.format == "mapdump":
sys.exit(0)
-t.gen_tree()
+l=()
+if opts.filter:
+ l = opts.filter.split(",")
+t.gen_tree(*l)
if opts.format == "graphviz":
gen_report(t,GraphReporter(out))
else:
gen_report(t,FileReporter(out))
+if opts.test:
+ buf=codecs.getreader("utf-8")(open(opts.filename))
+ err=0
+ for i in range(0,3):
+ for k in t:
+ buf.seek(0,0)
+ print "Testing keymap %s" % (k.dump(),)
+ s = Script(buf,FakeQuery(k))
+ name = s.run()
+ if name != k.name:
+ print "SCRIPT ERROR: %s != %s" % (name,k.name)
+ err += 1
+ else:
+ print "... OK."
+ print
+ if err:
+ print >>sys.stderr,"There are problems!"
+ sys.exit(1)
# done!
--- keymapper-0.5.3.orig/test_x11.py
+++ keymapper-0.5.3/test_x11.py
@@ -0,0 +1,74 @@
+#!/usr/bin/python
+
+# Copyright (c) 2005 by Matthias Urlichs <smurf@smurf.noris.de>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of Version 2 of the GNU General Public License as
+# published by the Free Software Foundation. See the file COPYING.txt
+# or (on Debian systems) /usr/share/common-licenses/GPL-2 for details.
+
+"""\
+This test script grabs a number of interesting key maps from
+keymapper.fakemaps, generates a decision tree, saves that in an
+in-memory file, and then runs each key map against the file's
+interpreter to see if the correct map is returned.
+"""
+
+from keymapper.parse.x11 import parse_file as parse_x11
+from keymapper.tree import Tree, gen_report
+from keymapper.file import FileReporter
+from keymapper.graph import GraphReporter
+from keymapper.script import Script
+from keymapper.fakequery import FakeQuery
+
+import sys
+import codecs
+
+import keymapper.tree
+keymapper.tree.trace = 1
+
+try:
+ from cStringIO import StringIO
+except ImportError:
+ from StringIO import StringIO
+
+keymaps = []
+t = Tree()
+for k in sys.argv[1:]:
+ k = parse_x11(k)
+ t.add(k)
+ print k.rdump()
+ keymaps.append(k)
+t.gen_tree()
+
+buf = StringIO()
+gen_report(t,FileReporter(codecs.getwriter("utf-8")(buf)))
+
+g = codecs.getwriter("latin1")(open("test.dot","w"),"replace")
+gen_report(t,GraphReporter(g))
+
+# 'buf' now contains our script.
+
+buf.seek(0,0)
+print buf.read(),
+
+err = 0
+for k in keymaps:
+ buf.seek(0,0)
+ print "Testing keymap %s" % (k.rdump(),)
+ s = Script(codecs.getreader("utf-8")(buf))
+ name = s.run(FakeQuery(k))
+ if name != k.name:
+ print "SCRIPT ERROR: %s != %s" % (name,k.name)
+ err += 1
+ else:
+ print "... OK."
+ print
+
+if err:
+ print "%d errors found!" % err
+ sys.exit(1)
+else:
+ print "Everything works."
+ sys.exit(0)
+
--- keymapper-0.5.3.orig/x2console_keymap
+++ keymapper-0.5.3/x2console_keymap
@@ -0,0 +1,67 @@
+#!/usr/bin/python
+
+# Copyright (c) 2005 by Matthias Urlichs <smurf@smurf.noris.de>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of Version 2 of the GNU General Public License as
+# published by the Free Software Foundation. See the file COPYING.txt
+# or (on Debian systems) /usr/share/common-licenses/GPL-2 for details.
+
+"""\
+This script analyzes an X11 keymap and prints the equivalent console
+keymap name, based on a decision tree.
+"""
+
+from keymapper.parse.x11 import parse_file as parse_x11
+from keymapper.fakequery import FakeQuery
+from keymapper.script import Script,DupMap,NoMap
+from optparse import OptionParser, OptParseError
+from sets import Set
+
+import sys
+import codecs
+
+sys.stdout = codecs.getwriter("utf-8")(sys.stdout)
+
+import keymapper.tree
+keymapper.tree.trace = 1
+
+try:
+ from cStringIO import StringIO
+except ImportError:
+ from StringIO import StringIO
+
+parser = OptionParser(usage="%prog tree_file x11name...", version="%prog 0.1")
+parser.remove_option("-h")
+#parser.remove_option("--help")
+parser.add_option("-?","--help", action="help", help="show this help text")
+parser.add_option("-v","--verbose", action="count", dest="verbose",
+ help="be more verbose")
+parser.add_option("-g","--graph", action="store_const", dest="format",
+ const="graphviz", help="generate a hopefully-nice-looking .dot file")
+(opts, args) = parser.parse_args()
+
+script = Script(codecs.getreader("utf-8")(open(args[0])), verbose=opts.verbose)
+rev = {}
+def rev_add(b,a):
+ if a not in rev:
+ rev[a] = Set()
+ rev[a].add(b)
+
+for x11map in args[1:]:
+ km = parse_x11(x11map)
+ if km is None: continue
+ try:
+ consolemap = script.run(FakeQuery(km, verbose=opts.verbose))
+ except DupMap,err:
+ for m in err.args[0]:
+ rev_add(km.name,m)
+ except NoMap:
+ print "# %s could not be mapped." % (km.name,)
+ else:
+ rev_add(km.name,consolemap)
+
+for a,b in rev.iteritems():
+ print a," ".join(b)
+
+
--- keymapper-0.5.3.orig/test_gen_map.py
+++ keymapper-0.5.3/test_gen_map.py
@@ -22,6 +22,12 @@
from keymapper.fakequery import FakeQuery
import sys
+import codecs
+
+sys.stdout = codecs.getwriter("utf-8")(sys.stdout)
+
+import keymapper.tree
+keymapper.tree.trace = 1
try:
from cStringIO import StringIO
@@ -32,13 +38,14 @@
t = Tree()
for k in maps():
t.add(k)
+ print k.dump()
keymaps.append(k)
t.gen_tree()
buf = StringIO()
-gen_report(t,FileReporter(buf))
+gen_report(t,FileReporter(codecs.getwriter("utf-8")(buf)))
-g = open("test.dot","w")
+g = codecs.getwriter("latin1")(open("test.dot","w"),"replace")
gen_report(t,GraphReporter(g))
# 'buf' now contains our script.
@@ -50,8 +57,8 @@
for k in keymaps:
buf.seek(0,0)
print "Testing keymap %s" % (k.dump(),)
- s = Script(buf,FakeQuery(k))
- name = s.run()
+ s = Script(codecs.getreader("utf-8")(buf))
+ name = s.run(FakeQuery(k))
if name != k.name:
print "SCRIPT ERROR: %s != %s" % (name,k.name)
err += 1
--- keymapper-0.5.3.orig/Makefile
+++ keymapper-0.5.3/Makefile
@@ -3,3 +3,7 @@
compile:
# python setup.py
$(MAKE) -C keymapper/parse
+
+clean:
+ # python setup.py clean --all
+ $(MAKE) -C keymapper/parse clean
--- keymapper-0.5.3.orig/README
+++ keymapper-0.5.3/README
@@ -162,7 +162,13 @@
This is a question of last resort; it's asked only if keymaps cannot be
distinguished otherwise.
-This command will be accompanied by one YES and one GOTO command.
+This command will be accompanied by one YES and one NO command.
+
+FINDP char
+++++++++++
+
+Equivalent to FIND, except that the user is asked to consider only the
+primary symbols (i.e. Plain and Shift).
YES ##
++++++
--- keymapper-0.5.3.orig/changelog
+++ keymapper-0.5.3/changelog
@@ -1,4 +1,743 @@
ChangeSet
+ 1.69 05/04/01 13:35:59 smurf@smurf.noris.de +2 -0
+ fixed heuristics
+
+ keymapper/tree.py
+ 1.17 05/04/01 13:35:59 smurf@smurf.noris.de +12 -10
+ fixed heuristics
+
+ keymapper/keymap.py
+ 1.14 05/04/01 13:35:59 smurf@smurf.noris.de +1 -1
+ comment added
+
+ChangeSet
+ 1.68 05/04/01 12:26:19 smurf@smurf.noris.de +5 -0
+ Ignore control, spacing, and unassigned characters.
+
+ keymapper/tree.py
+ 1.16 05/04/01 12:26:19 smurf@smurf.noris.de +3 -3
+ Ignore control, spacing, and unassigned characters.
+
+ keymapper/keymap.py
+ 1.13 05/04/01 12:26:19 smurf@smurf.noris.de +6 -2
+ Ignore control, spacing, and unassigned characters.
+
+ keymapper/equiv.py
+ 1.5 05/04/01 12:26:19 smurf@smurf.noris.de +12 -1
+ Ignore control, spacing, and unassigned characters.
+
+ debian/changelog
+ 1.27 05/04/01 12:26:19 smurf@smurf.noris.de +7 -0
+ Ignore control, spacing, and unassigned characters.
+
+ChangeSet
+ 1.67 05/04/01 12:25:48 smurf@smurf.noris.de +1 -0
+ broken bar == solid bar
+ unified angle brackets
+
+ data/equivs
+ 1.10 05/04/01 12:25:47 smurf@smurf.noris.de +3 -5
+ broken bar == solid bar
+ unified angle brackets
+
+ BitKeeper/deleted/.del-maps.py~ce085e4573381ab2
+ 1.9 05/03/30 22:13:12 smurf@smurf.noris.de +0 -0
+ Delete: keymapper/parse/maps.py
+
+ChangeSet
+ 1.66 05/03/30 18:43:06 smurf@smurf.noris.de +2 -0
+ Added shortcuts to break excessively-broad recursion
+
+ keymapper/tree.py
+ 1.15 05/03/30 18:43:06 smurf@smurf.noris.de +61 -10
+ Added shortcuts to break excessively-broad recursion
+
+ debian/changelog
+ 1.26 05/03/30 18:43:06 smurf@smurf.noris.de +2 -1
+ Added shortcuts to break excessively-broad recursion
+
+ChangeSet
+ 1.65 05/03/30 18:41:19 smurf@smurf.noris.de +2 -0
+ Increased the penalty for ALT-key combinations
+
+ keymapper/keymap.py
+ 1.12 05/03/30 18:41:19 smurf@smurf.noris.de +1 -1
+ Increased the penalty for ALT-key combinations
+
+ debian/changelog
+ 1.25 05/03/30 18:41:19 smurf@smurf.noris.de +2 -1
+ Increased the penalty for ALT-key combinations
+
+ChangeSet
+ 1.64 05/03/30 18:28:03 smurf@smurf.noris.de +2 -0
+ more character stuff
+
+ debian/changelog
+ 1.24 05/03/30 18:28:03 smurf@smurf.noris.de +3 -1
+ more character stuff
+
+ data/equivs
+ 1.9 05/03/30 18:28:03 smurf@smurf.noris.de +3 -3
+ more stuff
+
+ChangeSet
+ 1.63 05/03/30 10:53:24 smurf@smurf.noris.de +2 -0
+ Adjust heuristics
+
+ keymapper/tree.py
+ 1.14 05/03/30 10:53:24 smurf@smurf.noris.de +2 -2
+ Adjust heuristics
+
+ debian/changelog
+ 1.23 05/03/30 10:53:24 smurf@smurf.noris.de +2 -1
+ Adjust heuristics
+
+ChangeSet
+ 1.62 05/03/30 10:30:39 smurf@smurf.noris.de +4 -0
+ Fix a crash generating sparse mapping trees
+
+ keymapper/tree.py
+ 1.13 05/03/30 10:30:38 smurf@smurf.noris.de +5 -3
+ Fix a crash generating sparse mapping trees
+
+ keymapper/graph.py
+ 1.11 05/03/30 10:30:38 smurf@smurf.noris.de +6 -4
+ Fix a crash generating sparse mapping trees
+
+ keymapper/file.py
+ 1.9 05/03/30 10:30:38 smurf@smurf.noris.de +4 -2
+ Fix a crash generating sparse mapping trees
+
+ debian/changelog
+ 1.22 05/03/30 10:30:38 smurf@smurf.noris.de +1 -0
+ Fix a crash generating sparse mapping trees
+
+ChangeSet
+ 1.61 05/03/30 10:30:09 smurf@smurf.noris.de +2 -0
+ Another round of lookalike characters
+
+ debian/changelog
+ 1.21 05/03/30 10:30:08 smurf@smurf.noris.de +6 -0
+ Another round of lookalike characters
+
+ data/equivs
+ 1.8 05/03/30 10:30:08 smurf@smurf.noris.de +4 -5
+ Another round of lookalike characters
+
+ChangeSet
+ 1.60 05/03/25 01:08:37 smurf@smurf.noris.de +1 -0
+ more debugging
+
+ keymapper/script.py
+ 1.9 05/03/25 01:08:37 smurf@smurf.noris.de +6 -0
+ more debugging
+
+ChangeSet
+ 1.59 05/03/25 01:06:53 smurf@smurf.noris.de +2 -0
+ Aliased cedilla and comma
+
+ debian/changelog
+ 1.20 05/03/25 01:06:53 smurf@smurf.noris.de +1 -0
+ Aliased cedilla and comma
+
+ data/equivs
+ 1.7 05/03/25 01:06:53 smurf@smurf.noris.de +2 -2
+ Aliased cedilla and comma
+
+ChangeSet
+ 1.58 05/03/25 01:01:34 smurf@smurf.noris.de +3 -0
+ add filter option
+
+ keymapper/tree.py
+ 1.12 05/03/25 01:01:34 smurf@smurf.noris.de +29 -1
+ add filter option
+
+ gen_keymap
+ 1.17 05/03/25 01:01:34 smurf@smurf.noris.de +6 -1
+ add filter option
+
+ debian/changelog
+ 1.19 05/03/25 01:01:34 smurf@smurf.noris.de +7 -0
+ add filter option
+
+ChangeSet
+ 1.57 05/02/27 20:36:24 smurf@smurf.noris.de +1 -0
+ ignore more test stuff
+
+ BitKeeper/etc/ignore
+ 1.14 05/02/27 17:41:32 smurf@smurf.noris.de +2 -0
+ added map_equiv.py seektester
+
+ChangeSet
+ 1.56 05/02/27 17:40:58 smurf@smurf.noris.de +2 -0
+ Install scripts
+
+ debian/rules
+ 1.5 05/02/27 17:40:58 smurf@smurf.noris.de +2 -0
+ Install scripts
+
+ debian/changelog
+ 1.18 05/02/27 17:40:58 smurf@smurf.noris.de +2 -1
+ Added script
+
+ChangeSet
+ 1.55 05/02/27 17:37:59 smurf@smurf.noris.de +1 -0
+ Map comparison for X
+
+ x2console_keymap
+ 1.4 05/02/27 17:37:59 smurf@smurf.noris.de +38 -45
+ Map comparison for X
+
+ChangeSet
+ 1.54 05/02/27 17:37:31 smurf@smurf.noris.de +4 -0
+ Query parser refactoring
+
+ test_x11.py
+ 1.2 05/02/27 17:37:31 smurf@smurf.noris.de +2 -2
+ Query parser refactoring
+
+ test_gen_map.py
+ 1.10 05/02/27 17:37:31 smurf@smurf.noris.de +2 -2
+ Query parser refactoring
+
+ keymapper/script.py
+ 1.8 05/02/27 17:37:31 smurf@smurf.noris.de +23 -10
+ Query parser refactoring
+
+ keymapper/fakequery.py
+ 1.10 05/02/27 17:37:31 smurf@smurf.noris.de +17 -7
+ Query parser refactoring
+
+ChangeSet
+ 1.53 05/02/27 17:37:08 smurf@smurf.noris.de +1 -0
+ Ignore Hyper_* symbols
+
+ keymapper/parse/linuxsyms.py
+ 1.6 05/02/27 17:37:08 smurf@smurf.noris.de +2 -1
+ Ignore Hyper_ too
+
+ChangeSet
+ 1.52 05/02/27 17:36:14 smurf@smurf.noris.de +2 -0
+ X11 parser extensions
+
+ keymapper/parse/x11.g
+ 1.2 05/02/27 17:36:14 smurf@smurf.noris.de +30 -15
+ X11 parser extensions, bugfix for subdirectories
+
+ data/symbols
+ 1.3 05/02/27 17:36:14 smurf@smurf.noris.de +173 -32
+ More symbols, some of them typos, for X11.
+
+ChangeSet
+ 1.51 05/02/27 17:34:50 smurf@smurf.noris.de +2 -0
+ More equivalents.
+
+ debian/changelog
+ 1.17 05/02/27 17:34:50 smurf@smurf.noris.de +2 -1
+ Various small bugfixes.
+
+ data/equivs
+ 1.6 05/02/27 17:34:50 smurf@smurf.noris.de +2 -1
+ More equivalent characters.
+
+ x2console_keymap
+ 1.3 05/02/27 13:16:26 smurf@smurf.noris.de +0 -0
+ Rename: x2c_keymap -> x2console_keymap
+
+ x2c_keymap
+ 1.2 05/02/27 13:16:11 smurf@smurf.noris.de +0 -0
+ bk cp test_x11.py x2c_keymap
+
+ChangeSet
+ 1.50 05/02/27 13:14:44 smurf@smurf.noris.de +1 -0
+ reverse keymap output for the tester
+
+ keymapper/keymap.py
+ 1.11 05/02/27 13:14:44 smurf@smurf.noris.de +30 -6
+ reverse keymap output for the tester
+
+ChangeSet
+ 1.49 05/02/27 13:13:22 smurf@smurf.noris.de +1 -0
+ Skip meta and alt tags
+
+ keymapper/parse/linuxsyms.py
+ 1.5 05/02/27 13:13:22 smurf@smurf.noris.de +2 -3
+ Skip meta and alt tags
+
+ChangeSet
+ 1.48 05/02/27 13:12:54 smurf@smurf.noris.de +2 -0
+ Speed up keymap filtering when keymaps have subsets.
+
+ keymapper/tree.py
+ 1.11 05/02/27 13:12:54 smurf@smurf.noris.de +13 -5
+ Speed up keymap filtering when keymaps have subsets.
+
+ debian/changelog
+ 1.16 05/02/27 13:12:54 smurf@smurf.noris.de +2 -1
+ Speed up keymap filtering when keymaps have subsets.
+
+ChangeSet
+ 1.47 05/02/27 13:11:43 smurf@smurf.noris.de +2 -0
+ Fix color/style assignment in graph output.
+
+ keymapper/graph.py
+ 1.10 05/02/27 13:11:43 smurf@smurf.noris.de +5 -2
+ Fix color/style assignment in graph output.
+
+ debian/changelog
+ 1.15 05/02/27 13:11:43 smurf@smurf.noris.de +2 -1
+ Fix color/style assignment in graph output.
+
+ x2c_keymap
+ 1.1 05/02/27 13:10:39 smurf@smurf.noris.de +74 -0
+
+ test_x11.py
+ 1.1 05/02/27 13:10:39 smurf@smurf.noris.de +74 -0
+
+ keymapper/parse/x11.g
+ 1.1 05/02/27 13:10:39 smurf@smurf.noris.de +247 -0
+
+ data/xkeys
+ 1.1 05/02/27 13:10:39 smurf@smurf.noris.de +58 -0
+
+ChangeSet
+ 1.46 05/02/27 13:10:39 smurf@smurf.noris.de +8 -0
+ Added an analyzer for X11 keymaps.
+
+ x2c_keymap
+ 1.0 05/02/27 13:10:39 smurf@smurf.noris.de +0 -0
+ BitKeeper file /daten/src/debian/keymapper/test_x11.py
+
+ test_x11.py
+ 1.0 05/02/27 13:10:39 smurf@smurf.noris.de +0 -0
+ BitKeeper file /daten/src/debian/keymapper/test_x11.py
+
+ keymapper/parse/x11.g
+ 1.0 05/02/27 13:10:39 smurf@smurf.noris.de +0 -0
+ BitKeeper file /daten/src/debian/keymapper/keymapper/parse/x11.g
+
+ debian/rules
+ 1.4 05/02/27 13:10:39 smurf@smurf.noris.de +1 -0
+ Install keycode table for X => console.
+
+ debian/control
+ 1.7 05/02/27 13:10:39 smurf@smurf.noris.de +1 -1
+ depend on X keymaps.
+
+ debian/changelog
+ 1.14 05/02/27 13:10:39 smurf@smurf.noris.de +1 -0
+ Added an analyzer for X11 keymaps.
+
+ data/xkeys
+ 1.0 05/02/27 13:10:39 smurf@smurf.noris.de +0 -0
+ BitKeeper file /daten/src/debian/keymapper/data/xkeys
+
+ data/symbols
+ 1.2 05/02/27 13:10:39 smurf@smurf.noris.de +945 -338
+ Lots of new stuff for X.
+
+ BitKeeper/etc/ignore
+ 1.13 05/02/27 13:10:39 smurf@smurf.noris.de +1 -0
+ added keymapper/parse/x11.py
+
+ChangeSet
+ 1.45 05/02/27 13:07:11 smurf@smurf.noris.de +1 -0
+ utf-8-ize sys.stdout
+
+ test_gen_map.py
+ 1.9 05/02/27 13:07:11 smurf@smurf.noris.de +2 -0
+ utf-8-ize sys.stdout
+
+ChangeSet
+ 1.44 05/02/27 13:06:05 smurf@smurf.noris.de +2 -0
+ Added lots of new lookalike Unicode characters,
+ from Unicode's NamesList.txt.
+
+ debian/changelog
+ 1.13 05/02/27 13:06:05 smurf@smurf.noris.de +2 -0
+ Added lots of new lookalike Unicode characters,
+ from Unicode's NamesList.txt.
+
+ data/equivs
+ 1.5 05/02/27 13:06:05 smurf@smurf.noris.de +142 -28
+ Added lots of new lookalike Unicode characters,
+ from Unicode's NamesList.txt.
+
+ChangeSet
+ 1.43 05/02/27 13:01:17 smurf@smurf.noris.de +3 -0
+ Reworked the step file interpreter to process multiple possible choices in parallel
+
+ keymapper/script.py
+ 1.7 05/02/27 13:01:17 smurf@smurf.noris.de +37 -31
+ Reworked the step file interpreter to process multiple possible choices in parallel
+
+ keymapper/fakequery.py
+ 1.9 05/02/27 13:01:17 smurf@smurf.noris.de +9 -5
+ Reworked the step file interpreter to process multiple possible choices in parallel
+
+ debian/changelog
+ 1.12 05/02/27 13:01:17 smurf@smurf.noris.de +7 -0
+ Reworked the step file interpreter to process multiple possible choices in parallel
+
+ChangeSet
+ 1.42 05/02/15 20:27:44 smurf@smurf.noris.de +3 -0
+ Version 0.4.3-1
+ change search path logic to allow arbitrary paths
+
+ keymapper/parse/linux.g
+ 1.3 05/02/15 20:27:43 smurf@smurf.noris.de +8 -15
+ change search path logic to allow arbitrary paths
+
+ gen_keymap
+ 1.16 05/02/15 20:27:43 smurf@smurf.noris.de +6 -5
+ change search path logic to allow arbitrary paths
+
+ debian/changelog
+ 1.11 05/02/15 20:27:43 smurf@smurf.noris.de +3 -2
+ Version 0.4.3-1
+ change search path logic to allow arbitrary paths
+
+ChangeSet
+ 1.41 05/02/14 22:52:07 smurf@smurf.noris.de +2 -0
+ Fix dependency on python-dev.
+
+ debian/control
+ 1.6 05/02/14 22:51:57 smurf@smurf.noris.de +1 -1
+ Fix dependency on python-dev.
+
+ debian/changelog
+ 1.10 05/02/14 22:51:57 smurf@smurf.noris.de +6 -0
+ Fix dependency on python-dev.
+
+ChangeSet
+ 1.40 05/02/14 18:53:31 smurf@smurf.noris.de +1 -0
+ ignore unicode files
+
+ BitKeeper/etc/ignore
+ 1.12 05/02/14 18:53:20 smurf@smurf.noris.de +2 -0
+ added NamesList.txt UnicodeData.txt
+
+ChangeSet
+ 1.39 05/02/14 18:52:52 smurf@smurf.noris.de +1 -0
+ depend on current Python 2.4
+
+ debian/control
+ 1.5 05/02/14 18:52:52 smurf@smurf.noris.de +1 -1
+ depend on current Python 2.4
+
+ChangeSet
+ 1.38 05/02/14 18:49:16 smurf@smurf.noris.de +1 -0
+ unstable => hoary
+
+ debian/changelog
+ 1.9 05/02/14 18:49:15 smurf@smurf.noris.de +6 -6
+ unstable => hoary
+
+ChangeSet
+ 1.37 05/02/04 23:45:32 smurf@smurf.noris.de +1 -0
+ colorize the graph
+
+ keymapper/graph.py
+ 1.9 05/02/04 23:45:28 smurf@smurf.noris.de +20 -13
+ colorize
+
+ChangeSet
+ 1.36 05/02/04 23:45:10 smurf@smurf.noris.de +2 -0
+ Small test fixes
+
+ test_gen_map.py
+ 1.8 05/02/04 23:45:08 smurf@smurf.noris.de +1 -1
+ Use utf-8 in map reader
+
+ gen_keymap
+ 1.15 05/02/04 23:45:07 smurf@smurf.noris.de +27 -0
+ Add test option to run the generated maps
+
+ChangeSet
+ 1.35 05/02/04 23:44:27 smurf@smurf.noris.de +7 -0
+ Fix a couple of annoying bugs
+
+ keymapper/tree.py
+ 1.10 05/02/04 23:44:20 smurf@smurf.noris.de +30 -4
+ Use SymSet from keymapper.keymap
+ Check char type to prioritize better
+ Complain when a symbol doesn't print
+
+ keymapper/script.py
+ 1.6 05/02/04 23:44:19 smurf@smurf.noris.de +31 -5
+ fix multi-char "ask"
+ evaluate printed spacing symbols and control chars
+
+ keymapper/keymap.py
+ 1.10 05/02/04 23:44:19 smurf@smurf.noris.de +11 -4
+ Use NFC internally
+ add Set type to enfoce that
+
+ keymapper/file.py
+ 1.8 05/02/04 23:44:18 smurf@smurf.noris.de +21 -2
+ Print spacing symbols and some control chars
+
+ keymapper/fakequery.py
+ 1.8 05/02/04 23:44:17 smurf@smurf.noris.de +9 -8
+ Fix multi-char "ask"
+
+ keymapper/fakemaps.py
+ 1.7 05/02/04 23:44:17 smurf@smurf.noris.de +1 -1
+ Fix coding: header
+
+ keymapper/equiv.py
+ 1.4 05/02/04 23:44:15 smurf@smurf.noris.de +9 -3
+ Switch to NFC encoding internally
+
+ChangeSet
+ 1.34 05/02/03 13:57:10 smurf@smurf.noris.de +1 -0
+ fix priorities
+
+ keymapper/tree.py
+ 1.9 05/02/03 13:57:09 smurf@smurf.noris.de +38 -25
+ priority adjust
+
+ChangeSet
+ 1.33 05/02/03 11:39:16 smurf@smurf.noris.de +5 -0
+ Cleanup: The main programs are responsible for equipping the streams
+ passed into keymapper.* with appropriate codecs.
+
+ test_gen_map.py
+ 1.7 05/02/03 11:39:13 smurf@smurf.noris.de +4 -3
+ codec-ize the file streams here
+
+ keymapper/file.py
+ 1.7 05/02/03 11:39:13 smurf@smurf.noris.de +2 -2
+ don't encode, that's supposed to be done in the file
+
+ keymapper/fakequery.py
+ 1.7 05/02/03 11:39:13 smurf@smurf.noris.de +1 -1
+ don't utf8-decode here, input is supposed to be Unicode already
+
+ keymapper/fakemaps.py
+ 1.6 05/02/03 11:39:13 smurf@smurf.noris.de +2 -2
+ add a nice utf-8 character to the test to make it mroe interesting
+
+ debian/changelog
+ 1.8 05/02/03 11:39:13 smurf@smurf.noris.de +3 -1
+ Cleanup: The main programs are responsible for equipping the streams
+ passed into keymapper.* with appropriate codecs.
+
+ChangeSet
+ 1.32 05/02/03 11:31:42 smurf@smurf.noris.de +1 -0
+ cleanup, now works with Python 2.3
+
+ gen_keymap
+ 1.14 05/02/03 11:31:41 smurf@smurf.noris.de +3 -3
+ drop the subprocess import
+ syntax niceties
+
+ChangeSet
+ 1.31 05/02/03 11:31:16 smurf@smurf.noris.de +2 -0
+ added more interesting letters
+
+ debian/changelog
+ 1.7 05/02/03 11:31:15 smurf@smurf.noris.de +6 -0
+ added more interesting letters
+
+ data/equivs
+ 1.4 05/02/03 11:31:15 smurf@smurf.noris.de +22 -21
+ more interesting letters
+
+ChangeSet
+ 1.30 05/02/02 19:30:45 smurf@smurf.noris.de +2 -0
+ Add one and zero.
+ Conflate L and I.
+
+ debian/changelog
+ 1.6 05/02/02 19:30:44 smurf@smurf.noris.de +7 -0
+ Add one and zero.
+ Conflate L and I.
+
+ data/equivs
+ 1.3 05/02/02 19:30:44 smurf@smurf.noris.de +2 -3
+ Add one and zero.
+ Conflate L and I.
+
+ChangeSet
+ 1.29 05/02/02 19:28:52 smurf@smurf.noris.de +7 -0
+ Extension: We print only those characters under consideration in the present step.
+
+ keymapper/tree.py
+ 1.8 05/02/02 19:28:52 smurf@smurf.noris.de +30 -11
+ core code to display only those characters that actually appear on the keys
+
+ keymapper/keymap.py
+ 1.9 05/02/02 19:28:52 smurf@smurf.noris.de +4 -1
+ add list of symbols actually present
+
+ keymapper/graph.py
+ 1.8 05/02/02 19:28:52 smurf@smurf.noris.de +4 -3
+ fix output code to deal with symbol stuff
+
+ keymapper/file.py
+ 1.6 05/02/02 19:28:52 smurf@smurf.noris.de +5 -4
+ There may be more than one symbol -- print correctly
+
+ keymapper/fakequery.py
+ 1.6 05/02/02 19:28:52 smurf@smurf.noris.de +3 -3
+ fixed processing for symbols that aren't present
+
+ keymapper/equiv.py
+ 1.3 05/02/02 19:28:52 smurf@smurf.noris.de +5 -2
+ add lowercase and uppercase versions
+
+ debian/changelog
+ 1.5 05/02/02 19:28:52 smurf@smurf.noris.de +7 -0
+ print only those characters under consideration at this step.
+
+ChangeSet
+ 1.28 05/02/02 17:08:40 smurf@smurf.noris.de +1 -0
+ add more lookalike characters
+
+ data/equivs
+ 1.2 05/02/02 17:08:40 smurf@smurf.noris.de +33 -22
+ even more lookalike characters
+
+ChangeSet
+ 1.27 05/02/02 16:17:08 smurf@smurf.noris.de +1 -0
+ bad file name in keymapper/equiv.py
+
+ keymapper/equiv.py
+ 1.2 05/02/02 16:17:08 smurf@smurf.noris.de +2 -2
+ bad file name
+
+ keymapper/equiv.py
+ 1.1 05/02/02 16:14:49 smurf@smurf.noris.de +79 -0
+
+ data/equivs
+ 1.1 05/02/02 16:14:49 smurf@smurf.noris.de +30 -0
+
+ChangeSet
+ 1.26 05/02/02 16:14:49 smurf@smurf.noris.de +13 -0
+ Add character equivalence table.
+
+ test_gen_map.py
+ 1.6 05/02/02 16:14:49 smurf@smurf.noris.de +4 -0
+ Add character equivalence table.
+
+ keymapper/tree.py
+ 1.7 05/02/02 16:14:49 smurf@smurf.noris.de +19 -8
+ Add character equivalence table.
+
+ keymapper/script.py
+ 1.5 05/02/02 16:14:49 smurf@smurf.noris.de +2 -2
+ Add character equivalence table.
+
+ keymapper/parse/linuxsyms.py
+ 1.4 05/02/02 16:14:49 smurf@smurf.noris.de +5 -0
+ Add character equivalence table.
+
+ keymapper/keymap.py
+ 1.8 05/02/02 16:14:49 smurf@smurf.noris.de +3 -1
+ Add character equivalence table.
+
+ keymapper/graph.py
+ 1.7 05/02/02 16:14:49 smurf@smurf.noris.de +9 -2
+ Add character equivalence table.
+
+ keymapper/file.py
+ 1.5 05/02/02 16:14:49 smurf@smurf.noris.de +4 -2
+ Add character equivalence table.
+
+ keymapper/fakequery.py
+ 1.5 05/02/02 16:14:49 smurf@smurf.noris.de +13 -6
+ Add character equivalence table.
+
+ keymapper/fakemaps.py
+ 1.5 05/02/02 16:14:49 smurf@smurf.noris.de +2 -2
+ Add character equivalence table.
+
+ keymapper/equiv.py
+ 1.0 05/02/02 16:14:49 smurf@smurf.noris.de +0 -0
+ BitKeeper file /daten/src/debian/keymapper/keymapper/equiv.py
+
+ debian/rules
+ 1.3 05/02/02 16:14:49 smurf@smurf.noris.de +1 -0
+ Install character equivalence table.
+
+ debian/changelog
+ 1.4 05/02/02 16:14:49 smurf@smurf.noris.de +6 -0
+ Add character equivalence table.
+
+ data/equivs
+ 1.0 05/02/02 16:14:49 smurf@smurf.noris.de +0 -0
+ BitKeeper file /daten/src/debian/keymapper/data/equivs
+
+ChangeSet
+ 1.25 05/02/02 16:14:28 smurf@smurf.noris.de +1 -0
+ Add option to skip tables (if they're identical to other tables)
+
+ gen_keymap
+ 1.13 05/02/02 16:14:28 smurf@smurf.noris.de +8 -0
+ Add option to skip tables (if they're identical to other tables)
+
+ChangeSet
+ 1.24 05/02/02 09:50:40 smurf@smurf.noris.de +1 -0
+ ignore changelog
+
+ BitKeeper/etc/ignore
+ 1.11 05/02/02 09:50:30 smurf@smurf.noris.de +1 -0
+ added changelog
+
+ChangeSet
+ 1.23 05/02/02 09:50:27 smurf@smurf.noris.de +3 -0
+ more build and installation stuff
+
+ keymapper/parse/linuxsyms.py
+ 1.3 05/02/02 09:50:27 smurf@smurf.noris.de +1 -1
+ read the symfile from somewhere sane
+
+ gen_keymap
+ 1.12 05/02/02 09:50:27 smurf@smurf.noris.de +11 -8
+ input file format option
+
+ debian/rules
+ 1.2 05/02/02 09:50:27 smurf@smurf.noris.de +6 -1
+ build the parser
+ install the symbol map
+
+ChangeSet
+ 1.22 05/02/02 09:29:22 smurf@smurf.noris.de +3 -0
+ Added option to set the file system root.
+
+ keymapper/parse/linux.g
+ 1.2 05/02/02 09:29:22 smurf@smurf.noris.de +5 -1
+ Added option to set the file system root.
+
+ gen_keymap
+ 1.11 05/02/02 09:29:22 smurf@smurf.noris.de +6 -1
+ Added option to set the file system root.
+
+ debian/changelog
+ 1.3 05/02/02 09:29:22 smurf@smurf.noris.de +1 -0
+ Added option to set the file system root.
+
+ChangeSet
+ 1.21 05/02/02 08:58:42 smurf@smurf.noris.de +1 -0
+ fixed the dependencies
+
+ debian/control
+ 1.4 05/02/02 08:58:42 smurf@smurf.noris.de +1 -1
+ dependency
+
+ debian/exporter
+ 1.1 05/02/02 08:56:54 smurf@smurf.noris.de +10 -0
+
+ChangeSet
+ 1.20 05/02/02 08:56:54 smurf@smurf.noris.de +1 -0
+ added exporter for changelog
+
+ debian/exporter
+ 1.0 05/02/02 08:56:54 smurf@smurf.noris.de +0 -0
+ BitKeeper file /daten/src/debian/keymapper/debian/exporter
+
+ChangeSet
1.19 05/02/02 08:54:14 smurf@smurf.noris.de +1 -0
ignore stuff
--- keymapper-0.5.3.orig/gen_keymap.1
+++ keymapper-0.5.3/gen_keymap.1
@@ -0,0 +1,62 @@
+.Dd September 5, 2006
+.Os Ubuntu
+.ds volume-operating-system Ubuntu
+.Dt GEN_KEYMAP 1
+.Sh NAME
+.Nm gen_keymap
+.Nd generate a keyboard map decision tree
+.Sh SYNOPSIS
+.Nm
+.Ar list ...
+.Sh DESCRIPTION
+.Nm
+generates a decision tree from a set of keyboard maps which can be used to
+help a user decide which keyboard map to use.
+The program using the decision tree typically asks the user to press some
+keys; at each step, it examines the returned keycode and uses it to prune
+the list of possible keyboard maps until there is only one left.
+.Sh OPTIONS
+.Bl -tag -width 4n
+.It Fl Fl version
+Show program's version number and exit.
+.It Fl ? , Fl Fl help
+Show help text.
+.It Fl v , Fl Fl verbose
+Be more verbose.
+.It Fl m Ns Ar MINLEN , Fl Fl minlen Ns = Ns Ar MINLEN
+Too-short keymaps are skipped (default: 30 entries).
+.It Fl g , Fl Fl graph
+Generate a hopefully-nice-looking .dot file.
+.It Fl Fl maps
+Print the to-be-processed keymaps
+.It Fl i , Fl Fl installer
+Input files are in d-i map form.
+.It Fl I Ns Ar DIRS , Fl Fl inc Ns = Ns Ar DIRS , Fl Fl include Ns = Ns Ar DIRS
+Add a directory to the search path.
+.It Fl o Ns Ar FILENAME , Fl Fl output Ns = Ns Ar FILENAME
+Set output file (default: stdout).
+.It Fl f Ns Ar FILTER , Fl Fl filter Ns = Ns Ar FILTER
+Include only the branches leading to these keymaps.
+.It Fl u Ns Ar USEONLY , Fl Fl useonly Ns = Ns Ar USEONLY
+Start generating the tree based only on these keymaps.
+(The difference between
+.Fl Fl filter
+and
+.Fl Fl useonly
+is that the former generates the whole tree and then prunes it, while the
+latter only generates a reduced tree to begin with.
+This may have implications for performance on large trees.)
+.It Fl s Ns Ar SKIP , Fl Fl skip Ns = Ns Ar SKIP
+Keymaps to skip.
+.It Fl t , Fl Fl test
+Test the generated maps.
+.It Fl Fl interactive
+Ask user to choose among indistinguishable keymaps.
+.El
+.Sh AUTHORS
+.An -nosplit
+.Nm
+was written by
+.An "Matthias Urlichs" Aq smurf@debian.org .
+This manual page was written by
+.An "Colin Watson" Aq cjwatson@ubuntu.com .
--- keymapper-0.5.3.orig/keymapper/graph.py
+++ keymapper-0.5.3/keymapper/graph.py
@@ -16,15 +16,26 @@
from keymapper.tree import Reporter
import sys
import unicodedata
+from keymapper.equiv import get_sym, looks_like
+from random import uniform
+
+colors = ("red","green","blue","magenta","black","grey","yellowgreen","purple","plum")
+styles = ("solid","dotted","dashed")
def uname(sym):
try:
+ sym=unicodedata.normalize("NFC",sym)
return unicodedata.name(unicode(sym)).lower()
except ValueError:
return "U+%4x" % ord(sym)
+ except TypeError:
+ return sym
+
+#def uname(sym):
+# return ", ".join([_uname(s) for s in sym])
def symnums(syms):
- return ".".join([str(ord(s)) for s in syms])
+ return ".".join([str(looks_like(s)) for s in syms])
class GraphReporter(Reporter):
"""Report the result as a graphviz .dot file"""
@@ -43,32 +54,54 @@
def keymap(self,map):
"""This steps selects a unique keymap"""
- print >>self.file, '"Step %d" [label="Map: %s"]' % (self.nr,map.name)
+ print >>self.file, '"Step %d" [label="Map: %s", shape="box"]' % (self.nr,map.name)
def symbols(self,symbols):
"""Start a choice: display these symbols"""
- self.syms = symbols
+ self.syms = [ (s,c) for s,c in symbols ]
+ self.color=colors[int(uniform(0,len(colors)))]
+ self.style=styles[int(uniform(0,len(styles)))]
+ # copy, for we need it more than once
def choice(self,code,nextstep):
"""Choice: This keycode leads to that step"""
syms=[]
- for s,c in self.syms.items():
+ for s,c in self.syms:
if code in c:
syms.append(s)
- print >>self.file, '"Step %d" -> "S_%d_%s_%d"' % (self.nr,self.nr, symnums(syms), code)
- print >>self.file, '"S_%d_%s_%d" -> "Step %d"' % (self.nr,symnums(syms), code, nextstep.step)
- print >>self.file, '"S_%d_%s_%d" [ label="%s -> %d" ]' % (self.nr, symnums(syms), code, "\\n".join([uname(s) for s in syms]), code)
+ print >>self.file, '"Step %d" [ color="%s", shape="box" ] ' % (self.nr, self.color)
+ print >>self.file, '"Step %d" -> "S_%d_%s_%d" [ color="%s", style="%s", weight=2 ] ' % (self.nr,self.nr, symnums(syms), code, self.color,self.style)
+ print >>self.file, '"S_%d_%s_%d" -> "Step %d" [ color="%s", style="%s" ] ' % (self.nr,symnums(syms), code, nextstep.step, self.color,self.style)
+ print >>self.file, '"S_%d_%s_%d" [ label="%s -> %d", color="%s" ]' % (self.nr, symnums(syms), code, "\\n".join([uname(s) for s in syms]), code, self.color)
def ask(self,sym,no,yes):
"""Ask whether that symbol is visible"""
- print >>self.file, '"Step %d" [ label="Step %d\\nCheck for %s" ]' % (self.nr,self.nr,uname(sym))
- print >>self.file, '"Step %d" -> "AY-%d" -> "Step %d"' % (self.nr,self.nr,yes.step)
- print >>self.file, '"AY-%d" [ label="Yes" ]' % (self.nr,)
- print >>self.file, '"Step %d" -> "AN-%d" -> "Step %d"' % (self.nr,self.nr,no.step)
- print >>self.file, '"AN-%d" [ label="No" ]' % (self.nr,)
+ self.color=colors[int(uniform(0,len(colors)))]
+ self.style=styles[int(uniform(0,len(styles)))]
+
+ print >>self.file, '"Step %d" [ shape="box", label="Step %d\\nCheck for %s", color="%s" ]' % (self.nr,self.nr,"\\nor ".join([uname(s) for s in sym]), self.color)
+ if yes:
+ print >>self.file, '"Step %d" -> "AY-%d" -> "Step %d" [ color="%s", style="%s", weight=2 ]' % (self.nr,self.nr,yes.step, self.color,self.style)
+ print >>self.file, '"AY-%d" [ label="Yes", color="%s" ]' % (self.nr,self.color)
+ if no:
+ print >>self.file, '"Step %d" -> "AN-%d" -> "Step %d" [ color="%s", style="%s", weight=2 ]' % (self.nr,self.nr,no.step, self.color,self.style)
+ print >>self.file, '"AN-%d" [ label="No", color="%s" ]' % (self.nr,self.color)
+
+ def ask_no_alt(self,sym,no,yes):
+ """Ask whether that symbol is visible on primary keys"""
+ self.color=colors[int(uniform(0,len(colors)))]
+ self.style=styles[int(uniform(0,len(styles)))]
+
+ print >>self.file, '"Step %d" [ shape="box", label="Step %d\\nCheck for %s\\n(no Alt*)", color="%s" ]' % (self.nr,self.nr,"\\nor ".join([uname(s) for s in sym]), self.color)
+ if yes:
+ print >>self.file, '"Step %d" -> "AY-%d" -> "Step %d" [ color="%s", style="%s", weight=2 ]' % (self.nr,self.nr,yes.step, self.color,self.style)
+ print >>self.file, '"AY-%d" [ label="Yes", color="%s" ]' % (self.nr,self.color)
+ if no:
+ print >>self.file, '"Step %d" -> "AN-%d" -> "Step %d" [ color="%s", style="%s", weight=2 ]' % (self.nr,self.nr,no.step, self.color,self.style)
+ print >>self.file, '"AN-%d" [ label="No", color="%s" ]' % (self.nr,self.color)
def finish(self):
"""Conclude this step"""
--- keymapper-0.5.3.orig/keymapper/tree.py
+++ keymapper-0.5.3/keymapper/tree.py
@@ -35,12 +35,28 @@
"""
from sets import Set,ImmutableSet
+from keymapper.equiv import get_sym,chartype
+from keymapper.keymap import SymSet
+from unicodedata import category
# follow what's happening?
trace=False
last_trace=0
from time import time
+interactive=False
+
+charhash={}
+def chartype(c):
+ if c in charhash:
+ return charhash[c]
+ charhash[c] = h = category(c)[0]
+ return h
+
+class NoShownSyms(Exception):
+ """A step doesn't actually display anything"""
+ pass
+
class DupKeycode(Exception):
"""A key code has been added to a Choice node twice"""
pass
@@ -73,6 +89,9 @@
def ask(self,sym,no,yes):
"""Ask whether that symbol is visible"""
raise NotImplementedError
+ def ask_no_alt(self,sym,no,yes):
+ """Ask whether that symbol is visible on primary keys"""
+ raise NotImplementedError
def finish(self):
"""Conclude this step"""
pass
@@ -86,8 +105,9 @@
class Node(object):
"""a generic node in the keymap decision tree"""
- def __init__(self):
+ def __init__(self,maps):
self.delay = 0
+ self.maps = maps
def __eq__(self,other):
"""Compare this node to another"""
@@ -102,6 +122,7 @@
def simplify(self,cache):
"""Check whether this node is redundant"""
self = self._simplify(cache)
+ if self is None: return None
key = self.key()
if key in cache: return cache[key]
cache[key] = self
@@ -143,7 +164,8 @@
self.step = nr
nr += 1
for c in self: # iterates the children
- nr = c.seq1(nr)
+ if c is not None:
+ nr = c.seq1(nr)
self.maxstep = nr
return nr
@@ -158,15 +180,35 @@
return
yield self
for c in self: # iterates over child nodes
- for n in c.seq2():
- yield n
+ if c is not None:
+ for n in c.seq2():
+ yield n
+
+ def visible_syms(self, keys):
+ """List symbols which actually correspond to keycodes"""
+ num=0
+ for sym,codes in keys:
+ seen = SymSet()
+ for s in get_sym(sym):
+ for m in self.maps:
+ if s not in m.seen: continue
+ if s in seen: continue
+ seen.add(s)
+ break
+ for s in seen:
+ num += 1
+ yield s,codes
+ if not num:
+ raise NoShownSyms
+
+
class Choice(Node):
"""a node in the keymap decision tree which asks for one of a number
of symbols and selects by the keycode that's returned"""
- def __init__(self, sym2codes, code2map):
- Node.__init__(self)
+ def __init__(self, maps, sym2codes, code2map):
+ Node.__init__(self, maps)
self.sym2codes = sym2codes # list of symbols to display => key codes
self.children = code2map # key code => node or keymap
@@ -195,7 +237,7 @@
def key(self):
syms = [ sym for sym in self.sym2codes ]
syms.sort()
- ret = "Q:"+":".join(self.sym2codes.keys())+":"
+ ret = "Q:"+":".join(["".join(get_sym(s)) for s in self.sym2codes.keys()])+":"
codes = self.children.keys()
codes.sort()
for code in codes:
@@ -221,9 +263,23 @@
return self
return uniq
+ def filter(self,maps):
+ """Drop branches not in map list"""
+ for code,node in self.children.items():
+ if node:
+ node = node.filter(maps)
+ if not node:
+ del self.children[code]
+
+ # Throw this node away if it doesn't decide anything any more
+ if not self.children:
+ return None
+ return self
+
def report(self,gen):
gen.step(self.step)
- gen.symbols(self.sym2codes)
+
+ gen.symbols(self.visible_syms(self.sym2codes.iteritems()))
for code,node in self.children.items():
gen.choice(code,node)
gen.finish()
@@ -231,8 +287,8 @@
class Ask(Node):
"""a node in the keymap decision tree which asks whether a given keyboard symbol exists"""
- def __init__(self, sym,no,yes):
- Node.__init__(self)
+ def __init__(self, maps, sym,no,yes):
+ Node.__init__(self,maps)
self.sym = sym
self.no = no
self.yes = yes
@@ -265,16 +321,32 @@
if self.no: return self.no
return self.yes
+ def filter(self,maps):
+ if self.yes:
+ self.yes = self.yes.filter(maps)
+ if self.no:
+ self.no = self.no.filter(maps)
+ if not self.yes and not self.no: return None
+ return self
+
+ def report(self,gen):
+ gen.step(self.step)
+ gen.ask([s for s,c in self.visible_syms([(self.sym,None)])], self.no, self.yes)
+ gen.finish()
+
+class AskNoAlt(Ask):
+ """same as Ask, not without Alt* keys"""
def report(self,gen):
gen.step(self.step)
- gen.ask(self.sym, self.no, self.yes)
+ gen.ask_no_alt([s for s,c in self.visible_syms([(self.sym,None)])], self.no, self.yes)
gen.finish()
class Found(Node):
"""A node which resolves to a single keymap"""
def __init__(self, node):
- Node.__init__(self)
+ Node.__init__(self,[node])
self.node = node
+ self.maps = [node]
def __iter__(self):
return ().__iter__()
@@ -290,6 +362,11 @@
if self.node is None: return None
return self
+ def filter(self,maps):
+ print "%s %s" % (self.node,maps)
+ if self.node.name not in maps: return None
+ return self
+
def report(self,gen):
gen.step(self.step)
gen.keymap(self.node)
@@ -306,6 +383,9 @@
class SingleMapping(Exception):
pass
+class SingleMappingNoAlt(Exception):
+ pass
+
# The main code starts here.
@@ -316,23 +396,32 @@
self.maps=Set() # list of keyboards
self.symbols={} # symbol => [nummaps,sumpriority]
self._id = 0
+ self.interactively_skipped = Set()
def add(self,map):
"""add a keymap to the list"""
self.maps.add(map)
- def gen_tree(self):
+ def __iter__(self):
+ return iter(self.maps)
+
+ def gen_tree(self, *filter):
"""generate a decision tree"""
cache={}
self.tree = self._gen_tree(self.maps)
self.tree = self.tree.simplify(cache)
+ if self.tree and filter:
+ self.tree.filter(filter)
def report(self,gen):
"""Emit the generated nodes by passing them to a generator."""
self.tree.seq1(0)
for n in self.tree.seq2():
n.report(gen)
+ if interactive and self.interactively_skipped:
+ print >>sys.stderr, "Skipped these keymaps interactively:",
+ print >>sys.stderr, ' '.join(self.interactively_skipped)
def _gen_tree(self, maps, xsyms=None):
"""One step of the selection algorithm."""
@@ -354,11 +443,14 @@
syms = ImmutableSet() # selected symbols
codes = {} # keycode => number of selected keymaps
for alt in range(2): # Try to get one alternate mapping
+ steps=0 # for reporting
+ bt_steps=0 # for limiting backtracks
+ bt_level=None
if trace>1:
if alt:
- print "*** Alternate:",syms
+ print "*** Alternate:"," ".join(["".join(get_sym(s)) for s in syms]).encode("utf-8")
else:
- print "*** Start:",_id,len(maps),"maps:",",".join([m.name for m in maps])
+ print "*** Start:",_id,len(maps),"maps:",",".join([m.name for m in maps]).encode("utf-8")
try:
open_map = ImmutableSet(maps)
track = []
@@ -369,12 +461,17 @@
chooser=None
while open_map:
+ # Check if we overdid it
+ steps += 1
+ if alt and steps>1000:
+ break
+
if not chooser:
global last_trace
if trace>2 or trace and time()-last_trace > 3 and len(open_map)>2:
- print "choose from",",".join([m.name for m in open_map])
+ print "Step %d %d: choose from %s" % (steps, len(track), ",".join([m.name for m in open_map]))
last_trace=time()
- chooser = choose_sym(open_map, syms.union(xsyms), xcode=codes, all_maps=maps, alt=alt)
+ chooser = choose_sym(open_map, syms.union(xsyms), xcode=codes, all_maps=maps, alt=alt, depth=len(track))
while True:
# Loop invariant:
@@ -392,9 +489,27 @@
# This chooser is unable to return a
# suitable choice, so backtrack.
if trace>1: print "exhausted",",".join([m.name for m in open_map])
-
if not track:
raise AlgorithmProblem(syms,maps,open_map)
+
+ # Check if we need to backtrack more aggressively.
+ # Otherwise we run for *ages*.
+ bt_steps += 1
+ if bt_steps > 100000:
+ bt_steps=0
+ if bt_level is None or bt_level > len(track):
+ bt_level = len(track)
+ if trace>1: print "Backtrack stepup",bt_level
+ else:
+ track = track[0:bt_level]
+ # Drop off if we stepped way back
+ # one and two levels
+ if bt_level <= 1:
+ bt_level = None
+ else:
+ bt_level = bt_level-1
+ if trace>1: print "Backtrack stepdown",bt_level
+
chooser,syms,codes,open_map = track.pop()
if trace>1: print "... back to",",".join([m.name for m in open_map])
@@ -402,7 +517,7 @@
raise AlgorithmProblem(syms,maps,open_map)
else:
- if trace>2: print "got",sym.encode("utf-8"),
+ if trace>2: print "got",str(sym).encode("utf-8"),
# We have a possible candidate.
try:
# Get the list of keymaps chosen by it
@@ -417,13 +532,23 @@
if trace>2: print "no mapping"
continue
- except SingleMapping,exc:
+ except (SingleMapping,SingleMappingNoAlt),exc:
# This is a possible yes/no question.
# If that's the best we can do, OK.
map_yes,map_no = exc.args
- if trace>2: print "single mapping: yes",len(map_yes),"no",len(map_no)
+ if trace>2:
+ if exc == SingleMapping:
+ print "single mapping:",
+ else:
+ print "single mapping no alt:",
+ print "yes",len(map_yes),"no",len(map_no),"open",len(open_map),"track",len(track)
if not track:
- return Ask(sym,
+ if exc == SingleMapping:
+ return Ask(maps, sym,
+ yes=self._gen_tree(map_yes),
+ no=self._gen_tree(map_no))
+ else:
+ return AskNoAlt(maps, sym,
yes=self._gen_tree(map_yes),
no=self._gen_tree(map_no))
@@ -477,6 +602,24 @@
if trace:
for m in open_map:
print >>sys.stderr, m.dump().encode("utf-8")
+ if interactive:
+ print >>sys.stderr, "Enter a preferred keymap (or nothing to quit):"
+ while True:
+ line = sys.stdin.readline().strip()
+ if line:
+ for m in open_map:
+ if m.name == line:
+ for other in open_map:
+ if other.name != line:
+ self.interactively_skipped.add(other.name)
+ return Found(m)
+ else:
+ print >>sys.stderr, "%s not found." % line
+ else:
+ print >>sys.stderr, "OK, giving up."
+ print >>sys.stderr, "Skipped these keymaps interactively:",
+ print >>sys.stderr, ' '.join(self.interactively_skipped)
+ break
sys.exit(1)
# Now build a Choice node from what we have found.
@@ -500,39 +643,59 @@
for code,map in codes.items():
print code,map
print "*** end ***",_id,len(maps),"***", \
- " ".join(["%s:%s" % (s,",".join([str(cc) for cc in c])) for s,c in sym2codes.items()]).encode("utf-8")
+ " ".join(["%s:%s" % (s,",".join(["".join(get_sym(cc)) for cc in c])) for s,c in sym2codes.items()]).encode("utf-8")
print
for code,map in codes.items():
codes[code] = self._gen_tree(map)
- ch = Choice(sym2codes, codes)
+ ch = Choice(maps, sym2codes, codes)
return ch
-def choose_sym(maps, xsym=(), xcode=(), all_maps=(), alt=0):
+def choose_sym(maps, xsym=(), xcode=(), all_maps=(), alt=0, depth=None):
"""Find the 'best' symbol in a set of keymaps"""
symdata={} # symbol => [ preference, number of keymaps with that symbol,
# mapping keycode => number of keyboards with that mapping
+ symdata_no_alt={} # same, but without "alt" keys
+
+ supermaps = Set()
+ do_log=0
+ if depth is not None:
+ if depth >= 2:
+ depth = None # 10*depth
+ elif depth == 1:
+ do_log=2
+ depth = 30
+ else: # 0
+ do_log=1
+ depth = 10
# If any of these maps is a subset of one of all_maps, drop out.
# Reason: We can't put up a "do you have this key" question now.
for m in maps:
for am in all_maps:
- if am not in maps and m.is_submap(am):
- return
+ if m.is_submap(am):
+ if am not in maps:
+ return
+ supermaps.add(am)
+
+ # Otherwise, filter supermaps
+ if len(maps)-len(supermaps) <= 1:
+ supermaps = ()
for map in maps:
+ if map in supermaps: continue
for sym in map.symbols():
if sym in xsym: continue
if sym not in symdata:
symdata[sym] = [ 0, 0, {} ]
data = symdata[sym]
+ pri = 0
# Heuristic: We try to block keys on ALT mappings, which
# have values smaller than zero, by never raising the value
# if it ever goes below zero
- pri = map.priority(sym)
# if data[0] >= 0:
# if pri is None:
# pass
@@ -543,27 +706,39 @@
# if pri < 0:
# data[0] += pri
- if ord(sym) > 0x40 and ord(sym) <= 0x5a:
- if alt:
- pri += 300
- else:
- pri += 5000
- elif ord(sym) > 0x60 and ord(sym) <= 0x7a:
- if alt:
- pri += 300
- else:
- pri += 5000
- elif ord(sym) > 128:
- pri += 800
- elif ord(sym) < 32 or ord(sym) == 127:
- pri += -300
- else:
- if alt:
- pri += 600
+ for s in get_sym(sym):
+
+ if len(s) != 1:
+ pri += 100
+ elif ord(s) > 0x40 and ord(s) <= 0x5a:
+ if alt:
+ pri += 300
+ else:
+ pri += 2000
+ elif ord(s) > 0x60 and ord(s) <= 0x7a:
+ if alt:
+ pri += 300
+ else:
+ pri += 2000
+ elif ord(s) <= 32 or ord(s) == 127:
+ pri += -100000 # ... likewise ...
else:
- pri += 1000
+ cat = chartype(s)[0]
+ if cat == "L":
+ if alt:
+ pri += 600
+ else:
+ pri += 1500
+ elif cat == "Z" or cat == "C" or cat == "U":
+ pri -= 100000 # shouldn't happen, but ...
+ elif cat == "M":
+ pri -= 10000 # non-spacing modifiers
+ elif cat == "S":
+ pri += 100 # includes spacing modifiers
+ else:
+ pri += 200 # whatever's left
- data[0] += pri
+ data[0] += pri/len(get_sym(sym)) + map.priority(sym)
for code in map.sym2cod[sym]:
# This check must not be done here.
@@ -579,8 +754,72 @@
data[1] += 1
data[2][code] += 1
+ # Duplicate of the same, for the non-alt case
+ for sym in map.symbols_no_alt():
+ if sym in xsym: continue
+ if sym not in symdata_no_alt:
+ symdata_no_alt[sym] = [ 0, 0, {} ]
+ data_no_alt = symdata_no_alt[sym]
+ pri = 0
+
+ # Heuristic: We try to block keys on ALT mappings, which
+ # have values smaller than zero, by never raising the value
+ # if it ever goes below zero
+# if data_no_alt[0] >= 0:
+# if pri is None:
+# pass
+# data_no_alt[0] += pri
+# if pri >= 0 and data_no_alt[0] < 0:
+# data_no_alt[0] = 0
+# else:
+# if pri < 0:
+# data_no_alt[0] += pri
+
+ for s in get_sym(sym):
+
+ if len(s) != 1:
+ pri += 100
+ elif ord(s) > 0x40 and ord(s) <= 0x5a:
+ if alt:
+ pri += 300
+ else:
+ pri += 2000
+ elif ord(s) > 0x60 and ord(s) <= 0x7a:
+ if alt:
+ pri += 300
+ else:
+ pri += 2000
+ elif ord(s) <= 32 or ord(s) == 127:
+ pri += -100000 # ... likewise ...
+ else:
+ cat = chartype(s)[0]
+ if cat == "L":
+ if alt:
+ pri += 600
+ else:
+ pri += 1500
+ elif cat == "Z" or cat == "C" or cat == "U":
+ pri -= 100000 # shouldn't happen, but ...
+ elif cat == "M":
+ pri -= 10000 # non-spacing modifiers
+ elif cat == "S":
+ pri += 100 # includes spacing modifiers
+ else:
+ pri += 200 # whatever's left
+
+ data_no_alt[0] += pri/len(get_sym(sym)) + map.priority(sym)
+
+ for code in map.sym2cod_no_alt[sym]:
+ if code not in data_no_alt[2]:
+ data_no_alt[2][code] = 0
+
+ data_no_alt[1] += 1
+ data_no_alt[2][code] += 1
+
syms=[]
+ syms_no_alt=[]
xxsyms=Set()
+
for sym,(pri,sum,codes) in symdata.iteritems():
if not codes.values():
continue
@@ -596,26 +835,68 @@
maxcodes = reduce(max,[ num for num in codes.values() ])
nfull=0
for map in all_maps:
- if sym in map.sym2code:
+ if sym in map.sym2cod:
nfull += 1
- # more heuristics:
- # Prefer symbols that appear in all maps.
+ # Count the number of symbols which actually appear
+ nsym=0
+ for c in get_sym(sym):
+ for m in all_maps:
+ if c in m.seen:
+ nsym += 1
+ break
+ # adjust for capital letters
+ if nsym == 2:
+ nsym = 1
+
+ # heuristics:
+ # Prefer symbols that appear in all maps (slightly).
# Prefer symbols that don't appear in maps we already selected.
# Prefer symbols that appear in many keyboards.
# Prefer symbols which result in many small subtrees,
# i.e. the number of maps having that symbol on the same
# keycode is small.
- #pri -= 100*(len(maps)-sum)
+ # Prefer non-ambiguous symbols.
+ pri -= 50*(len(maps)-sum)
pri -= 500*(nfull-sum)
pri += 100*len(codes)
- pri -= 500*maxcodes
+ pri -= 1000*maxcodes
+ pri -= 500*nsym
syms.append((-pri,sym))
- if len(maps) > 1 and not syms:
- raise AlgorithmProblem
+ # Duplicate of the same, for the non-alt case
+ for sym,(pri,sum,codes) in symdata_no_alt.iteritems():
+ if not codes.values():
+ continue
+ for c in codes:
+ if c in xcode:
+ xxsyms.add(sym)
+ break
+
+ maxcodes = reduce(max,[ num for num in codes.values() ])
+ nfull=0
+ for map in all_maps:
+ if sym in map.sym2cod_no_alt:
+ nfull += 1
+
+ nsym=0
+ for c in get_sym(sym):
+ for m in all_maps:
+ if c in m.seen:
+ nsym += 1
+ break
+ if nsym == 2:
+ nsym = 1
+
+ pri -= 50*(len(maps)-sum)
+ pri -= 500*(nfull-sum)
+ pri += 100*len(codes)
+ pri -= 1000*maxcodes
+ pri -= 500*nsym
+ syms_no_alt.append((-pri,sym))
syms.sort()
+ syms_no_alt.sort()
# print
# print syms
# for m in maps:
@@ -623,23 +904,49 @@
# print
# First, generate normal "press a key" choices.
+ nret=0
for pri,sym in syms:
if sym not in xxsyms:
- if trace>2: print "check",sym.encode("utf-8"),
- yield sym,False
+ if trace>2: print "check",str(sym).encode("utf-8"),
+ if do_log and trace>1:
+ print "Return1",do_log,"".join(get_sym(sym)).encode("utf-8")
+ yield sym,None
+ if depth:
+ nret += 1
+ if nret > depth:
+ break
# If that didn't work, use excluded keycodes
if not alt:
+ nret=0
for pri,sym in syms:
if sym in xxsyms:
- if trace>2: print "check",sym.encode("utf-8"),
- yield sym,False
+ if trace>2: print "check",str(sym).encode("utf-8"),
+ if do_log and trace>1:
+ print "Return2",do_log,"".join(get_sym(sym)).encode("utf-8")
+ yield sym,None
+ if depth:
+ nret += 1
+ if nret > depth:
+ break
+
+ # If that didn't work, generate yes/no questions for non-ALT keys.
+ for pri,sym in syms_no_alt:
+ if symdata_no_alt[sym][1] < len(maps)-len(supermaps):
+ # ... but only if there are keyboards for which the answer is 'no'.
+ if do_log and trace>1:
+ print "Return3",do_log,"".join(get_sym(sym)).encode("utf-8")
+ yield sym,SingleMappingNoAlt
# If that didn't work, generate yes/no questions.
for pri,sym in syms:
- if symdata[sym][1] < len(maps):
+ if symdata[sym][1] < len(maps)-len(supermaps):
# ... but only if there are keyboards for which the answer is 'no'.
- yield sym,True
+ if do_log and trace>1:
+ print "Return4",do_log,"".join(get_sym(sym)).encode("utf-8")
+ yield sym,SingleMapping
+
+ if do_log and trace>1: print "ReturnEnd",do_log
def drop_sym(maps, xsym):
"""Find those symbol in a set of keymaps"""
@@ -649,12 +956,16 @@
"""Returns a list keycode => maps with the symbol on that key"""
codes = Set()
xmaps = Set()
+ xmaps_no_alt = Set()
altmaps = Set()
for map in maps:
- if not sym in map.sym2code:
+ if not sym in map.sym2cod:
xmaps.add(map)
+ xmaps_no_alt.add(map)
continue
+ if not sym in map.sym2cod_no_alt:
+ xmaps_no_alt.add(map)
for code,pri in map.sym2code[sym]:
codes.add(code)
if pri < 0:
@@ -662,12 +973,22 @@
# If there's less than two choices, return via an exception.
if len(codes) == 0:
+ if trace>3: print "unknown,",
raise NoMapping(sym)
- if len(codes) == 1:
- if not xmaps:
+ if choose or len(codes) == 1:
+ if not xmaps or (choose == SingleMappingNoAlt and not xmaps_no_alt):
+ if trace>3:
+ if len(codes) == 1:
+ print "same,",
+ else:
+ print "choice,",
raise NoMapping(sym)
if choose:
- raise SingleMapping(maps-xmaps, xmaps)
+ if trace>3: print "single,",
+ if choose == SingleMappingNoAlt:
+ raise choose(maps-xmaps_no_alt, xmaps_no_alt)
+ else:
+ raise choose(maps-xmaps, xmaps)
# If the symbol occurs with normal AND AltGr mappings,
# ignore the AltGr stuff -- the symbol may not actually be
--- keymapper-0.5.3.orig/keymapper/equiv.py
+++ keymapper-0.5.3/keymapper/equiv.py
@@ -0,0 +1,101 @@
+
+# equiv.py
+# find equivalent glyphs
+
+# Copyright (c) 2005 by Matthias Urlichs <smurf@smurf.noris.de>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of Version 2 of the GNU General Public License as
+# published by the Free Software Foundation. See the file COPYING.txt
+# or (on Debian systems) /usr/share/common-licenses/GPL-2 for details.
+
+"""\
+This module exports a 'looks_like()' function. it accepts a Unicode
+symbol and returns a list of symbols which look the same, in either
+upper or lower case.
+
+It also exports a chartype() function which returns the first letter
+of the Unicode category (e.g., 'C' for control characters, or 'Z' for
+spacing).
+
+"""
+
+from os.path import exists
+import codecs
+from unicodedata import normalize,category
+
+equivfile = "/usr/share/misc/keysym.equiv";
+if exists("data/equivs") and exists("gen_keymap"):
+ equivfile = "data/equivs";
+
+map = {}
+cache = {}
+syms = []
+
+charhash={}
+def chartype(c):
+ if c in charhash:
+ return charhash[c]
+ charhash[c] = h = category(c)[0]
+ return h
+
+def read_map():
+ for l in codecs.getreader("utf-8")(open(equivfile,"r")):
+ r = []
+ for c in l.strip():
+ cc = normalize("NFC",c.lower())
+ if cc not in r: r.append(cc)
+ cc = normalize("NFC",c.upper())
+ if cc not in r: r.append(cc)
+ found=1
+ while found:
+ found=0
+ for c in r:
+ if c in map:
+ for cc in map[c]:
+ if cc not in r:
+ found=1
+ r.append(cc)
+ r.sort()
+ r = tuple(r)
+ for c in r:
+ map[c] = r
+ cache[c] = len(syms)
+ syms.append(r)
+
+def looks_like(sym):
+ """Return a symbol number for something looking like sym"""
+
+ if not map:
+ read_map()
+
+ if sym in cache:
+ return cache[sym]
+
+ s = normalize("NFC",sym.lower())
+ if s in cache:
+ s = cache[s]
+ cache[sym] = s
+ return s
+
+ if s in map:
+ res = map[s]
+ else:
+ res = [s]
+ for c in res:
+ if c in cache:
+ res = cache[c]
+ cache[sym] = res
+ return res
+
+ syms.append(res)
+ res = len(syms)-1
+ cache[sym] = res
+ if sym != s:
+ cache[s] = res
+ return res
+
+def get_sym(pos):
+ """Return the symbols at that position"""
+ return syms[pos]
+
--- keymapper-0.5.3.orig/keymapper/file.py
+++ keymapper-0.5.3/keymapper/file.py
@@ -14,8 +14,29 @@
"""
from keymapper.tree import Reporter
+from keymapper.equiv import get_sym
+from unicodedata import normalize
import sys
+def nsym(s):
+ if len(s) != 1:
+ return s
+ elif ord(s) == 127:
+ return "<del>"
+ elif ord(s) == 32:
+ return "<spc>"
+ elif ord(s) == 10:
+ return "<lf>"
+ elif ord(s) == 13:
+ return "<cr>"
+ elif ord(s) == 8:
+ return "<bs>"
+ elif ord(s) == 9:
+ return "<tab>"
+ else:
+ return s
+
+
class FileReporter(Reporter):
"""Report the result as a list of steps to a file"""
def __init__(self,file=sys.stdout):
@@ -31,8 +52,8 @@
def symbols(self,symbols):
"""Start a choice: display these symbols"""
- for sym in symbols:
- print >>self.file,"PRESS %s" % sym
+ for sym,c in symbols:
+ print >>self.file,"PRESS %s" % nsym(normalize("NFC",sym))
def choice(self,code,nextstep):
"""Choice: This keycode leads to that step"""
@@ -40,11 +61,22 @@
def ask(self,sym,no,yes):
"""Ask whether that symbol is visible"""
- print >>self.file,"FIND %s" % sym
- print >>self.file,"YES %s" % yes.step
- print >>self.file,"NO %s" % no.step
+ print >>self.file,"FIND %s" % " ".join([nsym(normalize("NFC",s)) for s in sym])
+ if yes:
+ print >>self.file,"YES %s" % yes.step
+ if no:
+ print >>self.file,"NO %s" % no.step
+
+ def ask_no_alt(self,sym,no,yes):
+ """Ask whether that symbol is visible on primary keys"""
+ print >>self.file,"FINDP %s" % " ".join([nsym(normalize("NFC",s)) for s in sym])
+ if yes:
+ print >>self.file,"YES %s" % yes.step
+ if no:
+ print >>self.file,"NO %s" % no.step
def finish(self):
"""Conclude this step"""
pass
+
--- keymapper-0.5.3.orig/keymapper/fakequery.py
+++ keymapper-0.5.3/keymapper/fakequery.py
@@ -14,31 +14,53 @@
"""
from keymapper.query import Query
+from keymapper.equiv import looks_like,get_sym
from random import uniform
class FakeQuery(Query):
"""A fake keyboard inquiry which actually looks at a keymap.
Used for testing."""
- def __init__(self, map):
+ def __init__(self, map, verbose=1):
Query.__init__(self)
self.map = map
+ self.verbose = verbose
def press(self,syms):
- print "* Press one of '"+"' '".join(syms)+"' !"
- syms = [ sym for sym in syms if sym in self.map.sym2code ]
- print "I have '"+"' '".join(syms)+"'."
- sym = syms[int(uniform(0,len(syms)))]
- code = self.map.sym2code[sym]
- code = code[int(uniform(0,len(code)))][0]
- print "I choose %s => %d" % (sym,code)
- return code
-
- def ask(self,sym):
- print "* Do I see '"+sym+"' ?"
- if sym in self.map.sym2code:
- print "Yes"
- else:
+ if self.verbose:
+ print "* Press one of '"+"' '".join(syms)+"' !"
+ like=[]
+ for s in syms:
+ s = looks_like(s)
+ for ss in get_sym(s):
+ if ss not in like and ss in self.map.seen:
+ like.append(ss)
+ if self.verbose:
+ print "I have '"+"' '".join(like)+"'."
+ codes = []
+ for sym in like:
+ code = self.map.sym2code[looks_like(sym)]
+ for code in code:
+ code = code[0]
+ if self.verbose:
+ print "I can press %s => %d" % (sym,code)
+ if code not in codes:
+ codes.append(code)
+ return codes
+
+ def ask(self,syms):
+ if self.verbose:
+ print "* Do I see '"+"' or '".join(syms)+"' ?"
+ for sym in syms:
+ if looks_like(unicode(sym)) in self.map.sym2code \
+ and sym in self.map.seen:
+ if self.verbose:
+ print "Yes"
+ return True
+ if self.verbose:
print "No"
- return sym in self.map.sym2code
+ return False
+ def message(self,msg):
+ if self.verbose:
+ print msg
--- keymapper-0.5.3.orig/keymapper/script.py
+++ keymapper-0.5.3/keymapper/script.py
@@ -17,46 +17,81 @@
exception will be raised.
"""
+from sets import Set
+
+def osym(s):
+ if s == "<del>":
+ return u"\x7F"
+ elif s == "<spc>":
+ return u" "
+ elif s == "<lf>":
+ return u"\x0A"
+ elif s == "<cr>":
+ return u"\x0D"
+ elif s == "<bs>":
+ return u"\x08"
+ elif s == "<tab>":
+ return u"\x09"
+ else:
+ return s
-class FoundMap(Exception):
- """Pseudo-exception, raised when the script terminates with a unique keyboard map"""
- pass
class UnknownLine(Exception):
"""The script file contains a line that's not parseable"""
pass
class BadFile(Exception):
"""The script file isn't well-formed"""
pass
+class NoMap(Exception):
+ """No result!"""
+ pass
+class DupMap(Exception):
+ """Inconclusive result!"""
+ pass
class Script(object):
"""Run this script with that query. Return the result."""
- def __init__(self,file,query):
+ def __init__(self,file, verbose=1):
self.file = file
self.in_step = -1
- self.query = query
+ self.verbose = verbose
- def get_step(self,nr):
+ def get_step(self,nrs):
"""Return the data for step NR."""
+ reported=False
+ if self.verbose > 1:
+ print "want",nrs,", have",self.in_step
for f in self.file:
f = f.strip()
if f == "" or f.startswith("#"):
continue
if f.startswith("STEP"):
+ if self.verbose > 1:
+ print f
f = f[4:]
f = int(f.strip())
- if self.in_step == nr: # done
+ if self.in_step in nrs:
+ nrs.remove(self.in_step) # done with this one
self.in_step = f
return
self.in_step = f
- elif self.in_step == nr:
+ elif self.in_step in nrs:
+ if self.verbose:
+ if not reported:
+ print "Step",self.in_step
+ reported=True
+ if self.verbose > 1:
+ print "have",f
yield f
+ elif self.verbose > 1:
+ print "skip",f
# ran off the end of the file?
- if nr != self.in_step:
- raise BadFile
+ if self.in_step not in nrs:
+ raise BadFile,nrs
+ nrs.remove(self.in_step) # done, at EOF
- def run_step(self,step):
+ def run_step(self,query,step,res):
"""Run a singe step.
Returns the next step's number, or raise an exception."""
what = None
@@ -67,47 +102,63 @@
for line in self.get_step(step):
if line.startswith("PRESS") and what in (None,"press"):
what="press"
- syms.append(line[5:].strip())
+ syms.append(osym(line[5:].strip()))
elif line.startswith("CODE") and what in (None,"press"):
what="press"
- code,goal = line[4:].strip().split()
+ try:
+ code,goal = line[4:].strip().split()
+ except ValueError:
+ print "BAD LINE <"+line.strip()+">"
+ continue
keys[int(code)] = int(goal)
elif line.startswith("MAP") and what in (None,):
- raise FoundMap(line[3:].strip())
+ res.add(line[3:].strip())
elif line.startswith("FIND") and what in (None,):
what="find1"
- find = line[4:].strip()
+ find = line[4:].strip().split()
elif line.startswith("YES") and what in ("find1",):
what="find2"
- dest_yes = int(line[3:].strip())
+ dest_yes = int(line[4:].strip())
elif line.startswith("NO") and what in ("find2",):
what="find3"
- dest_no = int(line[4:].strip())
+ dest_no = int(line[3:].strip())
else:
raise UnknownLine(line.strip())
# Second, decide what to do
if what == "press" and syms and keys:
- while True:
- code = self.query.press(syms)
+ codes = query.press(syms)
+ for code in codes:
if code in keys:
- return keys[code]
- self.query.message("Unexpected key code: <%d>" % code)
+ step.add(keys[code])
+ if self.verbose:
+ print "Goto step step",keys[code]
+ else:
+ query.message("Unexpected key code: <%d>" % code)
elif what == "find3":
- if self.query.ask(find):
- return dest_yes
+ if query.ask([osym(f) for f in find]):
+ step.add(dest_yes)
+ if self.verbose:
+ print "Goto step step",dest_yes
else:
- return dest_no
-
- else:
- raise BadFile
+ step.add(dest_no)
+ if self.verbose:
+ print "Goto step step",dest_no
- def run(self):
+ def run(self,query):
"""Run this script, starting with step 0."""
- step=0
- while True:
- try:
- step = self.run_step(step)
- except FoundMap,exc:
- return exc.args[0]
-
+ self.file.seek(0,1) ## Python 2.4 regression workaround:
+ self.file.read() ## flush codec's input buffers
+ self.file.seek(0,0)
+ self.in_step = -1
+ step=Set((0,))
+ maps = Set()
+ while step:
+ self.run_step(query,step,maps)
+ if not maps:
+ raise NoMap
+ if len(maps) != 1:
+ raise DupMap(list(maps))
+ return list(maps)[0]
+
+
--- keymapper-0.5.3.orig/keymapper/fakemaps.py
+++ keymapper-0.5.3/keymapper/fakemaps.py
@@ -1,4 +1,4 @@
-
+# -*- coding: utf-8 -*-
# fakemaps.py
# invent fake keyboard maps for testing
@@ -28,7 +28,7 @@
"""synthesize a Keymap"""
map=Keymap(name)
for sym,code,mod in keys:
- map.add(sym,code,mod)
+ map.add(unicode(sym),code,mod)
return map
def maps():
@@ -42,7 +42,7 @@
# Remove a key
yield gen_map("removed",
- ("A",1,STD),("B",2,STD),("C",3,STD),("D",4,STD))
+ (u"α",1,STD),("B",2,STD),("C",3,STD),("D",4,STD))
# Duplicate a key
yield gen_map("duped",
@@ -62,7 +62,7 @@
# Totally different keys
yield gen_map("diff_keys",
- ("a",1,STD),("b",2,STD),("c",3,STD),("d",4,STD),("e",5,STD))
+ ("aa",1,STD),("bb",2,STD),("cc",3,STD),("dd",4,STD),("ee",5,STD))
# Totally different codes
yield gen_map("diff_codes",
--- keymapper-0.5.3.orig/keymapper/keymap.py
+++ keymapper-0.5.3/keymapper/keymap.py
@@ -14,7 +14,9 @@
keyboard mapping.
"""
-from sets import ImmutableSet
+from sets import Set,ImmutableSet
+from keymapper.equiv import looks_like,get_sym,chartype
+from unicodedata import normalize
# This code implements a bitmask and associated bit values.
modlist=("shift","altgr","control","alt","shiftl","shiftr","controll","controlr","capsshift")
@@ -50,7 +52,7 @@
pri=0
mods=self.mods
- for mod,val in (("altgr",500),("alt",1000),("control",1500)):
+ for mod,val in (("altgr",800),("alt",1000),("control",1500)):
if mod in self.mods:
pri -= val
mods = mods-ImmutableSet(mod)
@@ -111,15 +113,26 @@
# """Trying to add a code+modifier entry to a keymap that's already known"""
# pass
+class SymSet(Set):
+ """Add and compare with NFC"""
+ def __contains__(self,sym):
+ return Set.__contains__(self,normalize("NFC",sym.lower()))
+ def add(self,sym):
+ return Set.add(self,normalize("NFC",sym.lower()))
+
class Keymap(object):
"""encapsulates a named symbol <=> keycode+modifiers mapping"""
- def __init__(self,name):
+ def __init__(self,name, with_alt=True):
self.name = name
self.sym2code = {} # sym => (code,modifier) list
self.sym2cod = {} # sym => code list
-# self.code2sym = {} # <=
+ self.sym2cod_no_alt = {} # sym => code list
+ self.code2sym = {} # <=
self.submap_cache = {}
+ self.seen = SymSet() # symbols actually seen
+ self.stdseen = SymSet() # symbols reachable without modifier keys
+ self.with_alt = with_alt
def __str__(self):
return "Map<%s>" % (self.name,)
@@ -129,39 +142,86 @@
def add(self,sym,code,mod=STD):
"""add a single key mapping to this keymap"""
- if sym == "":
+ if sym == "" or sym is None:
return
+ if len(sym) == 1:
+ cat = chartype(sym)
+ if cat == "Z" or cat == "C" or cat == "U":
+ return # zero-width, control, unassigned
+ if not self.with_alt:
+ if mod != STD and mod != SHIFT:
+ return
+ self.seen.add(sym)
+ if mod == STD:
+ self.stdseen.add(sym)
+ sym = looks_like(sym)
if sym in self.sym2cod:
if code not in self.sym2cod[sym]:
self.sym2cod[sym].append(code)
else:
self.sym2cod[sym] = [code]
+ if mod in (STD,SHIFT):
+ if sym in self.sym2cod_no_alt:
+ if code not in self.sym2cod_no_alt[sym]:
+ self.sym2cod_no_alt[sym].append(code)
+ else:
+ self.sym2cod_no_alt[sym] = [code]
+
+ if mod == STD:
+ if code not in self.code2sym:
+ self.code2sym[code] = []
+ self.code2sym[code].append(sym)
+
code = (code,mod)
if sym in self.sym2code:
if code not in self.sym2code[sym]:
self.sym2code[sym].append(code)
return
-# if code in self.code2sym:
-# raise CodeKnown(self.name,code)
self.sym2code[sym] = [code]
-# self.code2sym[code] = sym
def symbols(self):
"""Return a list of known symbols"""
return self.sym2code.iterkeys()
+ def symbols_no_alt(self):
+ """Return a list of known symbols on non-alt keys"""
+ #for k,(c,m) in self.sym2code.iteritems():
+ for s in self.sym2code.iteritems():
+ (k,l) = s
+ for c,m in l:
+ if m == STD or m == SHIFT:
+ yield k
+ break
+
def priority(self,sym):
"""Return how likely it is that this symbol is actually shown
on the physical keyboard"""
if not self.sym2code[sym]:
pass
- return reduce(max, [ k[1].pri for k in self.sym2code[sym] ])
-
+ # Disambiguate. The 500 is here to make the values non-negative.
+ return 500-sym + reduce(max, [ k[1].pri for k in self.sym2code[sym] ])
def dump(self):
- """Show my mapping"""
- return self.name+": "+",".join([ "%s:%s" % (self.vis(s), "+".join([str(x) for x in c])) for s,c in self.sym2cod.items()])
+ """Show my mapping (sym => code)"""
+ return self.name+": "+",".join([ "%s:%s" % ("".join([self.vis(sy) for sy in get_sym(s) if sy in self.seen]), "+".join([str(x) for x in c])) for s,c in self.sym2cod.items()])
+
+ def rdump1(self,syms):
+ """Helper for rdump"""
+ seen={}
+ res=[]
+ for sym in syms:
+ if sym in seen: continue
+ seen[sym]=1
+ for s in get_sym(sym):
+ if s not in self.stdseen: continue
+ res.append(self.vis(s))
+ return res
+
+
+ def rdump(self):
+ """Show my reverse mapping (code => sym)"""
+ return self.name+": "+" ".join([ "%s:%s" % (c,",".join(self.rdump1(s))) for c,s in self.code2sym.items()])
def vis(self,s):
if len(s) == 1 and ord(s) < 128:
@@ -171,6 +231,8 @@
def is_submap(self,m):
"""Check if self is a submap of m."""
+ if self is m:
+ return False
try:
return self.submap_cache[m]
except KeyError:
--- keymapper-0.5.3.orig/keymapper/parse/linux.g
+++ keymapper-0.5.3/keymapper/parse/linux.g
@@ -3,22 +3,16 @@
"""
from keymapper.parse.linuxsyms import lookup_symbol,SymbolNotFound
-from os.path import exists,join
+from os.path import exists,join,curdir
from gzip import GzipFile
from keymapper.keymap import Keymap,Modifier
import os
dirs = [
-# ".",
- "/usr/share/keymaps/i386/azerty",
- "/usr/share/keymaps/i386/dvorak",
- "/usr/share/keymaps/i386/fgGIod",
- "/usr/share/keymaps/i386/qwerty",
- "/usr/share/keymaps/i386/qwertz",
-
- "/usr/share/keymaps/i386/include",
- "/usr/share/keymaps/include"
]
+def add_dir(d):
+ """Helper to add a directory to the search path"""
+ dirs.append(d)
class NoFileFound(Exception):
pass
@@ -29,6 +23,9 @@
def get_file(name):
"""Find a keymap file"""
+ global dirs
+ if not dirs:
+ dirs=(curdir,)
for end in ("",".kmap",".kmap.gz",".inc",".inc.gz", ".gz"):
for dir in dirs:
n = os.path.join(dir,name+end)
@@ -73,9 +70,9 @@
self.add(rvalue, code, keys)
-def parse_file(name):
+def parse_file(name, with_alt=True):
f = get_file(name)
- keymap = ConsoleKeymap(name)
+ keymap = ConsoleKeymap(name, with_alt=with_alt)
parser = linuxmap(linuxmapScanner("",file=f,filename=name))
try:
--- keymapper-0.5.3.orig/keymapper/parse/maps.py
+++ keymapper-0.5.3/keymapper/parse/maps.py
@@ -36,9 +36,9 @@
names={"plain":STD, "shift":SHIFT, "altgr":ALT, "shift_altgr":ALTSHIFT,
"shift_alt":ALTSHIFT,"altgr_alt":ALT,"alt":ALT,"shift_altgr_alt":ALTSHIFT}
-def parse_map(name,f):
+def parse_map(name,f,with_alt=True):
"""read a Keymap"""
- map=Keymap(name)
+ map=Keymap(name,with_alt)
l = f.read()
if not l:
raise EmptyMapError(name)
--- keymapper-0.5.3.orig/keymapper/parse/x11.g
+++ keymapper-0.5.3/keymapper/parse/x11.g
@@ -0,0 +1,262 @@
+"""
+This code implements a parser for Linux keyboard maps.
+"""
+
+from keymapper.parse.linuxsyms import lookup_symbol,SymbolNotFound
+from os.path import exists,join,curdir
+from gzip import GzipFile
+from keymapper.keymap import Keymap,Modifier, STD,SHIFT,ALT,ALTSHIFT
+import os, re
+
+symfile = "/usr/share/misc/keymap.xkeys";
+if exists("data/xkeys") and exists("gen_keymap"):
+ symfile = "data/xkeys";
+
+xsyms = {}
+def read_map():
+ f = open(symfile)
+ for l in f:
+ l = l.strip()
+ comment = l.find('#')
+ if comment > -1: l = l[:comment]
+ l = l.strip()
+ if l == "": continue
+ s,d = l.split()
+ xsyms[s] = eval("0x"+d, {},{})
+read_map()
+del read_map
+
+defmap="us"
+defkey="pc101"
+
+dirs = [
+]
+def add_dir(d):
+ """Helper to add a directory to the search path"""
+ dirs.append(d)
+
+class BadStep(Exception):
+ pass
+class NoFileFound(Exception):
+ pass
+class FileProblem(Exception):
+ pass
+class TooManySyms(Exception):
+ pass
+
+class Restart: # Marker
+ pass
+class UseOld:
+ pass
+class UseNew:
+ pass
+
+def get_file(name):
+ """Find a keymap file"""
+ global dirs
+ if not dirs:
+ dirs=("/usr/lib/X11/xkb/symbols",)
+ for end in ("",".gz"):
+ for dir in dirs:
+ n = os.path.join(dir,name+end)
+ if exists(n):
+ if n.endswith(".gz"):
+ f = GzipFile(n,"rb")
+ else:
+ f = open(n,"r")
+ return f
+
+ raise NoFileFound(name)
+
+m_incl2 = re.compile("^(.+)\\((.+)\\)$")
+next_mod = {STD:SHIFT, SHIFT:ALT, ALT:ALTSHIFT, ALTSHIFT:ALT}
+
+class X11Keymap(Keymap):
+ """submap with interesting features for generating X11 maps"""
+ def __init__(self,name,sub=None):
+ Keymap.__init__(self,name+"("+sub+")")
+ self.map_vector = []
+ self.steps = []
+ self.build_done = False
+
+ def append(self,what):
+ self.steps.append(what)
+
+ def build_map(self,to_map=None,keymap=None):
+ if to_map is None:
+ if self.build_done:
+ return
+ to_map = self
+
+ if keymap is None:
+ keymap={}
+ for s in self.steps:
+ if isinstance(s,list) or isinstance(s,tuple):
+ rep = s[0]
+ code = s[1]
+ try:
+ code = xsyms[code]
+ except KeyError:
+ continue
+ s = s[2:]
+ if rep == UseOld and code in keymap:
+ continue
+ keymap[code] = s
+
+ elif isinstance(s,basestring):
+ # include file. Can be "name(sub)".
+ m = m_incl2.match(s)
+ if m:
+ s = (m.group(1),m.group(2))
+ if not known.has_key(s):
+ parse_file(s[0],s[1])
+ else:
+ if not known.has_key(s):
+ parse_file(s)
+
+ known[s].build_map(to_map,keymap)
+ else:
+ raise BadStep
+
+ if to_map == self and not self.build_done:
+ self.build_done = True
+ s = (defmap,defkey)
+ if not known.has_key(s):
+ parse_file(defmap,defkey)
+ known[s].build_map(to_map,keymap)
+
+ for code,keys in keymap.iteritems():
+ mod=STD
+ for k in keys:
+ if k == Restart:
+ # mod=STD # heuristic
+ continue
+ to_map.add(k,code,mod)
+ mod=next_mod[mod]
+
+known = {}
+
+def parse_file(name, sub=None):
+ if sub:
+ k = (name,sub)
+ else:
+ m = m_incl2.match(name)
+ if m:
+ (name,sub) = (m.group(1),m.group(2))
+ k = (name,sub)
+ else:
+ k = name
+
+ if not known.has_key(k):
+ f = get_file(name)
+ parser = x11map(x11mapScanner("",file=f,filename=name))
+
+ try:
+ parser.map(name)
+ except SymbolNotFound,e:
+ print >>sys.stderr, "Keysym '%s' not found" % e.args
+ print >>sys.stderr, parser._scanner
+ raise FileProblem(name)
+ except runtime.SyntaxError, e:
+ runtime.print_error(e, parser._scanner, max_ctx=1)
+ raise FileProblem(name)
+ except runtime.NoMoreTokens:
+ print >>sys.stderr, 'Could not complete parsing; stopped around here:'
+ print >>sys.stderr, parser._scanner
+ raise FileProblem(name)
+
+ try:
+ map = known[k]
+ except KeyError:
+ return None
+ map.build_map()
+ return map
+
+%%
+
+parser x11map:
+ ignore: "[ \n\r\t]+"
+ ignore: "(#|!).*"
+ ignore: "\/\/.*"
+
+ token EOF: "$"
+ token INCLUDE: "include"
+ token SETMODWHAT: "SetMods\\.[a-zA-Z0-9_]+"
+ token KEYWHAT: "key\\.[a-zA-Z0-9_]+"
+ token HEX: "0x[a-zA-Z0-9]+"
+ token UNI: "U[0-9A-Fa-f]{4}"
+ token UNI3: "U[0-9A-Fa-f]{3}"
+ token SYM: "[a-zA-Z0-9_]+"
+ token NUM: "[-+]?[0-9_]+"
+ #token _CHAR1: "'([0-7]){1,3}'"
+ #token _CHAR2: "'\\\\.'"
+ #token _CHAR3: "'.'"
+ #token PLUS: "\\+"
+ token _STRLITERAL: '\'([^\\n\'\\\\]|\\\\.)*\'|"([^\\n"\\\\]|\\\\.)*"'
+ token _KEYLITERAL: '<[A-Za-z0-9]+>'
+
+ rule STRLITERAL: _STRLITERAL {{ return eval(_STRLITERAL,{},{}) }}
+ rule KEYLITERAL: _KEYLITERAL {{ return _KEYLITERAL[1:-1] }}
+
+ rule map<<name>>: one_map<<name>>* EOF
+
+ rule one_map<<name>>: {{ default = False }} {{ hidden = False }}
+ ( "partial"
+ | "default" {{ default=True }}
+ | "hidden" {{ hidden=True }}
+ )*
+ mods*
+ "xkb_symbols" STRLITERAL {{ sub=STRLITERAL }}
+ {{ data = X11Keymap(name,sub) }}
+ "{"
+ ( incl<<data>> | entry<<data>>
+ | setmod | vmod | naming | modmap | keyset ) *
+ "}"
+ {{ known[(name,sub)] = data }}
+ {{ if default: known[name] = data }}
+ ";"
+
+ rule naming: "[Nn]ame" "\\[" SYM "\\]" "=" STRLITERAL ";"
+
+ rule modmap: "modifier_map" SYM "{" symkey ( "," ? symkey ) * "}" ";"
+ #rule modmap: "modifier_map" SYM "{" SYM ( "," SYM ) * "}" ";"
+ rule symkey: SYM | _KEYLITERAL
+ rule vmod: "virtual_modifiers" SYM ";"
+ rule setmod: SETMODWHAT "=" SYM ";"
+
+
+ rule keyset: KEYWHAT ( "\\[" SYM "\\]" ) ? "=" STRLITERAL ";"
+
+
+ rule mods: "keypad_keys" | "function_keys"
+ | "alphanumeric_keys" | "modifier_keys" | "alternate_group"
+ rule incl<<data>>: "include" STRLITERAL {{ data.append(STRLITERAL) }}
+
+ rule entry<<data>>: {{ rep=UseOld }}
+ ( ( "replace" | "override" ) {{ rep=UseNew }} ) ?
+ "key" KEYLITERAL {{ k=[rep,KEYLITERAL] }}
+ "{" stuffgroup<<k>>
+ ( "," {{ k.append(Restart) }} stuffgroup<<k>> ) *
+ "}" ";" {{ data.append(k) }}
+
+ rule stuffgroup<<k>>: stuff | group<<k>>
+ rule stuff: stuffsym | stuffvirt | stufftype | stuffover
+ rule stuffsym: "symbols" "\\[" SYM "\\]" "="
+ "\\[" ( SYM ( "," SYM ) * ) ? "\\]"
+ rule stuffvirt: "virtualMods" "=" SYM
+ rule stufftype: "type" ( "\\[" SYM "\\]" ) ? "=" STRLITERAL
+ rule stuffover: "overlay[12]" "=" KEYLITERAL
+
+ rule group<<k>>: "\\[" ( sym {{ if sym: k.append(sym) }}
+ ( "," ? sym {{ if sym: k.append(sym) }} ) * ) ?
+ "\\]"
+
+ rule sym: "NoSymbol" {{ return None }}
+ | "SetMods" "\\(" SYM "=" SYM "\\)" {{ return None }}
+ | "LockGroup" "\\(" SYM "=" NUM "\\)" {{ return None }}
+ | UNI {{ return eval('u"\\u%s"' % (UNI[1:]),{},{}) }}
+ | UNI3 {{ return eval('u"\\u0%s"' % (UNI3[1:]),{},{}) }}
+ | HEX {{ return eval('u"\\U%08x"' % (eval(HEX)-0x1000000,),{},{}) }}
+ | SYM {{ return lookup_symbol(SYM) }}
+
+%%
--- keymapper-0.5.3.orig/keymapper/parse/Makefile
+++ keymapper-0.5.3/keymapper/parse/Makefile
@@ -1,8 +1,12 @@
# Makefile for keymapper stuff
#
-all: ${addsuffix .py, ${basename ${wildcard *.g}, .g}}
+GENPY := ${addsuffix .py, ${basename ${wildcard *.g}, .g}}
+
+all: $(GENPY)
%.py: %.g
yapps $<
+clean:
+ rm -f $(GENPY)
--- keymapper-0.5.3.orig/keymapper/parse/linuxsyms.py
+++ keymapper-0.5.3/keymapper/parse/linuxsyms.py
@@ -13,7 +13,12 @@
translate symbols to unicode (and back).
"""
-symfile = "data/symbols"
+from os.path import exists
+
+symfile = "/usr/share/misc/keymap.syms";
+if exists("data/symbols") and exists("gen_keymap"):
+ symfile = "data/symbols";
+
map = {}
alias = {}
@@ -57,9 +62,9 @@
read_table()
# print name,
- # XXX TODO: return that stuff somehow?
- if name.startswith("Meta_"):
- name = name[5:]
+ if name.startswith("Meta_") or name.startswith("Alt_") \
+ or name.startswith("Hyper_"):
+ return None
while name in alias:
name = alias[name]
--- keymapper-0.5.3.orig/data/symbols
+++ keymapper-0.5.3/data/symbols
@@ -31,14 +31,14 @@
001e Control_asciicircum
001f Control_underscore
0020 space
-0021 exclam
+0021 exclam excalem
0022 quotedbl
0023 numbersign
0024 dollar
0025 percent
0026 ampersand
0027 apostrophe
-0028 parenleft
+0028 parenleft parenlef
0029 parenright
002a asterisk
002b plus
@@ -46,21 +46,23 @@
002d minus
002e period
002f slash
-0030 zero
-0031 one
-0032 two
-0033 three
-0034 four
-0035 five
-0036 six
-0037 seven
-0038 eight
-0039 nine
+0030 0 zero
+0031 1 one
+0032 2 two
+0033 3 three
+0034 4 four
+0035 5 five
+0036 6 six
+0037 7 seven
+0038 8 eight
+0039 9 nine
003a colon
003b semicolon
+003c leftcaret
003c less
003d equal
003e greater
+003e rightcaret
003f question
0040 at
0041 A
@@ -92,9 +94,10 @@
005b bracketleft
005c backslash
005d bracketright
-005e asciicircum dead_circumflex
+005e asciicircum dead_circumflex SunFA_Circum
+005f underbar
005f underscore
-0060 grave dead_grave
+0060 grave dead_grave SunFA_Grave
0061 a
0062 b
0063 c
@@ -124,7 +127,7 @@
007b braceleft
007c bar
007d braceright
-007e asciitilde dead_tilde
+007e asciitilde dead_tilde SunFA_Tilde
007f Delete
00a0 nobreakspace
00a0 no-break_space
@@ -136,7 +139,7 @@
00a6 brokenbar
00a7 paragraph_sign
00a7 section
-00a8 diaeresis dead_diaeresis
+00a8 diaeresis dead_diaeresis SunFA_Diaeresis
00a9 copyright
00aa ordfeminine
00ab guillemotleft
@@ -144,16 +147,17 @@
00ad hyphen
00ad soft_hyphen
00ae registered
-00af macron
+00af macron dead_macron
+00af overbar
00b0 degree
00b1 plusminus
00b2 twosuperior
00b3 threesuperior
-00b4 acute dead_acute
+00b4 acute dead_acute SunFA_Acute
00b5 mu
00b6 paragraph
00b7 periodcentered
-00b8 cedilla dead_cedilla
+00b8 cedilla dead_cedilla SunFA_Cedilla
00b9 onesuperior
00ba masculine
00bb guillemotright
@@ -178,7 +182,7 @@
00cd Iacute
00ce Icircumflex
00cf Idiaeresis
-00d0 ETH
+00d0 ETH Eth
00d1 Ntilde
00d2 Ograve
00d3 Oacute
@@ -193,7 +197,7 @@
00db Ucircumflex
00dc Udiaeresis
00dd Yacute
-00de THORN
+00de THORN Thorn
00df ssharp
00e0 agrave
00e1 aacute
@@ -314,8 +318,8 @@
015f scedilla
0160 Scaron
0161 scaron
-0162 Tcedilla
-0163 tcedilla
+0162 Tcedilla Tcediila
+0163 tcedilla tcediila
0164 Tcaron
0165 tcaron
0166 Tslash
@@ -339,306 +343,852 @@
017c zabovedot
017d Zcaron
017e zcaron
-02bc rightquote
-02bd leftquote
+0192 function
+01e6 Gcaron
+01e7 gcaron
+01a0 Ohorn
+01a1 ohorn
+01af Uhorn
+01b0 uhorn
+02bc rightquote quoteright
+02bd leftquote quoteleft
02c7 caron
02d8 breve
-02d9 abovedot
+02d9 abovedot dead_abovedot
+02da abovering dead_abovering
02db ogonek
02dd doubleacute
+0309 dead_hook
+031b dead_horn
+0323 dead_belowdot
0384 accent
-0385 diaeresisaccent
-0386 Alphaaccent
-0388 Epsilonaccent
-0389 Etaaccent
-038a Iotaaccent
-038c Omicronaccent
-038e Upsilonaccent
-038f Omegaaccent
+0385 Greek_accentdieresis diaeresisaccent
+0386 Greek_ALPHAaccent Alphaaccent
+0388 Greek_EPSILONaccent Epsilonaccent
+0389 Greek_ETAaccent Etaaccent
+038a Greek_IOTAaccent Iotaaccent
+038c Greek_OMICRONaccent Omicronaccent
+038e Greek_UPSILONaccent Upsilonaccent
+038f Greek_OMEGAaccent Omegaaccent
+0390 Greek_iotaaccentdieresis
0390 iotadiaeresisaccent
-0391 Alpha
-0392 Beta
-0393 Gamma
-0394 Delta
-0395 Epsilon
-0396 Zeta
-0397 Eta
-0398 Theta
-0399 Iota
-039a Kappa
-039b Lamda
-039c Mu
-039d Nu
-039e Ksi
-039f Omicron
-03a0 Pi
-03a1 Rho
-03a3 Sigma
-03a4 Tau
-03a5 Upsilon
-03a6 Phi
-03a7 Khi
-03a8 Psi
-03a9 Omega
-03aa Iotadiaeresis
-03ab Upsilondiaeresis
-03ac alphaaccent
-03ad epsilonaccent
-03ae etaaccent
-03af iotaaccent
-03b0 upsilondiaeresisaccent
-03b1 alpha
-03b2 beta
-03b3 gamma
-03b4 delta
-03b5 epsilon
-03b6 zeta
-03b7 eta
-03b8 theta
-03b9 iota
-03ba kappa
-03bb lamda
-03bc mu
-03bd nu
-03be ksi
-03bf omicron
-03c0 pi
-03c1 rho
-03c2 terminalsigma
-03c3 sigma
-03c4 tau
-03c5 upsilon
-03c6 phi
-03c7 khi
-03c8 psi
-03c9 omega
-03ca iotadiaeresis
-03cb upsilondiaeresis
-03cc omicronaccent
-03cd upsilonaccent
-03ce omegaaccent
-0401 cyrillic_capital_letter_io
-0402 serbocroatian_cyrillic_capital_letter_dje
-0403 macedonian_cyrillic_capital_letter_gje
-0404 ukrainian_cyrillic_capital_letter_ie
-0405 macedonian_cyrillic_capital_letter_dze
-0406 ukrainian_cyrillic_capital_letter_i
-0407 ukrainian_cyrillic_capital_letter_yi
-0408 cyrillic_capital_letter_je
-0409 cyrillic_capital_letter_lje
-040a cyrillic_capital_letter_nje
-040b serbocroatian_cyrillic_capital_letter_chje
-040c macedonian_cyrillic_capital_letter_kje
-040e bielorussian_cyrillic_capital_letter_short_u
-040f cyrillic_capital_letter_dze
-0410 cyrillic_capital_letter_a
-0411 cyrillic_capital_letter_be
-0412 cyrillic_capital_letter_ve
-0413 cyrillic_capital_letter_ghe
-0414 cyrillic_capital_letter_de
-0415 cyrillic_capital_letter_ie
-0416 cyrillic_capital_letter_zhe
-0417 cyrillic_capital_letter_ze
-0418 cyrillic_capital_letter_i
-0419 cyrillic_capital_letter_short_i
-041a cyrillic_capital_letter_ka
-041b cyrillic_capital_letter_el
-041c cyrillic_capital_letter_em
-041d cyrillic_capital_letter_en
-041e cyrillic_capital_letter_o
-041f cyrillic_capital_letter_pe
-0420 cyrillic_capital_letter_er
-0421 cyrillic_capital_letter_es
-0422 cyrillic_capital_letter_te
-0423 cyrillic_capital_letter_u
-0424 cyrillic_capital_letter_ef
-0425 cyrillic_capital_letter_ha
-0426 cyrillic_capital_letter_tse
-0427 cyrillic_capital_letter_che
-0428 cyrillic_capital_letter_sha
-0429 cyrillic_capital_letter_shcha
-042a cyrillic_capital_hard_sign
-042b cyrillic_capital_letter_yeru
-042c cyrillic_capital_soft_sign
-042d cyrillic_capital_letter_e
-042e cyrillic_capital_letter_yu
-042f cyrillic_capital_letter_ya
-0430 cyrillic_small_letter_a
-0431 cyrillic_small_letter_be
-0432 cyrillic_small_letter_ve
-0433 cyrillic_small_letter_ghe
-0434 cyrillic_small_letter_de
-0435 cyrillic_small_letter_ie
-0436 cyrillic_small_letter_zhe
-0437 cyrillic_small_letter_ze
-0438 cyrillic_small_letter_i
-0439 cyrillic_small_letter_short_i
-043a cyrillic_small_letter_ka
-043b cyrillic_small_letter_el
-043c cyrillic_small_letter_em
-043d cyrillic_small_letter_en
-043e cyrillic_small_letter_o
-043f cyrillic_small_letter_pe
-0440 cyrillic_small_letter_er
-0441 cyrillic_small_letter_es
-0442 cyrillic_small_letter_te
-0443 cyrillic_small_letter_u
-0444 cyrillic_small_letter_ef
-0445 cyrillic_small_letter_ha
-0446 cyrillic_small_letter_tse
-0447 cyrillic_small_letter_che
-0448 cyrillic_small_letter_sha
-0449 cyrillic_small_letter_shcha
-044a cyrillic_small_hard_sign
-044b cyrillic_small_letter_yeru
-044c cyrillic_small_soft_sign
-044d cyrillic_small_letter_e
-044e cyrillic_small_letter_yu
-044f cyrillic_small_letter_ya
-0451 cyrillic_small_letter_io
-0452 serbocroatian_cyrillic_small_letter_dje
-0453 macedonian_cyrillic_small_letter_gje
-0454 ukrainian_cyrillic_small_letter_ie
-0455 macedonian_cyrillic_small_letter_dze
-0456 ukrainian_cyrillic_small_letter_i
-0457 ukrainian_cyrillic_small_letter_yi
-0458 cyrillic_small_letter_je
-0459 cyrillic_small_letter_lje
-045a cyrillic_small_letter_nje
-045b serbocroatian_cyrillic_small_letter_chje
-045c macedonian_cyrillic_small_letter_kje
-045e bielorussian_cyrillic_small_letter_short_u
-045f cyrillic_small_letter_dze
-05d0 alef
-05d1 bet
-05d2 gimel
-05d3 dalet
-05d4 he
-05d5 vav
-05d6 zayin
-05d7 het
-05d8 tet
-05d9 yod
-05da finalkaf
-05db kaf
-05dc lamed
-05dd finalmem
-05de mem
-05df finalnun
-05e0 nun
-05e1 samekh
-05e2 ayin
-05e3 finalpe
-05e4 pe
-05e5 finaltsadi
-05e6 tsadi
-05e7 qof
-05e8 resh
-05e9 shin
-05ea tav
-2017 doubleunderscore
-201e quotedblbase
-203e overscore
-20ac euro
-2116 number_acronym
-- F1 F2 F3 F4 F5
-- F6 F7 F8 F9 F10
-- F11 F12 F13 F14 F15
-- F16 F17 F18 F19 F20
-- Find
-- Insert
-- Remove
-- Select
-- Prior
-- Next
-- Macro
-- Help
-- Do
-- Pause
-- F21 F22 F23 F24 F25
-- F26 F27 F28 F29 F30
-- F31 F32 F33 F34 F35
-- F36 F37 F38 F39 F40
-- F41 F42 F43 F44 F45
-- F46 F47 F48 F49 F50
-- F51 F52 F53 F54 F55
-- F56 F57 F58 F59 F60
-- F61 F62 F63 F64 F65
-- F66 F67 F68 F69 F70
-- F71 F72 F73 F74 F75
-- F76 F77 F78 F79 F80
-- F81 F82 F83 F84 F85
-- F86 F87 F88 F89 F90
-- F91 F92 F93 F94 F95
-- F96 F97 F98 F99 F100
-- F101 F102 F103 F104 F105
-- F106 F107 F108 F109 F110
-- F111 F112 F113 F114 F115
-- F116 F117 F118 F119 F120
-- F121 F122 F123 F124 F125
-- F126 F127 F128 F129 F130
-- F131 F132 F133 F134 F135
-- F136 F137 F138 F139 F140
-- F141 F142 F143 F144 F145
-- F146 F147 F148 F149 F150
-- F151 F152 F153 F154 F155
-- F156 F157 F158 F159 F160
-- F161 F162 F163 F164 F165
-- F166 F167 F168 F169 F170
-- F171 F172 F173 F174 F175
-- F176 F177 F178 F179 F180
-- F181 F182 F183 F184 F185
-- F186 F187 F188 F189 F190
-- F191 F192 F193 F194 F195
-- F196 F197 F198 F199 F200
-- F201 F202 F203 F204 F205
-- F206 F207 F208 F209 F210
-- F211 F212 F213 F214 F215
-- F216 F217 F218 F219 F220
-- F221 F222 F223 F224 F225
-- F226 F227 F228 F229 F230
-- F231 F232 F233 F234 F235
-- F236 F237 F238 F239 F240
-- F241 F242 F243 F244 F245
-- F246
-- VoidSymbol
-- Return
-- Show_Registers
-- Show_Memory
-- Show_State
+0391 Greek_ALPHA Alpha
+0392 Greek_BETA Beta
+0393 Greek_GAMMA Gamma
+0394 Greek_DELTA Delta
+0395 Greek_EPSILON Epsilon
+0396 Greek_ZETA Zeta
+0397 Greek_ETA Eta
+0398 Greek_THETA Theta
+0399 Greek_IOTA Iota
+039a Greek_KAPPA Kappa
+039b Greek_LAMBDA Lamda Greek_LAMDA
+039c Greek_MU Mu
+039d Greek_NU Nu
+039e Greek_XI Ksi
+039f Greek_OMICRON Omicron
+03a0 Greek_PI Pi
+03a1 Greek_RHO Rho
+03a3 Greek_SIGMA Sigma
+03a4 Greek_TAU Tau
+03a5 Greek_UPSILON Upsilon
+03a6 Greek_PHI Phi
+03a7 Greek_CHI Khi
+03a8 Greek_PSI Psi
+03a9 Greek_OMEGA Omega
+03aa Greek_IOTAdiaeresis Iotadiaeresis
+03ab Greek_UPSILONdieresis Upsilondiaeresis
+03ac Greek_alphaaccent alphaaccent
+03ad Greek_epsilonaccent epsilonaccent
+03ae Greek_etaaccent etaaccent
+03af Greek_iotaaccent iotaaccent
+03b0 Greek_upsilonaccentdieresis upsilondiaeresisaccent
+03b1 Greek_alpha alpha
+03b2 Greek_beta beta
+03b3 Greek_gamma gamma
+03b4 Greek_delta delta
+03b5 Greek_epsilon epsilon
+03b6 Greek_zeta zeta
+03b7 Greek_eta eta
+03b8 Greek_theta theta
+03b9 Greek_iota iota dead_iota
+# What the hell is a dead iota supposed to accomplish ??
+03ba Greek_kappa kappa
+03bb Greek_lambda lamda Greek_lamda
+03bc Greek_mu mu
+03bd Greek_nu nu
+03be Greek_xi ksi
+03bf Greek_omicron omicron
+03c0 Greek_pi pi
+03c1 Greek_rho rho
+03c2 Greek_finalsmallsigma terminalsigma
+03c3 Greek_sigma sigma
+03c4 Greek_tau tau
+03c5 Greek_upsilon upsilon
+03c6 Greek_phi phi
+03c7 Greek_chi khi
+03c8 Greek_psi psi
+03c9 Greek_omega omega
+03ca Greek_iotadieresis iotadiaeresis
+03cb Greek_upsilondieresis upsilondiaeresis
+03cc Greek_omicronaccent omicronaccent
+03cd Greek_upsilonaccent upsilonaccent
+03ce Greek_omegaaccent omegaaccent
+0401 cyrillic_capital_letter_io Cyrillic_IO
+0402 Serbian_DJE serbocroatian_cyrillic_capital_letter_dje
+0403 Macedonia_GJE macedonian_cyrillic_capital_letter_gje
+0404 Ukrainian_IE ukrainian_cyrillic_capital_letter_ie
+0405 Macedonia_DSE macedonian_cyrillic_capital_letter_dze
+0406 ukrainian_cyrillic_capital_letter_i Ukrainian_I
+0407 ukrainian_cyrillic_capital_letter_yi Ukrainian_YI
+0408 cyrillic_capital_letter_je Cyrillic_JE
+0409 cyrillic_capital_letter_lje Cyrillic_LJE
+040a cyrillic_capital_letter_nje Cyrillic_NJE
+040b Serbian_TSHE serbocroatian_cyrillic_capital_letter_chje
+040c Macedonia_KJE macedonian_cyrillic_capital_letter_kje
+040e bielorussian_cyrillic_capital_letter_short_u Byelorussian_SHORTU
+040f cyrillic_capital_letter_dze Cyrillic_DZHE
+0410 Cyrillic_A cyrillic_capital_letter_a
+0411 Cyrillic_BE cyrillic_capital_letter_be
+0412 cyrillic_capital_letter_ve Cyrillic_VE
+0413 cyrillic_capital_letter_ghe Cyrillic_GHE
+0414 cyrillic_capital_letter_de Cyrillic_DE
+0415 cyrillic_capital_letter_ie Cyrillic_IE
+0416 cyrillic_capital_letter_zhe Cyrillic_ZHE
+0417 cyrillic_capital_letter_ze Cyrillic_ZE
+0418 cyrillic_capital_letter_i Cyrillic_I
+0419 cyrillic_capital_letter_short_i Cyrillic_SHORTI
+041a cyrillic_capital_letter_ka Cyrillic_KA
+041b cyrillic_capital_letter_el Cyrillic_EL
+041c cyrillic_capital_letter_em Cyrillic_EM
+041d cyrillic_capital_letter_en Cyrillic_EN
+041e cyrillic_capital_letter_o Cyrillic_O
+041f cyrillic_capital_letter_pe Cyrillic_PE
+0420 cyrillic_capital_letter_er Cyrillic_ER
+0421 cyrillic_capital_letter_es Cyrillic_ES
+0422 cyrillic_capital_letter_te Cyrillic_TE
+0423 cyrillic_capital_letter_u Cyrillic_U
+0424 cyrillic_capital_letter_ef Cyrillic_EF
+0425 cyrillic_capital_letter_ha Cyrillic_HA
+0426 cyrillic_capital_letter_tse Cyrillic_TSE
+0427 cyrillic_capital_letter_che Cyrillic_CHE
+0428 cyrillic_capital_letter_sha Cyrillic_SHA
+0429 cyrillic_capital_letter_shcha Cyrillic_SHCHA
+042a cyrillic_capital_hard_sign Cyrillic_HARDSIGN
+042b cyrillic_capital_letter_yeru Cyrillic_YERU
+042c cyrillic_capital_soft_sign Cyrillic_SOFTSIGN
+042d cyrillic_capital_letter_e Cyrillic_E
+042e cyrillic_capital_letter_yu Cyrillic_YU
+042f cyrillic_capital_letter_ya Cyrillic_YA
+0430 Cyrillic_a cyrillic_small_letter_a
+0431 Cyrillic_be cyrillic_small_letter_be
+0432 cyrillic_small_letter_ve Cyrillic_ve
+0433 Cyrillic_ghe cyrillic_small_letter_ghe
+0434 Cyrillic_de cyrillic_small_letter_de
+0435 Cyrillic_ie cyrillic_small_letter_ie
+0436 cyrillic_small_letter_zhe Cyrillic_zhe
+0437 cyrillic_small_letter_ze Cyrillic_ze
+0438 Cyrillic_i cyrillic_small_letter_i
+0439 Cyrillic_shorti cyrillic_small_letter_short_i
+043a Cyrillic_ka cyrillic_small_letter_ka
+043b Cyrillic_el cyrillic_small_letter_el
+043c Cyrillic_em cyrillic_small_letter_em
+043d Cyrillic_en cyrillic_small_letter_en
+043e Cyrillic_o cyrillic_small_letter_o
+043f Cyrillic_pe cyrillic_small_letter_pe
+0440 Cyrillic_er cyrillic_small_letter_er
+0441 Cyrillic_es cyrillic_small_letter_es
+0442 cyrillic_small_letter_te Cyrillic_te
+0443 cyrillic_small_letter_u Cyrillic_u
+0444 Cyrillic_ef cyrillic_small_letter_ef
+0445 Cyrillic_ha cyrillic_small_letter_ha
+0446 cyrillic_small_letter_tse Cyrillic_tse
+0447 Cyrillic_che cyrillic_small_letter_che
+0448 Cyrillic_sha cyrillic_small_letter_sha
+0449 Cyrillic_shcha cyrillic_small_letter_shcha
+044a Cyrillic_hardsign cyrillic_small_hard_sign
+044b cyrillic_small_letter_yeru Cyrillic_yeru
+044c cyrillic_small_soft_sign Cyrillic_softsign
+044d Cyrillic_e cyrillic_small_letter_e
+044e cyrillic_small_letter_yu Cyrillic_yu
+044f cyrillic_small_letter_ya Cyrillic_ya
+0451 Cyrillic_io cyrillic_small_letter_io
+0452 Serbian_dje serbocroatian_cyrillic_small_letter_dje
+0453 Macedonia_gje macedonian_cyrillic_small_letter_gje
+0454 ukrainian_cyrillic_small_letter_ie Ukrainian_ie
+0455 Macedonia_dse macedonian_cyrillic_small_letter_dze
+0456 ukrainian_cyrillic_small_letter_i Ukrainian_i
+0457 ukrainian_cyrillic_small_letter_yi Ukrainian_yi
+0458 Cyrillic_je cyrillic_small_letter_je
+0459 Cyrillic_lje cyrillic_small_letter_lje
+045a Cyrillic_nje cyrillic_small_letter_nje
+045b Serbian_tshe serbocroatian_cyrillic_small_letter_chje
+045c Macedonia_kje macedonian_cyrillic_small_letter_kje
+045e bielorussian_cyrillic_small_letter_short_u Byelorussian_shortu
+045f Cyrillic_dzhe cyrillic_small_letter_dze
+0490 Ukrainian_GHE_WITH_UPTURN
+0491 Ukrainian_ghe_with_upturn
+04ae Cyrillic_U_straight
+04af Cyrillic_u_straight
+04e8 Cyrillic_O_bar
+04e9 Cyrillic_o_bar
+05d0 alef hebrew_aleph
+05d1 bet hebrew_bet
+05d2 gimel hebrew_gimel
+05d3 dalet hebrew_dalet
+05d4 he hebrew_he
+05d5 hebrew_waw vav
+05d6 hebrew_zain zayin
+05d7 hebrew_chet het
+05d8 hebrew_tet tet
+05d9 hebrew_yod yod
+05da finalkaf hebrew_finalkaph
+05db hebrew_kaph kaf
+05dc hebrew_lamed lamed
+05dd finalmem hebrew_finalmem
+05de hebrew_mem mem
+05df finalnun hebrew_finalnun
+05e0 hebrew_nun nun
+05e1 hebrew_samech samekh
+05e2 ayin hebrew_ayin
+05e3 finalpe hebrew_finalpe
+05e4 hebrew_pe pe
+05e5 finaltsadi hebrew_finalzade
+05e6 hebrew_zade tsadi
+05e7 hebrew_qoph qof
+05e8 hebrew_resh resh
+05e9 hebrew_shin shin
+05ea hebrew_taw tav
+060c Arabic_comma
+061b Arabic_semicolon
+061f Arabic_question_mark
+0621 Arabic_hamza
+0622 Arabic_maddaonalef
+0623 Arabic_hamzaonalef
+0624 Arabic_hamzaonwaw
+0625 Arabic_hamzaunderalef
+0626 Arabic_hamzaonyeh
+0627 Arabic_alef
+0628 Arabic_beh
+0629 Arabic_tehmarbuta
+062a Arabic_teh
+062b Arabic_theh
+062c Arabic_jeem
+062d Arabic_hah
+062e Arabic_khah
+062f Arabic_dal
+0630 Arabic_thal
+0631 Arabic_ra
+0632 Arabic_zain
+0633 Arabic_seen
+0634 Arabic_sheen
+0635 Arabic_sad
+0636 Arabic_dad
+0637 Arabic_tah
+0638 Arabic_zah
+0639 Arabic_ain
+063a Arabic_ghain
+0640 Arabic_tatweel
+0641 Arabic_feh
+0642 Arabic_qaf
+0643 Arabic_kaf
+0644 Arabic_lam
+0645 Arabic_meem
+0646 Arabic_noon
+0647 Arabic_ha Arabic_heh
+0648 Arabic_waw
+0649 Arabic_alefmaksura
+064a Arabic_yeh
+064b Arabic_fathatan
+064c Arabic_dammatan
+064d Arabic_kasratan
+064e Arabic_fatha
+064f Arabic_damma
+0650 Arabic_kasra
+0651 Arabic_shadda
+0652 Arabic_sukun
+0653 Arabic_madda_above
+0654 Arabic_hamza_above
+0655 Arabic_hamza_below
+0670 Arabic_superscript_alef
+- gur_v_r gur_v_r_s
+0A02 gur_bindi
+0A03 gur_visarga
+0A05 gur_a
+0A06 gur_aa
+0A07 gur_i
+0A08 gur_ii
+0A09 gur_u
+0A0A gur_uu
+0A0F gur_ee
+0A10 gur_ai
+0A13 gur_oo
+0A14 gur_au
+0A15 gur_ka
+0A16 gur_kha
+0A17 gur_ga
+0A18 gur_gha
+0A19 gur_nga
+0A1A gur_ca
+0A1B gur_cha
+0A1C gur_ja
+0A1D gur_jha
+0A1E gur_nya
+0A1F gur_tta
+0A20 gur_ttha
+0A21 gur_dda
+0A22 gur_ddha
+0A23 gur_nna
+0A24 gur_ta
+0A25 gur_tha
+0A26 gur_da
+0A27 gur_dha
+0A28 gur_na
+0A2A gur_pa
+0A2B gur_pha
+0A2C gur_ba
+0A2D gur_bha
+0A2E gur_ma
+0A2F gur_ya
+0A30 gur_ra
+0A32 gur_la
+0A35 gur_va
+0A36 gur_sha
+0A38 gur_sa
+0A39 gur_ha
+0A3C gur_nukta
+0A3E gur_aamatra
+0A3F gur_imatra
+0A40 gur_iimatra
+0A41 gur_umatra
+0A42 gur_uumatra
+0A47 gur_eematra
+0A48 gur_aimatra
+0A4B gur_oomatra
+0A4C gur_aumatra
+0A4D gur_halant
+0A59 gur_khha
+0A5A gur_ghha
+0A5B gur_za
+0A5C gur_rra
+0A5E gur_fa
+0A66 gur_zero
+0A67 gur_one
+0A68 gur_two
+0A69 gur_three
+0A6A gur_four
+0A6B gur_five
+0A6C gur_six
+0A6D gur_seven
+0A6E gur_eight
+0A6F gur_nine
+0A70 gur_tippi
+0A71 gur_addak
+0A72 gur_iri
+0A73 gur_ura
+0A74 gur_ekonkar
+0A81 guj_candrabindu
+0A82 guj_anusvara
+0A83 guj_visarga
+0A85 guj_a
+0A86 guj_aa
+0A87 guj_i
+0A88 guj_ii
+0A89 guj_u
+0A8A guj_uu
+0A8B guj_rvocalic
+0A8D guj_ecandra
+0A8F guj_e
+0A90 guj_ai
+0A91 guj_ocandra
+0A93 guj_o
+0A94 guj_au
+0A95 guj_ka
+0A96 guj_kha
+0A97 guj_ga
+0A98 guj_gha
+0A99 guj_nga
+0A9A guj_ca
+0A9B guj_cha
+0A9C guj_ja
+0A9D guj_jha
+0A9E guj_nya
+0A9F guj_tta
+0AA0 guj_ttha
+0AA1 guj_dda
+0AA2 guj_ddha
+0AA3 guj_nna
+0AA4 guj_nnna
+0AA4 guj_ta
+0AA5 guj_tha
+0AA6 guj_da
+0AA7 guj_dha
+0AA8 guj_na
+0AAA guj_pa
+0AAB guj_pha
+0AAC guj_ba
+0AAD guj_bha
+0AAE guj_ma
+0AAF guj_ya
+0AB0 guj_ra
+0AB1 guj_rra
+0AB2 guj_la
+0AB3 guj_lla
+0AB4 guj_llla
+0AB5 guj_va
+0AB6 guj_sha
+0AB7 guj_ssa
+0AB8 guj_sa
+0AB9 guj_ha
+0ABC guj_nukta
+0ABE guj_aavowelsign
+0ABF guj_ivowelsign
+0AC0 guj_iivowelsign
+0AC1 guj_uvowelsign
+0AC2 guj_uuvowelsign
+0AC3 guj_rvocalicvowelsign
+0AC4 guj_rrvocalicvowelsign
+0AC5 guj_ecandravowelsign
+0AC7 guj_evowelsign
+0AC8 guj_aivowelsign
+0AC9 guj_ocandravowelsign
+0ACB guj_ovowelsign
+0ACC guj_auvowelsign
+0ACD guj_virama
+0AD0 guj_om
+0AE0 guj_rrvocalic
+0AE6 guj_zero
+0AE7 guj_one
+0AE8 guj_two
+0AE9 guj_three
+0AEA guj_four
+0AEB guj_five
+0AEC guj_six
+0AED guj_seven
+0AEE guj_eight
+0AEF guj_nine
+0e01 thai_kokai
+0e02 thai_khokhai
+0e03 thai_khokhuat
+0e04 thai_khokhwai
+0e05 thai_khokhon
+0e06 thai_khorakhang
+0e07 thai_ngongu
+0e08 thai_chochan
+0e09 thai_choching
+0e0a thai_chochang
+0e0b thai_soso
+0e0c thai_chochoe
+0e0d thai_yoying
+0e0e thai_dochada
+0e0f thai_topatak
+0e10 thai_thothan
+0e11 thai_thonangmontho
+0e12 thai_thophuthao
+0e13 thai_nonen
+0e14 thai_dodek
+0e15 thai_totao
+0e16 thai_thothung
+0e17 thai_thothahan
+0e18 thai_thothong
+0e19 thai_nonu
+0e1a thai_bobaimai
+0e1b thai_popla
+0e1c thai_phophung
+0e1d thai_fofa
+0e1e thai_phophan
+0e1f thai_fofan
+0e20 thai_phosamphao
+0e21 thai_moma
+0e22 thai_yoyak
+0e23 thai_rorua
+0e24 thai_ru
+0e25 thai_loling
+0e26 thai_lu
+0e27 thai_wowaen
+0e28 thai_sosala
+0e29 thai_sorusi
+0e2a thai_sosua
+0e2b thai_hohip
+0e2c thai_lochula
+0e2d thai_oang
+0e2e thai_honokhuk
+0e2f thai_paiyannoi
+0e30 thai_saraa
+0e31 thai_maihanakat
+0e32 thai_saraaa
+0e33 thai_saraam
+0e34 thai_sarai
+0e35 thai_saraii
+0e36 thai_saraue
+0e37 thai_sarauee
+0e38 thai_sarau
+0e39 thai_sarauu
+0e3a thai_phinthu
+0e3f thai_baht
+0e40 thai_sarae
+0e41 thai_saraae
+0e42 thai_sarao
+0e43 thai_saraaimaimuan
+0e44 thai_saraaimaimalai
+0e45 thai_lakkhangyao
+0e46 thai_maiyamok
+0e47 thai_maitaikhu
+0e48 thai_maiek
+0e49 thai_maitho
+0e4a thai_maitri
+0e4b thai_maichattawa
+0e4c thai_thanthakhat
+0e4d thai_nikhahit
+0e4e thai_yamakkan
+0e4f thai_fongman
+0e50 thai_leksun
+0e51 thai_leknung
+0e52 thai_leksong
+0e53 thai_leksam
+0e54 thai_leksi
+0e55 thai_lekha
+0e56 thai_lekhok
+0e57 thai_lekchet
+0e58 thai_lekpaet
+0e59 thai_lekkao
+0e5a thai_angkhankhu
+0e5b thai_khomut
+11a8 Hangul_J_Kiyeog
+11a9 Hangul_J_SsangKiyeog
+11aa Hangul_J_KiyeogSios
+11ab Hangul_J_Nieun
+11ac Hangul_J_NieunJieuj
+11ad Hangul_J_NieunHieuh
+11ae Hangul_J_Dikeud
+11af Hangul_J_Rieul
+11b0 Hangul_J_RieulKiyeog
+11b1 Hangul_J_RieulMieum
+11b2 Hangul_J_RieulPieub
+11b3 Hangul_J_RieulSios
+11b4 Hangul_J_RieulTieut
+11b5 Hangul_J_RieulPhieuf
+11b6 Hangul_J_RieulHieuh
+11b7 Hangul_J_Mieum
+11b8 Hangul_J_Pieub
+11b9 Hangul_J_PieubSios
+11ba Hangul_J_Sios
+11bb Hangul_J_SsangSios
+11bc Hangul_J_Ieung
+11bd Hangul_J_Jieuj
+11be Hangul_J_Cieuc
+11bf Hangul_J_Khieuq
+11c0 Hangul_J_Tieut
+11c1 Hangul_J_Phieuf
+11c2 Hangul_J_Hieuh
+11eb Hangul_J_PanSios
+11f0 Hangul_J_KkogjiDalrinIeung
+11f9 Hangul_J_YeorinHieuh
+1e02 Babovedot
+1e03 babovedot
+1e0a Dabovedot
+1e0b dabovedot
+1e1e Fabovedot
+1e1f fabovedot
+1e40 Mabovedot
+1e41 mabovedot
+1e56 Pabovedot
+1e57 pabovedot
+1e60 Sabovedot
+1e61 sabovedot
+1e6a Tabovedot
+1e6b tabovedot
+2002 enspace
+2003 emspace
+2004 em3space
+2005 em4space
+2007 digitspace
+2008 punctspace
+2009 thinspace
+200a hairspace
+2012 figdash
+2013 endash
+2014 emdash
+2015 Greek_horizbar
+2017 doubleunderscore hebrew_doublelowline
+2018 leftsinglequotemark
+2019 rightsinglequotemark
+201a singlelowquotemark
+201c leftdoublequotemark
+201d rightdoublequotemark
+201e doublelowquotemark quotedblbase
+2020 dagger
+2021 doubledagger
+2022 enfilledcircbullet
+2025 doubbaselinedot
+2026 ellipsis
+2032 minutes
+2033 seconds
+2038 caret
+203e overline overscore
+20a9 Korean_Won
+20ab DongSign
+20ac euro Euro EuroSign
+2105 careof
+2116 number_acronym numerosign
+2117 phonographcopyright
+211e prescription
+2122 trademark
+2153 onethird
+2154 twothirds
+2155 onefifth
+2156 twofifths
+2157 threefifths
+2158 fourfifths
+2159 onesixth
+215a fivesixths
+215b oneeighth
+215c threeeighths
+215d fiveeighths
+215e seveneighths
+2190 leftarrow
+2191 uparrow
+2192 rightarrow
+2193 downarrow
+21d2 implies
+21d4 ifonlyif
+2202 partialderivative
+2207 nabla
+2218 jot
+221a radical
+221d variation
+221e infinity
+2227 logicaland
+2227 upcaret
+2228 downcaret logicalor
+2229 intersection upshoe
+222a downshoe union
+222b integral
+2234 therefore
+223c approximate
+2243 similarequal
+2260 notequal
+2261 identical
+2264 lessthanequal
+2265 greaterthanequal
+2282 includedin leftshoe
+2283 includes rightshoe
+22a2 lefttack
+22a3 righttack
+22a4 uptack
+22a5 downtack
+2308 upstile
+230a downstile
+2315 telephonerecorder
+2320 topintegral
+2321 botintegral
+2329 leftanglebracket
+232a rightanglebracket
+2395 quad
+239b topleftparens
+239d botleftparens
+239e toprightparens
+23a0 botrightparens
+23a1 topleftsqbracket
+23a3 botleftsqbracket
+23a4 toprightsqbracket
+23a6 botrightsqbracket
+23a8 leftmiddlecurlybrace
+23ac rightmiddlecurlybrace
+23b7 leftradical
+23ba horizlinescan1
+23bb horizlinescan3
+23bc horizlinescan7
+23bd horizlinescan9
+2409 ht
+240a lf
+240b vt
+240c ff
+240d cr
+2424 nl
+2500 horizconnector horizlinescan5
+2502 vertbar vertconnector
+250c topleftradical upleftcorner
+2510 uprightcorner
+2514 lowleftcorner
+2518 lowrightcorner
+251c leftt
+2524 rightt
+252c topt
+2534 bott
+253c crossinglines
+2592 checkerboard
+25aa enfilledsqbullet
+25ab enopensquarebullet
+25ac filledrectbullet
+25ad openrectbullet
+25ae emfilledrect
+25af emopenrectangle
+25b2 filledtribulletup
+25b3 opentribulletup
+25b6 filledrighttribullet
+25b7 rightopentriangle
+25bc filledtribulletdown
+25bd opentribulletdown
+25c0 filledlefttribullet
+25c1 leftopentriangle
+25c6 soliddiamond
+25cb circle
+25cb emopencircle
+25cf emfilledcircle
+25e6 enopencircbullet
+2606 openstar
+260e telephone
+2613 signaturemark
+261c leftpointer
+261e rightpointer
+2640 femalesymbol
+2642 malesymbol
+2663 club
+2665 heart
+2666 diamond
+266d musicalflat
+266f musicalsharp
+2713 checkmark
+2717 ballotcross
+271d latincross
+2720 maltesecross
+3001 kana_comma
+3002 kana_fullstop
+300c kana_openingbracket
+300d kana_closingbracket
+309b voicedsound
+309c semivoicedsound
+30a1 kana_a
+30a2 kana_A
+30a3 kana_i
+30a4 kana_I
+30a5 kana_u
+30a6 kana_U
+30a7 kana_e
+30a8 kana_E
+30a9 kana_o
+30aa kana_O
+30ab kana_KA
+30ad kana_KI
+30af kana_KU
+30b1 kana_KE
+30b3 kana_KO
+30b5 kana_SA
+30b7 kana_SHI
+30b9 kana_SU
+30bb kana_SE
+30bd kana_SO
+30bf kana_TA
+30c1 kana_CHI
+30c3 kana_tsu
+30c4 kana_TSU
+30c6 kana_TE
+30c8 kana_TO
+30ca kana_NA
+30cb kana_NI
+30cc kana_NU
+30cd kana_NE
+30ce kana_NO
+30cf kana_HA
+30d2 kana_HI
+30d5 kana_FU
+30d8 kana_HE
+30db kana_HO
+30de kana_MA
+30df kana_MI
+30e0 kana_MU
+30e1 kana_ME
+30e2 kana_MO
+30e3 kana_ya
+30e4 kana_YA
+30e5 kana_yu
+30e6 kana_YU
+30e7 kana_yo
+30e8 kana_YO
+30e9 kana_RA
+30ea kana_RI
+30eb kana_RU
+30ec kana_RE
+30ed kana_RO
+30ef kana_WA
+30f2 kana_WO
+30f3 kana_N
+30fb kana_conjunctive kana_middledot
+30fc prolongedsound
+- Muhenkan
+3131 Hangul_Kiyeog
+3132 Hangul_SsangKiyeog
+3133 Hangul_KiyeogSios
+3134 Hangul_Nieun
+3135 Hangul_NieunJieuj
+3136 Hangul_NieunHieuh
+3137 Hangul_Dikeud
+3138 Hangul_SsangDikeud
+3139 Hangul_Rieul
+313a Hangul_RieulKiyeog
+313b Hangul_RieulMieum
+313c Hangul_RieulPieub
+313d Hangul_RieulSios
+313e Hangul_RieulTieut
+313f Hangul_RieulPhieuf
+3140 Hangul_RieulHieuh
+3141 Hangul_Mieum
+3142 Hangul_Pieub
+3143 Hangul_SsangPieub
+3144 Hangul_PieubSios
+3145 Hangul_Sios
+3146 Hangul_SsangSios
+3147 Hangul_Ieung
+3148 Hangul_Jieuj
+3149 Hangul_SsangJieuj
+314a Hangul_Cieuc
+314b Hangul_Khieuq
+314c Hangul_Tieut
+314d Hangul_Phieuf
+314e Hangul_Hieuh
+314f Hangul_A
+3150 Hangul_AE
+3151 Hangul_YA
+3152 Hangul_YAE
+3153 Hangul_EO
+3154 Hangul_E
+3155 Hangul_YEO
+3156 Hangul_YE
+3157 Hangul_O
+3158 Hangul_WA
+3159 Hangul_WAE
+315a Hangul_OE
+315b Hangul_YO
+315c Hangul_U
+315d Hangul_WEO
+315e Hangul_WE
+315f Hangul_WI
+3160 Hangul_YU
+3161 Hangul_EU
+3162 Hangul_YI
+3163 Hangul_I
+316d Hangul_RieulYeorinHieuh
+3171 Hangul_SunkyeongeumMieum
+3178 Hangul_SunkyeongeumPieub
+317f Hangul_PanSios
+3181 Hangul_KkogjiDalrinIeung
+3184 Hangul_SunkyeongeumPhieuf
+3186 Hangul_YeorinHieuh
+318d Hangul_AraeA
+318e Hangul_AraeAE
+- Alt Alt_Lock
+- AltGr AltGr_Lock
+- Ascii_0 Ascii_1 Ascii_2 Ascii_3 Ascii_4
+- Ascii_5 Ascii_6 Ascii_7 Ascii_8 Ascii_9
+- Bare_Num_Lock
+- Boot
- Break
-- Last_Console
- Caps_Lock
-- Num_Lock
-- Scroll_Lock
-- Scroll_Forward
-- Scroll_Backward
-- Boot
- Caps_On
+- CapsShift
+- Clear
- Compose
-- SAK
-- Decr_Console
-- Incr_Console
-- KeyboardSignal
-- Bare_Num_Lock
-- KP_0
-- KP_1
-- KP_2
-- KP_3
-- KP_4
-- KP_5
-- KP_6
-- KP_7
-- KP_8
-- KP_9
-- KP_Add
-- KP_Subtract
-- KP_Multiply
-- KP_Divide
-- KP_Enter
-- KP_Comma
-- KP_Period
-- KP_MinPlus
- Console_1
- Console_2
- Console_3
@@ -702,61 +1252,263 @@
- Console_61
- Console_62
- Console_63
+- Control
+- Control_Lock
+- CtrlL
+- CtrlL_Lock
+- CtrlR
+- CtrlR_Lock
+- Decr_Console
+- Do
- Down
+- Eisu_toggle
+- Execute
+- F1 F2 F3 F4 F5
+- F6 F7 F8 F9 F10
+- F11 F12 F13 F14 F15
+- F16 F17 F18 F19 F20
+- F21 F22 F23 F24 F25
+- F26 F27 F28 F29 F30
+- F31 F32 F33 F34 F35
+- F36 F37 F38 F39 F40
+- F41 F42 F43 F44 F45
+- F46 F47 F48 F49 F50
+- F51 F52 F53 F54 F55
+- F56 F57 F58 F59 F60
+- F61 F62 F63 F64 F65
+- F66 F67 F68 F69 F70
+- F71 F72 F73 F74 F75
+- F76 F77 F78 F79 F80
+- F81 F82 F83 F84 F85
+- F86 F87 F88 F89 F90
+- F91 F92 F93 F94 F95
+- F96 F97 F98 F99 F100
+- F101 F102 F103 F104 F105
+- F106 F107 F108 F109 F110
+- F111 F112 F113 F114 F115
+- F116 F117 F118 F119 F120
+- F121 F122 F123 F124 F125
+- F126 F127 F128 F129 F130
+- F131 F132 F133 F134 F135
+- F136 F137 F138 F139 F140
+- F141 F142 F143 F144 F145
+- F146 F147 F148 F149 F150
+- F151 F152 F153 F154 F155
+- F156 F157 F158 F159 F160
+- F161 F162 F163 F164 F165
+- F166 F167 F168 F169 F170
+- F171 F172 F173 F174 F175
+- F176 F177 F178 F179 F180
+- F181 F182 F183 F184 F185
+- F186 F187 F188 F189 F190
+- F191 F192 F193 F194 F195
+- F196 F197 F198 F199 F200
+- F201 F202 F203 F204 F205
+- F206 F207 F208 F209 F210
+- F211 F212 F213 F214 F215
+- F216 F217 F218 F219 F220
+- F221 F222 F223 F224 F225
+- F226 F227 F228 F229 F230
+- F231 F232 F233 F234 F235
+- F236 F237 F238 F239 F240
+- F241 F242 F243 F244 F245
+- F246
+- Find
+- Help
+- Hex_0 Hex_1 Hex_2 Hex_3 Hex_4 Hex_5 Hex_6 Hex_7
+- Hex_8 Hex_9 Hex_A Hex_B Hex_C Hex_D Hex_E Hex_F
+- Incr_Console
+- Insert
+- ISO_First_Group
+- ISO_Last_Group
+- ISO_Left_Tab
+- ISO_Level3_Lock
+- ISO_Level3_Shift
+- ISO_Lock
+- ISO_Next_Group
+- ISO_Prev_Group
+- KeyboardSignal
+- KP_0 KP_1 KP_2 KP_3 KP_4 KP_5 KP_6 KP_7 KP_8 KP_9
+- KP_Add
+- KP_Begin
+- KP_Comma
+- KP_Decimal
+- KP_Delete
+- KP_Divide
+- KP_Down
+- KP_End
+- KP_Enter
+- KP_Equal
+- KP_Home
+- KP_Insert
+- KP_Left
+- KP_MinPlus
+- KP_Multiply
+- KP_Next
+- KP_Period
+- KP_Prior
+- KP_Right
+- KP_Separator
+- KP_Seprator
+- KP_Subtract
+- KP_Up
+- Last_Console
- Left
+- Macro
+- Menu
+- Mode_switch
+- Multi_key
+- Next
+- Nosymbol
+- Num_Lock
+- Pause
+- Pointer_EnableKeys
+- Print
+- Prior
+- Redo
+- Remove
+- Return
- Right
-- Up
+- SAK
+- SAlt
+- SAltGr
+- SControl
+- Scroll_Backward
+- Scroll_Forward
+- Scroll_Lock
+- SCtrlL
+- SCtrlR
+- Select
- Shift
-- AltGr
-- Control
-- Alt
- ShiftL
-- ShiftR
-- CtrlL
-- CtrlR
-- CapsShift
-- Ascii_0
-- Ascii_1
-- Ascii_2
-- Ascii_3
-- Ascii_4
-- Ascii_5
-- Ascii_6
-- Ascii_7
-- Ascii_8
-- Ascii_9
-- Hex_0
-- Hex_1
-- Hex_2
-- Hex_3
-- Hex_4
-- Hex_5
-- Hex_6
-- Hex_7
-- Hex_8
-- Hex_9
-- Hex_A
-- Hex_B
-- Hex_C
-- Hex_D
-- Hex_E
-- Hex_F
-- Shift_Lock
-- AltGr_Lock
-- Control_Lock
-- Alt_Lock
- ShiftL_Lock
+- Shift_Lock
+- ShiftR
- ShiftR_Lock
-- CtrlL_Lock
-- CtrlR_Lock
+- Show_Memory
+- Show_Registers
+- Show_State
- SShift
-- SAltGr
-- SControl
-- SAlt
- SShiftL
- SShiftR
-- SCtrlL
-- SCtrlR
+- Super_L
+- Super_R
+- Sys_Req
+- Undo
+- Up
+- VoidSymbol
+- XF86AddFavorite
+- XF86ApplicationLeft
+- XF86ApplicationRight
+- XF86AudioLowerVolume
+- XF86AudioMedia
+- XF86AudioMute
+- XF86AudioNext
+- XF86AudioPause
+- XF86AudioPlay
+- XF86AudioPrev
+- XF86AudioRaiseVolume
+- XF86AudioRecord
+- XF86AudioRewind
+- XF86AudioStop
+- XF86Away
+- XF86Back
+- XF86BackForward
+- XF86Book
+- XF86BrightnessAdjust
+- XF86Calculator
+- XF86Calendar
+- XF86CD
+- XF86Clear
+- XF86Close
+- XF86Community
+- XF86ContrastAdjust
+- XF86Copy
+- XF86Cut
+- XF86Display
+- XF86Documents
+- XF86DOS
+- XF86Eject
+- XF86Excel
+- XF86Explorer
+- XF86Favorites
+- XF86Finance
+- XF86Forward
+- XF86Game
+- XF86Go
+- XF86History
+- XF86HomePage
+- XF86HotLinks
+- XF86Launch0
+- XF86Launch1
+- XF86Launch2
+- XF86Launch3
+- XF86Launch4
+- XF86Launch5
+- XF86LaunchA
+- XF86LaunchB
+- XF86LaunchC
+- XF86LightBulb
+- XF86LogOff
+- XF86Mail
+- XF86MailForward
+- XF86Market
+- XF86Meeting
+- XF86MenuKB
+- XF86MenuPB
+- XF86Messenger
+- XF86Music
+- XF86MyComputer
+- XF86MySites
+- XF86New
+- XF86News
+- XF86OfficeHome
+- XF86Open
+- XF86OpenURL
+- XF86Option
+- XF86Paste
+- XF86Phone
+- XF86Pictures
+- XF86PowerOff
+- XF86Q
+- XF86Refresh
+- XF86Reload
+- XF86Reply
+- XF86RotateWindows
+- XF86RotationKB
+- XF86RotationPB
+- XF86Save
+- XF86ScreenSaver
+- XF86ScrollClick
+- XF86ScrollDown
+- XF86ScrollUp
+- XF86Search
+- XF86Send
+- XF86Shop
+- XF86Sleep
+- XF86Spell
+- XF86SplitScreen
+- XF86Standby
+- XF86Start
+- XF86Stop
+- XF86Support
+- XF86TaskPane
+- XF86Terminal
+- XF86Tools
+- XF86Travel
+- XF86User1KB
+- XF86User2KB
+- XF86UserPB
+- XF86VendorHome
+- XF86Video
+- XF86WakeUp
+- XF86WebCam
+- XF86Word
+- XF86WWW
+- XF86Xfer
+- XF86ZoomIn
+- XF86ZoomOut
+- any
= Control_h BackSpace
= Control_i Tab
= Control_j Linefeed
--- keymapper-0.5.3.orig/data/xkeys
+++ keymapper-0.5.3/data/xkeys
@@ -0,0 +1,58 @@
+# Map: X11 key name => Linux keycode (hex)
+AB01 2c
+AB02 2d
+AB03 2e
+AB04 2f
+AB05 30
+AB06 31
+AB07 32
+AB08 33
+AB09 34
+AC01 1e
+AC02 1f
+AC03 20
+AC04 21
+AC05 22
+AC06 23
+AC07 24
+AC08 25
+AC09 26
+AC10 27
+AC11 28
+AD01 10
+AD02 11
+AD03 12
+AD04 13
+AD05 14
+AD06 15
+AD07 16
+AD08 17
+AD09 18
+AD10 19
+AD11 1a
+AD12 1b
+AE02 03
+AE03 04
+AE04 05
+AE05 06
+AE06 07
+AE07 08
+AE08 09
+AE09 0a
+AE10 0b
+AE11 0c
+AE12 0d
+BKSL 2b
+BKSP 0e
+CAPS 3a
+ESC 01
+LALT 38
+LCTL 1d
+LFSH 2a
+LSGT 56
+RALT 64
+RCTL 61
+RTRN 1c
+RTSH 36
+TAB 0f
+TLDE 29
--- keymapper-0.5.3.orig/data/equivs
+++ keymapper-0.5.3/data/equivs
@@ -0,0 +1,153 @@
+£₤
+aаAαАΑаαɑą
+bвBΒ♭ьƅВЬвьℬʙ
+чƨᠽᠴ
+cℂCСсʗ∁¢
+dD
+eE∈ℰεЕℇеєƐΕ℮Ɛɛeɛ∊∈∊ƹع
+fFϜϝℱ
+gGɡɢℊցɡ
+hнHНнһℋℍℌℎΗʜʰհ
+jJℐјℑϳʲ
+kкKКкҚқҠҡΚκKK
+l∟ΙL1iӀІİIℓℒ¡ІіΙιɪʟⅠˡւԼℭıi讠⻈ɩι℩Ɩɩɪ℩⍳וןוּיּיاﭐﺃﺄﺍﺎ
+mМℳMмΜмᠮ
+nNΝɴറℕոⁿה
+oOѺoѻОоΟο0ഠܘՕօ०∅⌀Ø
+pPРрΡℙρϱр
+qQℚ
+rRʀʳℛℝℜ
+sSѕЅˢടՏ
+șş
+tтTТтΤττէ⊤ʈƮ
+uUυՍսՄԱ
+wWωΩѠѡʷΩΩ
+xхXχΧХхˣﬡאאּ
+yУYүУуҮүΥγʸɣγƔvVѴѵν
+zZΖℤℨƶ
+äÄ
+ÏïϊÏïİı
+öÖ
+üÜϋŰű
+´`'
+ßβϐ阝ƀ
+θϑ
+ϕφΦՓ
+ѰѱΨψ
+Ϟϟ
+Ϡϡ
+зэ∃∋∍ӡʒȝ∍϶
+Ϛϛςσ
+гΓГгΓ୮
+пЛПΠπлᴫᠯ ᠳдΠ∏
+∂ĐƉÐđðђδɖ
+əӘǝәƏ
+ӨƟөθѳɵ
+υ℧ʋʊƲ
+1¹
+2Չշ²२Ձ
+3Յ३³ӠȜƷ
+5ƽ
+8ȣ
+-‒–—―─━﹣-⁻₋−᠆−-‑‐–‒ー—
++⁺₊∔﹢
+.·˙ׁׂ̇ׄ۰۔ܼ݀݁․⋅⠁⠂⠄⠈⠐⠠⡀⢀〮៙๏
+Ɓɓ
+
+⋀⌃̂˄∧ˆ⊍ʌ⨃⟑⩀‸Λ⍝^
+ǀ∣⧸⁄ʇ׀/∕❘̸|¦
+։ː׃:∶
+₠€
+́΄҆̍̓̒̕’‘❛ء'′´ʹʻʼʾˈˊ՛՚❜٬ʹ
+!ǃ❢יִ
+؟ˁ҅‽ʕ̔?ˀʔՙ
+‛ʽʿ
+;؛;
+٪%
+͇ˍ̱̳̲‗_
+בℶ
+∼̃⌇⫭˜〰⫬~⦚〜~
+ǁ∥⃦ʖ‖⫽
+☀⨀☉◉⊙ʘ☼⦿
+⋃∪
+⦁•⋅‧·⁰̊․●❌ˑ°·◘∙∘・˚◦
+ɪƗ
+ɔƆ
+〈〈<⟨‹≺⧼«≪⋘《⟪⋘⫷
+╳✕×
+★⋆✨*٭⁎✱∗¤
+℡℻
+ϛς
+⊚◎
+◆♦
+。۔.
+Ɗɗ
+〚⟦
+␣⌴
+▪◾
+ଓବ@
+±∓
+△⃤⧍Δ∆
+※྿
+ᠣо
+见⻅
+隸隷
+ىيی
+ℸד
+〃"❝̋”̎〞〝″‶ʺ˝“❞
+♥❤
+♢⋄◇◊⃟
+⌋⟓」⏌⨼
+ɲƝ
+◺◿⊿
+、‚،,¸
+■❎◼█
+民⺠
+ÅÅ
+疋⺪
+❡⁋¶
+µμ
+⁁⋌
+∩⋂⩍
+љlj
+⟩〉❭❯⊱〉≻›⧽>»≫≫》⟫⋙
+□☐◻⟤⃞
+œɶ
+ӕæ
+∐⨿
+Ƞƞ
+ ̄‾
+łƚ
+⊲◅
+՝`ˋ‵̀
+⧹⧵⃥\∖
+≠ǂ
+○⃝〇◯
+☓✗
+țţ
+⊠☒
+✩☆
+ʃ∫
+ƩΣ∑
+ɸϕφ
+⊥┴⟘
+刂
+ᚹƿ
+ֿﬞ
+ğǧ
+⋁∨˅
+Ћћℏħ
+✓√
+©℗
+☙❧
+Ɯɯ
+גℷ
+͵ˏ
+ˉ̅̄¯
+Бƃб
+肉⺼
+ɠƓ
+Ÿÿ
+Ѳϴ
+þᚦ
+Ṫṫ