2009-07-30 10:07:49 -04:00
|
|
|
#!/usr/bin/perl
|
|
|
|
|
2009-07-30 20:34:36 -04:00
|
|
|
# import module
|
|
|
|
use Getopt::Long;
|
|
|
|
|
|
|
|
$semicolon = ";"; # help out stupid emacs
|
2009-07-30 10:07:49 -04:00
|
|
|
$in_group_def = 0;
|
|
|
|
$group_name;
|
|
|
|
$group_text;
|
|
|
|
$group_key;
|
2009-07-30 20:34:36 -04:00
|
|
|
$group_number = 0;
|
2009-07-30 10:07:49 -04:00
|
|
|
%group_names;
|
|
|
|
%group_text;
|
2009-07-30 20:34:36 -04:00
|
|
|
%group_bindings;
|
|
|
|
%modifier_map;
|
|
|
|
%group_numbering;
|
|
|
|
|
|
|
|
$platform = linux;
|
|
|
|
|
|
|
|
GetOptions ("platform=s" => \$platform);
|
|
|
|
|
|
|
|
if ($platform eq "osx") {
|
|
|
|
$gtk_modifier_map{'PRIMARY'} = 'meta';
|
|
|
|
$gtk_modifier_map{'SECONDARY'} = 'Mod1';
|
|
|
|
$gtk_modifier_map{'TERTIARY'} = 'Shift';
|
|
|
|
$gtk_modifier_map{'LEVEL4'} = 'Control';
|
|
|
|
$gtk_modifier_map{'WINDOW'} = 'Mod1';
|
|
|
|
|
|
|
|
$cs_modifier_map{'PRIMARY'} = 'Command';
|
|
|
|
$cs_modifier_map{'SECONDARY'} = 'Alt';
|
|
|
|
$cs_modifier_map{'TERTIARY'} = 'Shift';
|
|
|
|
$cs_modifier_map{'LEVEL4'} = 'Control';
|
|
|
|
$cs_modifier_map{'WINDOW'} = 'Alt';
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
$gtk_modifier_map{'PRIMARY'} = 'Control';
|
|
|
|
$gtk_modifier_map{'SECONDARY'} = 'Alt';
|
|
|
|
$gtk_modifier_map{'TERTIARY'} = 'Shift';
|
|
|
|
$gtk_modifier_map{'LEVEL4'} = 'Mod4';
|
|
|
|
$gtk_modifier_map{'WINDOW'} = 'Alt';
|
|
|
|
|
|
|
|
$cs_modifier_map{'PRIMARY'} = 'Control';
|
|
|
|
$cs_modifier_map{'SECONDARY'} = 'Alt';
|
|
|
|
$cs_modifier_map{'TERTIARY'} = 'Shift';
|
|
|
|
$cs_modifier_map{'LEVEL4'} = 'Win';
|
|
|
|
$cs_modifier_map{'WINDOW'} = 'Alt';
|
|
|
|
}
|
|
|
|
|
|
|
|
%keycodes = (
|
|
|
|
'asciicircum' => '\\verb=^=',
|
|
|
|
'apostrophe' => '\'',
|
|
|
|
'bracketleft' => '[',
|
|
|
|
'bracketright' => ']',
|
|
|
|
'braceleft' => '\\{',
|
|
|
|
'braceright' => '\\}',
|
|
|
|
'backslash' => '$\\backslash$',
|
|
|
|
'rightanglebracket' => '>',
|
|
|
|
'leftanglebracket' => '<',
|
|
|
|
'ampersand' => '\\&',
|
|
|
|
'comma' => ',',
|
|
|
|
'period' => '.',
|
|
|
|
'semicolon' => ';',
|
|
|
|
'colon' => ':',
|
|
|
|
'equal' => '=',
|
|
|
|
'minus' => '-',
|
|
|
|
'plus' => '+',
|
|
|
|
'grave' => '`',
|
|
|
|
'rightarrow' => '$\rightarrow$',
|
|
|
|
'leftarrow' => '$\\leftarrow$',
|
|
|
|
'uparrow' => '$\\uparrow$',
|
|
|
|
'downarrow' => '$\\downarrow$',
|
|
|
|
'Page_Down' => 'Page Down',
|
|
|
|
'Page_Up' => 'Page Up',
|
|
|
|
'space' => 'space',
|
|
|
|
'KP_' => 'KP$\_$'
|
|
|
|
);
|
2009-07-30 10:07:49 -04:00
|
|
|
|
|
|
|
while (<>) {
|
2009-07-30 20:34:36 -04:00
|
|
|
next if /^$semicolon/;
|
2009-07-30 10:07:49 -04:00
|
|
|
|
|
|
|
if (/^%/) {
|
2009-07-30 20:34:36 -04:00
|
|
|
|
2009-07-30 10:07:49 -04:00
|
|
|
if ($in_group_def) {
|
|
|
|
chop $group_text;
|
|
|
|
$group_names{$group_key} = $group_name;
|
|
|
|
$group_text{$group_key} = $group_text;
|
2009-07-30 20:34:36 -04:00
|
|
|
$group_numbering{$group_key} = $group_number;
|
|
|
|
# each binding entry is 2 element array. bindings
|
|
|
|
# are all collected into a container array. create
|
|
|
|
# the first dummy entry so that perl knows what we
|
|
|
|
# are doing.
|
|
|
|
$group_bindings{$group_key} = [ [] ];
|
2009-07-30 10:07:49 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
s/^%//;
|
|
|
|
chop;
|
|
|
|
($group_key,$group_name) = split (/\s+/, $_, 2);
|
2009-07-30 20:34:36 -04:00
|
|
|
$group_number++;
|
2009-07-30 10:07:49 -04:00
|
|
|
$group_text = "";
|
|
|
|
$in_group_def = 1;
|
|
|
|
next;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($in_group_def) {
|
2009-07-30 20:34:36 -04:00
|
|
|
if (/^@/) {
|
|
|
|
chop $group_text;
|
|
|
|
$group_names{$group_key} = $group_name;
|
|
|
|
$group_text{$group_key} = $group_text;
|
|
|
|
$in_group_def = 0;
|
|
|
|
} else {
|
|
|
|
next if (/^[ \t]+$/);
|
|
|
|
$group_text .= $_;
|
|
|
|
$group_text;
|
|
|
|
next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (/^@/) {
|
|
|
|
s/^@//;
|
|
|
|
chop;
|
|
|
|
($key,$action,$binding,$text) = split (/\|/, $_, 4);
|
|
|
|
|
|
|
|
# substitute bindings
|
|
|
|
|
|
|
|
$gtk_binding = $binding;
|
|
|
|
|
|
|
|
foreach $k (keys %gtk_modifier_map) {
|
|
|
|
$gtk_binding =~ s/\@$k\@/$gtk_modifier_map{$k}/;
|
|
|
|
}
|
|
|
|
|
|
|
|
# print the accelmap output
|
|
|
|
|
|
|
|
if ($key =~ /^\+/) {
|
|
|
|
# remove + and don't print it in the accelmap
|
|
|
|
$key =~ s/^\+//;
|
|
|
|
} else {
|
|
|
|
# include this in the accelmap
|
|
|
|
# print "(gtk_accel_map \"<Actions>/$action\" \"$gtk_binding\")\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($key =~ /^-/) {
|
|
|
|
# do not include this binding in the cheat sheet
|
|
|
|
next;
|
|
|
|
}
|
|
|
|
|
|
|
|
$bref = $group_bindings{$key};
|
|
|
|
push (@$bref, [$binding, $text]);
|
|
|
|
|
2009-07-30 10:07:49 -04:00
|
|
|
next;
|
|
|
|
}
|
|
|
|
|
|
|
|
next;
|
|
|
|
}
|
|
|
|
|
2009-07-30 20:34:36 -04:00
|
|
|
# Now print the cheatsheet
|
|
|
|
|
|
|
|
$boilerplate_header = <<END_HEADER;
|
|
|
|
\\documentclass[10pt,landscape]{article}
|
|
|
|
\\usepackage{multicol}
|
|
|
|
\\usepackage{calc}
|
|
|
|
\\usepackage{ifthen}
|
|
|
|
\\usepackage{palatino}
|
|
|
|
\\usepackage[landscape]{geometry}
|
|
|
|
|
|
|
|
|
|
|
|
% This sets page margins to .5 inch if using letter paper, and to 1cm
|
|
|
|
% if using A4 paper. (This probably isnott strictly necessary.)
|
|
|
|
% If using another size paper, use default 1cm margins.
|
|
|
|
\\ifthenelse{\\lengthtest { \\paperwidth = 11in}}
|
|
|
|
{ \\geometry{top=.5in,left=.5in,right=.5in,bottom=.5in} }
|
|
|
|
{\\ifthenelse{ \\lengthtest{ \\paperwidth = 297mm}}
|
|
|
|
{\\geometry{top=1cm,left=1cm,right=1cm,bottom=1cm} }
|
|
|
|
{\\geometry{top=1cm,left=1cm,right=1cm,bottom=1cm} }
|
|
|
|
}
|
|
|
|
|
|
|
|
% Turn off header and footer
|
|
|
|
\\pagestyle{empty}
|
|
|
|
|
|
|
|
% Redefine section commands to use less space
|
|
|
|
\\makeatletter
|
|
|
|
\\renewcommand{\\section}{\\\@startsection{section}{1}{0mm}%
|
|
|
|
{-1ex plus -.5ex minus -.2ex}%
|
|
|
|
{0.5ex plus .2ex}%x
|
|
|
|
{\\normalfont\\large\\bfseries}}
|
|
|
|
\\renewcommand{\\subsection}{\\\@startsection{subsection}{2}{0mm}%
|
|
|
|
{-1explus -.5ex minus -.2ex}%
|
|
|
|
{0.5ex plus .2ex}%
|
|
|
|
{\\normalfont\\normalsize\\bfseries}}
|
|
|
|
\\renewcommand{\\subsubsection}{\\\@startsection{subsubsection}{3}{0mm}%
|
|
|
|
{-1ex plus -.5ex minus -.2ex}%
|
|
|
|
{1ex plus .2ex}%
|
|
|
|
{\\normalfont\\small\\bfseries}}
|
|
|
|
\\makeatother
|
|
|
|
|
|
|
|
% Define BibTeX command
|
|
|
|
\\def\\BibTeX{{\\rm B\\kern-.05em{\\sc i\\kern-.025em b}\\kern-.08em
|
|
|
|
T\\kern-.1667em\\lower.7ex\\hbox{E}\\kern-.125emX}}
|
|
|
|
|
|
|
|
% Do not print section numbers
|
|
|
|
\\setcounter{secnumdepth}{0}
|
|
|
|
|
|
|
|
\\setlength{\\parindent}{0pt}
|
|
|
|
\\setlength{\\parskip}{0pt plus 0.5ex}
|
|
|
|
|
|
|
|
%-------------------------------------------
|
|
|
|
|
|
|
|
\\begin{document}
|
|
|
|
\\newlength{\\MyLen}
|
|
|
|
\\raggedright
|
|
|
|
\\footnotesize
|
|
|
|
\\begin{multicols}{3}
|
|
|
|
END_HEADER
|
|
|
|
|
|
|
|
$boilerplate_footer = <<END_FOOTER;
|
|
|
|
\\end{multicols}
|
|
|
|
\\end{document}
|
|
|
|
END_FOOTER
|
|
|
|
|
|
|
|
print $boilerplate_header;
|
|
|
|
|
|
|
|
@groups_sorted_by_number = sort { $group_numbering{$a} <=> $group_numbering{$b} } keys %group_numbering;
|
|
|
|
|
|
|
|
foreach $gk (@groups_sorted_by_number) {
|
|
|
|
# $bref is a reference to the array of arrays for this group
|
|
|
|
$bref = $group_bindings{$gk};
|
|
|
|
|
|
|
|
if (scalar @$bref > 1) {
|
|
|
|
print "\\section*{$group_names{$gk}}\n";
|
|
|
|
|
|
|
|
if (!($group_text{$gk} eq "")) {
|
|
|
|
print "$group_text{$gk}\n\\par\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
# ignore the first entry, which was empty
|
|
|
|
|
|
|
|
shift (@$bref);
|
|
|
|
|
|
|
|
# find the longest descriptive text (this is not 100% accuracy due to typography)
|
|
|
|
|
|
|
|
$maxtextlen = 0;
|
|
|
|
$maxtext = "";
|
|
|
|
|
|
|
|
for $bbref (@$bref) {
|
|
|
|
# $bbref is a reference to an array
|
|
|
|
$text = @$bbref[1];
|
|
|
|
if ($text =~ /\\linebreak/) {
|
|
|
|
$matchtext = s/\\linebreak.*//;
|
|
|
|
} else {
|
|
|
|
$matchtext = $text;
|
|
|
|
}
|
|
|
|
if (length ($matchtext) > $maxtextlen) {
|
|
|
|
$maxtextlen = length ($matchtext);
|
|
|
|
$maxtext = $matchtext;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$maxtext .= "....";
|
|
|
|
|
|
|
|
# set up the table
|
|
|
|
|
|
|
|
print "\\settowidth{\\MyLen}{\\texttt{$maxtext}}\n";
|
|
|
|
print "\\begin{tabular}{\@{}p{\\the\\MyLen}%
|
|
|
|
\@{}p{\\linewidth-\\the\\MyLen}%
|
|
|
|
\@{}}\n";
|
|
|
|
|
|
|
|
# now print the bindings
|
|
|
|
|
|
|
|
for $bbref (@$bref) {
|
|
|
|
# $bbref is a reference to an array
|
|
|
|
|
|
|
|
$binding = @$bbref[0];
|
|
|
|
$text = @$bbref[1];
|
|
|
|
|
|
|
|
if ($binding =~ /:/) { # mouse binding with "where" clause
|
|
|
|
($binding,$where) = split (/:/, $binding, 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
$binding =~ s/></\+/g;
|
|
|
|
$binding =~ s/^<//;
|
|
|
|
$binding =~ s/>/\+/;
|
|
|
|
|
|
|
|
foreach $k (keys %cs_modifier_map) {
|
|
|
|
$binding =~ s/\@$k\@/$cs_modifier_map{$k}/;
|
|
|
|
}
|
|
|
|
|
|
|
|
# substitute keycode names for something printable
|
|
|
|
|
|
|
|
$re = qr/${ \(join'|', map quotemeta, keys %keycodes)}/;
|
|
|
|
$binding =~ s/($re)/$keycodes{$1}/g;
|
|
|
|
|
|
|
|
# split up mouse bindings to "click" and "where" parts
|
|
|
|
|
|
|
|
if ($gk eq "mobject") {
|
|
|
|
print "{\\tt @$bbref[1] } & {\\tt $binding} {\\it $where}\\\\\n";
|
|
|
|
} else {
|
|
|
|
print "{\\tt @$bbref[1] } & {\\tt $binding} \\\\\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
print "\\end{tabular}\n";
|
|
|
|
|
|
|
|
}
|
2009-07-30 10:07:49 -04:00
|
|
|
}
|
|
|
|
|
2009-07-30 20:34:36 -04:00
|
|
|
print $boilerplate_footer;
|
|
|
|
|
2009-07-30 10:07:49 -04:00
|
|
|
exit 0;
|