Fix utils/keylist.sh: resets locale to avoid broken table.
[geda-pcb/pcjc2.git] / utils / keylist.sh
blobc1eec28cbc5e39a308799930aeadbb881578a685
1 #!/bin/sh
2 # keylist - list hotkey->actions found in .res files in a html table, per HID
3 # Copyright (C) 2015 Tibor 'Igor2' Palinkas
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 along
16 # with this program; if not, write to the Free Software Foundation, Inc.,
17 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 # http://repo.hu/projects/pcb-rnd
21 AWK=awk
23 export LANG=C
25 if test -z "$*"
26 then
27 echo ""
28 echo "$0: Generate a html table from pcb menu res files."
29 echo "Usage: $0 file1 [file2 [file3 ... [fileN]]]"
30 echo ""
31 exit
32 else
33 res_files="$@"
36 # split the file into one token per line using a state machine
37 # tokens are:
38 # - quoted strings ("")
39 # - control characters: {, }, =
40 # - other words
41 tokenize()
43 $AWK '
44 BEGIN {
45 q = "\""
48 # echo a character and remember if it was a newline
49 function echo(c) {
50 had_nl = (c == "\n")
51 printf "%s", c
54 # echo a newline if the previous character written was not a newline
55 function nl() {
56 if (!had_nl)
57 echo("\n")
60 # parse state machine: eats input character by character
61 function parse(c) {
62 # ignore comments
63 if (in_comment)
64 return
66 # quote state machine
67 if (in_quote) {
68 if (bslash) {
69 echo(c)
70 bslash = 0
71 return
73 if (c == "\\")
74 bslash = 1
75 if (c == q) {
76 nl();
77 in_quote = 0
78 return
80 echo(c)
81 return
84 if (c == "#") {
85 in_comment = 1
86 return
89 # quote start
90 if (c == q) {
91 in_quote = 1
92 echo(c)
93 return
96 # whitespace are non-redundant newlines
97 if (c ~ "[ \t]") {
98 nl()
99 return
102 # "keywords"
103 if (c ~ "[{}=]") {
104 nl()
105 echo(c)
106 nl()
107 return
110 # anything else
111 echo(c)
114 # each new line of the input is a set of characters
115 # reset comment first, as it spanned to the previous newline
117 in_comment = 0
118 l = length($0)
119 for(n = 1; n <= l; n++)
120 parse(substr($0, n, 1))
125 # "grammar": read tokens and output "key src action" where
126 # key is in base-modified-modifier format, modifiers ordered
127 # src is the source res file we are working from, passed as $1
128 # action is the action given right after the key or before the key
129 extract_from_res()
131 tokenize | $AWK -v "src=$1" '
132 BEGIN {
133 sub(".*/", "", src)
135 /^=$/ {
136 if (last != "a") {
137 last = ""
138 getline t
139 next
141 last = ""
143 getline t
144 if (t != "{")
145 next
146 getline k1
147 getline k2
148 getline t
149 if (t != "}")
150 next
151 getline action
152 if (action == "}")
153 action = last_act
154 sub("^\"", "", k2)
155 sub("\"$", "", k2)
156 gsub(" \t", "", k2)
157 split(tolower(k2), K, "<key>")
158 if (K[1] != "") {
159 mods = ""
160 if (K[1] ~ "alt") mods = mods "-alt"
161 if (K[1] ~ "ctrl") mods = mods "-ctrl"
162 if (K[1] ~ "shift") mods = mods "-shift"
164 else
165 mods = ""
166 key = K[2] mods
167 gsub("[ \t]", "", key)
168 gsub("[ \t]", "", src)
169 gsub("[ \t]", "", action)
170 print key, src, action
171 last_act = ""
172 next
174 /[a-zA-Z]/ {
175 if (last != "")
176 last_act = last
178 { last = $0 }
182 # convert a "key src action" to a html table with rowspans for base keys
183 gen_html()
185 $AWK '
186 BEGIN {
187 HIDNAMES["gpcb-menu.res"] = "gtk"
188 HIDNAMES["pcb-menu.res"] = "lesstif"
189 CLR[0] = "#FFFFFF"
190 CLR[1] = "#DDFFFF"
191 key_combos = 0
193 function to_base_key(combo)
195 sub("-.*", "", combo)
196 return combo
199 function to_mods(combo)
201 if (!(combo ~ ".-"))
202 return ""
203 sub("^[^-]*[-]", "", combo)
204 return combo
208 if (last != $1) {
209 LIST[key_combos++] = $1
210 ROWSPAN[to_base_key($1)]++
212 ACTION[$2, $1] = $3
213 HIDS[$2]++
214 last = $1
217 END {
218 print "<html><body>"
219 print "<h1> Key to action bindings </h1>"
220 print "<table border=1 cellspacing=0>"
221 printf("<tr><th> key <th> modifiers")
222 colspan = 2
223 for(h in HIDS) {
224 printf(" <th>%s<br>%s", h, HIDNAMES[h])
225 colspan++
227 print ""
228 for(n = 0; n < key_combos; n++) {
229 key = LIST[n]
230 base = to_base_key(key)
231 mods = to_mods(key)
232 if (base != last_base)
233 clr_cnt++
234 print "<tr bgcolor=" CLR[clr_cnt % 2] ">"
235 if (base != last_base)
236 print " <th rowspan=" ROWSPAN[base] ">" base
237 if (mods == "")
238 mods = "&nbsp;"
239 print " <td>" mods
240 for(h in HIDS) {
241 act = ACTION[h, key]
242 if (act == "")
243 act = "&nbsp;"
244 print " <td>", act
246 last_base = base
248 print "</table>"
249 print "</body></html>"
254 for n in $res_files
256 extract_from_res "$n" < $n
257 done | sort | gen_html