From: Mischa POSLAWSKY Date: Mon, 5 Jan 2009 21:48:48 +0000 (+0000) Subject: split off common keys display to Shiar_Sheet::Keyboard X-Git-Tag: v1.2~2 X-Git-Url: http://git.shiar.nl/sheet.git/commitdiff_plain/a84b651b70f484379de8ac84a2abac91e59c1a6e split off common keys display to Shiar_Sheet::Keyboard Modularize the vim.plp code to generate HTML showing a keyboard sheet. This allows the code to be reused on other pages (non-vim key sheets). Besides using an object (instead of global variables) to store specific data, nothing much should have changed. The only exception is that $ascii is unavailable at keyboard initialization (do 'keys.inc.pl'), so key characters are always unicode. This is only relevant for "foreign" layouts, for which users are expected to have Unicode-capable environments anyway, so it doesn't seem an important issue. It could be solved by loading the map only at object creation, but this is faster for persistent servers. --- diff --git a/Shiar_Sheet/Keyboard.pm b/Shiar_Sheet/Keyboard.pm new file mode 100644 index 0000000..f56437f --- /dev/null +++ b/Shiar_Sheet/Keyboard.pm @@ -0,0 +1,177 @@ +package Shiar_Sheet::Keyboard; + +use strict; +use warnings; +no warnings 'uninitialized'; # save some useless checks for more legible code +use Carp; + +our $VERSION = '1.00'; + +my @casedesc = qw(ctrl shift); +my @rowdesc = qw(numeric top home bottom); +my %keyrows = do 'keys.inc.pl'; + +my %keytrans = qw( + ^@ NUL ^a SOH ^b STX ^c ETX ^d EOT ^e ENQ ^f ACK ^g BEL + ^h BS ^i tab ^j LF ^k VT ^l FF ^m CR ^n SO ^o SI + ^p DLE ^q DC1 ^r DC2 ^s DC3 ^t DC4 ^u NAK ^v SYN ^w ETB + ^x CAN ^y EM ^z SUB ^[ ESC ^\ FS ^] GS ^^ RS ^_ US + ^? DEL +); + +sub new { + my $self = shift; + my ($keys) = @_; + + croak 'Invalid key table specified' unless ref $keys eq 'HASH'; + my $parent = (caller)[0]; # calling module + my $sign = do { + no strict 'refs'; # temporarily allow variable references + \%{ $parent.'::sign' }; # return %sign from parent + }; + croak "%${parent}::sign not found" unless %$sign; + + bless {sign => $sign, keys => $keys, map => 'qwerty'}, $self; +} + +sub map { + my $self = shift; + my ($mapname) = @_; + + return $self->{map} = $mapname if defined $keyrows{$mapname}; + return undef; +} + +sub escapeclass { + local $_ = shift; + s/\^/_c/g; + s/\[/_sbo/g; + s/\]/_sbc/g; + s/^$/_/; + return $_; +} + +sub escapehtml { + local $_ = shift; + s//>/g; + s/ /  /g; + return $_; +} + +sub keyunalias { + my $self = shift; + my ($key, $ancestry) = @_; + + $key =~ s/(\S*?)(\^?\S)($|\s.*)/$2/; + my $mode = $1; + my $keyinfo = $self->{keys}->{$mode}->{$key}; + + return [] unless defined $keyinfo; + return $keyinfo if ref $keyinfo; + return if $ancestry->{$key}++; # endless loop failsafe + return $self->keyunalias($keyinfo, $ancestry); +} + +sub print_key { + my $self = shift; + my ($mode, $key, $keyinfo) = @_; + + $keyinfo = [ $self->{sign}->{alias}.$keyinfo, $self->keyunalias($keyinfo)->[1] . ' alias' ] + if defined $keyinfo and not ref $keyinfo; # alias + my ($desc, $flags, $mnem) = @$keyinfo if defined $keyinfo; + defined $desc or $flags = $key eq '^0' ? 'ni' : 'no'; + +# $key = $keytrans{$key} if defined $keytrans{$key}; + my $keytxt = $mode . escapehtml($key) if $key ne '^0'; + $keytxt .= $self->{sign}->{arg} while $flags =~ s/ ?\barg\b//; # argument + $keytxt .= "$self->{sign}->{motion}" if $flags =~ s/ ?\bargm\b//; # motion argument + $keytxt =~ s{\^(?=.)}{^}; # element around ctrl-identifier + my $onclick = $flags =~ s/ ?\bmode(\S*)// && defined $self->{keys}{$1} && sprintf( + ' onclick="setmode(%s)"', + $1 eq '' ? '' : sprintf(q{'mode%s'}, escapeclass($1)) + ); + $onclick .= sprintf(q{ onclick="document.location='%s'"}, $1) + if $flags =~ s/ ?\blink(\S*)//; + my $keyhint = defined($mnem) && qq{ title="$mnem"}; + + print qq{\t\t
  • $keytxt}; + print ' ', $desc if defined $desc; + print "\n"; +} + +sub print_rows { + my $self = shift; + my $static = shift; + my @moderows = $static ? split(/\s+/, $static) : sort keys %{ $self->{keys} }; + + for (my $row = 0; $row <= $#{ $keyrows{$self->{map}} }; $row++) { + my $keyrow = $keyrows{$self->{map}}->[$row]; + my @caserows = 0 .. $#$keyrow; + + print qq{
  • \n}; + } # row +} + +1; + +=head1 NAME + +Shiar_Sheet::Keyboard - Output HTML for key sheets + +=head1 SYNOPSIS + + our %sign = (alias => 'see: '); + + my $keys = Shiar_Sheet::Keyboard({ + 'mode' => { + desc => 'mode description', + 'A' => 'a', # alias + 'a' => ['description', 'classes', 'comments (on hover)'], + }, + }); + $keys->map('dvorak') or die "Keyboard map not found"; + + $keys->print_rows; + +=head1 DESCRIPTION + +Used by http://sheet.shiar.net to display keyboard sheets. +Assumes specific stylesheets and javascript from this site, +so probably not of much use elsewhere. + +=head1 AUTHOR + +Mischa POSLAWSKY + +=head1 LICENSE + +Licensed under the GNU Affero General Public License version 3. + diff --git a/vim-keys.inc.pl b/keys.inc.pl similarity index 100% rename from vim-keys.inc.pl rename to keys.inc.pl diff --git a/vim-cmds.inc.pl b/vim.inc.pl similarity index 100% rename from vim-cmds.inc.pl rename to vim.inc.pl diff --git a/vim.plp b/vim.plp index df3cca5..36975e3 100644 --- a/vim.plp +++ b/vim.plp @@ -100,103 +100,10 @@ our %sign = ( # default to use unofficial html for best support ); -my %keys = do 'vim-cmds.inc.pl'; - -my @casedesc = qw(ctrl shift); -my @rowdesc = qw(numeric top home bottom); -my %keyrows = do 'vim-keys.inc.pl'; - -sub keyunalias { - my ($key, %tree) = @_; - $key =~ s/(\S*?)(\^?\S)($|\s.*)/$2/; - my $mode = $1; - return [] unless defined $keys{$mode}{$key}; - return $keys{$mode}{$key} if ref $keys{$mode}{$key}; - return if $tree{$key}++; # endless loop failsafe - return keyunalias($keys{$mode}{$key}, %tree); -} - -sub escapeclass { - local $_ = shift; - s/\^/_c/g; - s/\[/_sbo/g; - s/\]/_sbc/g; - s/^$/_/; - return $_; -} - -my %keytrans = qw( - ^@ NUL ^a SOH ^b STX ^c ETX ^d EOT ^e ENQ ^f ACK ^g BEL - ^h BS ^i tab ^j LF ^k VT ^l FF ^m CR ^n SO ^o SI - ^p DLE ^q DC1 ^r DC2 ^s DC3 ^t DC4 ^u NAK ^v SYN ^w ETB - ^x CAN ^y EM ^z SUB ^[ ESC ^\ FS ^] GS ^^ RS ^_ US - ^? DEL -); - -sub print_key { - my ($mode, $key, $keyinfo) = @_; - - $keyinfo = [ $sign{alias}.$keyinfo, keyunalias($keyinfo)->[1] . ' alias' ] - if defined $keyinfo and not ref $keyinfo; # alias - my ($desc, $flags, $mnem) = @$keyinfo if defined $keyinfo; - defined $desc or $flags = $key eq '^0' ? 'ni' : 'no'; - -# $key = $keytrans{$key} if defined $keytrans{$key}; - my $keytxt = $mode . Entity($key) if $key ne '^0'; - $keytxt .= $sign{arg} while $flags =~ s/ ?\barg\b//; # argument - $keytxt .= "$sign{motion}" if $flags =~ s/ ?\bargm\b//; # motion argument - $keytxt =~ s{\^(?=.)}{^}; # element around ctrl-identifier - my $onclick = $flags =~ s/ ?\bmode(\S*)// && defined $keys{$1} && sprintf( - ' onclick="setmode(%s)"', - $1 eq '' ? '' : sprintf(q{'mode%s'}, escapeclass($1)) - ); - $onclick .= sprintf(q{ onclick="document.location='%s'"}, $1) - if $flags =~ s/ ?\blink(\S*)//; - my $keyhint = defined($mnem) && qq{ title="$mnem"}; - - print qq{\t\t
  • $keytxt}; - print ' ', $desc if defined $desc; - print "\n"; -} - -our $map = defined $keyrows{$get{map}} ? $get{map} : 'qwerty'; -my $keyrows = $keyrows{$map}; -my @moderows = $get{static} ? split(/\s+/, $get{static}) : sort keys %keys; - -for (my $row = 0; $row <= $#$keyrows; $row++) { - my $keyrow = $keyrows->[$row]; - my @caserows = 0 .. $#$keyrow; - - print qq{
  • \n}; -} # row - +use Shiar_Sheet::Keyboard; +my $keys = Shiar_Sheet::Keyboard->new({do 'vim.inc.pl'}); +$keys->map($get{map}) or undef $get{map}; +$keys->print_rows($get{static}); :> @@ -238,7 +145,7 @@ for (my $row = 0; $row <= $#$keyrows; $row++) {