Mercurial > rlmcintyre
diff javadoc-search.pl @ 0:0d795f02a8bb tip
initial committ. what was I thinking?
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Mon, 27 Sep 2010 16:57:26 -0400 |
parents | |
children |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/javadoc-search.pl Mon Sep 27 16:57:26 2010 -0400 1.3 @@ -0,0 +1,465 @@ 1.4 +#!/usr/bin/perl 1.5 + 1.6 +use strict; 1.7 +use vars qw / $javadocRoots $indexFile $resultFrame $linkFrame $gzip /; 1.8 +##################################################################### 1.9 +# 1.10 +# javadoc-search 1.11 +# 1.12 +# http://sourceforge.net/projects/javadoc-search/ 1.13 +# 1.14 +# Copyright (C) 2002-2003, Nicholas Sushkin. 1.15 +# 1.16 +# This program is free software; you can redistribute it and/or modify 1.17 +# it under the terms of the GNU General Public License as published by 1.18 +# the Free Software Foundation; either version 2 of the License, or 1.19 +# (at your option) any later version. 1.20 +# 1.21 +# This program is distributed in the hope that it will be useful, 1.22 +# but WITHOUT ANY WARRANTY; without even the implied warranty of 1.23 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1.24 +# GNU General Public License for more details. 1.25 +# 1.26 +# You should have received a copy of the GNU General Public License 1.27 +# along with this program; if not, write to the Free Software 1.28 +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 1.29 +# 1.30 +# 1.31 +# Instructions are at http://javadoc-search.sourceforge.net/ 1.32 +# 1.33 +# 1.34 +##################################################################### 1.35 +# 1.36 +# $Id: javadoc-search.pl,v 1.8 2003/08/19 00:11:09 nsushkin Exp $ 1.37 +# 1.38 +##################################################################### 1.39 + 1.40 +### Indexing setup 1.41 + 1.42 +# list of subdirectories of docroot to search for javadoc index files 1.43 +# Windows and Apache - prefix with drive letter and use only lowercase letters. 1.44 +# $javadocRoots = [ "c:/program\ files/apache/htdocs/docs" ]; 1.45 +# Unix 1.46 +# $javadocRoots = [ "/usr/local/apache/htdocs/docs" ]; 1.47 +$javadocRoots = [ "/usr/local/apache/htdocs/docs" ]; 1.48 + 1.49 +# index file, if ends with .gz will use gzip 1.50 +# Windows 1.51 +# $indexFile = "c:/bin/apache\ group/apache/javadoc-index.txt"; 1.52 +# Unix 1.53 +# $indexFile = "/usr/local/apache/htdocs/docs/javadoc-index.txt.gz"; 1.54 +$indexFile = "/usr/local/apache/htdocs/docs/javadoc-index.txt.gz"; 1.55 + 1.56 +### Display style setup 1.57 + 1.58 +# if $resultFrame is not empty, display search results in this frame 1.59 +$resultFrame = ""; 1.60 + 1.61 +# if $linkFrame is not empty, open javadoc links in this frame 1.62 +$linkFrame = ""; 1.63 + 1.64 +### Auxillary programs setup 1.65 + 1.66 +# which gzip 1.67 +$gzip = "/usr/bin/gzip"; 1.68 + 1.69 +# nothing below is customizable 1.70 +##################################################################### 1.71 +use Getopt::Std; 1.72 +use File::Find; 1.73 + 1.74 +my @indexFiles; 1.75 +my %links; 1.76 + 1.77 +(my $rev = '$Revision: 1.8 $') =~ s/^\$\w+: ([\.\d]+) \$$/$1/; 1.78 + 1.79 +sub usage 1.80 +{ 1.81 + print STDERR <<EOUSAGE; 1.82 +Javadoc Search $rev 1.83 + 1.84 +Usage: $0 [-h] [-r] 1.85 + 1.86 + -h prints this help 1.87 + -r builds index 1.88 + 1.89 + This is a cgi script to search javadoc for classes, members, and methods 1.90 + using an index. 1.91 +EOUSAGE 1.92 + 1.93 +} 1.94 + 1.95 +# 1.96 +# Build index part 1.97 +# 1.98 +sub indexWrite 1.99 +{ 1.100 + print STDERR "Writing all ", indexGetLinkCount(), " links to $indexFile .. "; 1.101 + 1.102 + if ($indexFile =~ /\.gz$/) 1.103 + { 1.104 + open(OUTPUT, "| $gzip -c > \"$indexFile\"") || die "unable to gzip to $indexFile: $!\n"; 1.105 + } 1.106 + else 1.107 + { 1.108 + open(OUTPUT, ">" . $indexFile) || die "unable to write to $indexFile: $!\n"; 1.109 + } 1.110 + 1.111 + my $oldSearchKey = ""; 1.112 + foreach (sort { $links{$a} cmp $links{$b} } keys %links) 1.113 + { 1.114 + my $searchKey = $links{$_}; 1.115 + if ($searchKey ne $oldSearchKey) 1.116 + { 1.117 + if ($oldSearchKey ne "") { print OUTPUT "\n"; } 1.118 + print OUTPUT $searchKey; 1.119 + } 1.120 + print OUTPUT "\t", $_; 1.121 + 1.122 + $oldSearchKey = $searchKey; 1.123 + } 1.124 + print OUTPUT "\n"; 1.125 + 1.126 + close(OUTPUT); 1.127 + 1.128 + print STDERR "done\n"; 1.129 +} 1.130 + 1.131 +sub indexGetLinkCount 1.132 +{ 1.133 + scalar(keys %links); 1.134 +} 1.135 + 1.136 +sub indexRebuild 1.137 +{ 1.138 + find(\&indexFileFinder, @$javadocRoots); 1.139 + 1.140 + foreach (@indexFiles) 1.141 + { 1.142 + parseLinks($$_[0], $$_[1]); 1.143 + } 1.144 +} 1.145 + 1.146 +sub indexFileFinder 1.147 +{ 1.148 + return unless -f $File::Find::name; 1.149 + return unless /^index-.*html??/; 1.150 + 1.151 + push @indexFiles, [$File::Find::name, $File::Find::dir]; 1.152 +} 1.153 + 1.154 +sub indexAddLink 1.155 +{ 1.156 + my $key = shift; 1.157 + my $link = shift; 1.158 + 1.159 + $links{$link} = $key; 1.160 +} 1.161 + 1.162 +sub parseLinks() 1.163 +{ 1.164 + my $fileName = shift; 1.165 + my $dirName = shift; 1.166 + 1.167 + print STDERR "Parsing ", $fileName, ": "; 1.168 + 1.169 + open(FILE, $fileName); 1.170 + 1.171 + while(<FILE>) 1.172 + { 1.173 + if($_ =~ m/<A[^>]+?HREF\s*=\s*[\"\']?([^\'\" >]+?)[ \'\"]?(>| title=)/sig) 1.174 + { 1.175 + parseLink($1, $dirName); 1.176 + } 1.177 + } 1.178 + 1.179 + close(FILE); 1.180 + 1.181 + print STDERR indexGetLinkCount(), " links\n"; 1.182 +} 1.183 + 1.184 +sub parseLink() 1.185 +{ 1.186 + my $link = shift; 1.187 + my $dirName = shift; 1.188 + 1.189 + return if $link =~ qr'^(http|ftp)://'i; 1.190 + 1.191 + # print "# link=", $link, "\n"; 1.192 + 1.193 + my $abslink = ( $link =~ qr'^[\./]*([^\./].*)' ) ? $1 : $link; 1.194 + # print "# abslink= $abslink\n"; 1.195 + 1.196 + return unless $abslink =~ qr'/'; 1.197 + 1.198 + my ($file,$anchor) = split '#', $abslink; 1.199 + # print "# file=$file, anchor=$anchor\n"; 1.200 + 1.201 + my $class = ($file =~ /(.*)\.html??/ ) ? $1 : return; 1.202 + $class =~ tr{\/}{\.}; 1.203 + 1.204 + # print "# class=", $class, "\n"; 1.205 + # print "# dirname=", $dirName, "\n"; 1.206 + 1.207 + # cancel out ".." 1.208 + if ($link =~ /^\.\.\//) 1.209 + { 1.210 + my @linkSegs = split '/', $link; 1.211 + my @dirSegs = split '/', $dirName; 1.212 + 1.213 + while (@linkSegs[0] eq '..' and $#dirSegs >= 0) 1.214 + { 1.215 + shift @linkSegs; 1.216 + pop @dirSegs; 1.217 + } 1.218 + $link = join '/', @linkSegs; 1.219 + $dirName = join '/', @dirSegs; 1.220 + } 1.221 + my $fullLink = ( $link =~ /^\// ) ? $link : $dirName . "/" . $link; 1.222 + 1.223 + my $key = $anchor eq "" ? $class : $class . '#' . $anchor; 1.224 + indexAddLink($key, $fullLink); 1.225 +} 1.226 + 1.227 +# 1.228 +# CGI part 1.229 +# 1.230 +use CGI qw(:standard); 1.231 + 1.232 +my $searchTypes = {'c'=>'class','cm'=>'class#member','cma'=>'class#member(args)'}; 1.233 + 1.234 +sub topFrameGenerate 1.235 +{ 1.236 + Delete('render'); 1.237 + param('render', 'query'); 1.238 + my $queryFrameUrl = self_url; 1.239 + 1.240 + Delete('render'); 1.241 + param('render', 'noResults'); 1.242 + my $noResultsFrameUrl = self_url; 1.243 + 1.244 + return 1.245 + header(), 1.246 + html(head(title('Javadoc search')), 1.247 + frameset({-rows => '150,*'}, 1.248 + frame({-name => 'query', -src => $queryFrameUrl}), 1.249 + frame({-name => $resultFrame, -src => $noResultsFrameUrl}))); 1.250 +} 1.251 + 1.252 +sub noResultsGenerate 1.253 +{ 1.254 + return 1.255 + header, 1.256 + start_html('Javadoc search'), 1.257 + h2('No results yet'), 1.258 + end_html, 1.259 + "\n"; 1.260 +} 1.261 + 1.262 +sub searchFormGenerate 1.263 +{ 1.264 + Delete('render'); 1.265 + 1.266 + return 1.267 + h1('Javadoc search'), 1.268 + $resultFrame ? start_form(-target => $resultFrame, -action=>script_name) : start_form(-action=>script_name), 1.269 + "Search pattern ", 1.270 + textfield(-name=>'pattern', -size=>15), 1.271 + " in ", 1.272 + scrolling_list(-name=>'type', 1.273 + -values=>[sort(keys(%$searchTypes))], 1.274 + -labels=>$searchTypes, 1.275 + -defaults=>['c'], 1.276 + -size=>1), 1.277 + " and display ", 1.278 + scrolling_list(-name=>'results', 1.279 + -values=>['1', '10', '20', '50', '0'], 1.280 + -labels=>{'1'=>'1', '10'=>'10', '20'=>'20', '50'=>'50', '0'=>'All'}, 1.281 + -defaults=>['10'], 1.282 + -size=>1), 1.283 + " results ", 1.284 + submit(-name=>'go', -value=>'Go'), submit(-name=>'lucky', -value=>'Go!'), 1.285 + $resultFrame ? hidden(-name => 'render', -default => 'results') : "", 1.286 + end_form, 1.287 + $resultFrame ? "" : hr; 1.288 +} 1.289 + 1.290 +sub doSearch 1.291 +{ 1.292 + my ($pattern, $type, $results) = @_; 1.293 + 1.294 + if (! -r $indexFile) 1.295 + { 1.296 + print strong("Error: index file is not readable"); 1.297 + return; 1.298 + } 1.299 + 1.300 + if ($indexFile =~ /\.gz$/) 1.301 + { 1.302 + open(INPUT, "$gzip -dc \"$indexFile\" |") || die "unable to un-gzip $indexFile: $!\n"; 1.303 + } 1.304 + else 1.305 + { 1.306 + open(INPUT, $indexFile) || die "unable to read $indexFile: $!\n"; 1.307 + } 1.308 + 1.309 + my $docRoot = $ENV{'DOCUMENT_ROOT'}; 1.310 + my @matches; 1.311 + 1.312 + INPUTLINE: 1.313 + while(<INPUT>) 1.314 + { 1.315 + chomp; 1.316 + my ($key, @urls) = split (/\t/); 1.317 + 1.318 + for ($key) 1.319 + { 1.320 + if (($type eq "c" and /\#/) || 1.321 + ($type eq "cm" and !(/\#/ and !/\)/)) || 1.322 + ($type eq "cma" and !(/\#/ and /\)/))) 1.323 + { 1.324 + next INPUTLINE; 1.325 + } 1.326 + } 1.327 + 1.328 + if ($key =~ /$pattern/ and ($results == 0 or $#matches < $results) ) 1.329 + { 1.330 + push @matches, [ ( $key, map { s/$docRoot//; $_ } @urls ) ]; 1.331 + } 1.332 + 1.333 + last if $results > 0 and $#matches >= $results; 1.334 + 1.335 + } 1.336 + close(INPUT); 1.337 + 1.338 + return \@matches; 1.339 +} 1.340 + 1.341 +sub displayLuckyMatch 1.342 +{ 1.343 + my $matches = shift; 1.344 + 1.345 + if ( $#$matches < 0 ) 1.346 + { 1.347 + print 1.348 + header, 1.349 + start_html('No matches'), 1.350 + p("No matches"), 1.351 + end_html; 1.352 + } 1.353 + else 1.354 + { 1.355 + print 1.356 + $linkFrame ? header(-target => $linkFrame) : "", 1.357 + redirect('-location'=> $$matches[0][1]); 1.358 + } 1.359 +} 1.360 + 1.361 + 1.362 +sub displayMatches 1.363 +{ 1.364 + my $matches = shift; 1.365 + 1.366 + if ( $#$matches < 0 ) 1.367 + { 1.368 + print p("No matches"); 1.369 + } 1.370 + else 1.371 + { 1.372 + print 1.373 + p( 1.374 + "Searching pattern ", em(escapeHTML(param('pattern'))), 1.375 + " in ", em(escapeHTML($$searchTypes{param('type')}))), 1.376 + h2("Search results"), 1.377 + "<ul>"; 1.378 + 1.379 + foreach my $match (@$matches) 1.380 + { 1.381 + my $searchKey = escapeHTML(shift @$match); 1.382 + my $cnt = -1; 1.383 + print li( map { 1.384 + a( $linkFrame ? {-href => $_, -target => $linkFrame } : { -href => $_}, ( $cnt++ >= 0 ? "alt".($cnt) : $searchKey) ) 1.385 + } @$match ); 1.386 + 1.387 + } 1.388 + 1.389 + print "</ul>"; 1.390 + } 1.391 +} 1.392 + 1.393 +# 1.394 +# main 1.395 +# 1.396 +use vars qw / $opt_h $opt_r /; 1.397 + 1.398 +if (server_software() eq 'cmdline') 1.399 +{ 1.400 + getopts("rh"); 1.401 + 1.402 + if ($opt_h) 1.403 + { 1.404 + usage; 1.405 + exit; 1.406 + } 1.407 + 1.408 + if ($opt_r) 1.409 + { 1.410 + indexRebuild; 1.411 + indexWrite; 1.412 + exit; 1.413 + } 1.414 +} 1.415 + 1.416 + 1.417 +if (param('render')) 1.418 +{ 1.419 + $resultFrame = 'results'; 1.420 + $linkFrame = ''; 1.421 +} 1.422 + 1.423 +my $thisFrame = param('render'); 1.424 + 1.425 +if ($thisFrame eq 'topFrame') 1.426 +{ 1.427 + print topFrameGenerate(); 1.428 + exit 0; 1.429 +} 1.430 +elsif ($thisFrame eq 'noResults') 1.431 +{ 1.432 + print noResultsGenerate(); 1.433 + exit 0; 1.434 +} 1.435 + 1.436 +unless (param('lucky') and param('pattern')) 1.437 +{ 1.438 + print 1.439 + header, 1.440 + start_html('Javadoc search'), 1.441 + defined(param('pattern')) && $resultFrame ? "" : searchFormGenerate(); 1.442 +} 1.443 + 1.444 +if (param('pattern')) 1.445 +{ 1.446 + my $matches = doSearch(param('pattern'), param('type'), param('results')); 1.447 + 1.448 + if (param('lucky')) 1.449 + { 1.450 + displayLuckyMatch($matches); 1.451 + } 1.452 + else 1.453 + { 1.454 + displayMatches($matches); 1.455 + } 1.456 +} 1.457 +else 1.458 +{ 1.459 + if ($thisFrame ne 'query') 1.460 + { 1.461 + print p('Specify non-blank search pattern'); 1.462 + } 1.463 +} 1.464 + 1.465 +unless (param('lucky') and param('pattern')) 1.466 +{ 1.467 + print end_html; 1.468 +}