revert changes to url_matches lost in last couple of commits
[rxvt-unicode-script-mark-and-yank.git] / mark-yank-urls
blob0285712b7b6cf4b1ab0365ac3e0eff279007d779
1 #!/usr/bin/perl
2 # Author: Bart Trojanowski <bart@jukie.net>
3 # Website: http://www.jukie.net/~bart/blog/urxvt-url-yank
4 # License: GPLv2
6 use strict;
7 use warnings;
9 my $url_matcher = qr{(
10 (?:https?://|ftp://|news://|mailto:|file://|www\.)[ab-zA-Z0-9\-\@;\/?:&=%\$_.+!*\x27(),~#]+
11 [ab-zA-Z0-9\-\@;\/?&=%\$_+!*\x27()~] # exclude some trailing characters (heuristic)
12 )}x;
15 sub on_start {
16 my ($term) = @_;
18 $term->{have_Clipboard} = eval { require Clipboard; };
19 if ($term->{have_Clipboard}) {
20 import Clipboard;
23 eval { require Regexp::Common::URI };
24 if(!$@) {
25 require Regexp::Common;
26 Regexp::Common->import('URI');
28 $url_matcher = $Regexp::Common::RE{URI}{HTTP};
31 $term->{browser} = $term->x_resource ("urlLauncher") || "x-www-browser";
36 sub on_line_update {
37 my ($term, $row) = @_;
39 # Fetch the line that has changed.
40 my $line = $term->line($row);
41 my $text = $line->t;
43 # Find and underline URLs.
44 while ($text =~ /($url_matcher)/g) {
45 my $rend = $line->r;
47 # Mark all characters as underlined. we _must_ not toggle underline, as
48 # we might get called on an already-marked URL.
49 if($term->x_resource ('underlineURLs') eq 'true') {
50 my $url = $1;
51 my ($first, $last) = ($-[1], $+[1] - 1);
53 --$last if $url =~ s/["']$//;
55 $_ |= urxvt::RS_Uline for @{$rend}[$first .. $last];
57 $line->r($rend);
64 sub on_button_release {
65 my ($term, $event) = @_;
67 my $mask = $term->ModLevel3Mask | $term->ModMetaMask
68 | urxvt::ShiftMask | urxvt::ControlMask;
70 if ($event->{button} == 2 && ($event->{state} & $mask) == 0) {
71 my $row = $event->{row};
72 my $col = $event->{col};
74 my $line = $term->line ($row);
75 my $text = $line->t;
77 while ($text =~ /($url_matcher)/g) {
78 my ($url, $first, $last) = ($1, $-[1], $+[1]);
80 if($first <= $col && $last >= $col) {
81 $url =~ s/["']$//;
82 $term->exec_async($term->{browser}, $url);
83 return 1;
92 my $mark_mode_active = 0;
93 my %mod = ( 'control' => 0, 'shift' => 0 );
94 my $url_selected = -1;
95 my @url_db = ();
98 sub do_scan_for_urls {
99 my ($term) = @_;
101 @url_db = ();
103 my $row_start = $term->top_row;
104 my $row_end = $term->nrow;
106 for my $row ($row_start .. $row_end) {
108 # Fetch the line that has changed.
109 my $line = $term->line ($row);
110 my $text = $line->t;
112 # Find all urls (if any).
113 while ($text =~ /($url_matcher)/g) {
114 my $rend = $line->r;
116 my ($url, $first, $last) = ($1, $-[1], $+[1] - 1);
118 --$last if $url =~ s/["']$//;
120 my %h = (
121 row => $row,
122 col_from => $first,
123 col_to => $last,
124 url => $url,
127 push @url_db, \%h;
131 # 0 for none, positive count otherwise
132 return $#url_db + 1;
136 sub on_user_command {
137 my ($term, $cmd) = @_;
139 activate_mark_mode($term) if $cmd eq 'mark-yank-urls:activate_mark_mode';
144 sub on_key_press {
145 my ($term, $event, $keysym, $octets) = @_;
147 $mod{control} = ($keysym == 65507);
148 $mod{shift} = ($keysym == 65505);
150 # Ignore all input when we are active.
151 $mark_mode_active && return 1;
156 sub on_key_release {
157 my ($term, $event, $keysym, $octets) = @_;
159 if ($mark_mode_active) {
160 my $ch = chr($keysym);
162 if ($keysym == 65307) { # <esc>
163 deactivate_mark_mode ($term);
164 return 1;
166 } elsif ($keysym == 65293) { # <enter>
167 my $url = get_active_url($term);
168 $term->exec_async($term->{browser}, $url);
169 deactivate_mark_mode ($term);
170 return 1;
172 } elsif ($keysym == 65507) { # <control>
173 $mod{control} = 0;
174 return 1;
176 } elsif ($keysym == 65505) { # <shift>
177 $mod{shift} = 0;
178 return 1;
180 } elsif ($mod{control} && (($ch eq 'n') || ($ch eq 'p'))) {
181 # ^n and ^p to cycle list
182 my $dir = ($ch eq 'n') ? 1 : -1;
183 move_highlight ($term, $dir);
185 } elsif ($ch eq 'y') { # y
186 do_copy ($term);
187 deactivate_mark_mode ($term);
188 return 1;
192 return 1;
198 sub get_active_url {
199 my ($term) = @_;
200 my $max = $#url_db + 1;
202 return if $url_selected < 0 || $url_selected >= $max;
203 return if not defined $url_db[$url_selected];
204 my $o = $url_db[$url_selected];
205 my %h = %$o;
207 return $h{url};
210 sub do_copy {
211 my ($term) = @_;
213 my $text = get_active_url ($term);
215 if ($term->{have_Clipboard}) {
216 Clipboard->copy($text);
217 } else {
218 $text =~ s/\(["|><&()]\)/\\$1/;
219 system ("echo -n \"$text\" | xclip -i");
223 sub move_highlight {
224 my ($term, $dir) = @_;
225 my $max = $#url_db + 1;
227 do_highlight ($term, 0);
229 $url_selected = ($max + $url_selected + $dir) % $max;
231 do_highlight ($term, 1);
233 $term->want_refresh;
236 sub do_highlight {
237 my ($term, $enable) = @_;
238 my $max = $#url_db + 1;
240 return if $url_selected < 0 || $url_selected >= $max;
241 return if not defined $url_db[$url_selected];
243 my $o = $url_db[$url_selected];
244 my %h = %$o;
246 my $row = $h{row};
247 my $line = $term->line ($row);
248 my $text = $line->t;
249 my $rend = $line->r;
251 if ($enable) {
252 $_ |= urxvt::RS_RVid
253 for @{$rend}[ $h{col_from} .. $h{col_to}];
255 # make it visible
256 $term->view_start ( $row < 0 ? $row : 0 );
258 } else {
259 $_ &= ~urxvt::RS_RVid
260 for @{$rend}[ $h{col_from} .. $h{col_to}];
263 $line->r ($rend);
266 sub activate_mark_mode {
267 my ($term) = @_;
269 if ($mark_mode_active) {
271 move_highlight ($term, -1);
273 } elsif ( do_scan_for_urls ($term) ) {
275 $term->{save_view_start} = $term->view_start;
277 move_highlight ($term, 0);
279 $mark_mode_active=1 if ($url_selected > -1);
283 sub deactivate_mark_mode {
284 my ($term) = @_;
286 do_highlight ($term, 0);
288 $mark_mode_active = 0;
289 $url_selected = -1;
291 $term->view_start ($term->{save_view_start});
292 $term->want_refresh;
295 # vim: set et ts=4 sw=4: