Added revised version from pcb-rnd.
[geda-pcb/pcjc2.git] / utils / keylist.sh
bloba2f180236eda0b9e751ea5b2fecf97fa2e25f38a
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 if test -z "$*"
24 then
25 echo ""
26 echo "$0: Generate a html table from pcb menu res files."
27 echo "Usage: $0 file1 [file2 [file3 ... [fileN]]]"
28 echo ""
29 exit
30 else
31 res_files="$@"
34 # split the file into one token per line using a state machine
35 # tokens are:
36 # - quoted strings ("")
37 # - control characters: {, }, =
38 # - other words
39 tokenize()
41 $AWK '
42 BEGIN {
43 q = "\""
46 # echo a character and remember if it was a newline
47 function echo(c) {
48 had_nl = (c == "\n")
49 printf "%s", c
52 # echo a newline if the previous character written was not a newline
53 function nl() {
54 if (!had_nl)
55 echo("\n")
58 # parse state machine: eats input character by character
59 function parse(c) {
60 # ignore comments
61 if (in_comment)
62 return
64 # quote state machine
65 if (in_quote) {
66 if (bslash) {
67 echo(c)
68 bslash = 0
69 return
71 if (c == "\\")
72 bslash = 1
73 if (c == q) {
74 nl();
75 in_quote = 0
76 return
78 echo(c)
79 return
82 if (c == "#") {
83 in_comment = 1
84 return
87 # quote start
88 if (c == q) {
89 in_quote = 1
90 echo(c)
91 return
94 # whitespace are non-redundant newlines
95 if (c ~ "[ \t]") {
96 nl()
97 return
100 # "keywords"
101 if (c ~ "[{}=]") {
102 nl()
103 echo(c)
104 nl()
105 return
108 # anything else
109 echo(c)
112 # each new line of the input is a set of characters
113 # reset comment first, as it spanned to the previous newline
115 in_comment = 0
116 l = length($0)
117 for(n = 1; n <= l; n++)
118 parse(substr($0, n, 1))
123 # "grammar": read tokens and output "key src action" where
124 # key is in base-modified-modifier format, modifiers ordered
125 # src is the source res file we are working from, passed as $1
126 # action is the action given right after the key or before the key
127 extract_from_res()
129 tokenize | $AWK -v "src=$1" '
130 BEGIN {
131 sub(".*/", "", src)
133 /^=$/ {
134 if (last != "a") {
135 last = ""
136 getline t
137 next
139 last = ""
141 getline t
142 if (t != "{")
143 next
144 getline k1
145 getline k2
146 getline t
147 if (t != "}")
148 next
149 getline action
150 if (action == "}")
151 action = last_act
152 sub("^\"", "", k2)
153 sub("\"$", "", k2)
154 gsub(" \t", "", k2)
155 split(tolower(k2), K, "<key>")
156 if (K[1] != "") {
157 mods = ""
158 if (K[1] ~ "alt") mods = mods "-alt"
159 if (K[1] ~ "ctrl") mods = mods "-ctrl"
160 if (K[1] ~ "shift") mods = mods "-shift"
162 else
163 mods = ""
164 key = K[2] mods
165 gsub("[ \t]", "", key)
166 gsub("[ \t]", "", src)
167 gsub("[ \t]", "", action)
168 print key, src, action
169 last_act = ""
170 next
172 /[a-zA-Z]/ {
173 if (last != "")
174 last_act = last
176 { last = $0 }
180 # convert a "key src action" to a html table with rowspans for base keys
181 gen_html()
183 $AWK '
184 BEGIN {
185 HIDNAMES["gpcb-menu.res"] = "gtk"
186 HIDNAMES["pcb-menu.res"] = "lesstif"
187 CLR[0] = "#FFFFFF"
188 CLR[1] = "#DDFFFF"
189 key_combos = 0
191 function to_base_key(combo)
193 sub("-.*", "", combo)
194 return combo
197 function to_mods(combo)
199 if (!(combo ~ ".-"))
200 return ""
201 sub("^[^-]*[-]", "", combo)
202 return combo
206 if (last != $1) {
207 LIST[key_combos++] = $1
208 ROWSPAN[to_base_key($1)]++
210 ACTION[$2, $1] = $3
211 HIDS[$2]++
212 last = $1
215 END {
216 print "<html><body>"
217 print "<h1> Key to action bindings </h1>"
218 print "<table border=1 cellspacing=0>"
219 printf("<tr><th> key <th> modifiers")
220 colspan = 2
221 for(h in HIDS) {
222 printf(" <th>%s<br>%s", h, HIDNAMES[h])
223 colspan++
225 print ""
226 for(n = 0; n < key_combos; n++) {
227 key = LIST[n]
228 base = to_base_key(key)
229 mods = to_mods(key)
230 if (base != last_base)
231 clr_cnt++
232 print "<tr bgcolor=" CLR[clr_cnt % 2] ">"
233 if (base != last_base)
234 print " <th rowspan=" ROWSPAN[base] ">" base
235 if (mods == "")
236 mods = "&nbsp;"
237 print " <td>" mods
238 for(h in HIDS) {
239 act = ACTION[h, key]
240 if (act == "")
241 act = "&nbsp;"
242 print " <td>", act
244 last_base = base
246 print "</table>"
247 print "</body></html>"
252 for n in $res_files
254 extract_from_res "$n" < $n
255 done | sort | gen_html