3 # Copyright 2020 Purdea Andrei
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation, either version 2 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program. If not, see <http://www.gnu.org/licenses/>.
18 import re
, glob
, os
, subprocess
, tempfile
, json
20 def handle_layouts(layouth_fn
, layoutc_fn
, infojson_fn
, config_fn
):
21 config
= open(config_fn
, "r").read()
22 cols
= int(re
.findall(r
"#define\s+MATRIX_COLS\s+([0-9]+)\n", config
)[0])
23 rows
= int(re
.findall(r
"#define\s+MATRIX_ROWS\s+([0-9]+)\n", config
)[0])
24 extra_direct_rows_l_str
= re
.findall(r
"#define\s+MATRIX_EXTRA_DIRECT_ROWS\s+([0-9]+)\n", config
)
25 if extra_direct_rows_l_str
:
26 extra_direct_rows
= int(extra_direct_rows_l_str
[0])
30 f
= open(infojson_fn
, "r")
31 js
= json
.loads(f
.read())['layouts']
34 d
= open(layouth_fn
, "r").read().replace("\\\n", " ")
35 dd
= re
.findall(r
'#define\s+(LAYOUT[a-zA-Z0-9_]*)\s*\(([^\)]*)\)', d
)
38 f
= open(temp_fn
, "w")
39 f
.write("#include \"" + layouth_fn
+ "\"\n")
41 le
= len(l
[1].split(","))
42 f
.write(separator
+ l
[0] + separator
+ "\n" + l
[0] + "(" + (",".join([str(i
) for i
in range(le
)])) + ")\n")
44 i
= os
.path
.split(os
.path
.abspath(layouth_fn
))[0]
48 i
, j
= os
.path
.split(i
)
49 if j
== "keyboards" or not i
:
51 for i
in "-Iusers/default -I. -Itmk_core -Iquantum -Iquantum/keymap_extras -Iquantum/audio -Iquantum/process_keycode -Iquantum/api -Idrivers -Idrivers/avr -Itmk_core/protocol -Itmk_core/common -Itmk_core/common/avr -Itmk_core/protocol/lufa -Ilib/lufa -Idrivers/avr".split(" "):
52 if i
.startswith("-I"):
53 includes
.append("../../../../" + i
[2:])
54 p
= subprocess
.Popen(["gcc", "-E"] + ["-I" + i
for i
in includes
] + ["-include", os
.path
.join(os
.path
.split(os
.path
.abspath(layouth_fn
))[0], "config.h"), temp_fn
], stdout
=subprocess
.PIPE
)
55 data
= p
.communicate()[0].split(separator
)
59 keybname
= re
.sub(r
'[^a-zA-Z0-9_]', '_', layoutc_fn
)
60 for i
in range(0, len(data
), 2):
62 desc
= "}".join(data
[i
+1].split("{", 1)[1].split("}")[:-1])
63 desc
= [i
.replace("{", "").replace("}", "") for i
in re
.findall("\{[^}]*\}", desc
)]
64 desc
= [[j
.strip() for j
in i
.split(",")] for i
in desc
]
66 for row
in range(len(desc
)):
67 for col
in range(len(desc
[row
])):
68 if desc
[row
][col
] != "KC_NO":
69 ind
= int(desc
[row
][col
])
70 while len(arr
) <= ind
:
73 layname
= keybname
+ "_" + re
.sub(r
'[^a-zA-Z0-9_]', '_', lname
)
74 print("struct key_def " + layname
+ "_keys[] = {")
75 for i
in range(len(arr
)):
76 item
= js
[lname
]['layout'][i
]
79 w
= item
['w'] if 'w' in item
else 1
80 h
= item
['h'] if 'h' in item
else 1
82 raise BaseException("Error index " + str(i
) + " in array " + str(arr
))
84 raise BaseException("Error array must have at least two elements: " + str(arr
[i
]) + " (full arr = " + str(arr
) + ")")
85 print (" { .row = %d, .col = %d, .x = %f, .y = %f, .w = %f, .h = %f }," % (arr
[i
][0], arr
[i
][1], x
, y
, w
, h
))
87 laynames
.append((layname
, lname
))
88 print("struct lay_def " + keybname
+ "_lays[] = {")
89 for layname
, lname
in sorted(laynames
):
91 print(" .lay_name = \"" + lname
+ "\",")
92 print(" .n_keys = sizeof(" + layname
+ "_keys) / sizeof(" + layname
+ "_keys[0]),")
93 print(" .keys = " + layname
+ "_keys,")
96 return keybname
, cols
, rows
, extra_direct_rows
99 def find_layouts(starting_dir
):
100 print("#include \"kbd_defs.h\"")
102 for root
, dirs
, files
in sorted(os
.walk(starting_dir
)):
103 for fil
in sorted(files
):
104 layouth_fn
= os
.path
.join(root
, fil
)
105 if layouth_fn
.endswith(".h"):
106 spl1
= os
.path
.split(layouth_fn
[:-2])
107 spl2
= os
.path
.split(spl1
[0])
108 if spl1
[1] == spl2
[1]:
109 infojson_fn
= os
.path
.join(spl2
[0], "info.json")
110 config_fn
= os
.path
.join(spl1
[0], "config.h")
111 layoutc_fn
= "keyboards/xwhatsit" + layouth_fn
[len(starting_dir
):-2] + ".c"
112 keybname
, cols
, rows
, extra_direct_rows
= handle_layouts(layouth_fn
, layoutc_fn
, infojson_fn
, config_fn
)
113 keebs
.append((keybname
, layoutc_fn
, cols
, rows
, extra_direct_rows
))
114 print("struct kbd_def keyboards[] = {")
115 for keybname
, layoutc_fn
, cols
, rows
, extra_direct_rows
in sorted(keebs
):
117 print(" .kbd_name = \"" + layoutc_fn
+ "\",")
118 print(" .n_layouts = sizeof(" + keybname
+ "_lays)/sizeof(" + keybname
+ "_lays[0]),")
119 print(" .layouts = " + keybname
+ "_lays,")
120 print(" .cols = %d," % (cols
,))
121 print(" .rows = %d," % (rows
,))
122 print(" .extra_direct_rows = %d," % (extra_direct_rows
,))
125 print("int n_keyboards = sizeof(keyboards)/sizeof(keyboards[0]);")
128 print("""/* Copyright 2020 Purdea Andrei
130 * This program is free software: you can redistribute it and/or modify
131 * it under the terms of the GNU General Public License as published by
132 * the Free Software Foundation, either version 2 of the License, or
133 * (at your option) any later version.
135 * This program is distributed in the hope that it will be useful,
136 * but WITHOUT ANY WARRANTY; without even the implied warranty of
137 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
138 * GNU General Public License for more details.
140 * You should have received a copy of the GNU General Public License
141 * along with this program. If not, see <http://www.gnu.org/licenses/>.
145 find_layouts("../..")