ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/perl/matcher
(Generate patch)

Comparing rxvt-unicode/src/perl/matcher (file contents):
Revision 1.1 by root, Sat Nov 11 20:06:34 2006 UTC vs.
Revision 1.7 by sf-tpope, Tue Aug 30 20:02:32 2011 UTC

1#! perl 1#! perl
2 2
3# Author: Tim Pope <rxvt-unicodeNOSPAM@tpope.info> 3# Author: Tim Pope <rxvt-unicodeNOSPAM@tpope.org>
4# Bob Farrell <robertanthonyfarrell@gmail.com>
4 5
5my $url = 6my $url =
6 qr{ 7 qr{
7 (?:https?://|ftp://|news://|mailto:|file://|\bwww\.)[ab-zA-Z0-9\-\@;\/?:&=%\$_.+!*\x27(),~#]+ 8 (?:https?://|ftp://|news://|mailto:|file://|\bwww\.)
9 [a-zA-Z0-9\-\@;\/?:&=%\$_.+!*\x27,~#]*
10 (
11 \([a-zA-Z0-9\-\@;\/?:&=%\$_.+!*\x27,~#]*\)| # Allow a pair of matched parentheses
8 [ab-zA-Z0-9\-\@;\/?:&=%\$_+*()~] # exclude some trailing characters (heuristic) 12 [a-zA-Z0-9\-\@;\/?:&=%\$_+*~] # exclude some trailing characters (heuristic)
13 )+
9 }x; 14 }x;
15
16sub on_key_press {
17 my ($self, $event, $keysym, $octets) = @_;
18
19 if (! $self->{showing} ) {
20 return;
21 }
22
23 my $i = ($keysym == 96 ? 0 : $keysym - 48);
24 if (($i > scalar(@{$self->{urls}})) || ($i < 0)) {
25 $self->matchlist();
26 return;
27 }
28
29 my @args = ($self->{urls}[ -$i-1 ]);
30 $self->matchlist();
31
32 $self->exec_async( $self->{launcher}, @args );
33}
34
35sub on_user_command {
36 my ($self, $cmd) = @_;
37
38 if($cmd =~ s/^matcher:list\b//) {
39 $self->matchlist();
40 } else {
41 if($cmd =~ s/^matcher:last\b//) {
42 $self->most_recent;
43 }
44 # For backward compatibility
45 else {
46 if($cmd =~ s/^matcher\b//) {
47 $self->most_recent;
48 }
49 }
50 }
51 ()
52}
53
54sub matchlist {
55 my ($self) = @_;
56 if ( $self->{showing} ) {
57 $self->{url_overlay}->hide();
58 $self->{showing} = 0;
59 return;
60 }
61 @{$self->{urls}} = ();
62 my $line;
63 for (my $i = 0; $i < $self->nrow; $i ++) {
64 $line = $self->line($i);
65 next if ($line->beg != $i);
66 for my $url ($self->get_urls_from_line($line->t)) {
67 if (scalar(@{$self->{urls}}) == 10) {
68 shift @{$self->{urls}};
69 }
70 push @{$self->{urls}}, $url;
71 }
72 }
73
74 if (! scalar(@{$self->{urls}})) {
75 return;
76 }
77
78 my $max = 0;
79 my $i = scalar( @{$self->{urls}} ) - 1 ;;
80
81 my @temp = ();
82
83 for my $url (@{$self->{urls}}) {
84 my $url = "$i-$url";
85 my $xpos = 0;
86
87 if ($self->ncol + (length $url) >= $self->ncol) {
88 $url = substr( $url, 0, $self->ncol );
89 }
90
91 push @temp, $url;
92
93 if( length $url > $max ) {
94 $max = length $url;
95 }
96
97 $i--;
98 }
99
100 @temp = reverse @temp;
101
102 $self->{url_overlay} = $self->overlay(0, 0, $max, scalar( @temp ), urxvt::OVERLAY_RSTYLE, 2);
103 my $i = 0;
104 for my $url (@temp) {
105 $self->{url_overlay}->set( 0, $i, $url, [(urxvt::OVERLAY_RSTYLE) x length $url]);
106 $self->{showing} = 1;
107 $i++;
108 }
109
110}
111
112sub most_recent {
113 my ($self) = shift;
114 my $row = $self->nrow;
115 my @exec;
116 while($row-- > $self->top_row) {
117 @exec = $self->command_for($row);
118 last if(@exec);
119 }
120 if(@exec) {
121 return $self->exec_async (@exec);
122 }
123 ()
124}
10 125
11sub my_resource { 126sub my_resource {
12 my $self = shift; 127 my $self = shift;
13 $self->x_resource("$self->{name}.$_[0]"); 128 $self->x_resource ("$self->{name}.$_[0]");
129}
130
131# turn a rendition spec in the resource into a sub that implements it on $_
132sub parse_rend {
133 my ($self, $str) = @_;
134 my ($mask, $fg, $bg, $failed) = $str ? urxvt::rend2mask($str)
135 : (urxvt::RS_Uline, undef, undef, []);
136 warn "Failed to parse rendition string: " . join(',', @$failed) if @$failed;
137 my @rend;
138 push @rend, sub { $_ |= $mask } if $mask;
139 push @rend, sub { $_ = urxvt::SET_FGCOLOR($_, $fg) } if defined $fg;
140 push @rend, sub { $_ = urxvt::SET_BGCOLOR($_, $bg) } if defined $bg;
141 sub {
142 for my $s ( @rend ) { &$s };
143 }
14} 144}
15 145
16sub on_start { 146sub on_start {
17 my ($self) = @_; 147 my ($self) = @_;
18 148
20 $self->{name} =~ tr/_/-/; 150 $self->{name} =~ tr/_/-/;
21 $self->{launcher} = $self->my_resource("launcher") || 151 $self->{launcher} = $self->my_resource("launcher") ||
22 $self->x_resource("urlLauncher") || 152 $self->x_resource("urlLauncher") ||
23 "sensible-browser"; 153 "sensible-browser";
24 154
155 $self->{urls} = [];
156 $self->{showing} = 0;
25 $self->{button} = 2; 157 $self->{button} = 2;
26 $self->{state} = 0; 158 $self->{state} = 0;
27 if($self->{argv}[0] || $self->my_resource("button")) { 159 if($self->{argv}[0] || $self->my_resource("button")) {
28 my @mods = split('', $self->{argv}[0] || $self->my_resource("button")); 160 my @mods = split('', $self->{argv}[0] || $self->my_resource("button"));
29 for my $mod (@mods) { 161 for my $mod (@mods) {
46 for (my $idx = 0; defined (my $res = $self->my_resource("pattern.$idx") || $defaults[$idx]); $idx++) { 178 for (my $idx = 0; defined (my $res = $self->my_resource("pattern.$idx") || $defaults[$idx]); $idx++) {
47 $res = $self->locale_decode ($res); 179 $res = $self->locale_decode ($res);
48 utf8::encode $res; 180 utf8::encode $res;
49 my $launcher = $self->my_resource("launcher.$idx"); 181 my $launcher = $self->my_resource("launcher.$idx");
50 $launcher =~ s/\$&|\$\{&\}/\${0}/g if ($launcher); 182 $launcher =~ s/\$&|\$\{&\}/\${0}/g if ($launcher);
183 my $rend = $self->parse_rend($self->my_resource("rend.$idx"));
51 push @matchers, [qr($res)x,$launcher]; 184 unshift @matchers, [qr($res)x,$launcher,$rend];
52 } 185 }
53 $self->{matchers} = \@matchers; 186 $self->{matchers} = \@matchers;
54 187
55 () 188 ()
189}
190
191sub get_urls_from_line {
192 my ($self, $line) = @_;
193 my @urls;
194 for my $matcher (@{$self->{matchers}}) {
195 while ($line =~ /$matcher->[0]/g) {
196 push @urls, substr( $line, $-[0], $+[0] - $-[0] );
197 }
198 }
199 return @urls;
56} 200}
57 201
58sub on_line_update { 202sub on_line_update {
59 my ($self, $row) = @_; 203 my ($self, $row) = @_;
60 204
64 my $i = 0; 208 my $i = 0;
65 209
66 # find all urls (if any) 210 # find all urls (if any)
67 for my $matcher (@{$self->{matchers}}) { 211 for my $matcher (@{$self->{matchers}}) {
68 while ($text =~ /$matcher->[0]/g) { 212 while ($text =~ /$matcher->[0]/g) {
213 #print "$&\n";
69 my $rend = $line->r; 214 my $rend = $line->r;
70 215
71 # mark all characters as underlined. we _must_ not toggle underline, 216 # mark all characters as underlined. we _must_ not toggle underline,
72 # as we might get called on an already-marked url. 217 # as we might get called on an already-marked url.
73 $_ |= urxvt::RS_Uline 218 &{$matcher->[2]}
74 for @{$rend}[ $-[0] .. $+[0] - 1]; 219 for @{$rend}[ $-[0] .. $+[0] - 1];
75 220
76 $line->r ($rend); 221 $line->r ($rend);
77 } 222 }
78 } 223 }
97 my $launcher = $matcher->[1] || $self->{launcher}; 242 my $launcher = $matcher->[1] || $self->{launcher};
98 while (($text =~ /$matcher->[0]/g)) { 243 while (($text =~ /$matcher->[0]/g)) {
99 my $match = $&; 244 my $match = $&;
100 my @begin = @-; 245 my @begin = @-;
101 my @end = @+; 246 my @end = @+;
102 if ($-[0] <= $col && $+[0] >= $col) { 247 if (!defined($col) || ($-[0] <= $col && $+[0] >= $col)) {
103 if ($launcher !~ /\$/) { 248 if ($launcher !~ /\$/) {
104 return ($launcher,$match); 249 return ($launcher,$match);
105 } else { 250 } else {
106 # It'd be nice to just access a list like ($&,$1,$2...), 251 # It'd be nice to just access a list like ($&,$1,$2...),
107 # but alas, m//g behaves differently in list context. 252 # but alas, m//g behaves differently in list context.
117 () 262 ()
118} 263}
119 264
120sub on_button_press { 265sub on_button_press {
121 my ($self, $event) = @_; 266 my ($self, $event) = @_;
122 if($self->valid_button($event)) { 267 if($self->valid_button($event)
268 && (my @exec = $self->command_for($event->{row},$event->{col}))) {
123 $self->{row} = $event->{row}; 269 $self->{row} = $event->{row};
124 $self->{col} = $event->{col}; 270 $self->{col} = $event->{col};
271 $self->{cmd} = \@exec;
272 return 1;
125 } else { 273 } else {
126 delete $self->{row}; 274 delete $self->{row};
127 delete $self->{col}; 275 delete $self->{col};
276 delete $self->{cmd};
128 } 277 }
129 278
130 () 279 ()
131} 280}
132 281
133sub on_button_release { 282sub on_button_release {
134 my ($self, $event) = @_; 283 my ($self, $event) = @_;
135 284
136 my $row = delete $self->{row}; 285 my $row = delete $self->{row};
137 my $col = delete $self->{col}; 286 my $col = delete $self->{col};
287 my $cmd = delete $self->{cmd};
138 288
289 return if !defined $row;
290
139 if(defined($row) && $row == $event->{row} && abs($col-$event->{col}) < 2) { 291 if($row == $event->{row} && abs($col-$event->{col}) < 2
292 && join("\x00", @$cmd) eq join("\x00", $self->command_for($row,$col))) {
140 if($self->valid_button($event)) { 293 if($self->valid_button($event)) {
141 294
142 my @exec = $self->command_for($row,$col); 295 $self->exec_async (@$cmd);
143 if(@exec) { 296
144 return $self->exec_async (@exec);
145 } 297 }
146
147 }
148 } 298 }
149 299
150 () 300 1;
151} 301}
152 302
153# vim:set sw=3 sts=3 et: 303# vim:set sw=3 sts=3 et:

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines