From 3d4c3d33652cf0eb73cef301598ac6fd10a02b5a Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 2 Jun 2021 11:11:04 +0200 Subject: Rename the extension to reselect. url-picker is no longer appropriate as other patterns beside URLs will be supported. --- reselect | 234 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ url-picker | 234 ------------------------------------------------------------- 2 files changed, 234 insertions(+), 234 deletions(-) create mode 100644 reselect delete mode 100644 url-picker diff --git a/reselect b/reselect new file mode 100644 index 0000000..ba14191 --- /dev/null +++ b/reselect @@ -0,0 +1,234 @@ +#! perl + +# Author: Chip Camden + +my $re_url = + qr{ + (?:https?://|ftp://|news://|mailto:|file://|\bwww\.) + [\w\-\@;\/?:&=%\$.+!*\x27,~#]* + ( + \([\w\-\@;\/?:&=%\$.+!*\x27,~#]*\)| # Allow a pair of matched parentheses + [\w\-\@;\/?:&=%\$+*~] # exclude some trailing characters (heuristic) + )+ + }x; + +sub find_matches { + my ($text, $rowmap) = @_; + + my @overlays; + while ($text =~ /$re_url/g) { + my $ndx = $-[0]; + my $href = $&; + my $col = 0; + my $row = 0; + + for my $key (keys %$rowmap) { + my $value = $rowmap->{$key}; + my ($start, $end) = @$value; + if (($start <= $ndx) && ($end >= $ndx)) { + $row = $key; + $col = $ndx - $start; + last; + } + } + my @ov = ($col, $row, $href); + push(@overlays, \@ov) if ($row >= 0); + } + + return @overlays; +} + +sub build_overlays { + my ($self, $text, $rowmap) = @_; + + my $label_rend = $self->get_rend("label", urxvt::OVERLAY_RSTYLE); + my $num = 0; + my $labels = {}; + my $hrefs = {}; + + my @overlays = find_matches($text, $rowmap); + @overlays = reverse @overlays if ($self->{descending}); + + for my $ov (@overlays) { + my ($col, $row, $href) = @$ov; + $num++; + my $overlay = $self->overlay($col, $row, $self->strwidth($num), + 1, $label_rend, 0); + $overlay->set(0, 0, $num); + + $labels->{$num} = $overlay; + $hrefs->{$num} = $href; + } + + return ($num, $labels, $hrefs) +}; + +sub on_user_command { + my ($self, $cmd) = @_; + if ($cmd =~ s/^reselect\b//) { + my $rowmap = {}; + my $row = 0; + my $base_col = 0; + my $text = ''; + + my ($brow, $bcol) = $self->selection_beg(); + my ($erow, $ecol) = $self->selection_end(); + my $issel = ($ecol > $bcol) || ($erow > $brow); + if ($issel) { # restrict to selection if one exists + ($row, $base_col) = ($brow - $self->view_start, $bcol); + for (split(/\n/, $self->selection())) { + my $start = length($text) - $base_col; + $text .= $_; + $rowmap->{$row} = [$start, (length($text)-1)]; + $base_col = 0; + $row++; + } + } else { # no selection, use visible terminal + for (0..($self->nrow - 1)) { + $row = $_; + my $start = length($text); + $text .= $self->ROW_t($row + $self->view_start); + $rowmap->{$row} = [$start, (length($text)-1)]; + } + } + + my ($num, $labels, $hrefs) = $self->build_overlays($text, $rowmap); + + if ($num < 1) { + my $desc = $issel ? "in visible selected text" : "on visible screen"; + $self->status_msg("url-picker: no URLs found $desc"); + } else { + my $url_picker = {}; + $url_picker->{prompt} = $self->overlay( + 0, -1, 8, 1, $self->get_rend("prompt", 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) = @_; + if ($self->{url_picker_msg}) { + $self->{url_picker_msg} = (); + } + my $p = $self->{url_picker}; + if ($p) { + if ($keysym == 0xff1b || $keysym == 113) { # escape or q + $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, $self->get_rend("input", 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; + } + } + # Auto-launch a single url only if the launchsingle resource is true + # (default), or if some digits were input + if (scalar(@matches) == 1 && ($self->{launchsingle} || $len > 0)) { + $self->launch(@matches[0]); + } else { + $self->screen_cur($self->nrow,8+$len); + } +} + +sub launch { + my ($self, $href) = @_; + my $p = $self->{url_picker}; + $self->screen_cur($p->{crow},$p->{ccol}); + $self->{url_picker} = (); + my $launcher = $self->{launcher}; + $self->status_msg($href); + $self->exec_async ($launcher,$href); +} + +sub status_msg { + my ($self, $msg) = @_; + $self->{url_picker_msg} = $self->overlay(0, -1, length($msg), 1, + $self->get_rend("status",urxvt::OVERLAY_RSTYLE), 0); + $self->{url_picker_msg}->set(0,0,$msg); + $self->{url_picker_timer} = urxvt::timer + ->new + ->after (5) + ->cb (sub { + $self->{url_picker_msg} = (); + $self->{url_pickertimer} = (); + }); +} + +sub get_rend { + my ($self, $name, $default) = @_; + urxvt::SET_COLOR $default, + $self->my_resource("$name.foregroundColor") || urxvt::GET_BASEFG $default, + $self->my_resource("$name.backgroundColor") || urxvt::GET_BASEBG $default; +} + +sub on_key_release { + my ($self, $event, $keysym) = @_; + $self->{url_picker}; +} + +sub my_resource { + my ($self, $name) = @_; + $self->x_resource ("$self->{name}.$name"); +} + +sub on_start { + my ($self) = @_; + + ($self->{name} = __PACKAGE__) =~ s/.*:://; + $self->{name} =~ tr/_/-/; + $self->{launcher} = $self->my_resource("launcher") || + $self->x_resource("url-launcher") || + "sensible-browser"; + $self->{launchsingle} = ($self->my_resource("launchsingle") ne "false"); + $self->{descending} = ($self->my_resource("order") eq "descending"); + $self->{url_picker} = (); +} diff --git a/url-picker b/url-picker deleted file mode 100644 index cce6d69..0000000 --- a/url-picker +++ /dev/null @@ -1,234 +0,0 @@ -#! perl - -# Author: Chip Camden - -my $re_url = - qr{ - (?:https?://|ftp://|news://|mailto:|file://|\bwww\.) - [\w\-\@;\/?:&=%\$.+!*\x27,~#]* - ( - \([\w\-\@;\/?:&=%\$.+!*\x27,~#]*\)| # Allow a pair of matched parentheses - [\w\-\@;\/?:&=%\$+*~] # exclude some trailing characters (heuristic) - )+ - }x; - -sub find_matches { - my ($text, $rowmap) = @_; - - my @overlays; - while ($text =~ /$re_url/g) { - my $ndx = $-[0]; - my $href = $&; - my $col = 0; - my $row = 0; - - for my $key (keys %$rowmap) { - my $value = $rowmap->{$key}; - my ($start, $end) = @$value; - if (($start <= $ndx) && ($end >= $ndx)) { - $row = $key; - $col = $ndx - $start; - last; - } - } - my @ov = ($col, $row, $href); - push(@overlays, \@ov) if ($row >= 0); - } - - return @overlays; -} - -sub build_overlays { - my ($self, $text, $rowmap) = @_; - - my $label_rend = $self->get_rend("label", urxvt::OVERLAY_RSTYLE); - my $num = 0; - my $labels = {}; - my $hrefs = {}; - - my @overlays = find_matches($text, $rowmap); - @overlays = reverse @overlays if ($self->{descending}); - - for my $ov (@overlays) { - my ($col, $row, $href) = @$ov; - $num++; - my $overlay = $self->overlay($col, $row, $self->strwidth($num), - 1, $label_rend, 0); - $overlay->set(0, 0, $num); - - $labels->{$num} = $overlay; - $hrefs->{$num} = $href; - } - - return ($num, $labels, $hrefs) -}; - -sub on_user_command { - my ($self, $cmd) = @_; - if ($cmd =~ s/^url-picker\b//) { - my $rowmap = {}; - my $row = 0; - my $base_col = 0; - my $text = ''; - - my ($brow, $bcol) = $self->selection_beg(); - my ($erow, $ecol) = $self->selection_end(); - my $issel = ($ecol > $bcol) || ($erow > $brow); - if ($issel) { # restrict to selection if one exists - ($row, $base_col) = ($brow - $self->view_start, $bcol); - for (split(/\n/, $self->selection())) { - my $start = length($text) - $base_col; - $text .= $_; - $rowmap->{$row} = [$start, (length($text)-1)]; - $base_col = 0; - $row++; - } - } else { # no selection, use visible terminal - for (0..($self->nrow - 1)) { - $row = $_; - my $start = length($text); - $text .= $self->ROW_t($row + $self->view_start); - $rowmap->{$row} = [$start, (length($text)-1)]; - } - } - - my ($num, $labels, $hrefs) = $self->build_overlays($text, $rowmap); - - if ($num < 1) { - my $desc = $issel ? "in visible selected text" : "on visible screen"; - $self->status_msg("url-picker: no URLs found $desc"); - } else { - my $url_picker = {}; - $url_picker->{prompt} = $self->overlay( - 0, -1, 8, 1, $self->get_rend("prompt", 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) = @_; - if ($self->{url_picker_msg}) { - $self->{url_picker_msg} = (); - } - my $p = $self->{url_picker}; - if ($p) { - if ($keysym == 0xff1b || $keysym == 113) { # escape or q - $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, $self->get_rend("input", 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; - } - } - # Auto-launch a single url only if the launchsingle resource is true - # (default), or if some digits were input - if (scalar(@matches) == 1 && ($self->{launchsingle} || $len > 0)) { - $self->launch(@matches[0]); - } else { - $self->screen_cur($self->nrow,8+$len); - } -} - -sub launch { - my ($self, $href) = @_; - my $p = $self->{url_picker}; - $self->screen_cur($p->{crow},$p->{ccol}); - $self->{url_picker} = (); - my $launcher = $self->{launcher}; - $self->status_msg($href); - $self->exec_async ($launcher,$href); -} - -sub status_msg { - my ($self, $msg) = @_; - $self->{url_picker_msg} = $self->overlay(0, -1, length($msg), 1, - $self->get_rend("status",urxvt::OVERLAY_RSTYLE), 0); - $self->{url_picker_msg}->set(0,0,$msg); - $self->{url_picker_timer} = urxvt::timer - ->new - ->after (5) - ->cb (sub { - $self->{url_picker_msg} = (); - $self->{url_pickertimer} = (); - }); -} - -sub get_rend { - my ($self, $name, $default) = @_; - urxvt::SET_COLOR $default, - $self->my_resource("$name.foregroundColor") || urxvt::GET_BASEFG $default, - $self->my_resource("$name.backgroundColor") || urxvt::GET_BASEBG $default; -} - -sub on_key_release { - my ($self, $event, $keysym) = @_; - $self->{url_picker}; -} - -sub my_resource { - my ($self, $name) = @_; - $self->x_resource ("$self->{name}.$name"); -} - -sub on_start { - my ($self) = @_; - - ($self->{name} = __PACKAGE__) =~ s/.*:://; - $self->{name} =~ tr/_/-/; - $self->{launcher} = $self->my_resource("launcher") || - $self->x_resource("url-launcher") || - "sensible-browser"; - $self->{launchsingle} = ($self->my_resource("launchsingle") ne "false"); - $self->{descending} = ($self->my_resource("order") eq "descending"); - $self->{url_picker} = (); -} -- cgit v1.2.3