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.30 by root, Tue Sep 4 22:41:12 2012 UTC vs.
Revision 1.44 by sf-exg, Tue Oct 24 20:12:08 2017 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 6
7=head1 NAME 7=head1 NAME
8 8
9searchable-scrollback<hotkey> - incremental scrollback search (enabled by default) 9searchable-scrollback - incremental scrollback search (enabled by default)
10 10
11=head1 DESCRIPTION 11=head1 DESCRIPTION
12 12
13Adds regex search functionality to the scrollback buffer, triggered 13Adds regex search functionality to the scrollback buffer, triggered by
14by a hotkey (default: C<M-s>). While in search mode, normal terminal 14the C<searchable-scrollback:start> action (bound to C<M-s> by
15default). While in search mode, normal terminal input/output is
15input/output is suspended and a regex is displayed at the bottom of the 16suspended and a regex is displayed at the bottom of the screen.
16screen.
17 17
18Inputting characters appends them to the regex and continues incremental 18Inputting characters appends them to the regex and continues incremental
19search. C<BackSpace> removes a character from the regex, C<Up> and C<Down> 19search. In addition, the following bindings are recognized:
20search upwards/downwards in the scrollback buffer, C<End> jumps to the 20
21bottom. C<Escape> leaves search mode and returns to the point where search 21=over 4
22was started, while C<Enter> or C<Return> stay at the current position and 22
23additionally stores the first match in the current line into the primary 23=item C<BackSpace>
24selection if the C<Shift> modifier is active. 24
25Remove a character from the regex.
26
27=item C<Insert>
28
29Append the value of the PRIMARY selection to the regex.
30
31=item C<Up>
32
33Search for a match upwards.
34
35=item C<Down>
36
37Search for a match downwards.
38
39=item C<Prior>
40
41Scroll up.
42
43=item C<Next>
44
45Scroll down.
46
47=item C<End>
48
49Scroll to the bottom.
50
51=item C<Escape>
52
53Leave the mode and return to the point where search was started.
54
55=item C<Enter> or C<Return>
56
57Leave the mode maintaining the current position in the scrollback.
58Additionally, if the C<Shift> modifier is active, store the first
59match in the current line into the primary selection.
60
61=back
25 62
26The regex defaults to "(?i)", resulting in a case-insensitive search. To 63The regex defaults to "(?i)", resulting in a case-insensitive search. To
27get a case-sensitive search you can delete this prefix using C<BackSpace> 64get a case-sensitive search you can delete this prefix using C<BackSpace>
28or simply use an uppercase character which removes the "(?i)" prefix. 65or simply use an uppercase character which removes the "(?i)" prefix.
29 66
32=cut 69=cut
33 70
34sub on_init { 71sub on_init {
35 my ($self) = @_; 72 my ($self) = @_;
36 73
74 # only for backwards compatibility
37 my $hotkey = $self->{argv}[0] 75 my $hotkey = $self->{argv}[0]
38 || $self->x_resource ("%") 76 || $self->x_resource ("%")
39 || "M-s"; 77 || "M-s";
40 78
41 $self->parse_keysym ($hotkey, "perl:searchable-scrollback:start") 79 $self->bind_action ($hotkey, "%:start")
42 or warn "unable to register '$hotkey' as scrollback search start hotkey\n"; 80 or warn "unable to register '$hotkey' as scrollback search start hotkey\n";
43 81
44 () 82 ()
45} 83}
46 84
47sub on_user_command { 85sub on_user_command {
48 my ($self, $cmd) = @_; 86 my ($self, $cmd) = @_;
49 87
50 $cmd eq "searchable-scrollback:start" 88 $cmd eq "searchable-scrollback:start"
89 and $self->enter;
90
91 ()
92}
93
94sub on_action {
95 my ($self, $action) = @_;
96
97 $action eq "start"
51 and $self->enter; 98 and $self->enter;
52 99
53 () 100 ()
54} 101}
55 102
89 $self->disable ("key_press", "tt_write", "refresh_begin", "refresh_end"); 136 $self->disable ("key_press", "tt_write", "refresh_begin", "refresh_end");
90 $self->pty_ev_events ($self->{pty_ev_events}); 137 $self->pty_ev_events ($self->{pty_ev_events});
91 138
92 delete $self->{manpage_overlay}; 139 delete $self->{manpage_overlay};
93 delete $self->{overlay}; 140 delete $self->{overlay};
94 delete $self->{history};
95 delete $self->{search}; 141 delete $self->{search};
142 delete $self->{found};
96} 143}
97 144
98sub idle { 145sub idle {
99 my ($self) = @_; 146 my ($self) = @_;
100 147
101 $self->msg ("(escape cancels) /$self->{search}█"); 148 $self->msg ("(escape cancels) /$self->{search}█");
102} 149}
103 150
104sub search { 151sub search {
105 my ($self, $dir) = @_; 152 my ($self, $dir, $row) = @_;
106
107 delete $self->{found};
108 my $row = $self->{row};
109 153
110 my $search = $self->special_encode ($self->{search}); 154 my $search = $self->special_encode ($self->{search});
111 155
112 no re 'eval'; # just to be sure 156 no re 'eval'; # just to be sure
113 if (my $re = eval { qr/$search/ }) { 157 if (my $re = eval { qr/$search/ }) {
115 my $line = $self->line ($row) 159 my $line = $self->line ($row)
116 or last; 160 or last;
117 161
118 my $text = $line->t; 162 my $text = $line->t;
119 if ($text =~ /$re/g) { 163 if ($text =~ /$re/g) {
164 delete $self->{found};
165
120 do { 166 do {
121 push @{ $self->{found} }, [$line->coord_of ($-[0]), $line->coord_of ($+[0])]; 167 push @{ $self->{found} }, [$line->coord_of ($-[0]), $line->coord_of ($+[0])];
122 } while $text =~ /$re/g; 168 } while $text =~ /$re/g;
123 169
124 $self->{row} = $row; 170 $self->{row} = $row;
125 $self->view_start (List::Util::min 0, $row - ($self->nrow >> 1)); 171 $self->view_start (List::Util::min 0, $row - ($self->nrow >> 1));
126 $self->want_refresh; 172 $self->want_refresh;
127 last; 173 return;
128 } 174 }
129 175
130 $row = $dir < 0 ? $line->beg - 1 : $line->end + 1; 176 $row = $dir < 0 ? $line->beg - 1 : $line->end + 1;
131 } 177 }
132 } 178 }
133 179
134 $self->scr_bell unless $self->{found}; 180 $self->scr_bell;
135} 181}
136 182
137sub refresh { 183sub refresh {
138 my ($self) = @_; 184 my ($self) = @_;
139 185
166 $self->leave; 212 $self->leave;
167 } elsif ($keysym == 0xff57) { # end 213 } elsif ($keysym == 0xff57) { # end
168 $self->{row} = $self->nrow - 1; 214 $self->{row} = $self->nrow - 1;
169 $self->view_start (0); 215 $self->view_start (0);
170 } elsif ($keysym == 0xff52) { # up 216 } elsif ($keysym == 0xff52) { # up
171 $self->{row}-- if $self->{row} > $self->top_row; 217 my $line = $self->line ($self->{row});
172 $self->search (-1); 218 $self->search (-1, $line->beg - 1)
219 if $line->beg > $self->top_row;
173 } elsif ($keysym == 0xff54) { # down 220 } elsif ($keysym == 0xff54) { # down
174 $self->{row}++ if $self->{row} < $self->nrow; 221 my $line = $self->line ($self->{row});
175 $self->search (+1); 222 $self->search (+1, $line->end + 1)
223 if $line->end < $self->nrow;
224 } elsif ($keysym == 0xff55) { # prior
225 my $row = $self->view_start - ($self->nrow - 1);
226 $self->view_start (List::Util::min 0, $row);
227 } elsif ($keysym == 0xff56) { # next
228 my $row = $self->view_start + ($self->nrow - 1);
229 $self->view_start (List::Util::min 0, $row);
230 } elsif ($keysym == 0xff63) { # insert
231 $self->selection_request (urxvt::CurrentTime, 1);
176 } elsif ($keysym == 0xff08) { # backspace 232 } elsif ($keysym == 0xff08) { # backspace
177 substr $self->{search}, -1, 1, ""; 233 substr $self->{search}, -1, 1, "";
178 $self->search; 234 $self->search (+1, $self->{row});
179 $self->idle; 235 $self->idle;
180 } elsif ($string !~ /[\x00-\x1f\x80-\xaf]/) { 236 } elsif ($string !~ /[\x00-\x1f\x80-\xaf]/) {
181 return; # pass to tt_write 237 return; # pass to tt_write
182 } 238 }
183 239
190 $self->{search} .= $self->locale_decode ($data); 246 $self->{search} .= $self->locale_decode ($data);
191 247
192 $self->{search} =~ s/^\(\?i\)// 248 $self->{search} =~ s/^\(\?i\)//
193 if $self->{search} =~ /^\(.*[[:upper:]]/; 249 if $self->{search} =~ /^\(.*[[:upper:]]/;
194 250
251 delete $self->{found};
195 $self->search (-1); 252 $self->search (-1, $self->{row});
196 $self->idle; 253 $self->idle;
197 254
198 1 255 1
199} 256}
200 257

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines