Improve the documentation search code.

Instead of just one array for exact results and one for all the rest,
use one array for each possible comparison result, and concatenate them
all for the final list.
This commit is contained in:
Eli Barzilay 2012-06-14 11:08:09 -04:00
parent 41745e4f38
commit ecc43ff104

View File

@ -246,26 +246,26 @@ function AdjustResultsNum() {
}
}
// Terms are compared using Compare(), which returns one of several constants:
// - C_fail: there was no match
// - C_match: there was a match somewhere in the string
// - C_prefix: there was a prefix match (starts at 0)
// - C_rexact: there was a ("real") exact match
// There is also C_exact which can be returned by some of the X: operators.
// It's purpose is to be able to return a result that doesn't affect the
// exactness of the search (for example L:foo searches for a source module that
// is exactly `foo', but it will return C_exact which means that it doesn't
// change whether the match is considered exact or not). Note that these
// constants are ordered, so:
// - < exact => this match is inexact
// - = exact => does not affect the exactness of this match
// - > exact => this is an exact match as far as this predicate goes
// Finally, there is also a C_wordmatch that is used when there is no proper
// match, but all the words in the term match (where a word is an alphanumeric
// sequence or a punctuation, for example, "foo-bar!!" has these words: "foo",
// "-", "bar", "!!")
// Terms are compared using Compare(pat,str), which returns one of several
// constants, in increasing order of success:
// - C_fail: no match
// - C_words: all of the "subwords" in pat matched, where a word is an
// alphanumeric or a punctuation substring (for example, "foo-bar!!" has
// these words: "foo", "-", "bar", "!!"), and a match means a prefix of a
// subword in str matched one of pat's subwords
// - C_match: pat matched somewhere in str
// - C_prefix: pat is a prefix of str
// - C_exact: pat is equal to str
// - C_rexact: there was a ("real") exact match, see below
// Note that the value is searched from the last one and going back, so, for
// example, if pat is a prefix of str the result is C_prefix, and no subword
// matching is attempted. A result of C_exact can be returned by some of the
// `X:' operators: its purpose is to be able to return a result that doesn't
// affect the exactness of the search (for example L:foo searches for a source
// module that is exactly `foo', but it will return C_exact which means that it
// doesn't change whether the match is considered exact or not).
var C_fail = 0, C_min = 0,
C_wordmatch = 1,
C_words = 1,
C_match = 2,
C_prefix = 3,
C_exact = 4,
@ -287,18 +287,18 @@ function CompareRx(pat, str) {
return C_match;
}
function MaxCompares(pat, strs) {
var r = C_min;
var r = C_min, c;
for (var i=0; i<strs.length; i++) {
r = Math.max(r, Compare(pat,strs[i]));
if (r >= C_max) return r;
c = Compare(pat,strs[i]);
if (c > r) { if (c >= C_max) return c; else r = c; }
}
return r;
}
function MinComparesRx(pats, str) {
var r = C_max;
var r = C_max, c;
for (var i=0; i<pats.length; i++) {
r = Math.min(r, CompareRx(pats[i],str));
if (r <= C_min) return r;
c = CompareRx(pats[i],str);
if (c < r) { if (c <= C_min) return c; else r = c; }
}
return r;
}
@ -329,9 +329,10 @@ function UrlToManual(url) {
// Tests for matches and highlights:
// "append"
// "L:scheme append"
// "L:scheme" (no exact matches except for the `scheme' module)
// "L:schem" (only module names that match `schem')
// "L:racket append"
// "L:racket" (no exact matches except for the `racket' module)
// "L:racke" (only module names that match `racke')
// "edi" and "edit" (the top few should be the same)
// Additional "hidden" operators:
// "A:{ foo bar }" -- an `and' query
@ -374,24 +375,24 @@ function CompileTerm(term) {
for (var i=0; i<words.length; i++)
if (words[i].search(/^\w/) >= 0) words[i] = new RegExp("\\b"+words[i]);
// (note: seems like removing duplicates is not important since search
// strings will not have them, except, maybe, for an occasional x-y-z)
// strings will not have them, except for dashes in things like x-y-z)
return function(x) {
var r = Compare(term,x[0]);
// only bindings can be used for exact matches
if (r >= C_exact) return (x[3] ? C_rexact : C_match);
if (r >= C_match) return r;
if (MinComparesRx(words,x[0]) > C_fail) return C_wordmatch;
return r;
// only bindings can be used for rexact matches
if (r >= C_rexact) return (x[3] ? r : C_exact);
if (r > C_words) return r;
if (MinComparesRx(words,x[0]) <= C_fail) return r;
return C_words;
}
}
}
function CompileAndTerms(preds) {
return function(x) {
var r = C_max;
var r = C_max, c;
for (var i=0; i<preds.length; i++) {
r = Math.min(r, preds[i](x));
if (r <= C_min) return r;
c = preds[i](x);
if (c < r) { if (c <= C_min) return c; else r = c; }
}
return r;
};
@ -399,10 +400,10 @@ function CompileAndTerms(preds) {
function CompileOrTerms(preds) {
return function(x) {
var r = C_min;
var r = C_min, c;
for (var i=0; i<preds.length; i++) {
r = Math.max(r, preds[i](x));
if (r >= C_max) return r;
c = preds[i](x);
if (c > r) { if (c >= C_max) return c; else r = c; }
}
return r;
};
@ -471,27 +472,32 @@ function Search(data, term, is_pre, K) {
if (K) { K(ret); return killer; }
else return ret;
}
var matches = new Array(), exacts = new Array(), wordmatches = new Array();
var i = 0;
var matches = new Array(C_max-C_min);
for (i=0; i<matches.length; i++) matches[i] = new Array();
var chunk_fuel = K ? Math.round(data.length/10) : data.length;
var progress = K ? MakeShowProgress() : Id;
i = 0;
var DoChunk = function() {
var fuel = Math.min(chunk_fuel, data.length-i);
progress(i+fuel);
while (fuel > 0) {
var r, min = C_max, max = C_min;
for (var j=0; j<preds.length; j++) {
r = preds[j](data[i]); min = Math.min(r, min); max = Math.max(r, max);
if (min <= C_min) break; // get out if it's hopeless
r = preds[j](data[i]);
if (r < min) {
min = r;
if (r <= C_min) break; // get out if it's hopeless
}
if (max >= C_rexact && min >= C_exact) exacts.push(data[i]);
else if (min > C_wordmatch) matches.push(data[i]);
else if (min > C_fail) wordmatches.push(data[i]);
if (r > max) max = r;
}
if (max >= C_rexact && min >= C_exact) min = C_rexact;
if (min > C_min) matches[C_max - min].push(data[i]);
fuel--; i++;
}
if (i<data.length) t = setTimeout(DoChunk,5);
else {
r = [exacts.length, exacts.concat(matches).concat(wordmatches)];
r = [matches[0].length, [].concat.apply([],matches)];
if (K) K(r); else return r;
}
};