1 |
=head1 NAME |
2 |
|
3 |
RCU::Context - Remote Control Unit Interface |
4 |
|
5 |
=head1 SYNOPSIS |
6 |
|
7 |
use RCU::Context; |
8 |
|
9 |
=head1 DESCRIPTION |
10 |
|
11 |
=over 4 |
12 |
|
13 |
=cut |
14 |
|
15 |
package RCU::Context; |
16 |
|
17 |
$VERSION = 0.01; |
18 |
|
19 |
use Carp; |
20 |
|
21 |
# the maximum context length required by any context |
22 |
$histsize = 0; |
23 |
|
24 |
=item $ctx = new RCU::Context; |
25 |
|
26 |
Create a new key context. |
27 |
|
28 |
=cut |
29 |
|
30 |
sub new { |
31 |
my $class = shift; |
32 |
my $self = bless {}, $class; |
33 |
$self; |
34 |
} |
35 |
|
36 |
=item $ctx->bind(event, action) |
37 |
|
38 |
Bind the given action to an event (see EVENT SYNTAX, below, for an |
39 |
explanation of this string). |
40 |
|
41 |
C<action> must be one of the following: |
42 |
|
43 |
A code-reference |
44 |
This code reference will be called with the event name, generating rcu, |
45 |
timestamp and any additional arguments (usually none) fiven to the |
46 |
inject method. |
47 |
|
48 |
"enter", $context |
49 |
"enter*", $context |
50 |
Enter the given context object. The forms with an appended star "re-exec" |
51 |
the event in the new context. |
52 |
|
53 |
"leave" |
54 |
"leave*" |
55 |
leave the current context (restoring the context active before it was |
56 |
"enter"'ed) |
57 |
|
58 |
"switch", $context |
59 |
"switch*", $context |
60 |
switch to the given context object |
61 |
|
62 |
For every keypress, I<only the first> (in order of their definition) |
63 |
matching event handler is being executed. |
64 |
|
65 |
=cut |
66 |
|
67 |
sub bind { |
68 |
my $self = shift; |
69 |
while (@_) { |
70 |
my $event = shift; |
71 |
my $action = shift; |
72 |
|
73 |
$event = ":$event"; |
74 |
$event =~ s/:(?=[^=~.<:][^:]*$)/:=/; |
75 |
|
76 |
my $len = $event =~ y/://; |
77 |
$histsize = $len if $histsize < $len; |
78 |
|
79 |
unless (ref $action) { |
80 |
my $context = shift; |
81 |
|
82 |
if ($action eq "enter" ) { $action = sub { $_[2]->push_context($context) } } |
83 |
elsif ($action eq "enter*" ) { $action = sub { $_[2]->push_context($context); $context->inject(@_) } } |
84 |
elsif ($action eq "leave" ) { $action = sub { $_[2]->pop_context } } |
85 |
elsif ($action eq "leave*" ) { $action = sub { $_[2]->pop_context; $context->inject(@_) } } |
86 |
elsif ($action eq "switch" ) { $action = sub { $_[2]->set_context($context) } } |
87 |
elsif ($action eq "switch*") { $action = sub { $_[2]->set_context($context); $context->inject(@_) } } |
88 |
} |
89 |
|
90 |
$event =~ y/:/\n/; |
91 |
$event = qr<$event\Z>m; |
92 |
push @{$self->{events}}, $event; |
93 |
$self->{event}{$event} = $action; |
94 |
} |
95 |
} |
96 |
|
97 |
=item $ctx->inject(event, time, rcu, args...) |
98 |
|
99 |
Simulate the given event (see "EVENT SYNTAX", below). |
100 |
|
101 |
=cut |
102 |
|
103 |
sub inject { |
104 |
my $self = shift; |
105 |
# remaining args are passed through |
106 |
my $event = ":$_[0]"; $event =~ y/:/\n/; |
107 |
for (@{$self->{events}}) { |
108 |
if ($event =~ $_) { |
109 |
#print "calling $_ $self->{event}{$_}\n";#d# |
110 |
goto &{$self->{event}{$_}}; |
111 |
die; |
112 |
} |
113 |
} |
114 |
} |
115 |
|
116 |
=item $ctx->enter($rcu) |
117 |
|
118 |
=item $ctx->leave($rcu) |
119 |
|
120 |
"Enter" ("Leave") the context (and create an <enter> (<leave>") |
121 |
event). Not usually called by application code. |
122 |
|
123 |
=cut |
124 |
|
125 |
sub enter { |
126 |
my ($self, $rcu) = @_; |
127 |
$self->inject("<enter>", $rcu); |
128 |
} |
129 |
|
130 |
sub leave { |
131 |
my ($self, $rcu) = @_; |
132 |
$self->inject("<leave>", $rcu); |
133 |
} |
134 |
|
135 |
1; |
136 |
|
137 |
=back |
138 |
|
139 |
=head1 EVENT SYNTAX |
140 |
|
141 |
The simplest way to specify events is using the (cooked) keyname, e.g. the |
142 |
event C<cd-shuffle> occurs when the key named "cd-shuffle" was pressed |
143 |
down. |
144 |
|
145 |
Since events are regular expressions, you have to quote any special |
146 |
characters (like C<.> or C<*>, where C<^>, C<$> and C<.> stop at keys |
147 |
boundaries) if you want to use them. On the other hand, regexes give you |
148 |
great freedom, if you specify the event: |
149 |
|
150 |
rcu-key-(\d+) |
151 |
|
152 |
... you can then use "$1" in your callback to find out which digit was |
153 |
pressed. |
154 |
|
155 |
You can prefix a keyname with a "~" which means the key was released |
156 |
(deactivates, switched off) instead of being pressed. If you want to force |
157 |
interpretation as a key-down event you can prefix the keyname with an "=" |
158 |
character. |
159 |
|
160 |
Every key will always generate two events: one key-down (activate) event |
161 |
when it is pressed and one "~" (key-up) event when it is released again. |
162 |
It is not possible that two keys are active at the same time. |
163 |
|
164 |
To make matters slightly more complicated, you can also prepend a |
165 |
"history" of key names (all seperated by ":") before the current |
166 |
event. This means that the event depends on previous key-presses (no |
167 |
prefix characters are there). |
168 |
|
169 |
Examples (all key names are, of course, hypothetical): |
170 |
|
171 |
<enter> enter the current context |
172 |
key-ff the fast forward key was pressed down |
173 |
=key-ff same as above |
174 |
~key-rev the "rev"-key was released |
175 |
key-tuner:key-4 first the tuner key was pressed (and released), then "4" |
176 |
key-tuner:~key-4 first the tuner key was pressed, then "4" was released |
177 |
k1:k2:k3 the keys "1", "2" were pressed and released, then |
178 |
"3" was pressed. |
179 |
|
180 |
EBNF-Grammar |
181 |
|
182 |
For those of you who need it... |
183 |
|
184 |
event := history prefix eventname |
185 |
history := <empty> | keyname ":" history |
186 |
prefix := <empty> | "=" | "~" |
187 |
eventname := keyname | "<enter>" | "<leave>" |
188 |
keyname := any string consisting of printable, non-whitespace |
189 |
characters without ":" |
190 |
|
191 |
=head1 SEE ALSO |
192 |
|
193 |
L<RCU>. |
194 |
|
195 |
=head1 AUTHOR |
196 |
|
197 |
This perl extension was written by Marc Lehmann <schmorp@schmorp.de>. |
198 |
|
199 |
=cut |
200 |
|
201 |
|
202 |
|
203 |
|
204 |
|