… | |
… | |
71 | =head2 General API Considerations |
71 | =head2 General API Considerations |
72 | |
72 | |
73 | All objects (such as terminals, time watchers etc.) are typical |
73 | All objects (such as terminals, time watchers etc.) are typical |
74 | reference-to-hash objects. The hash can be used to store anything you |
74 | reference-to-hash objects. The hash can be used to store anything you |
75 | like. All members starting with an underscore (such as C<_ptr> or |
75 | like. All members starting with an underscore (such as C<_ptr> or |
76 | C<_hook>) are reserved for internal uses and must not be accessed or |
76 | C<_hook>) are reserved for internal uses and B<MUST NOT> be accessed or |
77 | modified). |
77 | modified). |
78 | |
78 | |
79 | When objects are destroyed on the C++ side, the perl object hashes are |
79 | When objects are destroyed on the C++ side, the perl object hashes are |
80 | emptied, so its best to store related objects such as time watchers and |
80 | emptied, so its best to store related objects such as time watchers and |
81 | the like inside the terminal object so they get destroyed as soon as the |
81 | the like inside the terminal object so they get destroyed as soon as the |
82 | terminal is destroyed. |
82 | terminal is destroyed. |
83 | |
83 | |
84 | =head2 Hooks |
84 | =head2 Hooks |
85 | |
85 | |
86 | The following subroutines can be declared in loaded scripts, and will be called |
86 | The following subroutines can be declared in loaded scripts, and will be |
87 | whenever the relevant event happens. |
87 | called whenever the relevant event happens. |
|
|
88 | |
|
|
89 | The first argument passed to them is an object private to each terminal |
|
|
90 | and extension package. You can call all C<urxvt::term> methods on it, but |
|
|
91 | its not a real C<urxvt::term> object. Instead, the real C<urxvt::term> |
|
|
92 | object that is shared between all packages is stored in the C<term> |
|
|
93 | member. |
88 | |
94 | |
89 | All of them must return a boolean value. If it is true, then the event |
95 | All of them must return a boolean value. If it is true, then the event |
90 | counts as being I<consumed>, and the invocation of other hooks is skipped, |
96 | counts as being I<consumed>, and the invocation of other hooks is skipped, |
91 | and the relevant action might not be carried out by the C++ code. |
97 | and the relevant action might not be carried out by the C++ code. |
92 | |
98 | |
… | |
… | |
183 | C<perl:string> action bound to it (see description of the B<keysym> |
189 | C<perl:string> action bound to it (see description of the B<keysym> |
184 | resource in the @@RXVT_NAME@@(1) manpage). |
190 | resource in the @@RXVT_NAME@@(1) manpage). |
185 | |
191 | |
186 | =back |
192 | =back |
187 | |
193 | |
|
|
194 | =head2 Variables in the C<urxvt> Package |
|
|
195 | |
|
|
196 | =over 4 |
|
|
197 | |
|
|
198 | =item $urxvt::TERM |
|
|
199 | |
|
|
200 | The current terminal. Whenever a callback/Hook is bein executed, this |
|
|
201 | variable stores the current C<urxvt::term> object. |
|
|
202 | |
|
|
203 | =back |
|
|
204 | |
188 | =head2 Functions in the C<urxvt> Package |
205 | =head2 Functions in the C<urxvt> Package |
189 | |
206 | |
190 | =over 4 |
207 | =over 4 |
191 | |
208 | |
192 | =item urxvt::fatal $errormessage |
209 | =item urxvt::fatal $errormessage |
… | |
… | |
265 | =cut |
282 | =cut |
266 | |
283 | |
267 | package urxvt; |
284 | package urxvt; |
268 | |
285 | |
269 | use strict; |
286 | use strict; |
|
|
287 | use Scalar::Util (); |
270 | |
288 | |
271 | our $term; |
289 | our $TERM; |
272 | our @HOOKNAME; |
290 | our @HOOKNAME; |
273 | our $LIBDIR; |
291 | our $LIBDIR; |
274 | |
292 | |
275 | BEGIN { |
293 | BEGIN { |
276 | urxvt->bootstrap; |
294 | urxvt->bootstrap; |
… | |
… | |
301 | my $name = $HOOKNAME[$htype]; |
319 | my $name = $HOOKNAME[$htype]; |
302 | |
320 | |
303 | my $ref = $pkg->can ("on_" . lc $name) |
321 | my $ref = $pkg->can ("on_" . lc $name) |
304 | or next; |
322 | or next; |
305 | |
323 | |
306 | $term->{_hook}[$htype]{$ref*1} = $ref; |
324 | $TERM->{_hook}[$htype]{$pkg} = $ref; |
307 | $hook_count[$htype]++ |
325 | $hook_count[$htype]++ |
308 | or set_should_invoke $htype, 1; |
326 | or set_should_invoke $htype, 1; |
309 | } |
327 | } |
310 | } |
328 | } |
311 | |
329 | |
… | |
… | |
335 | } |
353 | } |
336 | } |
354 | } |
337 | |
355 | |
338 | # called by the rxvt core |
356 | # called by the rxvt core |
339 | sub invoke { |
357 | sub invoke { |
340 | local $term = shift; |
358 | local $TERM = shift; |
341 | my $htype = shift; |
359 | my $htype = shift; |
342 | |
360 | |
343 | if ($htype == 0) { # INIT |
361 | if ($htype == 0) { # INIT |
344 | my @dirs = ((split /:/, $term->resource ("perl_lib")), "$LIBDIR/perl"); |
362 | my @dirs = ((split /:/, $TERM->resource ("perl_lib")), "$LIBDIR/perl"); |
345 | |
363 | |
346 | for my $ext (split /:/, $term->resource ("perl_ext")) { |
364 | for my $ext (split /:/, $TERM->resource ("perl_ext")) { |
347 | my @files = grep -f $_, map "$_/$ext", @dirs; |
365 | my @files = grep -f $_, map "$_/$ext", @dirs; |
348 | |
366 | |
349 | if (@files) { |
367 | if (@files) { |
350 | register_package script_package $files[0]; |
368 | register_package script_package $files[0]; |
351 | } else { |
369 | } else { |
352 | warn "perl extension '$ext' not found in perl library search path\n"; |
370 | warn "perl extension '$ext' not found in perl library search path\n"; |
353 | } |
371 | } |
354 | } |
372 | } |
355 | |
373 | |
356 | } elsif ($htype == 1) { # DESTROY |
374 | } elsif ($htype == 1) { # DESTROY |
357 | if (my $hook = $term->{_hook}) { |
375 | if (my $hook = $TERM->{_hook}) { |
358 | for my $htype (0..$#$hook) { |
376 | for my $htype (0..$#$hook) { |
359 | $hook_count[$htype] -= scalar keys %{ $hook->[$htype] || {} } |
377 | $hook_count[$htype] -= scalar keys %{ $hook->[$htype] || {} } |
360 | or set_should_invoke $htype, 0; |
378 | or set_should_invoke $htype, 0; |
361 | } |
379 | } |
362 | } |
380 | } |
363 | } |
381 | } |
364 | |
382 | |
365 | my $cb = $term->{_hook}[$htype] |
383 | my $cb = $TERM->{_hook}[$htype] |
366 | or return; |
384 | or return; |
367 | |
385 | |
368 | verbose 10, "$HOOKNAME[$htype] (" . (join ", ", $term, @_) . ")" |
386 | verbose 10, "$HOOKNAME[$htype] (" . (join ", ", $TERM, @_) . ")" |
369 | if $verbosity >= 10; |
387 | if $verbosity >= 10; |
370 | |
388 | |
371 | while (my ($k, $v) = each %$cb) { |
389 | while (my ($pkg, $cb) = each %$cb) { |
372 | return 1 if $v->($term, @_); |
390 | return 1 |
|
|
391 | if $cb->( |
|
|
392 | $TERM->{$pkg} ||= do { |
|
|
393 | my $proxy = bless { }, urxvt::term::proxy::; |
|
|
394 | Scalar::Util::weaken ($proxy->{term} = $TERM); |
|
|
395 | $proxy |
|
|
396 | }, |
|
|
397 | @_, |
|
|
398 | ); |
373 | } |
399 | } |
374 | |
400 | |
375 | 0 |
401 | 0 |
|
|
402 | } |
|
|
403 | |
|
|
404 | sub urxvt::term::proxy::AUTOLOAD { |
|
|
405 | $urxvt::term::proxy::AUTOLOAD =~ /:([^:]+)$/ |
|
|
406 | or die "FATAL: \$AUTOLOAD '$urxvt::term::proxy::AUTOLOAD' unparsable"; |
|
|
407 | |
|
|
408 | eval qq{ |
|
|
409 | sub $urxvt::term::proxy::AUTOLOAD { |
|
|
410 | unshift \@_, shift->{term}; |
|
|
411 | goto &urxvt::term::$1; |
|
|
412 | } |
|
|
413 | 1 |
|
|
414 | } or die "FATAL: unable to compile method forwarder: $@"; |
|
|
415 | |
|
|
416 | goto &$urxvt::term::proxy::AUTOLOAD; |
376 | } |
417 | } |
377 | |
418 | |
378 | =head2 The C<urxvt::term> Class |
419 | =head2 The C<urxvt::term> Class |
379 | |
420 | |
380 | =over 4 |
421 | =over 4 |