2 # SPDX-License-Identifier: GPL-2.0-or-later
5 # * Are there bad xml elements / parsing
6 # * Does it contain non-key xml elements
7 # * Does the keys file reference something unknown
8 # * Does it repeat empty actions
9 # * Are there keys formatted as verbs
10 # * Are some of the keys missing
11 # * Does it include the default xml
13 # Author: Martin Owens <doctormo@geek-2.com>
14 # Licensed under GPL version 2 or any later version, read the file "COPYING" for more information.
20 from collections
import defaultdict
22 from lxml
import etree
24 KEYS_PATH
= os
.path
.join('.', 'share', 'keys')
25 DEFAULT
= 'inkscape.xml'
27 IGNORE_MISSING_KEYS
= ['org.']
30 """Open and parse a keys xml file"""
31 def __init__(self
, filename
):
32 self
.filename
= filename
36 self
.ticks
= defaultdict(list)
38 self
.parse(etree
.parse(filename
))
41 """Parse the document into checkable concerns"""
42 for child
in doc
.getroot().getchildren():
44 if child
.tag
== "modifier":
45 name
= child
.attrib
['action']
47 self
.ticks
[name
].append(child
.attrib
.get('modifiers'))
48 elif child
.tag
== "bind":
49 name
= child
.attrib
['gaction']
51 self
.ticks
[name
].append(child
.attrib
.get('keys'))
52 if 'key' in child
.attrib
or 'modifiers' in child
.attrib
:
54 elif child
.tag
== "{http://www.w3.org/2001/XInclude}include":
55 self
.parse_include(child
.attrib
['href'])
56 elif isinstance(child
.tag
, str):
57 sys
.stderr
.write(f
"Unrecognised tag in keys file {child.tag}\n")
59 except KeyError as err
:
60 sys
.stderr
.write(f
"Missing attribute g/action in {self.filename}\n")
63 def parse_include(self
, file):
64 """Parse in the linked file"""
65 other
= Keys(os
.path
.join(os
.path
.dirname(self
.filename
), file))
66 self
.mods
= self
.mods
.union(other
.mods
)
67 self
.keys
= self
.keys
.union(other
.keys
)
71 """Load all non default keys"""
72 for name
in os
.listdir(KEYS_PATH
):
73 filename
= os
.path
.join(KEYS_PATH
, name
)
76 if not os
.path
.isfile(filename
) or not filename
.endswith('.xml'):
78 yield name
, cls(filename
)
82 """Load default keys"""
83 return cls(os
.path
.join(KEYS_PATH
, DEFAULT
))
86 if __name__
== '__main__':
87 sys
.stderr
.write("\n\n==== CHECKING KEYBOARD FILES ====\n\n")
88 data
= defaultdict(set)
95 for name
, this
in Keys
.others():
96 sys
.stderr
.write(f
"Checking '{name}'\n")
99 sys
.stderr
.write(f
" ! Old formatted key binding {old}\n")
102 if '-' not in sys
.argv
:
103 for key
in this
.keys ^
(that
.keys
& this
.keys
):
104 sys
.stderr
.write(f
" + Unknown extra key {key}\n")
107 for mod
in this
.mods ^
(that
.mods
& this
.mods
):
108 sys
.stderr
.write(f
" + Unknown extra modifier {mod}\n")
111 for tick
, lst
in this
.ticks
.items():
112 if len(lst
) > 1 and None in lst
:
113 sys
.stderr
.write(f
" * Multiple empty references to {tick}\n")
115 if '+' not in sys
.argv
:
116 for key
in that
.keys ^
(that
.keys
& this
.keys
):
117 if [ig
for ig
in IGNORE_MISSING_KEYS
if key
.startswith(ig
)]:
120 add
.append(f
"<bind gaction=\"{key}\" />")
122 sys
.stderr
.write(f
" - Missing key {key}\n")
125 for mod
in that
.mods ^
(that
.mods
& this
.mods
):
127 add
.append(f
"<modifier action=\"{mod}\" />")
129 sys
.stderr
.write(f
" - Missing modifier {mod}\n")
132 for item
in sorted(add
):
133 sys
.stderr
.write(f
" {item}\n")
134 sys
.stderr
.write("\n")