ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/perl/searchable-scrollback
(Generate patch)

Comparing rxvt-unicode/src/perl/searchable-scrollback (file contents):
Revision 1.29 by root, Sun Jun 10 17:31:53 2012 UTC vs.
Revision 1.41 by sf-exg, Tue Oct 14 09:00:52 2014 UTC

1#! perl 1#! perl
2 2
3# this extension implements scrollback buffer search 3# this extension implements scrollback buffer search
4 4
5#:META:X_RESOURCE:%:string:activation hotkey keysym 5#:META:RESOURCE:%:string:activation hotkey keysym
6#:META:BINDING:M-s:start
6 7
7=head1 NAME 8=head1 NAME
8 9
9 searchable-scrollback<hotkey> - incremental scrollback search (enabled by default) 10searchable-scrollback - incremental scrollback search (enabled by default)
10 11
11=head1 DESCRIPTION 12=head1 DESCRIPTION
12 13
13Adds regex search functionality to the scrollback buffer, triggered 14Adds regex search functionality to the scrollback buffer, triggered by
14by a hotkey (default: C<M-s>). While in search mode, normal terminal 15the C<searchable-scrollback:start> action (bound to C<M-s> by
16default). While in search mode, normal terminal input/output is
15input/output is suspended and a regex is displayed at the bottom of the 17suspended and a regex is displayed at the bottom of the screen.
16screen.
17 18
18Inputting characters appends them to the regex and continues incremental 19Inputting characters appends them to the regex and continues incremental
19search. C<BackSpace> removes a character from the regex, C<Up> and C<Down> 20search. C<BackSpace> removes a character from the regex, C<Up> and C<Down>
20search upwards/downwards in the scrollback buffer, C<End> jumps to the 21search upwards/downwards in the scrollback buffer, C<End> jumps to the
21bottom. C<Escape> leaves search mode and returns to the point where search 22bottom. C<Escape> leaves search mode and returns to the point where search
32=cut 33=cut
33 34
34sub on_init { 35sub on_init {
35 my ($self) = @_; 36 my ($self) = @_;
36 37
38 # only for backwards compatibility
37 my $hotkey = $self->{argv}[0] 39 my $hotkey = $self->{argv}[0]
38 || $self->x_resource ("%") 40 || $self->x_resource ("%")
39 || "M-s"; 41 || return;
40 42
41 $self->parse_keysym ($hotkey, "perl:searchable-scrollback:start") 43 $self->bind_action ($hotkey, "searchable-scrollback:start") # ugh
42 or warn "unable to register '$hotkey' as scrollback search start hotkey\n"; 44 or warn "unable to register '$hotkey' as scrollback search start hotkey\n";
43 45
44 () 46 ()
45} 47}
46 48
47sub on_user_command { 49sub on_user_command {
48 my ($self, $cmd) = @_; 50 my ($self, $cmd) = @_;
49 51
50 $cmd eq "searchable-scrollback:start" 52 $cmd eq "searchable-scrollback:start"
53 and $self->enter;
54
55 ()
56}
57
58sub on_action {
59 my ($self, $action) = @_;
60
61 $action eq "start"
51 and $self->enter; 62 and $self->enter;
52 63
53 () 64 ()
54} 65}
55 66
89 $self->disable ("key_press", "tt_write", "refresh_begin", "refresh_end"); 100 $self->disable ("key_press", "tt_write", "refresh_begin", "refresh_end");
90 $self->pty_ev_events ($self->{pty_ev_events}); 101 $self->pty_ev_events ($self->{pty_ev_events});
91 102
92 delete $self->{manpage_overlay}; 103 delete $self->{manpage_overlay};
93 delete $self->{overlay}; 104 delete $self->{overlay};
94 delete $self->{history};
95 delete $self->{search}; 105 delete $self->{search};
106 delete $self->{found};
96} 107}
97 108
98sub idle { 109sub idle {
99 my ($self) = @_; 110 my ($self) = @_;
100 111
101 $self->msg ("(escape cancels) /$self->{search}█"); 112 $self->msg ("(escape cancels) /$self->{search}█");
102} 113}
103 114
104sub search { 115sub search {
105 my ($self, $dir) = @_; 116 my ($self, $dir, $row) = @_;
106
107 delete $self->{found};
108 my $row = $self->{row};
109 117
110 my $search = $self->special_encode ($self->{search}); 118 my $search = $self->special_encode ($self->{search});
111 119
112 no re 'eval'; # just to be sure 120 no re 'eval'; # just to be sure
113 if (my $re = eval { qr/$search/ }) { 121 if (my $re = eval { qr/$search/ }) {
115 my $line = $self->line ($row) 123 my $line = $self->line ($row)
116 or last; 124 or last;
117 125
118 my $text = $line->t; 126 my $text = $line->t;
119 if ($text =~ /$re/g) { 127 if ($text =~ /$re/g) {
128 delete $self->{found};
129
120 do { 130 do {
121 push @{ $self->{found} }, [$line->coord_of ($-[0]), $line->coord_of ($+[0])]; 131 push @{ $self->{found} }, [$line->coord_of ($-[0]), $line->coord_of ($+[0])];
122 } while $text =~ /$re/g; 132 } while $text =~ /$re/g;
123 133
124 $self->{row} = $row; 134 $self->{row} = $row;
125 $self->view_start (List::Util::min 0, $row - ($self->nrow >> 1)); 135 $self->view_start (List::Util::min 0, $row - ($self->nrow >> 1));
126 $self->want_refresh; 136 $self->want_refresh;
127 last; 137 return;
128 } 138 }
129 139
130 $row = $dir < 0 ? $line->beg - 1 : $line->end + 1; 140 $row = $dir < 0 ? $line->beg - 1 : $line->end + 1;
131 } 141 }
132 } 142 }
133 143
134 $self->scr_bell unless $self->{found}; 144 $self->scr_bell;
135} 145}
136 146
137sub refresh { 147sub refresh {
138 my ($self) = @_; 148 my ($self) = @_;
139 149
166 $self->leave; 176 $self->leave;
167 } elsif ($keysym == 0xff57) { # end 177 } elsif ($keysym == 0xff57) { # end
168 $self->{row} = $self->nrow - 1; 178 $self->{row} = $self->nrow - 1;
169 $self->view_start (0); 179 $self->view_start (0);
170 } elsif ($keysym == 0xff52) { # up 180 } elsif ($keysym == 0xff52) { # up
171 $self->{row}-- if $self->{row} > $self->top_row; 181 my $line = $self->line ($self->{row});
172 $self->search (-1); 182 $self->search (-1, $line->beg - 1)
183 if $line->beg > $self->top_row;
173 } elsif ($keysym == 0xff54) { # down 184 } elsif ($keysym == 0xff54) { # down
174 $self->{row}++ if $self->{row} < $self->nrow; 185 my $line = $self->line ($self->{row});
175 $self->search (+1); 186 $self->search (+1, $line->end + 1)
187 if $line->end < $self->nrow;
176 } elsif ($keysym == 0xff08) { # backspace 188 } elsif ($keysym == 0xff08) { # backspace
177 substr $self->{search}, -1, 1, ""; 189 substr $self->{search}, -1, 1, "";
178 $self->search; 190 $self->search (+1, $self->{row});
179 $self->idle; 191 $self->idle;
180 } elsif ($string !~ /[\x00-\x1f\x80-\xaf]/) { 192 } elsif ($string !~ /[\x00-\x1f\x80-\xaf]/) {
181 return; # pass to tt_write 193 return; # pass to tt_write
182 } 194 }
183 195
190 $self->{search} .= $self->locale_decode ($data); 202 $self->{search} .= $self->locale_decode ($data);
191 203
192 $self->{search} =~ s/^\(\?i\)// 204 $self->{search} =~ s/^\(\?i\)//
193 if $self->{search} =~ /^\(.*[[:upper:]]/; 205 if $self->{search} =~ /^\(.*[[:upper:]]/;
194 206
207 delete $self->{found};
195 $self->search (-1); 208 $self->search (-1, $self->{row});
196 $self->idle; 209 $self->idle;
197 210
198 1 211 1
199} 212}
200 213

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines