--- rxvt-unicode/src/urxvt.pm 2014/12/26 21:01:46 1.248 +++ rxvt-unicode/src/urxvt.pm 2021/07/24 12:17:08 1.267 @@ -6,24 +6,24 @@ =head1 SYNOPSIS - # create a file grab_test in $HOME: + # create a file grab_test in some directory: sub on_sel_grab { warn "you selected ", $_[0]->selection; () } - # start a urxvt using it: + # start a urxvt instance using it: - urxvt --perl-lib $HOME -pe grab_test + urxvt --perl-lib path/to/somedirectory -pe grab_test =head1 DESCRIPTION Every time a terminal object gets created, extension scripts specified via the C resource are loaded and associated with it. -Scripts are compiled in a 'use strict "vars"' and 'use utf8' environment, and -thus must be encoded as UTF-8. +Scripts are compiled in a 'use strict qw(vars subs)' and 'use utf8' +environment, and thus must be encoded as UTF-8. Each script will only ever be loaded once, even in urxvtd, where scripts will be shared (but not enabled) for all terminals. @@ -47,11 +47,10 @@ Extensions may add additional resources and C, i.e., methods which can be bound to a key and invoked by the user. An extension can -define the resources it support and also default bindings for one or -more actions it provides using so called META comments, described -below. Similarly to builtin resources, extension resources can also be -specified on the command line as long options (with C<.> replaced by -C<->), in which case the corresponding extension is loaded +define the resources it support using so called META comments, +described below. Similarly to builtin resources, extension resources +can also be specified on the command line as long options (with C<.> +replaced by C<->), in which case the corresponding extension is loaded automatically. For this to work the extension B define META comments for its resources. @@ -73,7 +72,7 @@ Argument names also often indicate the type of a parameter. Here are some hints on what they mean: -=over 4 +=over =item $text @@ -118,11 +117,15 @@ =head2 META comments Rxvt-unicode recognizes special meta comments in extensions that define -different types of metadata. +different types of metadata. These comments are scanned whenever a +terminal is created and are typically used to autoload extensions when +their resources or command line parameters are used. + +Currently, it recognises these comments below. Individual components are +separated by colons (C<:>), and should not contain colons themselves - +there is also currently no escaping mechanism provided for this. -Currently, it recxognises only one such comment: - -=over 4 +=over =item #:META:RESOURCE:name:type:desc @@ -130,6 +133,54 @@ C is the resource name, C is the resource type, C or C, and C is the resource description. +The extension will be autoloaded when this resource is specified or used +as a command line parameter. + +Example: matcher provides the C resource by having this +comment: + + #:META:RESOURCE:%.launcher:string:default launcher command + +Example: load this extension when the C<-tr> command line option or +resource name is used. + + #:META:RESOURCE:tr:boolean:set root pixmap as background + +=item #:META:OSC:number:desc + +The OSC comment specifies an OSC sequence, where C is the +numerical OSC code and C is a short description that is currently +unused. + +This will cause the extension to be autoloaded when the OSC sequence is +used for the first time. + +Note that autoloading carries some extra responsibilities with it: +although the terminal cannot really protect itself against malicious +sources of command sequences, therefore relying on the programs running +I to sanitize data that they output, it is very common for +programs to emit command sequences from untrusted sources. + +While this means that extensions should, as a defense-in-depth mechanism, +always consider whether OSC sequences are safe, autoloading automatically +exposes any autoloaded extension in all terminal windows, so extra care +should be taken. + +Example: the background extension registers OSC C<20> like this: + + #:META:OSC:20:change/query background image + +=item #:META:OSC_PERL:prefix:desc + +The same as the OSC comment, but for the Perl OSC sequence (C<777>). The +C should be unique among extensions, of course, which is most +easily arranged by using the extension name, although this is not +required. + +Example: the overlay-osc extension registers its Perl OSC like this: + + #:META:OSC_PERL:overlay:man overlay-osc + =back =head2 Hooks @@ -146,7 +197,7 @@ I<< When in doubt, return a false value (preferably C<()>). >> -=over 4 +=over =item on_init $term @@ -238,12 +289,12 @@ =item on_osc_seq_perl $term, $args, $resp -Called whenever the B command sequence (OSC = -operating system command) is processed. Cursor position and other state -information is up-to-date when this happens. For interoperability, the -string should start with the extension name (sans -osc) and a semicolon, -to distinguish it from commands for other extensions, and this might be -enforced in the future. +Called whenever the B command sequence +(OSC = operating system command) is processed. Cursor position and other +state information is up-to-date when this happens. For interoperability, +the argument should start with the extension name (sans -osc) or some +other suitable prefix, and a semicolon, to distinguish it from commands +for other extensions. For example, C uses this: @@ -398,7 +449,7 @@ package urxvt; use utf8; -use strict 'vars'; +use strict qw(vars subs); use Carp (); use Scalar::Util (); use List::Util (); @@ -420,7 +471,7 @@ =head2 Variables in the C Package -=over 4 +=over =item $urxvt::LIBDIR @@ -460,7 +511,7 @@ =head2 Functions in the C Package -=over 4 +=over =item urxvt::fatal $errormessage @@ -515,6 +566,18 @@ Various constants for use in X calls and event processing. +=item urxvt::PrivMode_132, PrivMode_132OK, PrivMode_rVideo, PrivMode_relOrigin, +PrivMode_Screen, PrivMode_Autowrap, PrivMode_aplCUR, PrivMode_aplKP, +PrivMode_HaveBackSpace, PrivMode_BackSpace, PrivMode_ShiftKeys, +PrivMode_VisibleCursor, PrivMode_MouseX10, PrivMode_MouseX11, +PrivMode_scrollBar, PrivMode_TtyOutputInh, PrivMode_Keypress, +PrivMode_smoothScroll, PrivMode_vt52, PrivMode_LFNL, PrivMode_MouseBtnEvent, +PrivMode_MouseAnyEvent, PrivMode_BracketPaste, PrivMode_ExtMouseUTF8, +PrivMode_ExtMouseUrxvt, PrivMode_BlinkingCursor, PrivMode_mouse_report, +PrivMode_Default + +Constants for checking DEC private modes. + =back =head2 RENDITION @@ -527,7 +590,7 @@ as they contain important information required for correct operation of rxvt-unicode. -=over 4 +=over =item $rend = urxvt::DEFAULT_RSTYLE @@ -591,6 +654,8 @@ $term->scan_extensions; + # iterating over all resources has quadratic time overhead + # overall, maybe this could be optimised? my $r = $term->{meta}{resource}; keys %$r; # reset iterator while (my ($k, $v) = each %$r) { @@ -607,6 +672,8 @@ push @{ $term->{perl_ext_3} }, $v->[0]; + return 1 unless $isarg; + if ($v->[1] eq "boolean") { $term->put_option_db ($name, $flag ? "true" : "false"); return 1; @@ -648,7 +715,7 @@ } } -my $verbosity = $ENV{URXVT_PERL_VERBOSITY}; +my $verbosity = $ENV{URXVT_PERL_VERBOSITY} // 2; sub verbose { my ($level, $msg) = @_; @@ -675,7 +742,7 @@ or die "$path: $!"; my $source = - "package $pkg; use strict 'vars'; use utf8; no warnings 'utf8';\n" + "package $pkg; use strict qw(vars subs); use utf8; no warnings 'utf8';\n" . "#line 1 \"$path\"\n{\n" . (do { local $/; <$fh> }) . "\n};\n1"; @@ -695,8 +762,6 @@ my $htype = shift; if ($htype == HOOK_INIT) { - my @dirs = $TERM->perl_libdirs; - $TERM->scan_extensions; my %ext_arg; @@ -711,13 +776,13 @@ } for ( + @{ delete $TERM->{perl_ext_3} }, (grep $_, map { split /,/, $TERM->resource ("perl_ext_$_") } 1, 2), - @{ delete $TERM->{perl_ext_3} } ) { if ($_ eq "default") { $ext_arg{$_} = [] - for qw(selection option-popup selection-popup readline searchable-scrollback); + for qw(selection option-popup selection-popup readline searchable-scrollback confirm-paste); for ($TERM->_keysym_resources) { next if /^(?:string|command|builtin|builtin-string|perl)/; @@ -728,24 +793,31 @@ $ext_arg{$ext} = []; } - } elsif (/^-(.*)$/) { + } elsif (/^-(.*)$/) { # remove from set delete $ext_arg{$1}; - } elsif (/^([^<]+)<(.*)>$/) { - push @{ $ext_arg{$1} }, $2; + } elsif (/^\/(.*)$/) { # prohibit loading + undef $TERM->{ext_prohibit}{$1}; + + } elsif (/^([^<]+)(?:<(.*)>)?$/) { # add to set, clear prohibit status + delete $TERM->{ext_prohibit}{$1}; + push @{ $ext_arg{$1} }, defined $2 ? $2 : (); } else { - $ext_arg{$_} ||= []; + verbose 2, "cannot parse extension specification '$_', ignoring."; } } + $TERM->set_should_invoke (HOOK_OSC_SEQ , +1) if $TERM->{meta}{autoload_osc}; + $TERM->set_should_invoke (HOOK_OSC_SEQ_PERL, +1) if $TERM->{meta}{autoload_osc_perl}; + for my $ext (sort keys %ext_arg) { - my @files = grep -f $_, map "$_/$ext", @dirs; + my $path = $TERM->extension_path ($ext); - if (@files) { - $TERM->register_package (extension_package $files[0], $ext_arg{$ext}); + if (defined $path) { + $TERM->autoload_extension ($ext, $ext_arg{$ext}); } else { - warn "perl extension '$ext' not found in perl library search path\n"; + verbose 2, "perl extension '$ext' not found in perl library search path"; } } @@ -755,6 +827,16 @@ $retval = undef; + if ($htype == HOOK_OSC_SEQ) { + if (my $exts = delete $TERM->{meta}{autoload_osc}{$_[0]}) { + $TERM->autoload_extension ($_->[0]) for @$exts; + } + } elsif ($htype == HOOK_OSC_SEQ_PERL) { + if ($_[0] =~ /^([^;]+)/ and (my $exts = delete $TERM->{meta}{autoload_osc_perl}{$1})) { + $TERM->autoload_extension ($_->[0]) for @$exts; + } + } + if (my $cb = $TERM->{_hook}[$htype]) { verbose 10, "$HOOKNAME[$htype] (" . (join ", ", $TERM, @_) . ")" if $verbosity >= 10; @@ -840,7 +922,7 @@ objects, in addition to call methods documented for the class. -=over 4 +=over =item $urxvt_term = $self->{term} @@ -1091,7 +1173,7 @@ =head2 The C Class -=over 4 +=over =cut @@ -1122,6 +1204,30 @@ } } +# map extension name to filesystem path +sub extension_path { + (grep -f $_, map "$_/$_[1]", $_[0]->perl_libdirs)[0] +} + +# load an extension by name +sub load_extension_file { + my ($self, $path, $argv) = @_; + + $self->register_package (urxvt::extension_package $path, $argv); +} + +# autoload an extension unless loading it is prohibited +sub autoload_extension { + my ($self, $name, $argv) = @_; + + return if exists $self->{ext_prohibit}{$name}; + + my $path = $self->extension_path ($name) + // return urxvt::verbose 2, "perl extension '$name' not found in perl library search path (during autoload)"; + + $self->load_extension_file ($path, $argv); +} + sub perl_libdirs { map { split /:/ } $_[0]->resource ("perl_lib"), @@ -1136,23 +1242,33 @@ return if exists $self->{meta}; - my @libdirs = perl_libdirs $self; + my @urxvtdirs = perl_libdirs $self; +# my @cpandirs = grep -d, map "$_/URxvt/Ext", @INC; -# return if $self->{meta_libdirs} eq join "\x00", @libdirs;#d# - -# $self->{meta_libdirs} = join "\x00", @libdirs;#d# - $self->{meta} = \my %meta; + $self->{meta} = \my %allmeta; # first gather extensions - for my $dir (reverse @libdirs) { + + my $gather = sub { + my ($dir, $core) = @_; + opendir my $fh, $dir - or next; + or return; + for my $ext (readdir $fh) { $ext !~ /^\./ - and open my $fh, "<", "$dir/$ext" or next; - my %ext = (dir => $dir); + open my $fh, "<", "$dir/$ext" + or next; + + -f $fh + or next; + + $ext =~ s/\.uext$// or $core + or next; + + my %meta = (dir => $dir); while (<$fh>) { if (/^#:META:(?:X_)?RESOURCE:(.*)/) { @@ -1161,23 +1277,37 @@ if ($pattern =~ /[^a-zA-Z0-9\-\.]/) { warn "$dir/$ext: meta resource '$pattern' contains illegal characters (not alphanumeric nor . nor *)\n"; } else { - $ext{resource}{$pattern} = [$ext, $type, $desc]; + $meta{resource}{$pattern} = [$ext, $type, $desc]; } + + } elsif (/^#:META:OSC:([0-9]+):(.*)/) { + push @{$allmeta{autoload_osc}{$1}}, [$ext, $2]; + + } elsif (/^#:META:OSC_PERL:([^:]+):(.*)/) { + push @{$allmeta{autoload_osc_perl}{$1}}, [$ext, $2]; + } elsif (/^\s*(?:#|$)/) { # skip other comments and empty lines + } else { last; # stop parsing on first non-empty non-comment line } } - $meta{ext}{$ext} = \%ext; + $allmeta{ext}{$ext} = \%meta; } - } + }; + +# $gather->($_, 0) for @cpandirs; + $gather->($_, 1) for @urxvtdirs; # and now merge resources - while (my ($k, $v) = each %{ $meta{ext} }) { + + $allmeta{resource} = \my %resource; + + while (my ($k, $v) = each %{ $allmeta{ext} }) { #TODO: should check for extensions overriding each other - %{ $meta{resource} } = (%{ $meta{resource} }, %{ $v->{resource} }); + %resource = (%resource, %{ $v->{resource} }); } } @@ -1250,7 +1380,7 @@ pointerBlank reverseVideo scrollBar scrollBar_floating scrollBar_right scrollTtyKeypress scrollTtyOutput scrollWithBuffer secondaryScreen secondaryScroll skipBuiltinGlyphs skipScroll transparent tripleclickwords - urgentOnBell utmpInhibit visualBell + urgentOnBell utmpInhibit visualBell disablePasteBrackets =item $value = $term->resource ($name[, $newval]) @@ -1286,7 +1416,7 @@ scrollTtyKeypress scrollTtyOutput scrollWithBuffer scrollstyle secondaryScreen secondaryScroll shade skipBuiltinGlyphs skipScroll term_name title transient_for transparent tripleclickwords urgentOnBell - utmpInhibit visualBell + utmpInhibit visualBell rewrapMode disablePasteBrackets =cut @@ -1333,14 +1463,19 @@ $res =~ /^\s*(?:true|yes|on|1)\s*$/i ? 1 : defined $res && 0 } +=item $action = $term->lookup_keysym ($keysym, $state) + +Returns the action bound to key combination C<($keysym, $state)>, +if a binding for it exists, and C otherwise. + =item $success = $term->bind_action ($key, $action) Adds a key binding exactly as specified via a C resource. See the C resource in the urxvt(1) manpage. -To add default bindings for an extension, the extension should call C<< -->bind_action >> on it's C hook for every such binding. Doing it -in the C hook allows users the override or remove the the binding +To add default bindings for actions, an extension should call C<< +->bind_action >> in its C hook for every such binding. Doing it +in the C hook allows users to override or remove the binding again. Example: the C by default binds itself @@ -1438,7 +1573,7 @@ The methods currently supported on C objects are: -=over 4 +=over =item $overlay->set ($x, $y, $text[, $rend]) @@ -1599,31 +1734,32 @@ Deliver various fake events to to terminal. -=item $window_width = $term->width +=item $window_width = $term->width ([$new_value]) -=item $window_height = $term->height +=item $window_height = $term->height ([$new_value]) -=item $font_width = $term->fwidth +=item $font_width = $term->fwidth ([$new_value]) -=item $font_height = $term->fheight +=item $font_height = $term->fheight ([$new_value]) -=item $font_ascent = $term->fbase +=item $font_ascent = $term->fbase ([$new_value]) -=item $terminal_rows = $term->nrow +=item $terminal_rows = $term->nrow ([$new_value]) -=item $terminal_columns = $term->ncol +=item $terminal_columns = $term->ncol ([$new_value]) -=item $has_focus = $term->focus +=item $has_focus = $term->focus ([$new_value]) -=item $is_mapped = $term->mapped +=item $is_mapped = $term->mapped ([$new_value]) -=item $max_scrollback = $term->saveLines +=item $max_scrollback = $term->saveLines ([$new_value]) -=item $nrow_plus_saveLines = $term->total_rows +=item $nrow_plus_saveLines = $term->total_rows ([$new_value]) -=item $topmost_scrollback_row = $term->top_row +=item $topmost_scrollback_row = $term->top_row ([$new_value]) -Return various integers describing terminal characteristics. +Return various integers describing terminal characteristics. If an +argument is given, changes the value and returns the previous one. =item $x_display = $term->display_id @@ -1670,11 +1806,22 @@ Returns whether the cursor is currently hidden or not. +=item $priv_modes = $term->priv_modes + +Returns a bitset with the state of DEC private modes. + +Example: + + if ($term->priv_modes & urxvt::PrivMode_mouse_report) { + # mouse reporting is turned on + } + =item $view_start = $term->view_start ([$newvalue]) -Returns the row number of the topmost displayed line. Maximum value is -C<0>, which displays the normal terminal contents. Lower values scroll -this many lines into the scrollback buffer. +Returns the row number of the topmost displayed line and changes it, +if an argument is given. Values greater than or equal to C<0> display +the terminal contents. Lower values scroll this many lines into the +scrollback buffer. =item $term->want_refresh @@ -1684,6 +1831,10 @@ Used after changing terminal contents to display them. +=item $term->refresh_check + +Checks if a refresh has been requested and, if so, schedules one. + =item $text = $term->ROW_t ($row_number[, $new_text[, $start_col]]) Returns the text of the entire row with number C<$row_number>. Row C<< $term->top_row >> @@ -1738,7 +1889,7 @@ about the logical line that row C<$row_number> is part of. It supports the following methods: -=over 4 +=over =item $text = $line->t ([$new_text]) @@ -1852,7 +2003,7 @@ =item $string = $term->special_decode $text -Converts rxvt-unicodes text representation into a perl string. See +Converts rxvt-unicode's text representation into a perl string. See C<< $term->ROW_t >> for details. =item $success = $term->grab_button ($button, $modifiermask[, $window = $term->vt]) @@ -1928,7 +2079,7 @@ =head2 The C Class -=over 4 +=over =cut @@ -2074,7 +2225,7 @@ sprintf "%2d:%02d:%02d", (localtime urxvt::NOW)[2,1,0]); }); -=over 4 +=over =item $timer = new urxvt::timer @@ -2133,7 +2284,7 @@ }); -=over 4 +=over =item $iow = new urxvt::iow @@ -2170,7 +2321,7 @@ the process is idle. They should return as fast as possible, after doing some useful work. -=over 4 +=over =item $iw = new urxvt::iw @@ -2205,7 +2356,7 @@ ... }); -=over 4 +=over =item $pw = new urxvt::pw @@ -2232,9 +2383,11 @@ This variable controls the verbosity level of the perl extension. Higher numbers indicate more verbose output. -=over 4 +=over + +=item == 0 - fatal messages only -=item == 0 - fatal messages +=item >= 2 - general warnings (default level) =item >= 3 - script loading and management