From 6771d56ee4c2f28ca1d50e5f93e447819b61a582 Mon Sep 17 00:00:00 2001 From: Sterling Camden Date: Fri, 10 Sep 2010 20:03:22 -0700 Subject: Initial version. --- README | 65 +++++++++++++++++++++++++++ url-picker | 150 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 215 insertions(+) create mode 100644 README create mode 100644 url-picker diff --git a/README b/README new file mode 100644 index 0000000..97c0a23 --- /dev/null +++ b/README @@ -0,0 +1,65 @@ +NAME url-picker + +SITE http://chipstips.com/?tag=plurlpicker + http://bitbucket.org/sterlingcamden/urlpicker + +AUTHOR Chip Camden + +DATE September, 2010 + +DESCRIPTION + +Perl extension for rxvt-unicode (aka urxvt) to enable quick keyboard +navigation of URLs shown in the terminal window. The design is similar +to the 'follow hints' feature of Vimperator +(http://vimperator.org/vimperator). + +INSTALLATION + +See the man page for urxvtperl(3) for a full discussion of Perl +extensions. Enable this extension using one of the methods documented +there. For instance, you could place the script url-picker in +/usr/local/lib/urxvt/perl, then add the following to .Xdefaults: + +URxvt.perl-ext: default,matcher,url-picker +URxvt.keysym.C-0xff0d: perl:url-picker + +I find that url-picker works well in combination with matcher, but you +can leave out the latter if you don't care for it. The above enables, in +addition to the default behavior, the matcher extension and url-picker. +It directs the key combination of ctrl+enter to call the on_user_command +function of url-picker. + +OPERATION + +If no URLs are visible on the screen, url-picker just pops up an overlay +window that warns "no URLs found on screen". The overlay disappears +after five seconds, but the terminal is immediately operable. + +If the terminal display contains only one URL, that URL is launched to +the browser. The browser is determined by X resources +url-picker.launcher if defined, otherwise URxvt.urlLauncher. If neither +of these are defined, the 'sensible-browser' is used. The URL will be +passed as the first argument. + +If more than one URL is visible in the terminal window, url-picker places +numbered labels over the first characters of each URL on the screen. A +prompt "Follow: " appears at the bottom of the terminal window, at which +you can type only numbers, backspace, enter, or escape (all other input is +ignored). + +Escape exits this mode and removes all overlay windows, without doing +anything. + +Enter launches the URL associated with the number that has been typed, of +that number matches one of the URL labels. Otherwise, nothing happens. + +When typing numbers, if the number typed so far uniquely identifies a +URL, that URL is launched immediately. Otherwise, the labels that do not +match the numbers typed so far will be hidden. + +The backspace key erases the last number typed, if there is one. + +When a URL is launched, all overlay windows are removed and the cursor +position is restored to where it was in the terminal window before +url-picker was invoked. diff --git a/url-picker b/url-picker new file mode 100644 index 0000000..8036a8d --- /dev/null +++ b/url-picker @@ -0,0 +1,150 @@ +#! perl + +# Author: Chip Camden + +my $url = + qr{ + (?:https?://|ftp://|news://|mailto:|file://|\bwww\.) + [a-zA-Z0-9\-\@;\/?:&=%\$_.+!*\x27,~#]* + ( + \([a-zA-Z0-9\-\@;\/?:&=%\$_.+!*\x27,~#]*\)| # Allow a pair of matched parentheses + [a-zA-Z0-9\-\@;\/?:&=%\$_+*~] # exclude some trailing characters (heuristic) + )+ + }x; + +sub on_user_command { + my ($self, $cmd) = @_; + if($cmd =~ s/^url-picker\b//) { + my $labels = {}; + my $hrefs = {}; + my $row = -1; + my $num = 0; + while ($row++ < $self->nrow) { + my $text = $self->line($row)->t; + while ($text =~ /$url/g) + { + my $col = $-[0]; + my $href = $&; + $num++; + my $overlay = $self->overlay($col, $row, $self->strwidth($num), 1, urxvt::OVERLAY_RSTYLE, 0); + $overlay->set(0,0,$num); + $labels->{$num} = $overlay; + $hrefs->{$num} = $href; + } + } + + if ($num < 1) { + my $ermsg = $self->overlay(0,-1,35,1,urxvt::OVERLAY_RSTYLE,0); + $ermsg->set(0,0,"url-picker: no URLs found on screen"); + $self->{ermsg} = $ermsg; + $self->{timer} = urxvt::timer + ->new + ->after (5) + ->cb (sub { + $self->{ermsg} = (); + $self->{timer} = (); + }); + } + else { + my $url_picker = {}; + $url_picker->{prompt} = $self->overlay(0,-1,8,1,urxvt::OVERLAY_RSTYLE, 0); + $url_picker->{prompt}->set(0,0,"Follow:"); + $url_picker->{labels} = $labels; + $url_picker->{hrefs} = $hrefs; + $url_picker->{num} = $num; + $url_picker->{buffer} = ''; + my ($crow,$ccol) = $self->screen_cur; + $url_picker->{crow} = $crow; + $url_picker->{ccol} = $ccol; + $self->{url_picker} = $url_picker; + $self->update($url_picker); + } + } + () +} + +sub on_key_press { + my ($self, $event, $keysym) = @_; + my $p = $self->{url_picker}; + if ($p) { + if ($keysym == 0xff1b) { # escape + $self->screen_cur($p->{crow},$p->{ccol}); + $self->{url_picker} = (); + } elsif ($keysym == 0xff08) { # backspace + if (length($p->{buffer}) > 0) { + $p->{buffer} = substr($p->{buffer},0,-1); + $self->update($p); + } + } elsif (($keysym >= 48) && ($keysym <= 57)) { + $p->{buffer} = $p->{buffer} . ($keysym - 48); + $self->update($p); + } elsif ($keysym == 0xff0d) { # CR + my $num = $p->{buffer}; + my $hrefs = $p->{hrefs}; + if (($num > 0) && ($num <= $p->{num})) { + my $href = $hrefs->{$num}; + $self->launch($href); + } + } + return 1; + } + () +} + +sub update { + my ($self, $p) = @_; + $p->{typing} = $self->overlay(8,-1,length($p->{buffer}),1,urxvt::DEFAULT_RSTYLE,0); + $p->{typing}->set(0,0,$p->{buffer}); + my $ndx = 0; + my $labels = $p->{labels}; + my $hrefs = $p->{hrefs}; + my $len = length($p->{buffer}); + my $size = $p->{num}; + my @matches; + while (++$ndx <= $size) { + my $overlay = $labels->{$ndx}; + if (($len == 0) || (($len <= length($ndx)) && (substr($ndx,0,$len) eq $p->{buffer}))) { + $overlay->show; + unshift @matches,$hrefs->{$ndx}; + } else { + $overlay->hide; + } + } + if (scalar(@matches) == 1) { + $self->launch(@matches[0]); + } else { + $self->screen_cur($self->nrow,8+$len); + } +} + +sub launch { + my ($self, $href) = @_; + my $launcher = $self->{launcher}; + $self->exec_async ($launcher,$href); + my $p = $self->{url_picker}; + $self->screen_cur($p->{crow},$p->{ccol}); + $self->{url_picker} = (); +} + +sub on_key_release { + my ($self, $event, $keysym) = @_; + $self->{url_picker}; +} + +sub my_resource { + my ($self) = @_; + $self->x_resource ("$self->{name}.$_[0]"); +} + +sub on_start { + my ($self) = @_; + + ($self->{name} = __PACKAGE__) =~ s/.*:://; + $self->{name} =~ tr/_/-/; + $self->{launcher} = $self->my_resource("launcher") || + $self->x_resource("urlLauncher") || + "sensible-browser"; + $self->{url_picker} = (); +} + +# vim:set sw=3 sts=3 et: -- cgit v1.2.3