]> git.mjollnir.org Git - dotfiles/urxvt.git/commitdiff
put mark-yan-urls into its own script master
authorPenny Leach <penny@mjollnir.org>
Mon, 29 Mar 2010 13:50:24 +0000 (15:50 +0200)
committerPenny Leach <penny@mjollnir.org>
Mon, 29 Mar 2010 13:50:24 +0000 (15:50 +0200)
.urxvt [deleted file]
.urxvt/mark-yank-urls [new file with mode: 0755]

diff --git a/.urxvt b/.urxvt
deleted file mode 100644 (file)
index 92b5bef..0000000
--- a/.urxvt
+++ /dev/null
@@ -1 +0,0 @@
-mark-yank-urls
diff --git a/.urxvt/mark-yank-urls b/.urxvt/mark-yank-urls
new file mode 100755 (executable)
index 0000000..831f95e
--- /dev/null
@@ -0,0 +1,301 @@
+#!/usr/bin/perl
+# Author:  Bart Trojanowski <bart@jukie.net>
+# Website: http://www.jukie.net/~bart/blog/urxvt-url-yank
+# License: GPLv2
+
+use strict;
+use warnings;
+
+my $url_matcher = qr{(
+        (?:https?://|ftp://|news://|mailto:|file://|www\.)[ab-zA-Z0-9\-\@;\/?:&=%\$_.+!*\x27(),~#]+
+        [ab-zA-Z0-9\-\@;\/?&=%\$_+!*\x27()~]   # exclude some trailing characters (heuristic)
+)}x;
+
+
+sub on_start {
+    my ($term) = @_;
+
+    $term->{have_Clipboard} = eval { require Clipboard; };
+    if ($term->{have_Clipboard}) {
+        import Clipboard;
+    }
+
+       eval { require Regexp::Common::URI };
+       if(!$@) {
+               require Regexp::Common;
+               Regexp::Common->import('URI');
+
+               $url_matcher = $Regexp::Common::RE{URI}{HTTP};
+       }
+
+    $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 and underline URLs.
+    while ($text =~ /($url_matcher)/g) {
+        my $url = $1;
+        my $rend = $line->r;
+
+        # Mark all characters as underlined. we _must_ not toggle underline, as
+        # we might get called on an already-marked URL.
+        my $underlineURLs = $term->x_resource ('underlineURLs') || 'false';
+        if($underlineURLs eq 'true') {
+                       my ($first, $last) = ($-[1], $+[1] - 1);
+
+                       --$last if $url =~ s/["']$//;
+
+            $_ |= urxvt::RS_Uline for @{$rend}[$first .. $last];
+
+            $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) {
+            my ($url, $first, $last) = ($1, $-[1], $+[1]);
+
+            if($first <= $col && $last >= $col) {
+                $url =~ s/["']$//;
+                $term->exec_async($term->{browser}, $url);
+                return 1;
+            }
+        }
+    }
+
+    ()
+}
+
+
+my $mark_mode_active = 0;
+my %mod = ( 'control' => 0, 'shift' => 0 );
+my $url_selected = -1;
+my @url_db = ();
+
+
+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_end) {
+
+        # 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, $first, $last) = ($1, $-[1], $+[1] - 1);
+
+                       --$last if $url =~ s/["']$//;
+
+            my %h = (
+                               row => $row,
+                               col_from => $first,
+                               col_to => $last,
+                               url => $url,
+                       );
+                               
+                       push @url_db, \%h;
+        }
+    }
+
+    # 0 for none, positive count otherwise
+    return $#url_db + 1;
+}
+
+
+sub on_user_command {
+    my ($term, $cmd) = @_;
+
+       activate_mark_mode($term) if $cmd eq 'mark-yank-urls:activate_mark_mode';
+
+    ()
+}
+
+sub on_key_press {
+    my ($term, $event, $keysym, $octets) = @_;
+
+    if ($keysym == 65507) {                     # <control>
+        $mod{control} = 1;
+
+    } elsif ($keysym == 65505) {                # <shift>
+        $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 ($keysym == 65307) {                     # <esc>
+            deactivate_mark_mode ($term);
+            return 1;
+
+        } elsif ($keysym == 65293) {                # <enter>
+            my $url = get_active_url($term);
+            $term->exec_async($term->{browser}, $url);
+            deactivate_mark_mode ($term);
+            return 1;
+
+        } elsif ($keysym == 65507) {                # <control>
+            $mod{control} = 0;
+            return 1;
+
+        } elsif ($keysym == 65505) {                # <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: set et ts=4 sw=4: