diff options
| -rw-r--r-- | cgi-bin/css/lxrng.css | 22 | ||||
| -rwxr-xr-x | cgi-bin/lxr | 33 | ||||
| -rw-r--r-- | lib/LXRng/Index/DBI.pm | 114 | ||||
| -rw-r--r-- | lib/LXRng/Index/Generic.pm | 11 | ||||
| -rw-r--r-- | lib/LXRng/Lang.pm | 2 | ||||
| -rw-r--r-- | lib/LXRng/Search/Xapian.pm | 4 | ||||
| -rw-r--r-- | tmpl/search_result.tt2 | 117 | 
7 files changed, 195 insertions, 108 deletions
diff --git a/cgi-bin/css/lxrng.css b/cgi-bin/css/lxrng.css index d8c18d3..f5d84c0 100644 --- a/cgi-bin/css/lxrng.css +++ b/cgi-bin/css/lxrng.css @@ -1,3 +1,5 @@ +/* -*- mode: fundamental -*- */ +  body {   	font-family: sans-serif;  	margin-top: 3px; @@ -114,8 +116,28 @@ body.popup div.search_results {  	margin: 1px;  } +span.identtype {  +	display: block; +/*	font-weight: bold; */ +	font-style: italic; +	margin-top: 10px; +	margin-left: 1em; +} + +span.resultline { +	display: block; +	margin-left: 2em; +} + +span.resultdetails { +	font-size: 75%; +/*	font-style: italic; */ +}  +  div.query_desc {  	font-weight: bold; +	margin-top: 10px; +	margin-bottom: 5px;  }  span.close-button { diff --git a/cgi-bin/lxr b/cgi-bin/lxr index 375b640..719bf96 100755 --- a/cgi-bin/lxr +++ b/cgi-bin/lxr @@ -307,9 +307,24 @@ sub search {      if ($find =~ /\S/) { +	if ($find =~ /^(ident|code):(.*)/) { +	    $type = 'code'; +	    $find = $2; +	} +	elsif ($find =~ /^(file|path):(.*)/) { +	    $type = 'file'; +	    $find = $2; +	} +	elsif ($find =~ /^(text):(.*)/) { +	    $type = 'text'; +	    $find = $2; +	} +  	if ($type eq 'file' or $type eq 'search') { -	    # $template_args{'file_res'} = {'query' => $find, -	    #				  'files' => \@args,} +	    my $files = $index->files_by_wildcard($context->tree, +						  $ver, $find); +	    $template_args{'file_res'} = {'query' => $find, +	    				  'files' => $files,}  	}  	if ($type eq 'text' or $type eq 'search') {  	    my $hash  = $context->config->{'search'}; @@ -320,12 +335,14 @@ sub search {  					  'files' => $res};  	}  	if ($type eq 'code' or $type eq 'search') { -	    my $result = $index->symbols_by_name($context->tree, $ver, $find); -	    my @cooked = (map { $$_[1] = $LXRng::Lang::deftypes{$$_[1]}; -				$$_[5] &&= $LXRng::Lang::deftypes{$$_[5]}; +	    my $result = $index->identifiers_by_name($context->tree,  +						     $ver, $find); +	    my @cooked = (map { $$_[1] = ucfirst($LXRng::Lang::deftypes{$$_[1]});  				$_ }  			  sort { $LXRng::Lang::defweight{$$a[1]} cmp -				     $LXRng::Lang::defweight{$$b[1]} } +				     $LXRng::Lang::defweight{$$b[1]} || +				 $$a[2] cmp $$b[2] || +				 $$a[3] <=> $$b[3] }  			  @$result);  	    $template_args{'code_res'} = {'query' => $find,  					  'idents' => \@cooked}; @@ -335,11 +352,9 @@ sub search {  	    my ($symname, $symid, $ident, $refs) =  		$index->get_identifier_info($usage, $find, $rel_id); -	    $$ident[1] = $LXRng::Lang::deftypes{$$ident[1]}; +	    $$ident[1] = ucfirst($LXRng::Lang::deftypes{$$ident[1]});  	    $$ident[5] &&= $LXRng::Lang::deftypes{$$ident[5]}; -	    # use Data::Dumper; -	    # warn Dumper($symname, $symid, $ident, $refs);  	    $template_args{'ident_res'} = {'query' => $symname,  					   'ident' => $ident,  					   'refs' => $refs}; diff --git a/lib/LXRng/Index/DBI.pm b/lib/LXRng/Index/DBI.pm index 7f94a6f..2069db3 100644 --- a/lib/LXRng/Index/DBI.pm +++ b/lib/LXRng/Index/DBI.pm @@ -278,27 +278,16 @@ sub _identifiers_by_name {      my $pre = $self->prefix;      my $sth = $$self{'sth'}{'_identifiers_by_name'} ||=  	$dbh->prepare(qq{ -	    select i.id, i.type, f.path, i.line, s.name, c.type, c.id,  -	    i.id_rfile -		from ${pre}identifiers i -	        left outer join ${pre}identifiers c on i.context = c.id -		left outer join ${pre}symbols s on c.id_symbol = s.id, -		${pre}files f, ${pre}filereleases r, ${pre}revisions v +	    select i.id, i.type, f.path, i.line, i.id_rfile +		from ${pre}identifiers i, ${pre}files f, +			 ${pre}filereleases r, ${pre}revisions v  		where i.id_rfile = v.id and v.id = r.id_rfile   		and r.id_release = ? and v.id_file = f.id  -		and i.id_symbol = ?}); +		and i.id_symbol = ? limit 500});      $sth->execute($rel_id, $sym_id);      my $res = $sth->fetchall_arrayref(); -    use Data::Dumper; -    foreach my $def (@$res) { -#	warn Dumper($def); -	$$def[7] = 42; -#	my @files = $self->get_referring_files($rel_id, $$def[7]); -#	warn Dumper(\@files); -    } -      return $res;  } @@ -354,34 +343,46 @@ sub _rfile_path_by_id {  sub _get_includes_by_file {      my ($self, $res, $rel_id, @rfile_ids) = @_; -    my $placeholders = join(', ', ('?') x @rfile_ids); -    my $dbh = $self->dbh; -    my $pre = $self->prefix; -    my $sth = $dbh->prepare(qq{select rf.id, f.path  -				   from ${pre}revisions rf, -				   ${pre}filereleases v, -				   ${pre}includes i, -				   ${pre}revisions ri, -				   ${pre}files f -				   where rf.id = i.id_rfile -				   and rf.id_file = f.id -				   and rf.id = v.id_rfile -				   and v.id_release = ? -				   and i.id_include_path = ri.id_file -				   and ri.id in ($placeholders)}); - - -    $sth->execute($rel_id, @rfile_ids); -    my $files = $sth->fetchall_arrayref(); -    $sth->finish(); -      my @recurse; -    foreach my $r (@$files) { -	push(@recurse, $$r[0]) unless exists($$res{$$r[0]}); +    while (@rfile_ids > 0) { +	my @rfile_batch = splice(@rfile_ids, 0, 8192); + +	my $dbh = $self->dbh; +	my $pre = $self->prefix; +	my $sth; + +	$sth = $$self{'sth'}{'get_includes_by_file'} if +	    @rfile_batch == 1024; + +	unless ($sth) { +	    my $placeholders = join(', ', ('?') x @rfile_batch); +	    $sth = $dbh->prepare(qq{select rf.id, f.path  +					from ${pre}revisions rf, +					${pre}filereleases v, +					${pre}includes i, +					${pre}revisions ri, +					${pre}files f +					where rf.id = i.id_rfile +					and rf.id_file = f.id +					and rf.id = v.id_rfile +					and v.id_release = ? +					and i.id_include_path = ri.id_file +					and ri.id in ($placeholders)}); + +	    $$self{'sth'}{'get_includes_by_file'} = $sth if +		@rfile_batch == 8192; +	} -	$$res{$$r[0]} = $$r[1]; -    } +	$sth->execute($rel_id, @rfile_batch); +	my $files = $sth->fetchall_arrayref(); +	$sth->finish(); +	foreach my $r (@$files) { +	    push(@recurse, $$r[0]) unless exists($$res{$$r[0]}); + +	    $$res{$$r[0]} = $$r[1]; +	} +    }      $self->_get_includes_by_file($res, $rel_id, @recurse) if @recurse;      return 1; @@ -512,4 +513,37 @@ sub get_rfile_timestamp {      return ($epoch, $tz);  }     +sub files_by_wildcard { +    my ($self, $tree, $release, $query) = @_; + +    return [] unless $query =~ /[a-zA-Z0-9]/; +     +    my $rel_id = $self->release_id($tree, $release); +    return [] unless $rel_id; + +    $query =~ tr/\?\*/_%/; +    unless ($query =~ s,^/,,) { +	# Absolute path queries are left alone, module leading-slash-removal. +	$query = '%'.$query.'%'; +    } + +    my $dbh = $self->dbh; +    my $pre = $self->prefix; +    my $sth = $$self{'sth'}{'files_by_wildcard'} ||= +	$dbh->prepare(qq{ +	    select f.path +		from lxgit_files f, lxgit_revisions v, lxgit_filereleases r +		where f.path like ? and f.id = v.id_file and v.id = r.id_rfile +		and r.id_release = ? +		order by f.path}); + +    $sth->execute($query, $rel_id); +    my @res; +    while (my ($path) = $sth->fetchrow_array()) { +	push(@res, $path); +    } + +    return \@res; +} +  1; diff --git a/lib/LXRng/Index/Generic.pm b/lib/LXRng/Index/Generic.pm index c756b5f..dfeb754 100644 --- a/lib/LXRng/Index/Generic.pm +++ b/lib/LXRng/Index/Generic.pm @@ -102,11 +102,6 @@ sub includes_by_file {      return $self->_includes_by_id($file_id);  } -#sub add_symbol { -#    my ($self, $file_id, $line, $symbol, $type, $ctx_id) = @_; -#    return $self->_add_symbol($file_id, $line, $symbol, $type, $ctx_id); -#} -  sub add_ident {      my ($self, $rfile_id, $line, $symbol, $type, $ctx_id) = @_; @@ -121,14 +116,12 @@ sub symbol_by_id {      return $self->_symbol_by_id($id);  } -sub symbols_by_name { +sub identifiers_by_name {      my ($self, $tree, $release, $symbol) = @_;      my $rel_id = $self->release_id($tree, $release); -#    return $cache_sym{$rel_id}{$symbol} if -#	exists $cache_sym{$rel_id} and exists $cache_sym{$rel_id}{$symbol}; +      return $self->_identifiers_by_name($rel_id, $symbol); -#    $cache_sym{$rel_id}{$symbol} = $id;  }  sub symbols_by_file { diff --git a/lib/LXRng/Lang.pm b/lib/LXRng/Lang.pm index 754cb72..1ed134c 100644 --- a/lib/LXRng/Lang.pm +++ b/lib/LXRng/Lang.pm @@ -25,7 +25,7 @@ use vars qw(@languages %deftypes %defweight);  %defweight = do { my $i = 0;   		  map { $_ => $i++ } -		  qw(c f i n s t u p x v d e g m l) }; +		  qw(c p f i n s t u x v d e g m l) };  sub init { diff --git a/lib/LXRng/Search/Xapian.pm b/lib/LXRng/Search/Xapian.pm index 769cb9c..6f29c46 100644 --- a/lib/LXRng/Search/Xapian.pm +++ b/lib/LXRng/Search/Xapian.pm @@ -186,6 +186,9 @@ sub get_symbol_usage {      my $match = $matches->begin();      my $i = 0; +    my $lines = 0; + +  match:      while ($i++ < $size) {  	my $term = $enq->get_matching_terms_begin($match);  	my $termend = $enq->get_matching_terms_end($match); @@ -197,6 +200,7 @@ sub get_symbol_usage {  		while ($pos ne $posend) {  		    $res{$match->get_document->get_data()}{0+$pos} = 1;  		    $pos++; +		    last match if $lines++ > 1000;  		}  	    }  	    $term++; diff --git a/tmpl/search_result.tt2 b/tmpl/search_result.tt2 index d093968..cc2af1c 100644 --- a/tmpl/search_result.tt2 +++ b/tmpl/search_result.tt2 @@ -4,63 +4,82 @@  </span>  [% IF search_type == "code" or (code_res and code_res.idents.0) %] -<div class="query_desc">Code search: [% code_res.query %]</div> -<ul> -[% FOREACH ident = code_res.idents %] -<li><a class="iref"  -  href="+ident=[% ident.0 %][% IF navtarget %]?nav[% navtarget %][% END %]" -  onclick="return ajax_lookup_anchor(null, this);"> -[% ident.1 %]</a> at [% INCLUDE line_reference.tt2, file = ident.2, line = ident.3 %] -</li> -[% END %] -</ul> +  <div class="query_desc">Code search: [% code_res.query %]</div> +  [% ptype = '' %] +  [% FOREACH ident = code_res.idents %] +    [% IF ptype != ident.1 %] +      <span class="identtype">[% ident.1 %]</span> +      [% ptype = ident.1 %] +    [% END %] +    <span class="resultline"> +      [% INCLUDE line_reference.tt2, file = ident.2, line = ident.3 %] +      <span class="resultdetails">[<a class="iref" +          href="+ident=[% ident.0 %][% IF navtarget %]?nav[% navtarget %][% END %]" +          onclick="return ajax_lookup_anchor(null, this);">usage...</a>]</span> +    </span> +  [% END %]  [% END %]  [% IF ident_res %] -<div class="query_desc">Identifier: -[% ident_res.ident.1 %] -<a class="sref" -  href="+code=[% ident_res.query %][% IF navtarget %]?nav[% navtarget %][% END %]" -  onclick="return ajax_lookup_anchor(null, this);"> -[% ident_res.query %]</a>, from  -[% INCLUDE line_reference.tt2, -	 file = ident_res.ident.2, line = ident_res.ident.3 %] -</div> -<em>References:</em> -<ul> -[% FOREACH file = ident_res.refs.keys %] -[% FOREACH line = ident_res.refs.$file %] -<li> -[% INCLUDE line_reference.tt2, -	 file = file, line = line %] -</li> -[% END %] -[% END %] -</ul> -[% END %] +  <div class="query_desc">Identifier: +    <a class="sref" +        href="+code=[% ident_res.query %][% IF navtarget %]?nav[% navtarget %][% END %]" +        onclick="return ajax_lookup_anchor(null, this);"> +      [% ident_res.query %] +    </a> +  </div> +  <span class="identdesc"> +    [% ident_res.ident.1 %] +    [% IF ident_res.ident.4 %] +      in [% ident_res.ident.5 %] +      <a class="iref" +          href="+ident=[% ident_res.ident.6 %][% IF navtarget %]?nav[% navtarget %][% END %]" +          onclick="return ajax_lookup_anchor(null, this);"> +        [% ident_res.ident.4 %] +      </a> +    [% END %] +    at +  </span> +  [% INCLUDE line_reference.tt2, +	file = ident_res.ident.2, line = ident_res.ident.3 %] -[% IF text_res %] -<div class="query_desc">Freetext search: [% text_res.query %] -([% text_res.total %] estimated hits)</div> -<ul> -[% FOREACH file = text_res.files %] -<li>[% file.0 %]% -at [% INCLUDE line_reference.tt2, file = file.1, line = file.2 %] -</li> -[% END %] -</ul> +  [% FOREACH file = ident_res.refs.keys.sort %] +    [% IF loop.first %] +      <span class="identtype">References:</span> +    [% END %] + +    [% FOREACH line = ident_res.refs.$file %] +      <span class="resultline"> +        [% INCLUDE line_reference.tt2, +	  file = file, line = line %] +      </span> +    [% END %] +  [% END %]  [% END %]  [% IF file_res %] -<div class="query_desc">Filename search: [% file_res.query %]</div> -<ul> -[% FOREACH file = file_res.files %] -<li><a href="[% file %]" onclick="return load_file('[% context.tree %]', -       '[% file %][% context.args_url %]', '[% context.release %]', '');" -    [% navtarget %]>[% file %]</a> -</li> +  [% FOREACH file = file_res.files %] +    [% IF loop.first %] +      <div class="query_desc">Filename search: [% file_res.query %]</div> +    [% END %] +    <span class="resultline"> +      <a href="[% file %]" onclick="return load_file('[% context.tree %]', +        '[% file %][% context.args_url %]', '[% context.release %]', '');" +        [% navtarget %]>[% file %]</a> +    </span> +  [% END %]  [% END %] -</ul> + +[% IF text_res %] +  <div class="query_desc">Freetext search: [% text_res.query %] +    ([% text_res.total %] estimated hits)</div> + +  [% FOREACH file = text_res.files %] +    <span class="resultline"> +      [% INCLUDE line_reference.tt2, file = file.1, line = file.2 %] +      <span class="resultdetails">([% file.0 %]%)</span> +    </span> +  [% END %]  [% END %]  [% IF ambig_res %]  | 
