ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/RCU/RCU/Context.pm
Revision: 1.1
Committed: Sun Nov 6 17:17:37 2005 UTC (19 years, 1 month ago) by root
Branch: MAIN
CVS Tags: HEAD
Log Message:
*** empty log message ***

File Contents

# Content
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