… | |
… | |
2 | |
2 | |
3 | # Author: Tim Pope <rxvt-unicodeNOSPAM@tpope.info> |
3 | # Author: Tim Pope <rxvt-unicodeNOSPAM@tpope.info> |
4 | |
4 | |
5 | my $url = |
5 | my $url = |
6 | qr{ |
6 | qr{ |
7 | (?:https?://|ftp://|news://|mailto:|file://|\bwww\.)[ab-zA-Z0-9\-\@;\/?:&=%\$_.+!*\x27(),~#]+ |
7 | (?:https?://|ftp://|news://|mailto:|file://|\bwww\.) |
|
|
8 | [a-zA-Z0-9\-\@;\/?:&=%\$_.+!*\x27,~#]* |
|
|
9 | ( |
|
|
10 | \([a-zA-Z0-9\-\@;\/?:&=%\$_.+!*\x27,~#]*\)| # Allow a pair of matched parentheses |
8 | [ab-zA-Z0-9\-\@;\/?:&=%\$_+*()~] # exclude some trailing characters (heuristic) |
11 | [a-zA-Z0-9\-\@;\/?:&=%\$_+*~] # exclude some trailing characters (heuristic) |
|
|
12 | )+ |
9 | }x; |
13 | }x; |
|
|
14 | |
|
|
15 | sub on_user_command { |
|
|
16 | my ($self, $cmd) = @_; |
|
|
17 | if($cmd =~ s/^matcher\b//) { |
|
|
18 | $self->most_recent; |
|
|
19 | } |
|
|
20 | my $row = $self->nrow; |
|
|
21 | my @exec; |
|
|
22 | while($row-- > $self->top_row) { |
|
|
23 | #my $line = $self->line ($row); |
|
|
24 | #my $text = $line->t; |
|
|
25 | @exec = $self->command_for($row); |
|
|
26 | last if(@exec); |
|
|
27 | } |
|
|
28 | if(@exec) { |
|
|
29 | return $self->exec_async (@exec); |
|
|
30 | } |
|
|
31 | () |
|
|
32 | } |
|
|
33 | |
|
|
34 | sub most_recent { |
|
|
35 | my ($self) = shift; |
|
|
36 | () |
|
|
37 | } |
10 | |
38 | |
11 | sub my_resource { |
39 | sub my_resource { |
12 | my $self = shift; |
40 | my $self = shift; |
13 | $self->x_resource("$self->{name}.$_[0]"); |
41 | $self->x_resource("$self->{name}.$_[0]"); |
|
|
42 | } |
|
|
43 | |
|
|
44 | # turn a rendition spec in the resource into a sub that implements it on $_ |
|
|
45 | sub parse_rend { |
|
|
46 | my ($self, $str) = @_; |
|
|
47 | my ($mask, $fg, $bg, $failed) = $str ? urxvt::rend2mask($str) |
|
|
48 | : (urxvt::RS_Uline, undef, undef, []); |
|
|
49 | warn "Failed to parse rendition string: " . join(',', @$failed) if @$failed; |
|
|
50 | my @rend; |
|
|
51 | push @rend, sub { $_ |= $mask } if $mask; |
|
|
52 | push @rend, sub { $_ = urxvt::SET_FGCOLOR($_, $fg) } if defined $fg; |
|
|
53 | push @rend, sub { $_ = urxvt::SET_BGCOLOR($_, $bg) } if defined $bg; |
|
|
54 | sub { |
|
|
55 | for my $s ( @rend ) { &$s }; |
|
|
56 | } |
14 | } |
57 | } |
15 | |
58 | |
16 | sub on_start { |
59 | sub on_start { |
17 | my ($self) = @_; |
60 | my ($self) = @_; |
18 | |
61 | |
… | |
… | |
46 | for (my $idx = 0; defined (my $res = $self->my_resource("pattern.$idx") || $defaults[$idx]); $idx++) { |
89 | for (my $idx = 0; defined (my $res = $self->my_resource("pattern.$idx") || $defaults[$idx]); $idx++) { |
47 | $res = $self->locale_decode ($res); |
90 | $res = $self->locale_decode ($res); |
48 | utf8::encode $res; |
91 | utf8::encode $res; |
49 | my $launcher = $self->my_resource("launcher.$idx"); |
92 | my $launcher = $self->my_resource("launcher.$idx"); |
50 | $launcher =~ s/\$&|\$\{&\}/\${0}/g if ($launcher); |
93 | $launcher =~ s/\$&|\$\{&\}/\${0}/g if ($launcher); |
|
|
94 | my $rend = $self->parse_rend($self->my_resource("rend.$idx")); |
51 | push @matchers, [qr($res)x,$launcher]; |
95 | unshift @matchers, [qr($res)x,$launcher,$rend]; |
52 | } |
96 | } |
53 | $self->{matchers} = \@matchers; |
97 | $self->{matchers} = \@matchers; |
54 | |
98 | |
55 | () |
99 | () |
56 | } |
100 | } |
… | |
… | |
64 | my $i = 0; |
108 | my $i = 0; |
65 | |
109 | |
66 | # find all urls (if any) |
110 | # find all urls (if any) |
67 | for my $matcher (@{$self->{matchers}}) { |
111 | for my $matcher (@{$self->{matchers}}) { |
68 | while ($text =~ /$matcher->[0]/g) { |
112 | while ($text =~ /$matcher->[0]/g) { |
|
|
113 | #print "$&\n"; |
69 | my $rend = $line->r; |
114 | my $rend = $line->r; |
70 | |
115 | |
71 | # mark all characters as underlined. we _must_ not toggle underline, |
116 | # mark all characters as underlined. we _must_ not toggle underline, |
72 | # as we might get called on an already-marked url. |
117 | # as we might get called on an already-marked url. |
73 | $_ |= urxvt::RS_Uline |
118 | &{$matcher->[2]} |
74 | for @{$rend}[ $-[0] .. $+[0] - 1]; |
119 | for @{$rend}[ $-[0] .. $+[0] - 1]; |
75 | |
120 | |
76 | $line->r ($rend); |
121 | $line->r ($rend); |
77 | } |
122 | } |
78 | } |
123 | } |
… | |
… | |
97 | my $launcher = $matcher->[1] || $self->{launcher}; |
142 | my $launcher = $matcher->[1] || $self->{launcher}; |
98 | while (($text =~ /$matcher->[0]/g)) { |
143 | while (($text =~ /$matcher->[0]/g)) { |
99 | my $match = $&; |
144 | my $match = $&; |
100 | my @begin = @-; |
145 | my @begin = @-; |
101 | my @end = @+; |
146 | my @end = @+; |
102 | if ($-[0] <= $col && $+[0] >= $col) { |
147 | if (!defined($col) || ($-[0] <= $col && $+[0] >= $col)) { |
103 | if ($launcher !~ /\$/) { |
148 | if ($launcher !~ /\$/) { |
104 | return ($launcher,$match); |
149 | return ($launcher,$match); |
105 | } else { |
150 | } else { |
106 | # It'd be nice to just access a list like ($&,$1,$2...), |
151 | # It'd be nice to just access a list like ($&,$1,$2...), |
107 | # but alas, m//g behaves differently in list context. |
152 | # but alas, m//g behaves differently in list context. |