unexist.dev

View .urxvt/mark-yank-urls @ 482:93ac94dc3feb

Updated config
author unexist
date Thu, 29 Nov 2018 09:25:32 +0100
parents 7477775a1bc4
children
line wrap: on
line source
                    
#! perl

# same url as used in "selection"
my $url_matcher =
  qr{(
    (?:https?://|ftp://|news://|mailto:|file://)[ab-zA-Z0-9\-\@;\/?:&=%\$_.+!*\x27(),~#]+
    [ab-zA-Z0-9\-\@;\/?:&=%\$_+!*\x27()~]   # exclude some trailing characters (heuristic)
  )}x;

my $mark_mode_active = 0;
my %mod = ('control' => 0, 'shift' => 0);
my $url_selected = -1;
my @url_db = ();

sub on_start # {{{
{
  my ($term) = @_;

  $term->{have_Clipboard} = eval { require Clipboard; };
  if($term->{have_Clipboard})
    {
      import Clipboard;
    }

  $term->{browser} = $term->x_resource ("urlLauncher") || "x-www-browser";

  ()
} # }}}

sub on_line_update # {{{
{
  my ($term, $row) = @_;

  # fetch the line that has changed
  my $line = $term->line ($row);
  my $text = $line->t;

  # find all urls (if any)
  while ($text =~ /$url_matcher/g)
    {
      my $rend = $line->r;

      # mark all characters as underlined. we _must_ not toggle underline,
      # as we might get called on an already-marked url.
      if($term->x_resource ("underlineURLs") eq "true")
        {
          $_ |= urxvt::RS_Uline
          for @{$rend}[ $-[1] .. $+[1] - 1];

          $line->r ($rend);
       }
    }

  ()
} # }}}

sub on_button_release # {{{
{
  my ($term, $event) = @_;

  my $mask = $term->ModLevel3Mask|$term->ModMetaMask|
    urxvt::ShiftMask|urxvt::ControlMask;

  if($event->{button} == 2 && ($event->{state} & $mask) == 0)
    {
      my $row = $event->{row};
      my $col = $event->{col};

      my $line = $term->line ($row);
      my $text = $line->t;

      while ($text =~ /$url_matcher/g)
        {
          if($-[1] <= $col && $+[1] >= $col)
            {
              # Switch to browser
              $term->exec_async("subtler -cf", $term->{browser});

              if("opera" == $term->{browser})
                {
                  $term->exec_async($term->{browser} . ' -remote openURL(' . $1 . ', new-page)');
                }
              else
                {
                  $term->exec_async($term->{browser}, $1);
                }

              return 1;
            }
        }
    }

   ()
} # }}}

sub do_scan_for_urls # {{{
{
  my ($term) = @_;

  @url_db = ();

  my $row_start = $term->top_row;
  my $row_end = $term->nrow;

  for(my $row=$row_start; $row<=$row_end; $row++)
    {
      # fetch the line that has changed
      my $line = $term->line ($row);
      my $text = $line->t;

      # find all urls (if any)
      while($text =~ /$url_matcher/g)
        {
          my $rend = $line->r;
          my $url = $1;

          my %h = ('row'      => $row,
                   'col_from' => $-[1],
                   'col_to'   => $+[1] - 1,
                   'url'      => $url);
          push @url_db, \%h;
        }
    }

  # 0 for none, positive count otherwise
  return $#url_db + 1;
} # }}}

sub on_user_command # {{{
{
  my($term, $cmd) = @_;

  $cmd eq "mark-yank-urls:activate_mark_mode" and activate_mark_mode($term);

  ()
} # }}}

sub on_key_press # {{{
{
  my($term, $event, $keysym, $octets) = @_;

  ($keysym == 65507) && { $mod{control} = 1 };
  ($keysym == 65505) && { $mod{shift} = 1 };

  # ignore all input when we are active
  $mark_mode_active && return 1;

  ()
} # }}}

sub on_key_release # {{{
{
  my($term, $event, $keysym, $octets) = @_;

  if($mark_mode_active)
    {
     my $ch = chr($keysym);

     if(65307 == $keysym) # <esc>
      {
        deactivate_mark_mode($term);

        return 1;
      }
    elsif(65293 == $keysym) # <enter>
      {
        my $url = get_active_url($term);
        $url =~ s/\(["|><&()]\)/\\$1/;
        $term->exec_async ($term->{browser} . ' ' . $url);
        deactivate_mark_mode ($term);

        return 1;
      }
    elsif(65507 == $keysym) # <control>
      {
        $mod{control} = 0;

        return 1;
      }
    elsif(65505 == $keysym) # <shift>
      {
        $mod{shift} = 0;

        return 1;
      }
    elsif($mod{control} && (($ch eq 'n') || ($ch eq 'p')))
      {
        # ^n and ^p to cycle list
        my $dir = ($ch eq 'n') ? 1 : -1;
        move_highlight ($term, $dir);
      }
    elsif($ch eq 'y') # y
      {
        do_copy ($term);
        deactivate_mark_mode ($term);

        return 1;
      }

    return 1;
  }

  ()
} # }}}

sub get_active_url # {{{
{
  my($term) = @_;
  my $max = $#url_db + 1;

  return if $url_selected < 0 || $url_selected >= $max;
  return if not defined $url_db[$url_selected];

  my $o = $url_db[$url_selected];
  my %h = %$o;

  return $h{url};
} # }}}

sub do_copy # {{{
{
  my($term) = @_;

  my $text = get_active_url ($term);

  if($term->{have_Clipboard})
    {
      Clipboard->copy($text);
    }
  else
    {
      $text =~ s/\(["|><&()]\)/\\$1/;
      system("echo -n \"$text\" | xclip -i");
    }
} # }}}

sub move_highlight # # {{{
{
  my($term, $dir) = @_;
  my $max = $#url_db + 1;

  do_highlight($term, 0);

  $url_selected = ($max + $url_selected + $dir) % $max;

  do_highlight($term, 1);

  $term->want_refresh;
} # }}}

sub do_highlight # {{{
{
  my($term, $enable) = @_;
  my $max = $#url_db + 1;

  return if $url_selected < 0 || $url_selected >= $max;
  return if not defined $url_db[$url_selected];

  my $o = $url_db[$url_selected];
  my %h = %$o;

  my $row = $h{row};
  my $line = $term->line ($row);
  my $text = $line->t;
  my $rend = $line->r;

  if($enable)
    {
      $_ |= urxvt::RS_RVid
      for @{$rend}[ $h{col_from} .. $h{col_to}];

      # make it visible
      $term->view_start ( $row < 0 ? $row : 0 );
    }
  else
    {
      $_ &= ~urxvt::RS_RVid
      for @{$rend}[ $h{col_from} .. $h{col_to}];
    }

  $line->r ($rend);
} # }}}

sub activate_mark_mode # {{{
{
  my($term) = @_;

  if($mark_mode_active)
    {
      move_highlight ($term, -1);
    }
  elsif(do_scan_for_urls ($term))
    {
      $term->{save_view_start} = $term->view_start;

      move_highlight ($term, 0);

      $mark_mode_active=1 if($url_selected > -1);
    }
} # }}}

sub deactivate_mark_mode # {{{
{
  my($term) = @_;

  do_highlight($term, 0);

  $mark_mode_active = 0;
  $url_selected = -1;

  $term->view_start($term->{save_view_start});
  $term->want_refresh;
} # }}}

# vim:ts=2:bs=2:sw=2:et:fdm=marker