--- rxvt-unicode/src/urxvt.pm 2011/11/29 19:20:18 1.201 +++ rxvt-unicode/src/urxvt.pm 2012/06/10 17:31:53 1.218 @@ -22,7 +22,7 @@ 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' and 'use utf8' environment, and +Scripts are compiled in a 'use strict "vars"' and 'use utf8' environment, and thus must be encoded as UTF-8. Each script will only ever be loaded once, even in @@RXVT_NAME@@d, where @@ -33,8 +33,9 @@ =head1 PREPACKAGED EXTENSIONS -This section describes the extensions delivered with this release. You can -find them in F<@@RXVT_LIBDIR@@/urxvt/perl/>. +A number of extensions are delivered with this release. You can find them +in F<@@RXVT_LIBDIR@@/urxvt/perl/>, and the documentation can be vewiwed +using F<< man urxvt- >>. You can activate them like this: @@ -44,373 +45,8 @@ URxvt.perl-ext-common: default,selection-autotransform -=over 4 - -=item selection (enabled by default) - -(More) intelligent selection. This extension tries to be more intelligent -when the user extends selections (double-click and further clicks). Right -now, it tries to select words, urls and complete shell-quoted -arguments, which is very convenient, too, if your F supports -C<--quoting-style=shell>. - -A double-click usually selects the word under the cursor, further clicks -will enlarge the selection. - -The selection works by trying to match a number of regexes and displaying -them in increasing order of length. You can add your own regexes by -specifying resources of the form: - - URxvt.selection.pattern-0: perl-regex - URxvt.selection.pattern-1: perl-regex - ... - -The index number (0, 1...) must not have any holes, and each regex must -contain at least one pair of capturing parentheses, which will be used for -the match. For example, the following adds a regex that matches everything -between two vertical bars: - - URxvt.selection.pattern-0: \\|([^|]+)\\| - -Another example: Programs I use often output "absolute path: " at the -beginning of a line when they process multiple files. The following -pattern matches the filename (note, there is a single space at the very -end): - - URxvt.selection.pattern-0: ^(/[^:]+):\ - -You can look at the source of the selection extension to see more -interesting uses, such as parsing a line from beginning to end. - -This extension also offers following bindable keyboard commands: - -=over 4 - -=item rot13 - -Rot-13 the selection when activated. Used via keyboard trigger: - - URxvt.keysym.C-M-r: perl:selection:rot13 - -=back - -=item option-popup (enabled by default) - -Binds a popup menu to Ctrl-Button2 that lets you toggle (some) options at -runtime. - -Other extensions can extend this popup menu by pushing a code reference -onto C<@{ $term->{option_popup_hook} }>, which gets called whenever the -popup is being displayed. - -Its sole argument is the popup menu, which can be modified. It should -either return nothing or a string, the initial boolean value and a code -reference. The string will be used as button text and the code reference -will be called when the toggle changes, with the new boolean value as -first argument. - -The following will add an entry C that changes -C<< $self->{myoption} >>: - - push @{ $self->{term}{option_popup_hook} }, sub { - ("my option" => $myoption, sub { $self->{myoption} = $_[0] }) - }; - -=item selection-popup (enabled by default) - -Binds a popup menu to Ctrl-Button3 that lets you convert the selection -text into various other formats/action (such as uri unescaping, perl -evaluation, web-browser starting etc.), depending on content. - -Other extensions can extend this popup menu by pushing a code reference -onto C<@{ $term->{selection_popup_hook} }>, which gets called whenever the -popup is being displayed. - -Its sole argument is the popup menu, which can be modified. The selection -is in C<$_>, which can be used to decide whether to add something or not. -It should either return nothing or a string and a code reference. The -string will be used as button text and the code reference will be called -when the button gets activated and should transform C<$_>. - -The following will add an entry C that transforms all Cs in -the selection to Cs, but only if the selection currently contains any -Cs: - - push @{ $self->{term}{selection_popup_hook} }, sub { - /a/ ? ("a to b" => sub { s/a/b/g } - : () - }; - -=item searchable-scrollback (enabled by default) - -Adds regex search functionality to the scrollback buffer, triggered -by a hotkey (default: C). While in search mode, normal terminal -input/output is suspended and a regex is displayed at the bottom of the -screen. - -Inputting characters appends them to the regex and continues incremental -search. C removes a character from the regex, C and C -search upwards/downwards in the scrollback buffer, C jumps to the -bottom. C leaves search mode and returns to the point where search -was started, while C or C stay at the current position and -additionally stores the first match in the current line into the primary -selection if the C modifier is active. - -The regex defaults to "(?i)", resulting in a case-insensitive search. To -get a case-sensitive search you can delete this prefix using C -or simply use an uppercase character which removes the "(?i)" prefix. - -See L for more info about perl regular expression syntax. - -=item readline (enabled by default) - -A support package that tries to make editing with readline easier. At -the moment, it reacts to clicking shift-left mouse button by trying to -move the text cursor to this position. It does so by generating as many -cursor-left or cursor-right keypresses as required (this only works -for programs that correctly support wide characters). - -To avoid too many false positives, this is only done when: - -=over 4 - -=item - the tty is in ICANON state. - -=item - the text cursor is visible. - -=item - the primary screen is currently being displayed. - -=item - the mouse is on the same (multi-row-) line as the text cursor. - -=back - -The normal selection mechanism isn't disabled, so quick successive clicks -might interfere with selection creation in harmless ways. - -=item selection-autotransform - -This selection allows you to do automatic transforms on a selection -whenever a selection is made. - -It works by specifying perl snippets (most useful is a single C -operator) that modify C<$_> as resources: - - URxvt.selection-autotransform.0: transform - URxvt.selection-autotransform.1: transform - ... - -For example, the following will transform selections of the form -C, often seen in compiler messages, into C: - - URxvt.selection-autotransform.0: s/^([^:[:space:]]+):(\\d+):?$/vi +$2 \\Q$1\\E\\x0d/ - -And this example matches the same,but replaces it with vi-commands you can -paste directly into your (vi :) editor: - - URxvt.selection-autotransform.0: s/^([^:[:space:]]+(\\d+):?$/:e \\Q$1\\E\\x0d:$2\\x0d/ - -Of course, this can be modified to suit your needs and your editor :) - -To expand the example above to typical perl error messages ("XXX at -FILENAME line YYY."), you need a slightly more elaborate solution: - - URxvt.selection.pattern-0: ( at .*? line \\d+[,.]) - URxvt.selection-autotransform.0: s/^ at (.*?) line (\\d+)[,.]$/:e \\Q$1\E\\x0d:$2\\x0d/ - -The first line tells the selection code to treat the unchanging part of -every error message as a selection pattern, and the second line transforms -the message into vi commands to load the file. - -=item tabbed - -This transforms the terminal into a tabbar with additional terminals, that -is, it implements what is commonly referred to as "tabbed terminal". The topmost line -displays a "[NEW]" button, which, when clicked, will add a new tab, followed by one -button per tab. - -Clicking a button will activate that tab. Pressing B and -B will switch to the tab left or right of the current one, -while B creates a new tab. - -The tabbar itself can be configured similarly to a normal terminal, but -with a resource class of C. In addition, it supports the -following four resources (shown with defaults): - - URxvt.tabbed.tabbar-fg: - URxvt.tabbed.tabbar-bg: - URxvt.tabbed.tab-fg: - URxvt.tabbed.tab-bg: - -See I in the @@RXVT_NAME@@(1) manpage for valid -indices. - -=item matcher - -Uses per-line display filtering (C) to underline text -matching a certain pattern and make it clickable. When clicked with the -mouse button specified in the C resource (default 2, or -middle), the program specified in the C resource -(default, the C resource, C) will be started -with the matched text as first argument. The default configuration is -suitable for matching URLs and launching a web browser, like the -former "mark-urls" extension. - -The default pattern to match URLs can be overridden with the -C resource, and additional patterns can be specified -with numbered patterns, in a manner similar to the "selection" extension. -The launcher can also be overridden on a per-pattern basis. - -It is possible to activate the most recently seen match or a list of matches -from the keyboard. Simply bind a keysym to "perl:matcher:last" or -"perl:matcher:list" as seen in the example below. - -Example configuration: - - URxvt.perl-ext: default,matcher - URxvt.urlLauncher: sensible-browser - URxvt.keysym.C-Delete: perl:matcher:last - URxvt.keysym.M-Delete: perl:matcher:list - URxvt.matcher.button: 1 - URxvt.matcher.pattern.1: \\bwww\\.[\\w-]+\\.[\\w./?&@#-]*[\\w/-] - URxvt.matcher.pattern.2: \\B(/\\S+?):(\\d+)(?=:|$) - URxvt.matcher.launcher.2: gvim +$2 $1 - -=item xim-onthespot - -This (experimental) perl extension implements OnTheSpot editing. It does -not work perfectly, and some input methods don't seem to work well with -OnTheSpot editing in general, but it seems to work at least for SCIM and -kinput2. - -You enable it by specifying this extension and a preedit style of -C, i.e.: - - @@RXVT_NAME@@ -pt OnTheSpot -pe xim-onthespot - -=item kuake - -A very primitive quake-console-like extension. It was inspired by a -description of how the programs C and C work: Whenever the -user presses a global accelerator key (by default C), the terminal -will show or hide itself. Another press of the accelerator key will hide -or show it again. - -Initially, the window will not be shown when using this extension. - -This is useful if you need a single terminal that is not using any desktop -space most of the time but is quickly available at the press of a key. - -The accelerator key is grabbed regardless of any modifiers, so this -extension will actually grab a physical key just for this function. - -If you want a quake-like animation, tell your window manager to do so -(fvwm can do it). - -=item overlay-osc - -This extension implements some OSC commands to display timed popups on the -screen - useful for status displays from within scripts. You have to read -the sources for more info. - -=item block-graphics-to-ascii - -A not very useful example of filtering all text output to the terminal -by replacing all line-drawing characters (U+2500 .. U+259F) by a -similar-looking ascii character. - -=item digital-clock - -Displays a digital clock using the built-in overlay. - -=item remote-clipboard - -Somewhat of a misnomer, this extension adds two menu entries to the -selection popup that allows one to run external commands to store the -selection somewhere and fetch it again. - -We use it to implement a "distributed selection mechanism", which just -means that one command uploads the file to a remote server, and another -reads it. - -The commands can be set using the C and -C resources. The first should read the -selection to store from STDIN (always in UTF-8), the second should provide -the selection data on STDOUT (also in UTF-8). - -The defaults (which are likely useless to you) use rsh and cat: - - URxvt.remote-selection.store: rsh ruth 'cat >/tmp/distributed-selection' - URxvt.remote-selection.fetch: rsh ruth 'cat /tmp/distributed-selection' - -=item selection-pastebin - -This is a little rarely useful extension that uploads the selection as -textfile to a remote site (or does other things). (The implementation is -not currently secure for use in a multiuser environment as it writes to -F directly.). - -It listens to the C keyboard command, -i.e. - - URxvt.keysym.C-M-e: perl:selection-pastebin:remote-pastebin - -Pressing this combination runs a command with C<%> replaced by the name of -the textfile. This command can be set via a resource: - - URxvt.selection-pastebin.cmd: rsync -apP % ruth:/var/www/www.ta-sa.org/files/txt/. - -And the default is likely not useful to anybody but the few people around -here :) - -The name of the textfile is the hex encoded md5 sum of the selection, so -the same content should lead to the same filename. - -After a successful upload the selection will be replaced by the text given -in the C resource (again, the % is the placeholder -for the filename): - - URxvt.selection-pastebin.url: http://www.ta-sa.org/files/txt/% - -I xrdb uses the C preprocessor, which might interpret -the double C characters as comment start. Use C<\057\057> instead, -which works regardless of whether xrdb is used to parse the resource file -or not. - -=item macosx-clipboard and macosx-clipboard-native - -These two modules implement an extended clipboard for Mac OS X. They are -used like this: - - URxvt.perl-ext-common: default,macosx-clipboard - URxvt.keysym.M-c: perl:macosx-clipboard:copy - URxvt.keysym.M-v: perl:macosx-clipboard:paste - -The difference between them is that the native variant requires a -perl from apple's devkit or so, and C requires the -C module, works with other perls, has fewer bugs, is -simpler etc. etc. - -=item example-refresh-hooks - -Displays a very simple digital clock in the upper right corner of the -window. Illustrates overwriting the refresh callbacks to create your own -overlays or changes. - -=item confirm-paste - -Displays a confirmation dialog when a paste containing at least a full -line is detected. - -=item bell-command - -Runs the command specified by the C resource when -a bell event occurs. For example, the following pops up a notification -bubble with the text "Beep, Beep" using notify-send: - - URxvt.bell-command: notify-send "Beep, Beep" - -=back +Extensions that add command line parameters or resources on their own are +laoded automatically when used. =head1 API DOCUMENTATION @@ -448,6 +84,12 @@ Either binary data or - more common - a text string encoded in a locale-specific way. +=item $keysym + +an integer that is a valid X11 keysym code. You can convert a string +into a keysym and viceversa by using C and +C. + =back =head2 Extension Objects @@ -668,6 +310,13 @@ The event is simply the action string. This interface is assumed to change slightly in the future. +=item on_register_command $term, $keysym, $modifiermask, $string + +Called after parsing a keysym resource but before registering the +associated binding. If this hook returns TRUE the binding is not +registered. It can be used to modify a binding by calling +C. + =item on_resize_all_windows $term, $new_width, $new_height Called just after the new window size has been calculated, but before @@ -744,15 +393,15 @@ package urxvt; use utf8; -use strict; +use strict 'vars'; use Carp (); use Scalar::Util (); use List::Util (); our $VERSION = 1; our $TERM; -our @TERM_INIT; -our @TERM_EXT; +our @TERM_INIT; # should go, prevents async I/O etc. +our @TERM_EXT; # should go, prevents async I/O etc. our @HOOKNAME; our %HOOKTYPE = map +($HOOKNAME[$_] => $_), 0..$#HOOKNAME; our %OPTION; @@ -932,6 +581,66 @@ no warnings 'utf8'; +sub parse_resource { + my ($term, $name, $isarg, $longopt, $flag, $value) = @_; + + $name =~ y/-/./ if $isarg; + + $term->scan_meta; + + my $r = $term->{meta}{resource}; + keys %$r; # reste iterator + while (my ($pattern, $v) = each %$r) { + if ( + $pattern =~ /\.$/ + ? $pattern eq substr $name, 0, length $pattern + : $pattern eq $name + ) { + $name = "$urxvt::RESCLASS.$name"; + + push @{ $term->{perl_ext_3} }, $v->[0]; + + if ($v->[1] eq "boolean") { + $term->put_option_db ($name, $flag ? "true" : "false"); + return 1; + } else { + $term->put_option_db ($name, $value); + return 1 + 2; + } + } + } + + 0 +} + +sub usage { + my ($term, $usage_type) = @_; + + $term->scan_meta; + + my $r = $term->{meta}{resource}; + + for my $pattern (sort keys %$r) { + my ($ext, $type, $desc) = @{ $r->{$pattern} }; + + $desc .= " (-pe $ext)"; + + if ($usage_type == 1) { + $pattern =~ y/./-/; + $pattern =~ s/-$/-.../g; + + if ($type eq "boolean") { + urxvt::log sprintf " -%-30s %s\n", "/+$pattern", $desc; + } else { + urxvt::log sprintf " -%-30s %s\n", "$pattern $type", $desc; + } + } else { + $pattern =~ s/\.$/.*/g; + urxvt::log sprintf " %-31s %s\n", "$pattern:", $type; + } + } +} + my $verbosity = $ENV{URXVT_PERL_VERBOSITY}; sub verbose { @@ -953,11 +662,13 @@ verbose 3, "loading extension '$path' into package '$pkg'"; + (${"$pkg\::_NAME"} = $path) =~ s/^.*[\\\/]//; # hackish + open my $fh, "<:raw", $path or die "$path: $!"; my $source = - "package $pkg; use strict; use utf8; no warnings 'utf8';\n" + "package $pkg; use strict 'vars'; use utf8; no warnings 'utf8';\n" . "#line 1 \"$path\"\n{\n" . (do { local $/; <$fh> }) . "\n};\n1"; @@ -977,7 +688,7 @@ my $htype = shift; if ($htype == 0) { # INIT - my @dirs = ((split /:/, $TERM->resource ("perl_lib")), "$ENV{HOME}/.urxvt/ext", "$LIBDIR/perl"); + my @dirs = $TERM->perl_libdirs; my %ext_arg; @@ -990,7 +701,10 @@ $TERM->register_package ($_) for @pkg; } - for (grep $_, map { split /,/, $TERM->resource ("perl_ext_$_") } 1, 2) { + for ( + @{ delete $TERM->{perl_ext_3} }, + grep $_, map { split /,/, $TERM->resource ("perl_ext_$_") } 1, 2 + ) { if ($_ eq "default") { $ext_arg{$_} ||= [] for qw(selection option-popup selection-popup searchable-scrollback readline); } elsif (/^-(.*)$/) { @@ -1076,8 +790,6 @@ ($mask, @color{qw(fg bg)}, \@failed) } -# urxvt::term::extension - package urxvt::term::extension; sub enable { @@ -1141,6 +853,18 @@ bless \shift, urxvt::destroy_hook:: } +sub x_resource { + my ($self, $name) = @_; + $name =~ s/^%(\.|$)/$_[0]{_name}$1/; + $self->{term}->x_resource ($name) +} + +sub x_resource_boolean { + my ($self, $name) = @_; + $name =~ s/^%(\.|$)/$_[0]{_name}$1/; + $self->{term}->x_resource_boolean ($name) +} + package urxvt::anyevent; =head2 The C Class @@ -1148,9 +872,10 @@ The sole purpose of this class is to deliver an interface to the C module - any module using it will work inside urxvt without further programming. The only exception is that you cannot wait on -condition variables, but non-blocking condvar use is ok. What this means -is that you cannot use blocking APIs, but the non-blocking variant should -work. +condition variables, but non-blocking condvar use is ok. + +In practical terms this means is that you cannot use blocking APIs, but +the non-blocking variant should work. =cut @@ -1244,8 +969,9 @@ @{"$pkg\::ISA"} = urxvt::term::extension::; my $proxy = bless { - _pkg => $pkg, - argv => $argv, + _pkg => $pkg, + _name => ${"$pkg\::_NAME"}, # hackish + argv => $argv, }, $pkg; Scalar::Util::weaken ($proxy->{term} = $self); @@ -1258,6 +984,53 @@ } } +sub perl_libdirs { + map { split /:/ } + $_[0]->resource ("perl_lib"), + $ENV{URXVT_PERL_LIB}, + "$ENV{HOME}/.urxvt/ext", + "$LIBDIR/perl" +} + +sub scan_meta { + my ($self) = @_; + my @libdirs = perl_libdirs $self; + + return if $self->{meta_libdirs} eq join "\x00", @libdirs; + + my %meta; + + $self->{meta_libdirs} = join "\x00", @libdirs; + $self->{meta} = \%meta; + + for my $dir (reverse @libdirs) { + opendir my $fh, $dir + or next; + for my $ext (readdir $fh) { + $ext ne "." + and $ext ne ".." + and open my $fh, "<", "$dir/$ext" + or next; + + while (<$fh>) { + if (/^#:META:X_RESOURCE:(.*)/) { + my ($pattern, $type, $desc) = split /:/, $1; + $pattern =~ s/^%(\.|$)/$ext$1/g; # % in pattern == extension name + if ($pattern =~ /[^a-zA-Z0-9\-\.]/) { + warn "$dir/$ext: meta resource '$pattern' contains illegal characters (not alphanumeric nor . nor *)\n"; + } else { + $meta{resource}{$pattern} = [$ext, $type, $desc]; + } + } elsif (/^\s*(?:#|$)/) { + # skip other comments and empty lines + } else { + last; # stop parsing on first non-empty non-comment line + } + } + } + } +} + =item $term = new urxvt::term $envhashref, $rxvtname, [arg...] Creates a new terminal, very similar as if you had started it with system @@ -1380,15 +1153,48 @@ same value as used by this instance of rxvt-unicode. Returns C if no resource with that pattern exists. +Extensions that define extra resource or command line arguments also need +to call this method to access their values. + +If the method is called on an extension object (basically, from an +extension), then the special prefix C<%.> will be replaced by the name of +the extension and a dot, and the lone string C<%> will be replcaed by the +extension name itself. This makes it possible to code extensions so you +can rename them and get a new set of commandline switches and resources +without having to change the actual code. + This method should only be called during the C hook, as there is only one resource database per display, and later invocations might return the wrong resources. +=item $value = $term->x_resource_boolean ($pattern) + +Like C, above, but interprets the string value as a boolean +and returns C<1> for true values, C<0> for false values and C if +the resource or option isn't specified. + +You should always use this method to parse boolean resources. + +=cut + +sub x_resource_boolean { + my $res = &x_resource; + + $res =~ /^\s*(?:true|yes|on|1)\s*$/i ? 1 : defined $res && 0 +} + =item $success = $term->parse_keysym ($key, $octets) Adds a key binding exactly as specified via a resource. See the C resource in the @@RXVT_NAME@@(1) manpage. +=item $term->register_command ($keysym, $modifiermask, $string) + +Adds a key binding. This is a lower level api compared to +C, as it expects a parsed key description, and can be +used only inside either the C hook, to add a binding, or the +C hook, to modify a parsed binding. + =item $rend = $term->rstyle ([$new_rstyle]) Return and optionally change the current rendition. Text that is output by @@ -1611,6 +1417,10 @@ $term->vt_emask_add (urxvt::PointerMotionMask); +=item $term->set_urgency ($set) + +Enable/disable the urgency hint on the toplevel window. + =item $term->focus_in =item $term->focus_out @@ -1936,6 +1746,10 @@ =item $term->XChangeInput ($window, $add_events[, $del_events]) +=item $keysym = $term->XStringToKeysym ($string) + +=item $string = $term->XKeysymToString ($keysym) + Various X or X-related functions. The C<$term> object only serves as the source of the display, otherwise those functions map more-or-less directly onto the X functions of the same name.