dave0's font-size
[rxvt-unicode-script-mark-and-yank.git] / mark-yank-urls
blob831f95efe3b88508ef7ea7946875a8b7d8d5e581
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 $url = $1;
46 my $rend = $line->r;
48 # Mark all characters as underlined. we _must_ not toggle underline, as
49 # we might get called on an already-marked URL.
50 my $underlineURLs = $term->x_resource ('underlineURLs') || 'false';
51 if($underlineURLs eq 'true') {
52 my ($first, $last) = ($-[1], $+[1] - 1);
54 --$last if $url =~ s/["']$//;
56 $_ |= urxvt::RS_Uline for @{$rend}[$first .. $last];
58 $line->r($rend);
65 sub on_button_release {
66 my ($term, $event) = @_;
68 my $mask = $term->ModLevel3Mask | $term->ModMetaMask
69 | urxvt::ShiftMask | urxvt::ControlMask;
71 if ($event->{button} == 2 && ($event->{state} & $mask) == 0) {
72 my $row = $event->{row};
73 my $col = $event->{col};
75 my $line = $term->line ($row);
76 my $text = $line->t;
78 while ($text =~ /($url_matcher)/g) {
79 my ($url, $first, $last) = ($1, $-[1], $+[1]);
81 if($first <= $col && $last >= $col) {
82 $url =~ s/["']$//;
83 $term->exec_async($term->{browser}, $url);
84 return 1;
93 my $mark_mode_active = 0;
94 my %mod = ( 'control' => 0, 'shift' => 0 );
95 my $url_selected = -1;
96 my @url_db = ();
99 sub do_scan_for_urls {
100 my ($term) = @_;
102 @url_db = ();
104 my $row_start = $term->top_row;
105 my $row_end = $term->nrow;
107 for my $row ($row_start .. $row_end) {
109 # Fetch the line that has changed.
110 my $line = $term->line ($row);
111 my $text = $line->t;
113 # Find all urls (if any).
114 while ($text =~ /($url_matcher)/g) {
115 my $rend = $line->r;
117 my ($url, $first, $last) = ($1, $-[1], $+[1] - 1);
119 --$last if $url =~ s/["']$//;
121 my %h = (
122 row => $row,
123 col_from => $first,
124 col_to => $last,
125 url => $url,
128 push @url_db, \%h;
132 # 0 for none, positive count otherwise
133 return $#url_db + 1;
137 sub on_user_command {
138 my ($term, $cmd) = @_;
140 activate_mark_mode($term) if $cmd eq 'mark-yank-urls:activate_mark_mode';
145 sub on_key_press {
146 my ($term, $event, $keysym, $octets) = @_;
148 if ($keysym == 65507) { # <control>
149 $mod{control} = 1;
151 } elsif ($keysym == 65505) { # <shift>
152 $mod{shift} = 1;
156 # Ignore all input when we are active.
157 $mark_mode_active && return 1;
162 sub on_key_release {
163 my ($term, $event, $keysym, $octets) = @_;
165 if ($mark_mode_active) {
166 my $ch = chr($keysym);
168 if ($keysym == 65307) { # <esc>
169 deactivate_mark_mode ($term);
170 return 1;
172 } elsif ($keysym == 65293) { # <enter>
173 my $url = get_active_url($term);
174 $term->exec_async($term->{browser}, $url);
175 deactivate_mark_mode ($term);
176 return 1;
178 } elsif ($keysym == 65507) { # <control>
179 $mod{control} = 0;
180 return 1;
182 } elsif ($keysym == 65505) { # <shift>
183 $mod{shift} = 0;
184 return 1;
186 } elsif ($mod{control} && (($ch eq 'n') || ($ch eq 'p'))) {
187 # ^n and ^p to cycle list
188 my $dir = ($ch eq 'n') ? 1 : -1;
189 move_highlight ($term, $dir);
191 } elsif ($ch eq 'y') { # y
192 do_copy ($term);
193 deactivate_mark_mode ($term);
194 return 1;
198 return 1;
204 sub get_active_url {
205 my ($term) = @_;
206 my $max = $#url_db + 1;
208 return if $url_selected < 0 || $url_selected >= $max;
209 return if not defined $url_db[$url_selected];
210 my $o = $url_db[$url_selected];
211 my %h = %$o;
213 return $h{url};
216 sub do_copy {
217 my ($term) = @_;
219 my $text = get_active_url ($term);
221 if ($term->{have_Clipboard}) {
222 Clipboard->copy($text);
223 } else {
224 $text =~ s/\(["|><&()]\)/\\$1/;
225 system ("echo -n \"$text\" | xclip -i");
229 sub move_highlight {
230 my ($term, $dir) = @_;
231 my $max = $#url_db + 1;
233 do_highlight ($term, 0);
235 $url_selected = ($max + $url_selected + $dir) % $max;
237 do_highlight ($term, 1);
239 $term->want_refresh;
242 sub do_highlight {
243 my ($term, $enable) = @_;
244 my $max = $#url_db + 1;
246 return if $url_selected < 0 || $url_selected >= $max;
247 return if not defined $url_db[$url_selected];
249 my $o = $url_db[$url_selected];
250 my %h = %$o;
252 my $row = $h{row};
253 my $line = $term->line ($row);
254 my $text = $line->t;
255 my $rend = $line->r;
257 if ($enable) {
258 $_ |= urxvt::RS_RVid
259 for @{$rend}[ $h{col_from} .. $h{col_to}];
261 # make it visible
262 $term->view_start ( $row < 0 ? $row : 0 );
264 } else {
265 $_ &= ~urxvt::RS_RVid
266 for @{$rend}[ $h{col_from} .. $h{col_to}];
269 $line->r ($rend);
272 sub activate_mark_mode {
273 my ($term) = @_;
275 if ($mark_mode_active) {
277 move_highlight ($term, -1);
279 } elsif ( do_scan_for_urls ($term) ) {
281 $term->{save_view_start} = $term->view_start;
283 move_highlight ($term, 0);
285 $mark_mode_active=1 if ($url_selected > -1);
289 sub deactivate_mark_mode {
290 my ($term) = @_;
292 do_highlight ($term, 0);
294 $mark_mode_active = 0;
295 $url_selected = -1;
297 $term->view_start ($term->{save_view_start});
298 $term->want_refresh;
301 # vim: set et ts=4 sw=4: