rewritten URL search and capture to support scrolling and applications that change...
[rxvt-unicode-script-mark-and-yank.git] / mark-yank-urls
blob9a1d43d4cb71857da53b02bff7bee050cef1947e
1 #! perl
3 # ----------------------------------------
5 # same url as used in "selection"
6 my $url =
7    qr{(
8       (?:https?://|ftp://|news://|mailto:|file://)[ab-zA-Z0-9\-\@;\/?:&=%\$_.+!*\x27(),~#]+
9       [ab-zA-Z0-9\-\@;\/?:&=%\$_+!*\x27()~]   # exclude some trailing characters (heuristic)
10    )}x;
12 sub on_start {
13    my ($term) = @_;
15    $term->{browser} = $term->x_resource ("urlLauncher") || "x-www-browser";
17    ()
20 sub on_line_update {
21     my ($term, $row) = @_;
23     # fetch the line that has changed
24     my $line = $term->line ($row);
25     my $text = $line->t;
27     # find all urls (if any)
28     while ($text =~ /$url/g) {
29         my $rend = $line->r;
31         # mark all characters as underlined. we _must_ not toggle underline,
32         # as we might get called on an already-marked url.
33         if ($term->x_resource ("underlineURLs") eq "true") {
34             $_ |= urxvt::RS_Uline
35             for @{$rend}[ $-[1] .. $+[1] - 1];
37             $line->r ($rend);
38         }
39     }
41     ()
44 sub on_button_release {
45     my ($term, $event) = @_;
47     my $mask = $term->ModLevel3Mask | $term->ModMetaMask
48     | urxvt::ShiftMask | urxvt::ControlMask;
50     if ($event->{button} == 2 && ($event->{state} & $mask) == 0) {
51         my $row = $event->{row};
52         my $col = $event->{col};
54         my $line = $term->line ($row);
55         my $text = $line->t;
57         while ($text =~ /$url/g) {
58             if ($-[1] <= $col && $+[1] >= $col) {
59                 $term->exec_async ($term->{browser}, $1);
60                 return 1;
61             }
62         }
63     }
65     ()
68 #sub on_scroll_back {
69 #    my ($term, $lines, $saved) = @_;
71 #    if ($lines > $url_selected && $url_selected>0) {
72 #        move_highlight ($term, 1);
73 #    }
75 #    for (my $n=0; $n<$lines; $n++) {
76 #        shift @url_db 
77 #    }
79 #    ()
82 # ----------------------------------------
84 my $mark_mode_active = 0;
85 my %mod = ( 'control' => 0, 'shift' => 0 );
86 my $url_selected = -1;
87 my @url_db = ();
89 # ----------------------------------------
91 sub do_scan_for_urls {
92     my ($term) = @_;
94     @url_db = ();
96     my $row_start = $term->top_row;
97     my $row_end = $term->nrow;
99     for (my $row=$row_start; $row<=$row_end; $row++) {
101         # fetch the line that has changed
102         my $line = $term->line ($row);
103         my $text = $line->t;
105         # find all urls (if any)
106         while ($text =~ /$url/g) {
107             my $rend = $line->r;
109             my %h = ( 'row'      => $row,
110                       'col_from' => $-[1], 
111                       'col_to'   => $+[1] - 1,
112                       'text'     => $text);
113             push @url_db, \%h;
114         }
115     }
117     # 0 for none, positive count otherwise
118     return $#url_db + 1;
121 sub on_user_command {
122     my ($term, $cmd) = @_;
124     $cmd eq "mark-yank-urls:activate_mark_mode"
125         and activate_mark_mode($term);
127     ()
130 sub on_key_press {
131     my ($term, $event, $keysym, $octets) = @_;
133     ($keysym == 65507) && { $mod{control} = 1 };
134     ($keysym == 65505) && { $mod{shift} = 1 };
136     # ignore all input when we are active
137     $mark_mode_active && return 1;
139     ()
142 sub on_key_release {
143     my ($term, $event, $keysym, $octets) = @_;
145     if ($mark_mode_active) {
146         my $ch = chr($keysym);
148         if ($keysym == 65307) {                     # <esc>
149             $mark_mode_active = 0;
150             do_highlight ($term, 0);
151             $term->want_refresh;
152             $url_selected = -1;
153             return 1;
155         } elsif ($keysym == 65293) {                # <enter>
156             do_copy ($term);
157             $mark_mode_active = 0;
158             do_highlight ($term, 0);
159             $term->want_refresh;
160             $url_selected = -1;
161             $term->exec_async ($term->{browser} . ' `xclip -o`');
162             return 1;
164         } elsif ($keysym == 65507) {                # <control>
165             $mod{control} = 0;
166             return 1;
168         } elsif ($keysym == 65505) {                # <shift>
169             $mod{shift} = 0;
170             return 1;
172         } elsif ($mod{control} && (($ch eq 'n') || ($ch eq 'p'))) {
173                                                     # ^n and ^p to cycle list
174             my $dir = ($ch eq 'n') ? 1 : -1;
175             move_highlight ($term, $dir);
177         } elsif ($ch eq 'y') {
178             do_copy ($term);
179             $mark_mode_active = 0;
180             do_highlight ($term, 0);
181             $term->want_refresh;
182             $url_selected = -1;
183             return 1;
185         }
187         return 1;
188     }
190     ()
193 sub do_copy {
194     my ($term) = @_;
195     my $max = $#url_db + 1;
197     return if $url_selected < 0 || $url_selected >= $max;
198     return if not defined $url_db[$url_selected];
199     my $o = $url_db[$url_selected];
200     my %h = %$o;
202     my $line = $term->line ($url_selected);
203     my $text = substr($line->t, $h{col_from}, $h{col_to} - $h{col_from} + 1);
205     $text =~ s/\(["|><&()]\)/\\$1/;
206     system ("echo -n \"$text\" | xclip -i");
209 sub move_highlight {
210     my ($term, $dir) = @_;
211     my $max = $#url_db + 1;
213     do_highlight ($term, 0);
214     
215     $url_selected = ($max + $url_selected + $dir) % $max;
216         
217     do_highlight ($term, 1);
219     $term->want_refresh;
222 sub do_highlight {
223     my ($term, $enable) = @_;
224     my $max = $#url_db + 1;
226     return if $url_selected < 0 || $url_selected >= $max;
227     return if not defined $url_db[$url_selected];
229     my $o = $url_db[$url_selected];
230     my %h = %$o;
232     my $row = $h{row};
233     my $line = $term->line ($row);
234     my $text = $line->t;
235     my $rend = $line->r;
237     if ($enable) {
238         $_ |= urxvt::RS_RVid
239         for @{$rend}[ $h{col_from} .. $h{col_to}];
241         # make it visible
242         $term->view_start ( $row < 0 ? $row : 0 );
244     } else {
245         $_ &= ~urxvt::RS_RVid
246         for @{$rend}[ $h{col_from} .. $h{col_to}];
247     }
249     $line->r ($rend);
252 sub activate_mark_mode {
253     my ($term, $cmd) = @_;
255     if ($mark_mode_active) {
256         move_highlight ($term, -1);
258     } elsif ( do_scan_for_urls ($term) ) {
259         move_highlight ($term, 0);
260         $mark_mode_active=1 if ($url_selected > -1)
262     }
265 # vim: set et ts=4 sw=4: