6 $semicolon = ";"; # help out stupid emacs
7 $title = "Ardour Shortcuts";
21 $winkey = 'Mod4\>\<Super';
27 GetOptions ("platform=s" => \$platform,
28 "winkey=s" => \$winkey,
29 "cheatsheet" => \$make_cheatsheet,
30 "accelmap" => \$make_accelmap,
31 "merge=s" => \$merge_from,
34 if ($platform eq "darwin") {
36 $gtk_modifier_map{'PRIMARY'} = 'Primary';
37 $gtk_modifier_map{'SECONDARY'} = 'Control';
38 $gtk_modifier_map{'TERTIARY'} = 'Shift';
39 $gtk_modifier_map{'LEVEL4'} = 'Mod1';
40 $gtk_modifier_map{'WINDOW'} = 'Control';
42 $cs_modifier_map{'PRIMARY'} = 'Cmd';
43 $cs_modifier_map{'SECONDARY'} = 'Control';
44 $cs_modifier_map{'TERTIARY'} = 'Shift';
45 $cs_modifier_map{'LEVEL4'} = 'Mod1';
46 $cs_modifier_map{'WINDOW'} = 'Control';
48 $mouse_modifier_map{'PRIMARY'} = 'Cmd';
49 $mouse_modifier_map{'SECONDARY'} = 'Ctrl';
50 $mouse_modifier_map{'TERTIARY'} = 'Shift';
51 $mouse_modifier_map{'LEVEL4'} = 'Opt';
52 $mouse_modifier_map{'WINDOW'} = 'Ctrl';
56 $gtk_modifier_map{'PRIMARY'} = 'Control';
57 $gtk_modifier_map{'SECONDARY'} = 'Alt';
58 $gtk_modifier_map{'TERTIARY'} = 'Shift';
59 $gtk_modifier_map{'LEVEL4'} = $winkey;
60 $gtk_modifier_map{'WINDOW'} = 'Alt';
61 $gtk_modifier_map{$winkey} => 'Win';
63 $cs_modifier_map{'PRIMARY'} = 'Control';
64 $cs_modifier_map{'SECONDARY'} = 'Alt';
65 $cs_modifier_map{'TERTIARY'} = 'Shift';
66 $cs_modifier_map{'LEVEL4'} = 'Win';
67 $cs_modifier_map{'WINDOW'} = 'Alt';
68 $cs_modifier_map{$winkey} => 'Win';
70 $mouse_modifier_map{'PRIMARY'} = 'Ctl';
71 $mouse_modifier_map{'SECONDARY'} = 'Alt';
72 $mouse_modifier_map{'TERTIARY'} = 'Shift';
73 $mouse_modifier_map{'LEVEL4'} = 'Win';
74 $mouse_modifier_map{'WINDOW'} = 'Alt';
75 $mouse_modifier_map{$winkey} => 'Win';
85 'bracketright' => ']',
90 'rightanglebracket' => '>',
91 'leftanglebracket' => '<',
101 'rightarrow' => '→',
102 'leftarrow' => '←',
103 'uparrow' => '↑',
104 'downarrow' => '↓',
105 'Page_Down' => 'PageDown',
106 'Page_Up' => 'PageUp',
108 'KP_Right' => 'KP-→',
109 'KP_Left' => 'KP-←',
110 'KP_Up' => 'KP-↑',
111 'KP_Down' => 'KP-↓',
119 'asciicircum' => '\\verb=^=',
120 'apostrophe' => '\'',
121 'bracketleft' => '[',
122 'bracketright' => ']',
123 'braceleft' => '\\{',
124 'braceright' => '\\}',
125 'backslash' => '$\\backslash$',
127 'rightanglebracket' => '>',
128 'leftanglebracket' => '<',
129 'ampersand' => '\\&',
138 'rightarrow' => '$\rightarrow$',
139 'leftarrow' => '$\\leftarrow$',
140 'uparrow' => '$\\uparrow$',
141 'downarrow' => '$\\downarrow$',
142 'Page_Down' => 'Page Down',
143 'Page_Up' => 'Page Up',
152 open (BINDINGS, $merge_from) || die ("merge from bindings: file not readable");
154 next if (/^$semicolon/);
155 if (/^\(gtk_accel/) {
157 chop; # closing parenthesis
159 ($junk, $action, $binding) = split;
160 $merge_bindings{$action} = $binding;
166 if ($make_accelmap && !$merge_from) {
167 print ";; this accelmap was produced by tools/fmt-bindings\n";
171 next if /^$semicolon/;
183 $group_names{$group_key} = $group_name;
184 $group_text{$group_key} = $group_text;
185 $group_numbering{$group_key} = $group_number;
186 # each binding entry is 2 element array. bindings
187 # are all collected into a container array. create
188 # the first dummy entry so that perl knows what we
190 $group_bindings{$group_key} = [ [] ];
195 ($group_key,$group_name) = split (/\s+/, $_, 2);
205 $group_names{$group_key} = $group_name;
206 $group_text{$group_key} = $group_text;
209 next if (/^[ \t]+$/);
219 ($key,$action,$binding,$text) = split (/\|/, $_, 4);
221 # substitute bindings
223 $gtk_binding = $binding;
226 $lookup = "<Actions>/" . $action;
227 if ($merge_bindings{$lookup}) {
228 $binding = $merge_bindings{$lookup};
231 # forced inclusion of bindings from template
233 # this action is not defined in the merge from set, so forget it
239 # print the accelmap output
242 # remove + and don't print it in the accelmap
245 # include this in the accelmap
246 if (!$merge_from && $make_accelmap) {
247 foreach $k (keys %gtk_modifier_map) {
248 $gtk_binding =~ s/\@$k\@/$gtk_modifier_map{$k}/;
250 print "(gtk_accel_path \"<Actions>/$action\" \"$gtk_binding\")\n";
255 # do not include this binding in the cheat sheet
259 $bref = $group_bindings{$key};
260 push (@$bref, [$binding, $text]);
268 if ($make_accelmap || !$make_cheatsheet) {
274 @groups_sorted_by_number = sort { $group_numbering{$a} <=> $group_numbering{$b} } keys %group_numbering;
276 foreach $gk (@groups_sorted_by_number) {
279 # mouse stuff - ignore
283 # $bref is a reference to the array of arrays for this group
284 $bref = $group_bindings{$gk};
286 if (scalar @$bref > 1) {
288 $name = $group_names{$gk};
289 $name =~ s/\\linebreak.*//;
291 $name =~ s/\$\\_\$/-/g;
292 $name =~ s/\\[a-z]+ //g;
296 print "<h3>$name</h3>\n";
298 $gtext = $group_text{$gk};
299 $gtext =~ s/\\linebreak.*//;
301 $gtext =~ s/\$\\_\$/-/g;
302 $gtext =~ s/\\[a-z]+ //g;
304 $gtext =~ s/\\par//g;
306 if (!($gtext eq "")) {
310 # ignore the first entry, which was empty
316 print "<dl class=\"bindings\">\n";
318 # sort the array of arrays by the descriptive text for nicer appearance,
321 for $bbref (sort { @$a[1] cmp @$b[1] } @$bref) {
322 # $bbref is a reference to an array
324 $binding = @$bbref[0];
327 if ($binding =~ /:/) { # mouse binding with "where" clause
328 ($binding,$where) = split (/:/, $binding, 2);
331 foreach $k (keys %cs_modifier_map) {
332 $binding =~ s/\@$k\@/$cs_modifier_map{$k}/;
335 # remove braces for HTML
337 $binding =~ s/></\+/g;
341 # substitute keycode names for something printable
343 $re = qr/${ \(join'|', map quotemeta, keys %keycodes)}/;
344 $binding =~ s/($re)/$keycodes{$1}/g;
346 # tidy up description
349 $descr =~ s/\\linebreak.*//;
351 $descr =~ s/\$\\_\$/-/g;
352 $descr =~ s/\\[a-z]+ //g;
354 $descr =~ s/\\par//g;
356 print "<dt>$descr</dt><dd>$binding</dd>\n";
363 print " <!-- remove this if more text is added below -->\n";
368 # Now print the cheatsheet
370 $boilerplate_header = <<END_HEADER;
371 \\documentclass[10pt,landscape]{article}
372 %\\documentclass[10pt,landscape,a4paper]{article}
373 %\\documentclass[10pt,landscape,letterpaper]{article}
374 \\usepackage{multicol}
377 \\usepackage{palatino}
378 \\usepackage{geometry}
380 \\setlength{\\parskip}{0pt}
381 \\setlength{\\parsep}{0pt}
382 \\setlength{\\headsep}{0pt}
383 \\setlength{\\topskip}{0pt}
384 \\setlength{\\topmargin}{0pt}
385 \\setlength{\\topsep}{0pt}
386 \\setlength{\\partopsep}{0pt}
388 % This sets page margins to .5 inch if using letter paper, and to 1cm
389 % if using A4 paper. (This probably isnott strictly necessary.)
390 % If using another size paper, use default 1cm margins.
391 \\ifthenelse{\\lengthtest { \\paperwidth = 11in}}
392 { \\geometry{top=.5in,left=.5in,right=.5in,bottom=.5in} }
393 {\\ifthenelse{ \\lengthtest{ \\paperwidth = 297mm}}
394 {\\geometry{top=1cm,left=1cm,right=1cm,bottom=1cm} }
395 {\\geometry{top=1cm,left=1cm,right=1cm,bottom=1cm} }
398 % Turn off header and footer
401 % Redefine section commands to use less space
403 \\renewcommand{\\section}{\\\@startsection{section}{1}{0mm}%
404 {-1ex plus -.5ex minus -.2ex}%
406 {\\normalfont\\large\\bfseries}}
407 \\renewcommand{\\subsection}{\\\@startsection{subsection}{2}{0mm}%
408 {-1explus -.5ex minus -.2ex}%
410 {\\normalfont\\normalsize\\bfseries}}
411 \\renewcommand{\\subsubsection}{\\\@startsection{subsubsection}{3}{0mm}%
412 {-1ex plus -.5ex minus -.2ex}%
414 {\\normalfont\\small\\bfseries}}
417 % Do not print section numbers% Do not print section numbers
418 \\setcounter{secnumdepth}{0}
420 \\setlength{\\parindent}{0pt}
421 \\setlength{\\parskip}{0pt plus 0.5ex}
423 %-------------------------------------------
429 \\begin{multicols}{3}
432 $boilerplate_footer = <<END_FOOTER;
433 \\rule{0.3\\linewidth}{0.25pt}
436 Copyright \\copyright\\ 2013 ardour.org
438 % Should change this to be date of file, not current date.
440 http://manual.ardour.org
446 if ($make_cheatsheet) {
447 print $boilerplate_header;
448 print "\\begin{center}\\Large\\bf $title \\end{center}\n";
451 @groups_sorted_by_number = sort { $group_numbering{$a} <=> $group_numbering{$b} } keys %group_numbering;
453 foreach $gk (@groups_sorted_by_number) {
454 # $bref is a reference to the array of arrays for this group
455 $bref = $group_bindings{$gk};
457 if (scalar @$bref > 1) {
458 print "\\section{$group_names{$gk}}\n";
460 if (!($group_text{$gk} eq "")) {
461 print "$group_text{$gk}\n\\par\n";
464 # ignore the first entry, which was empty
468 # find the longest descriptive text (this is not 100% accuracy due to typography)
473 for $bbref (@$bref) {
474 # $bbref is a reference to an array
478 # if there is a linebreak, just use everything up the linebreak
479 # to determine the width
482 if ($text =~ /\\linebreak/) {
483 $matchtext = s/\\linebreak.*//;
487 if (length ($matchtext) > $maxtextlen) {
488 $maxtextlen = length ($matchtext);
489 $maxtext = $matchtext;
494 # mouse mode: don't extend max text at all - space it tight
502 print "\\settowidth{\\MyLen}{\\texttt{$maxtext}}\n";
503 print "\\begin{tabular}{\@{}p{\\the\\MyLen}%
504 \@{}p{\\linewidth-\\the\\MyLen}%
507 # sort the array of arrays by the descriptive text for nicer appearance,
510 for $bbref (sort { @$a[1] cmp @$b[1] } @$bref) {
511 # $bbref is a reference to an array
513 $binding = @$bbref[0];
516 if ($binding =~ /:/) { # mouse binding with "where" clause
517 ($binding,$where) = split (/:/, $binding, 2);
521 # mouse mode - use shorter abbrevs
522 foreach $k (keys %mouse_modifier_map) {
523 $binding =~ s/\@$k\@/$mouse_modifier_map{$k}/;
526 foreach $k (keys %cs_modifier_map) {
527 $binding =~ s/\@$k\@/$cs_modifier_map{$k}/;
531 $binding =~ s/></\+/g;
535 # substitute keycode names for something printable
537 $re = qr/${ \(join'|', map quotemeta, keys %keycodes)}/;
538 $binding =~ s/($re)/$keycodes{$1}/g;
540 # split up mouse bindings to "click" and "where" parts
542 if ($gk eq "mobject") {
543 print "{\\tt @$bbref[1] } & {\\tt $binding} {\\it $where}\\\\\n";
545 print "{\\tt @$bbref[1] } & {\\tt $binding} \\\\\n";
549 print "\\end{tabular}\n";
554 print $boilerplate_footer;