1package Term::ReadLine::Zoid::ISearch;
2
3use strict;
4use base 'Term::ReadLine::Zoid';
5no warnings; # undef == '' down here
6
7our $VERSION = 0.06;
8
9our %_keymap = (
10	backspace  => 'backward_delete_char',
11	ctrl_R     => 'isearch_again',
12	_on_switch => 'is_switch',
13	_default   => 'self_insert'
14);
15
16sub keymap { return \%_keymap }
17
18sub is_switch {
19	my $self = shift;
20	$$self{is_lock} = undef;
21	$$self{is_hist_p} = -1;
22	$$self{is_save} = [[''], [0,0], undef];
23}
24
25sub is_switch_back {
26	my ($self, $key) = @_;
27	$$self{_hist_save} = $self->save();
28	@$self{qw/lines pos hist_p/} = @{$$self{is_save}};
29	$self->switch_mode();
30	$self->do_key($key);
31}
32
33sub draw { # rendering this inc mode is kinda consuming
34	my ($self, @args) = @_;
35	my $save = $self->save();
36	my $string = join "\n", @{$$self{lines}};
37	$$self{prompt} = "i-search qr($string): ";
38	goto DRAW unless length $string;
39
40	my ($result, $match, $hist_p) = (undef, '', $$self{is_hist_p});
41	$$self{last_search} = ['b', $string];
42	my $reg = eval { qr/^(.*?$string)/ };
43	goto DRAW if $@;
44
45	while ($hist_p < $#{$$self{history}}) {
46		$hist_p++;
47		next unless $$self{history}[$hist_p] =~ $reg;
48		($result, $match) = ($$self{history}[$hist_p], $1);
49		last;
50	}
51
52	if (defined $result) {
53		push @{$$self{last_search}}, $hist_p;
54		$$self{is_lock} = undef;
55		$$self{lines} = [ split /\n/, $result ];
56		my @match = split /\n/, $match;
57		$$self{pos} = [length($match[-1]), $#match];
58	}
59	else { $$self{is_lock} = 1 }
60
61	DRAW: Term::ReadLine::Zoid::draw($self, @args);
62	$$self{is_save} = [ $$self{lines}, $$self{pos}, $hist_p];
63	$self->restore($save);
64}
65
66sub self_insert {
67	if ($_[0]{is_lock}) { $_[0]->bell }
68	elsif ($_[0]->key_binding($_[1], $_[0]{config}{default_mode})) {
69		goto \&is_switch_back;
70	}
71	else { goto \&Term::ReadLine::Zoid::self_insert }
72}
73
74sub isearch_again { $_[0]{is_hist_p} = $_[0]{last_search}[-1] if $_[0]{last_search} }
75
761;
77
78__END__
79
80=head1 NAME
81
82Term::ReadLine::Zoid::ISearch - a readline incremental search mode
83
84=head1 SYNOPSIS
85
86This class is used as a mode under L<Term::ReadLine::Zoid>,
87see there for usage details.
88
89=head1 DESCRIPTION
90
91This mode is intended as a work alike for the incremental search
92found in the gnu readline library.
93
94In this mode the string you enter is regarded as a B<perl regex> which is used
95to do an incremental histroy search.
96
97Pressing '^R' repeatingly will give alternative results.
98
99Special keys like movements or the C<return> drop you out of this mode
100and set the edit line to the last search result.
101
102=head1 AUTHOR
103
104Jaap Karssenberg || Pardus [Larus] E<lt>pardus@cpan.orgE<gt>
105
106Copyright (c) 2004 Jaap G Karssenberg. All rights reserved.
107This program is free software; you can redistribute it and/or
108modify it under the same terms as Perl itself.
109
110=head1 SEE ALSO
111
112=cut
113
114