diff options
author | Arne Georg Gleditsch <argggh@lxr.linpro.no> | 2007-12-04 08:45:41 +0100 |
---|---|---|
committer | Arne Georg Gleditsch <argggh@lxr.linpro.no> | 2007-12-04 08:45:41 +0100 |
commit | 15f50e9ba5f64594ac610ad42ac75e484147f8a2 (patch) | |
tree | 7de2a7e6bcee6dd6b369c4cb3b6a6aaf512eff35 | |
parent | 8c290c3b917b1683a8f4355019366d45d5ddb42f (diff) |
Add file search caps, some tuning.
-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 d4fdadf..c6c0556 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 %] |