#!/usr/bin/perl use warnings; use strict; use Tk; use Tk::HList; use Tk::Pane; use File::Find; use File::Spec; my $maxfilesize = 5000000; #limit file opens to 5 meg my $h; #my HList; my $search = ''; #string to search for my $regex; my $case = 1; #defaults to case sensitive my $cur_info; #currently selected file info my $display; #labels to display info my $display1; my $display2; my $text; #the textbox my $firstflag; #flag for displaying first result my $indicator; #searching indicator my $indicate = -1; my $stop; #used to stop excessively long searches my $mw = MainWindow->new(-bg=>'black'); $mw->geometry('800x700+100+15'); $mw->bind('', [sub{Tk::exit;}] ); my $topframe = $mw->Frame(-height =>30, -background=>'darkgrey') ->pack(-fill=>'both', -expand=>1); my $leftframe = $mw->Frame( -width =>25, -background=>'black', )->pack(-side => "left", -anchor => "n", -fill=>'both', -expand=>1); my $mainframe = $mw->Frame(-background=>'black') ->pack(-side => "right", -anchor => "n", -fill=>'both', -expand=>1); #create leftframe HList2(); #fill mainframe with default screen setup_pane(); $topframe->Button(-text => "Next", -bg=>'cyan3', -activebackground =>'cyan', -padx=>40, -relief=>'raised', -command => sub { if(defined $h->info('selection')){ my $next = $h->info('next',$h->info('selection')); if($next){ $h->selectionClear($h->info('selection')); $h->selectionSet($next); $h->see($next); browseThis($next); }else{print chr(07)} } })->pack(-side =>'left'); $topframe->Button(-text => "Previous", -bg=>'thistle3', -activebackground =>'thistle1', -padx=>40, -relief=>'raised', -command => sub { if(defined $h->info('selection')){ my $prev = $h->info('prev',$h->info('selection')); if($prev){ $h->selectionClear($h->info('selection')); $h->selectionSet($prev); $h->see($prev); browseThis($prev); }else{print chr(07)} } })->pack(-side =>'left'); $topframe->Button(-text => "Exit", -bg => 'lightgrey', -activebackground =>'snow', -padx=>40, -relief=>'raised', -command => sub { exit; })->pack(-side =>'right'); $topframe->Button(-text => "Stop Search", -bg => 'red', -activebackground =>'yellow', -relief=>'raised', -command => sub {$stop = 1})->pack(-side =>'right',-padx => 20); $topframe->Button(-text => "Delete Entry", -bg=>'pink', -activebackground =>'hotpink', -padx=>40, -relief=>'raised', -command => sub { if(defined $h->info('selection')){ my $next = $h->info('next',$h->info('selection')); my $prev = $h->info('prev',$h->info('selection')); $h->delete( 'entry', $h->info('selection') ); if($next){ $h->selectionClear($h->info('selection')); $h->selectionSet($next); $h->see($next); browseThis($next); }elsif($prev){ $h->selectionClear($h->info('selection')); $h->selectionSet($prev); $h->see($prev); browseThis($prev); }else{print chr(07)} } })->pack(); MainLoop; sub HList2 { $h = $leftframe->Scrolled( 'HList', -header => 1, -columns => 1, -width => 20, -height => 60, -takefocus => 1, -background => 'steelblue', -foreground =>'snow', -selectmode => 'single', -selectforeground => 'pink', -selectbackground => 'black', -browsecmd => \&browseThis, )->pack(-side => "left", -anchor => "n"); $h->header('create', 0, -text => ' FILENAME ', -borderwidth => 3, -headerbackground => 'steelblue', -relief => 'raised'); } ############################################################# sub setup_pane{ my $pane = $mainframe->Pane( -width => 1000, -height =>1000, -background => 'black', -sticky => 'n', )->pack(-side => "left", -anchor => "n", -fill=>'both',-expand=>1); # search entry box my $f1 = $pane->Frame(-background => 'black') ->pack(-side => 'top', -fill => 'x', -expand => 1, -pady =>5); $f1->Label(-text=>"Search: ",-background => 'black',-foreground => 'green') -> pack(-side =>'left', -anchor => 'n'); my $entry = $f1->Entry(-textvariable => \$search, -width =>50, -bg => 'white', ) ->pack(-side=>'left', -anchor => 'n'); $entry->focus(); $entry->bind('', [sub{&search_it}] ); $f1->Checkbutton(-text => 'Case Sensitive', -bg => 'grey', -fg => 'black', -padx => 10, -onvalue => 1, -offvalue => 0, -variable => \$case)->pack(-side =>'left'); ########################################################## #currently selected file info my $f1a = $pane->Frame(-background => 'black') ->pack(-side => 'top', -fill => 'x', -expand => 1); $f1a->Label(-text=>"Filename: ",-background => 'black',-foreground => 'green') -> pack(-side =>'left', -anchor => 'n'); $display = $f1a->Label(-text=>'' ,-background => 'black',-foreground => 'lightblue') -> pack(-side =>'left', -anchor => 'n'); my $f1b = $pane->Frame(-background => 'black') ->pack(-side => 'top', -fill => 'x', -expand => 1); $f1b->Label(-text=>"Size: ",-background => 'black',-foreground => 'green') -> pack(-side =>'left', -anchor => 'n'); $display1 = $f1b->Label(-text=>'' ,-background => 'black',-foreground => 'pink') -> pack(-side =>'left', -anchor => 'n'); my $f1c = $pane->Frame(-background => 'black') ->pack(-side => 'top', -fill => 'x', -expand => 1); $f1c->Label(-text=>"FullPath: ",-background => 'black',-foreground => 'green') -> pack(-side =>'left', -anchor => 'n'); $display2 = $f1c->Label(-text=>'' ,-background => 'black',-foreground => 'yellow') -> pack(-side =>'left', -anchor => 'w'); ################################################################## #text box to display files my $f2 = $pane->Frame(-background => 'black') ->pack(-side => 'bottom', -fill => 'both', -expand => 1,); $text = $f2->Scrolled('Text',-scrollbars=>'se', -bg => 'lightyellow', -height=>45 )->pack(-fill=>'both', -expand=>1); } ############################################################## sub browseThis { my $ent = shift; my $data = $h->info('data',$ent); $indicator->cancel; my (undef,undef,$filename) = File::Spec->splitpath( $data ); my $size = -s $data; $display->configure(-text=> $filename); $display1->configure(-text=> $size); $display2->configure(-text=> $data); &display_text($data); } ############################################################ sub add_file{ my ($file,$abs_path) = @_; my $e = $h->addchild("",-data => $abs_path); $h->itemCreate ($e, 0, -itemtype => 'text', -text => $file, ); } ################################################################# sub search_it{ if(length $search == 0){print chr(07);return} $h->delete('all'); $firstflag = 0; $stop = 0; #start the blinking "Searching message indicator " $indicator = $mw->repeat(500,\&indicate); my $path = File::Spec->rel2abs('.'); if ($case){$regex = qr/\Q$search\E/} else{$regex = qr/\Q$search\E/i} find(\&wanted,$path); if($firstflag == 0){ print chr(07); $indicator->cancel; $text->delete("1.0","end"); $text->see("1.0"); $text->insert('end',"NO RESULTS !!!!!"); } #goto hack to exit File::Find early FINISHED: } ################################################################# sub wanted{ return unless (-f and -T); #only consider text files if(-s $File::Find::name > $maxfilesize){return} open(FILE, $File::Find::name) || die "Cant open $File::Find::name: $!\n"; while () { #process files line by line, no slurp next unless /$regex/; my $localname = File::Spec->abs2rel($File::Find::name); &add_file($localname, $File::Find::name); if($firstflag == 0){ #on subsequent searches the first entry #will not be 0, due to HList's internal counter my $first = $h->info('children'); &browseThis($first); $h->selectionSet($first); $firstflag = 1; } last; #quit searching file after first match #the textbox will show all matches } close(FILE); $h->update; if($stop == 1){ goto FINISHED} } ##################################################################### sub display_text { my $file = shift; $text->delete("1.0","end"); $text->see("1.0"); $text->tagConfigure( 'search', -foreground => 'black',-background => 'lightgreen' ); my $buf; if($file =~ /([Hh]tml?|HTML?)$/ ){ $buf = `lynx -dump -force_html $file`; }elsif($file =~ /(pdf|PDF)$/){ $buf = `pdftotext $file -`; }elsif($file =~ /(ps|PS|eps|EPS)$/){ $buf = `ps2ascii $file`; }elsif($file =~ /(pod)$/){ $buf = `pod2text $file`; }else{ open (FH,"< $file") or warn "$! \n"; read( FH, $buf, -s FH ); close FH; } $text->insert('end',$buf); &search_text($text,\$search,'search','exact'); } #################################################################### sub search_text { # The utility procedure below searches for all instances of a given # string in a text widget and applies a given tag to each instance found. # Arguments: # # w - The window in which to search. Must be a text widget. # string - Reference to the string to search for. The search is done # using exact matching only; no special characters. # tag - Tag to apply to each instance of a matching string. my ( $w, $string, $tag, $kind ) = @_; #print "@_\n"; return unless ref($string) && length($$string); $w->tagRemove( $tag, qw/0.0 end/ ); my ( $current, $length ) = ( '1.0', 0 ); my ($current_last, $length_last); while (1) { if($case){ $current = $w->search(-count => \$length, "-$kind", $$string, $current, 'end' ); }else{ $current = $w->search(-count => \$length, "-$kind",'-nocase', $$string, $current, 'end' ); } last if not $current; # warn "Posn=$current count=$length\n", $w->see($current); $w->tagAdd( $tag, $current, "$current + $length char" ); $current = $w->index("$current + $length char"); } } # end search_text ###################################################################### sub indicate { $indicate = -$indicate; #negative toggle $text->delete("1.0","end"); $text->see("1.0"); $text->insert('end','Searching '); if($indicate == -1){$text->insert('end',' .....No Results Yet')} $text->update; } ####################################################################