App-Codit

 view release on metacpan or  search on metacpan

lib/App/Codit/Plugins/SearchReplace.pm  view on Meta::CPAN

my $srchcur = 'Search in current document';
my $srchall = 'Search in all documents';
my $srchprj = 'Search in project files';
my $srchres = 'Search in results';

=head1 DESCRIPTION

Search and replace across multiple files.

=head1 DETAILS

This plugin allows you to do a search and replace across multiple or just one file.

After filling out the search and replace fields you first click Find.
The list box will fill with the search results.

When you click Replace the first item in the list is replaced and then removed from the list.

You can skip replaces by pressing Skip.

When searching with a regular expression you can include the captures you make with () in
the replace string with ‘$1’, ‘$2’, etcetera.

Clear removes all search results.

=cut

sub new {
	my $class = shift;
	my $self = $class->SUPER::new(@_);
	return undef unless defined $self;
	
#	my $tp = $self->extGet('ToolPanel');
#	my $page = $tp->addPage('SearchReplace', 'edit-find-replace', undef, 'Search and replace');
	my $page = $self->ToolRightPageAdd('SearchReplace', 'edit-find-replace', undef, 'Search and replace', 350);

	my $searchterm = '';
	my $replaceterm = '';
	my $casesensitive = '-case';
	my $useregex = '-exact';
	my $searchmode = 'Search in current document';

	$self->{CASE} = \$casesensitive;
	$self->{CURRENT} = undef;
	$self->{LASTRESULTS} = [];
	$self->{MODE} = \$searchmode;
	$self->{OFFSET} = {};
	$self->{REPLACE} = \$replaceterm;
	$self->{REPLACED} = 0;
	$self->{REGEX} = \$useregex;
	$self->{SEARCH} = \$searchterm;
	$self->{SKIPPED} = 0;

	my @padding = (-padx => 2, -pady => 2);

	my $sa = $page->Frame(
		-relief => 'groove',
		-borderwidth => 2,
	)->pack(@padding, -fill => 'x');

	my $sf = $sa->Frame->pack(-expand => 1, -fill => 'x');
	$sf->Label(
		-text => 'Search',
		-width => 7,
		-anchor => 'e',
	)->pack(@padding, -side => 'left');
	my $se = $sf->Entry(
		-textvariable => \$searchterm,
	)->pack(@padding, -side => 'left', -expand => 1, -fill => 'x');
	$se->bind('<Return>', [$self, 'Find']);

	my $rf = $sa->Frame->pack(-expand => 1, -fill => 'x');
	$rf->Label(
		-text => 'Replace',
		-width => 7,
		-anchor => 'e',
	)->pack(@padding, -side => 'left');
	$rf->Entry(
		-textvariable => \$replaceterm,
	)->pack(@padding, -side => 'left', -expand => 1, -fill => 'x');

	my $sb = $page->LabFrame(
		-labelside => 'acrosstop',
		-relief => 'groove',
		-label => 'Search options',
	)->pack(@padding, -fill => 'x');

	$sb->Checkbutton(
		-variable => \$useregex,
		-text => 'Regular expression',
		-onvalue => '-regexp',
		-offvalue => '-exact',
		-anchor => 'w',
	)->pack(@padding, -fill => 'x');
	$sb->Checkbutton(
		-variable => \$casesensitive,
		-onvalue => '-case',
		-offvalue => '-nocase',
		-text => 'Case sensitive',
		-anchor => 'w',
	)->pack(@padding, -fill => 'x');
	my $mb = $sb->Menubutton(
#		-relief => 'raised',
		-anchor => 'w',
		-textvariable => \$searchmode,
	)->pack(@padding, -fill => 'x');
	my @menu = ();
	for ($srchcur, $srchall, $srchprj, $srchres) {
		my $mode = $_;
		push @menu, [command => $mode,
			-command => sub { $searchmode = $mode },
		];
	}
	$mb->configure(-menu => $mb->Menu(
		-menuitems => \@menu,
	));


	my $sc = $page->Frame(
		-relief => 'groove',
		-borderwidth => 2,
	)->pack(@padding, -fill => 'x');
	$sc->gridColumnconfigure(0, -weight => 2);
	$sc->gridColumnconfigure(1, -weight => 2);
	$sc->Button(
		-command => ['Find', $self],
		-text => 'Find',
		-width => 8,
	)->grid(@padding, -column => 0, -row => 0, -sticky => 'ew');
	$sc->Button(
		-command => ['Clear', $self],
		-text => 'Clear',
		-width => 8,
	)->grid(@padding, -column => 1, -row => 0, -sticky => 'ew');
	$sc->Button(
		-command => ['Replace', $self],
		-text => 'Replace',
		-width => 8,
	)->grid(@padding, -column => 0, -row => 1, -sticky => 'ew');
	$sc->Button(
		-command => ['Skip', $self],
		-text => 'Skip',
		-width => 8,
	)->grid(@padding, -column => 1, -row => 1, -sticky => 'ew');


	my $tf = $page->Frame(
		-relief => 'groove',
		-borderwidth => 2,
	)->pack(@padding, -expand => 1, -fill => 'both');
	$tf->gridColumnconfigure(0, -weight => 2);
	$tf->gridColumnconfigure(1, -weight => 2);
	$tf->gridRowconfigure(1, -weight => 2);
	$tf->Button(
		-text => 'Previous',
		-command => ['BrowsePrevious', $self],
		-width => 8,
	)->grid(@padding, -column => 0, -row => 0, -sticky => 'ew');
	$tf->Button(
		-text => 'Next',
		-command => ['BrowseNext', $self],
		-width => 8,
	)->grid(@padding, -column => 1, -row => 0, -sticky => 'ew');
	my $results = $tf->Scrolled('ITree',
		-height => 4,
		-browsecmd => ['Select', $self],
		-scrollbars => 'osoe',
		-separator => '@',
	)->grid(@padding, -column => 0, -columnspan => 2, -row => 1, -sticky => 'nsew');
	$results->autosetmode;
	$self->{RESULTSLIST} = $results;
	
	$self->cmdHookAfter('doc_select', 'ShowResults', $self);

	return $self;
}

sub BrowseNext {
	my $self = shift;
	my $list = $self->list;
	my ($sel) = $list->infoSelection;

	#select the first hit if no selection is set
	unless (defined $sel) {
		$sel = $self->SelectFirst;
		return
	}
	return unless defined $sel;

	#select the first hit is the last hit is selected
	my $last = $self->GetLast;
	if ($self->IsSelected($last)) {
		$sel = $self->SelectFirst;
		return
	}

	my ($name, $index) = split(/@/, $sel);
	if (defined $index) {
		my $next = $list->infoNext($sel);
		return unless defined $next;
		my ($nname, $nindex) = split(/@/, $next);
		unless (defined $nindex) {
			my @d = $list->infoChildren($nname);
			if (@d) {
				$self->Select($d[0]);
				return
			}
		} else {
			$self->Select($next);
		}



( run in 0.623 second using v1.01-cache-2.11-cpan-5623c5533a1 )