From e1ea08a1fbb2799e7a96466b93e80a3baf454a17 Mon Sep 17 00:00:00 2001 From: Bert Date: Sun, 12 Sep 2010 20:45:54 +0200 Subject: [PATCH] keyboard-select: [/?nN] mappings --- keyboard-select | 155 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 121 insertions(+), 34 deletions(-) diff --git a/keyboard-select b/keyboard-select index 6ddcc6f..d7ab826 100644 --- a/keyboard-select +++ b/keyboard-select @@ -1,7 +1,7 @@ #! perl -w # Author: Bert Muennich # Website: http://www.github.com/muennich/urxvt-perls -# Version: 1.2 +# Version: git-20100912 # License: GPLv2 # Use keyboard shortcuts to select and copy text. @@ -37,9 +37,11 @@ sub on_start{ sub on_user_command { my ($self, $cmd) = @_; - if ($cmd eq 'keyboard-select:activate') { - if (not $self->{active}) { + if (not $self->{active}) { + if ($cmd eq 'keyboard-select:activate') { activate($self); + } elsif ($cmd eq 'keyboard-select:search') { + activate($self, 1); } } @@ -51,7 +53,28 @@ sub key_press { my ($self, $event, $keysym, $char) = @_; my $key = chr($keysym); - if ($self->{move_to}) { + if ($self->{search}) { + if ($keysym == 0xff1b) { + $self->{search} = ''; + status_area($self); + } elsif ($keysym == 0xff08) { + $self->{search} = substr($self->{search}, 0, -1); + status_area($self); + } elsif ($keysym == 0xff0d) { + my $txt = substr($self->{search}, 1); + if ($txt) { + $self->{pattern} = ($txt =~ m/[[:upper:]]/) ? qr/\Q$txt\E/ : + qr/\Q$txt\E/i; + } else { + delete $self->{pattern} if $self->{pattern}; + } + $self->{search} = ''; + find_next($self); + } elsif (length($char) > 0) { + $self->{search} .= $self->locale_decode($char); + status_area($self); + } + } elsif ($self->{move_to}) { if ($keysym == 0xff1b) { $self->{move_to} = 0; status_area($self); @@ -62,10 +85,7 @@ sub key_press { move_to($self, ';'); status_area($self); } - return 1; - } - - if ($keysym == 0xff1b || lc($key) eq 'q') { + } elsif ($keysym == 0xff1b || lc($key) eq 'q') { deactivate($self); } elsif ($key eq 'y' || $keysym == 0xff0d) { if ($self->{select}) { @@ -116,6 +136,12 @@ sub key_press { status_area($self, $key); } elsif (';,wWbB' =~ m/\Q$key\E/) { move_to($self, $key); + } elsif ($key eq '/' || $key eq '?') { + $self->{search} = $key; + $self->{search_dir} = $key eq '?' ? -1 : 1; + status_area($self); + } elsif (lc($key) eq 'n') { + find_next($self, $self->{search_dir} * ($key eq 'N' ? -1 : 1)); } return 1; @@ -175,15 +201,7 @@ sub move_cursor { $line = $self->line($cr); $self->{offset} = $line->l - 1 if $self->{dollar} or $self->{offset} >= $line->l; - ($cr, $cc) = $line->coord_of($self->{offset}); - $self->screen_cur($cr, $cc); - - # scroll the current cursor position into visible area - if ($cr < $self->view_start()) { - $self->view_start($cr); - } elsif ($cr >= $self->view_start() + $self->nrow) { - $self->view_start($cr - $self->nrow + 1); - } + $self->screen_cur($line->coord_of($self->{offset})); status_area($self); $self->want_refresh(); @@ -252,6 +270,56 @@ sub move_to { } +sub find_next { + my ($self, $dir) = @_; + + return if not $self->{pattern}; + $dir = $self->{search_dir} if not $dir; + + my ($cr, $cc) = $self->screen_cur(); + my $line = $self->line($cr); + my $offset = $line->offset_of($cr, $cc); + my $text; + my $found = 0; + + ++$offset if $dir > 0; + + while (not $found) { + if ($dir > 0) { + $text = substr($line->t, $offset); + if ($text =~ m/$self->{pattern}/) { + $found = 1; + $offset += $-[0]; + } else { + last if $line->end >= $self->nrow; + $line = $self->line($line->end + 1); + $offset = 0; + } + } else { + $text = substr($line->t, 0, $offset); + if ($text =~ m/$self->{pattern}/) { + $found = 1; + $offset = $-[0] while $text =~ m/$self->{pattern}/g; + } else { + last if $line->beg <= $self->top_row; + $line = $self->line($line->beg - 1); + $offset = $line->l; + } + } + } + + if ($found) { + $self->{dollar} = 0; + $self->{offset} = $offset; + $self->screen_cur($line->coord_of($offset)); + status_area($self); + $self->want_refresh(); + } + + () +} + + sub tt_write { return 1; } @@ -292,19 +360,33 @@ sub refresh { } } + # scroll the current cursor position into visible area + if ($cr < $self->view_start()) { + $self->view_start($cr); + } elsif ($cr >= $self->view_start() + $self->nrow) { + $self->view_start($cr - $self->nrow + 1); + } + () } sub activate { - my ($self) = @_; + my ($self, $search) = @_; $self->{active} = 1; - $self->{select} = ""; + $self->{select} = ''; $self->{dollar} = 0; $self->{move_to} = 0; + if ($search) { + $self->{search} = '?'; + $self->{search_dir} = -1; + } else { + $self->{search} = ''; + } + ($self->{oldcr}, $self->{oldcc}) = $self->screen_cur(); $self->{old_view_start} = $self->view_start(); $self->{old_pty_ev_events} = $self->pty_ev_events(urxvt::EV_NONE); @@ -361,23 +443,28 @@ sub status_area { my ($self, $extra) = @_; my ($stat, $stat_len); - if ($self->{select}) { - $stat = "-V" . ($self->{select} ne 'n' ? uc($self->{select}) : "") . "- "; - } - - if ($self->top_row == 0) { - $stat .= "All"; - } elsif ($self->view_start() == $self->top_row) { - $stat .= "Top"; - } elsif ($self->view_start() == 0) { - $stat .= "Bot"; + if ($self->{search}) { + $stat_len = $self->ncol; + $stat = $self->{search} . ' ' x ($stat_len - length($self->{search})); } else { - $stat .= sprintf("%2d%%", - ($self->top_row - $self->view_start) * 100 / $self->top_row); + if ($self->{select}) { + $stat = "-V" . ($self->{select} ne 'n' ? uc($self->{select}) : "") . "- "; + } + + if ($self->top_row == 0) { + $stat .= "All"; + } elsif ($self->view_start() == $self->top_row) { + $stat .= "Top"; + } elsif ($self->view_start() == 0) { + $stat .= "Bot"; + } else { + $stat .= sprintf("%2d%%", + ($self->top_row - $self->view_start) * 100 / $self->top_row); + } + + $stat = "$extra $stat" if $extra; + $stat_len = length($stat); } - - $stat = "$extra $stat" if $extra; - $stat_len = length($stat); if (!$self->{overlay} || $self->{overlay_len} != $stat_len) { delete $self->{overlay} if $self->{overlay};