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.36 by sf-exg, Sat May 31 08:33:47 2014 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:RESOURCE:%:string:activation hotkey keysym 5#:META:RESOURCE:%:string:activation hotkey keysym
6#:META:BINDING:M-s:start
7 6
8=head1 NAME 7=head1 NAME
9 8
10searchable-scrollback - incremental scrollback search (enabled by default) 9searchable-scrollback - incremental scrollback search (enabled by default)
11 10
15the C<searchable-scrollback:start> action (bound to C<M-s> by 14the C<searchable-scrollback:start> action (bound to C<M-s> by
16default). While in search mode, normal terminal input/output is 15default). While in search mode, normal terminal input/output is
17suspended and a regex is displayed at the bottom of the screen. 16suspended and a regex is displayed at the bottom of the screen.
18 17
19Inputting characters appends them to the regex and continues incremental 18Inputting characters appends them to the regex and continues incremental
20search. C<BackSpace> removes a character from the regex, C<Up> and C<Down> 19search. In addition, the following bindings are recognized:
21search upwards/downwards in the scrollback buffer, C<End> jumps to the 20
22bottom. C<Escape> leaves search mode and returns to the point where search 21=over 4
23was started, while C<Enter> or C<Return> stay at the current position and 22
24additionally stores the first match in the current line into the primary 23=item C<BackSpace>
25selection 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
26 62
27The regex defaults to "(?i)", resulting in a case-insensitive search. To 63The regex defaults to "(?i)", resulting in a case-insensitive search. To
28get 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>
29or simply use an uppercase character which removes the "(?i)" prefix. 65or simply use an uppercase character which removes the "(?i)" prefix.
30 66
36 my ($self) = @_; 72 my ($self) = @_;
37 73
38 # only for backwards compatibility 74 # only for backwards compatibility
39 my $hotkey = $self->{argv}[0] 75 my $hotkey = $self->{argv}[0]
40 || $self->x_resource ("%") 76 || $self->x_resource ("%")
41 || return; 77 || "M-s";
42 78
43 $self->bind_action ($hotkey, "searchable-scrollback:start") # ugh 79 $self->bind_action ($hotkey, "%:start")
44 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";
81
82 ()
83}
84
85sub on_user_command {
86 my ($self, $cmd) = @_;
87
88 $cmd eq "searchable-scrollback:start"
89 and $self->enter;
45 90
46 () 91 ()
47} 92}
48 93
49sub on_action { 94sub on_action {
92 $self->pty_ev_events ($self->{pty_ev_events}); 137 $self->pty_ev_events ($self->{pty_ev_events});
93 138
94 delete $self->{manpage_overlay}; 139 delete $self->{manpage_overlay};
95 delete $self->{overlay}; 140 delete $self->{overlay};
96 delete $self->{search}; 141 delete $self->{search};
142 delete $self->{found};
97} 143}
98 144
99sub idle { 145sub idle {
100 my ($self) = @_; 146 my ($self) = @_;
101 147
102 $self->msg ("(escape cancels) /$self->{search}█"); 148 $self->msg ("(escape cancels) /$self->{search}█");
103} 149}
104 150
105sub search { 151sub search {
106 my ($self, $dir) = @_; 152 my ($self, $dir, $row) = @_;
107
108 delete $self->{found};
109 my $row = $self->{row};
110 153
111 my $search = $self->special_encode ($self->{search}); 154 my $search = $self->special_encode ($self->{search});
112 155
113 no re 'eval'; # just to be sure 156 no re 'eval'; # just to be sure
114 if (my $re = eval { qr/$search/ }) { 157 if (my $re = eval { qr/$search/ }) {
116 my $line = $self->line ($row) 159 my $line = $self->line ($row)
117 or last; 160 or last;
118 161
119 my $text = $line->t; 162 my $text = $line->t;
120 if ($text =~ /$re/g) { 163 if ($text =~ /$re/g) {
164 delete $self->{found};
165
121 do { 166 do {
122 push @{ $self->{found} }, [$line->coord_of ($-[0]), $line->coord_of ($+[0])]; 167 push @{ $self->{found} }, [$line->coord_of ($-[0]), $line->coord_of ($+[0])];
123 } while $text =~ /$re/g; 168 } while $text =~ /$re/g;
124 169
125 $self->{row} = $row; 170 $self->{row} = $row;
126 $self->view_start (List::Util::min 0, $row - ($self->nrow >> 1)); 171 $self->view_start (List::Util::min 0, $row - ($self->nrow >> 1));
127 $self->want_refresh; 172 $self->want_refresh;
128 last; 173 return;
129 } 174 }
130 175
131 $row = $dir < 0 ? $line->beg - 1 : $line->end + 1; 176 $row = $dir < 0 ? $line->beg - 1 : $line->end + 1;
132 } 177 }
133 } 178 }
134 179
135 $self->scr_bell unless $self->{found}; 180 $self->scr_bell;
136} 181}
137 182
138sub refresh { 183sub refresh {
139 my ($self) = @_; 184 my ($self) = @_;
140 185
167 $self->leave; 212 $self->leave;
168 } elsif ($keysym == 0xff57) { # end 213 } elsif ($keysym == 0xff57) { # end
169 $self->{row} = $self->nrow - 1; 214 $self->{row} = $self->nrow - 1;
170 $self->view_start (0); 215 $self->view_start (0);
171 } elsif ($keysym == 0xff52) { # up 216 } elsif ($keysym == 0xff52) { # up
172 $self->{row}-- if $self->{row} > $self->top_row; 217 my $line = $self->line ($self->{row});
173 $self->search (-1); 218 $self->search (-1, $line->beg - 1)
219 if $line->beg > $self->top_row;
174 } elsif ($keysym == 0xff54) { # down 220 } elsif ($keysym == 0xff54) { # down
175 $self->{row}++ if $self->{row} < $self->nrow; 221 my $line = $self->line ($self->{row});
176 $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);
177 } elsif ($keysym == 0xff08) { # backspace 232 } elsif ($keysym == 0xff08) { # backspace
178 substr $self->{search}, -1, 1, ""; 233 substr $self->{search}, -1, 1, "";
179 $self->search; 234 $self->search (+1, $self->{row});
180 $self->idle; 235 $self->idle;
181 } elsif ($string !~ /[\x00-\x1f\x80-\xaf]/) { 236 } elsif ($string !~ /[\x00-\x1f\x80-\xaf]/) {
182 return; # pass to tt_write 237 return; # pass to tt_write
183 } 238 }
184 239
191 $self->{search} .= $self->locale_decode ($data); 246 $self->{search} .= $self->locale_decode ($data);
192 247
193 $self->{search} =~ s/^\(\?i\)// 248 $self->{search} =~ s/^\(\?i\)//
194 if $self->{search} =~ /^\(.*[[:upper:]]/; 249 if $self->{search} =~ /^\(.*[[:upper:]]/;
195 250
251 delete $self->{found};
196 $self->search (-1); 252 $self->search (-1, $self->{row});
197 $self->idle; 253 $self->idle;
198 254
199 1 255 1
200} 256}
201 257

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines