aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArne Georg Gleditsch <argggh@lxr.linpro.no>2007-12-04 08:45:41 +0100
committerArne Georg Gleditsch <argggh@lxr.linpro.no>2007-12-04 08:45:41 +0100
commit15f50e9ba5f64594ac610ad42ac75e484147f8a2 (patch)
tree7de2a7e6bcee6dd6b369c4cb3b6a6aaf512eff35
parent8c290c3b917b1683a8f4355019366d45d5ddb42f (diff)
Add file search caps, some tuning.
-rw-r--r--cgi-bin/css/lxrng.css22
-rwxr-xr-xcgi-bin/lxr33
-rw-r--r--lib/LXRng/Index/DBI.pm114
-rw-r--r--lib/LXRng/Index/Generic.pm11
-rw-r--r--lib/LXRng/Lang.pm2
-rw-r--r--lib/LXRng/Search/Xapian.pm4
-rw-r--r--tmpl/search_result.tt2117
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 %]