|
58 | 58 | }
|
59 | 59 | $('#' + from)[0].scrollIntoView();
|
60 | 60 | $('.line-numbers span').removeClass('line-highlighted');
|
61 |
| - for (i = from; i <= to; i += 1) { |
| 61 | + for (i = from; i <= to; ++i) { |
62 | 62 | $('#' + i).addClass('line-highlighted');
|
63 | 63 | }
|
64 | 64 | }
|
|
99 | 99 | stripped = '',
|
100 | 100 | len = rootPath.match(/\.\.\//g).length + 1;
|
101 | 101 |
|
102 |
| - for (i = 0; i < len; i += 1) { |
| 102 | + for (i = 0; i < len; ++i) { |
103 | 103 | match = url.match(/\/[^\/]*$/);
|
104 | 104 | if (i < len - 1) {
|
105 | 105 | stripped = match[0] + stripped;
|
|
111 | 111 |
|
112 | 112 | document.location.href = url;
|
113 | 113 | });
|
| 114 | + /** |
| 115 | + * Code from Stackoverflow to compute the Levenshtein distance between two strings |
| 116 | + * Written by Marco de Wit at http://stackoverflow.com/a/18514751/745719 |
| 117 | + */ |
| 118 | + var levenshtein = (function() { |
| 119 | + var row2 = []; |
| 120 | + return function(s1, s2) { |
| 121 | + if (s1 === s2) { |
| 122 | + return 0; |
| 123 | + } else { |
| 124 | + var s1_len = s1.length, s2_len = s2.length; |
| 125 | + if (s1_len && s2_len) { |
| 126 | + var i1 = 0, i2 = 0, a, b, c, c2, row = row2; |
| 127 | + while (i1 < s1_len) |
| 128 | + row[i1] = ++i1; |
| 129 | + while (i2 < s2_len) { |
| 130 | + c2 = s2.charCodeAt(i2); |
| 131 | + a = i2; |
| 132 | + ++i2; |
| 133 | + b = i2; |
| 134 | + for (i1 = 0; i1 < s1_len; ++i1) { |
| 135 | + c = a + (s1.charCodeAt(i1) !== c2 ? 1 : 0); |
| 136 | + a = row[i1]; |
| 137 | + b = b < a ? (b < c ? b + 1 : c) : (a < c ? a + 1 : c); |
| 138 | + row[i1] = b; |
| 139 | + } |
| 140 | + } |
| 141 | + return b; |
| 142 | + } else { |
| 143 | + return s1_len + s2_len; |
| 144 | + } |
| 145 | + } |
| 146 | + }; |
| 147 | + })(); |
114 | 148 |
|
115 | 149 | function initSearch(rawSearchIndex) {
|
116 | 150 | var currentResults, index, searchIndex;
|
| 151 | + var MAX_LEV_DISTANCE = 3; |
117 | 152 | var params = getQueryStringParams();
|
118 | 153 |
|
119 | 154 | // Populate search bar with query string search term when provided,
|
|
140 | 175 | split = valLower.split("::");
|
141 | 176 |
|
142 | 177 | //remove empty keywords
|
143 |
| - for (var j = 0; j < split.length; j++) { |
| 178 | + for (var j = 0; j < split.length; ++j) { |
144 | 179 | split[j].toLowerCase();
|
145 | 180 | if (split[j] === "") {
|
146 | 181 | split.splice(j, 1);
|
|
153 | 188 | val.charAt(val.length - 1) === val.charAt(0))
|
154 | 189 | {
|
155 | 190 | val = val.substr(1, val.length - 2);
|
156 |
| - for (var i = 0; i < nSearchWords; i += 1) { |
| 191 | + for (var i = 0; i < nSearchWords; ++i) { |
157 | 192 | if (searchWords[i] === val) {
|
158 | 193 | // filter type: ... queries
|
159 | 194 | if (typeFilter < 0 || typeFilter === searchIndex[i].ty) {
|
|
167 | 202 | } else {
|
168 | 203 | // gather matching search results up to a certain maximum
|
169 | 204 | val = val.replace(/\_/g, "");
|
170 |
| - for (var i = 0; i < split.length; i++) { |
171 |
| - for (var j = 0; j < nSearchWords; j += 1) { |
| 205 | + for (var i = 0; i < split.length; ++i) { |
| 206 | + for (var j = 0; j < nSearchWords; ++j) { |
| 207 | + var lev_distance; |
172 | 208 | if (searchWords[j].indexOf(split[i]) > -1 ||
|
173 | 209 | searchWords[j].indexOf(val) > -1 ||
|
174 | 210 | searchWords[j].replace(/_/g, "").indexOf(val) > -1)
|
175 | 211 | {
|
176 | 212 | // filter type: ... queries
|
177 | 213 | if (typeFilter < 0 || typeFilter === searchIndex[j].ty) {
|
178 |
| - results.push({id: j, index: searchWords[j].replace(/_/g, "").indexOf(val)}); |
| 214 | + results.push({ |
| 215 | + id: j, |
| 216 | + index: searchWords[j].replace(/_/g, "").indexOf(val), |
| 217 | + lev: 0, |
| 218 | + }); |
| 219 | + } |
| 220 | + } else if ( |
| 221 | + (lev_distance = levenshtein(searchWords[j], val)) <= |
| 222 | + MAX_LEV_DISTANCE) { |
| 223 | + if (typeFilter < 0 || typeFilter === searchIndex[j].ty) { |
| 224 | + results.push({ |
| 225 | + id: j, |
| 226 | + index: 0, |
| 227 | + // we want lev results to go lower than others |
| 228 | + lev: lev_distance, |
| 229 | + }); |
179 | 230 | }
|
180 | 231 | }
|
181 | 232 | if (results.length === max) {
|
|
186 | 237 | }
|
187 | 238 |
|
188 | 239 | var nresults = results.length;
|
189 |
| - for (var i = 0; i < nresults; i += 1) { |
| 240 | + for (var i = 0; i < nresults; ++i) { |
190 | 241 | results[i].word = searchWords[results[i].id];
|
191 | 242 | results[i].item = searchIndex[results[i].id] || {};
|
192 | 243 | }
|
|
198 | 249 | results.sort(function(aaa, bbb) {
|
199 | 250 | var a, b;
|
200 | 251 |
|
| 252 | + // Sort by non levenshtein results and then levenshtein results by the distance |
| 253 | + // (less changes required to match means higher rankings) |
| 254 | + a = (aaa.lev); |
| 255 | + b = (bbb.lev); |
| 256 | + if (a !== b) return a - b; |
| 257 | + |
201 | 258 | // sort by crate (non-current crate goes later)
|
202 | 259 | a = (aaa.item.crate !== window.currentCrate);
|
203 | 260 | b = (bbb.item.crate !== window.currentCrate);
|
|
255 | 312 | results[i].id = -1;
|
256 | 313 | }
|
257 | 314 | }
|
258 |
| - for (var i = 0; i < results.length; i++) { |
| 315 | + for (var i = 0; i < results.length; ++i) { |
259 | 316 | var result = results[i],
|
260 | 317 | name = result.item.name.toLowerCase(),
|
261 | 318 | path = result.item.path.toLowerCase(),
|
|
285 | 342 | * @return {[boolean]} [Whether the result is valid or not]
|
286 | 343 | */
|
287 | 344 | function validateResult(name, path, keys, parent) {
|
288 |
| - //initially valid |
289 |
| - var validate = true; |
290 |
| - //if there is a parent, then validate against parent |
291 |
| - if (parent !== undefined) { |
292 |
| - for (var i = 0; i < keys.length; i++) { |
293 |
| - // if previous keys are valid and current key is in the |
294 |
| - // path, name or parent |
295 |
| - if ((validate) && |
296 |
| - (name.toLowerCase().indexOf(keys[i]) > -1 || |
297 |
| - path.toLowerCase().indexOf(keys[i]) > -1 || |
298 |
| - parent.name.toLowerCase().indexOf(keys[i]) > -1)) |
299 |
| - { |
300 |
| - validate = true; |
301 |
| - } else { |
302 |
| - validate = false; |
303 |
| - } |
304 |
| - } |
305 |
| - } else { |
306 |
| - for (var i = 0; i < keys.length; i++) { |
307 |
| - // if previous keys are valid and current key is in the |
308 |
| - // path, name |
309 |
| - if ((validate) && |
310 |
| - (name.toLowerCase().indexOf(keys[i]) > -1 || |
311 |
| - path.toLowerCase().indexOf(keys[i]) > -1)) |
312 |
| - { |
313 |
| - validate = true; |
314 |
| - } else { |
315 |
| - validate = false; |
316 |
| - } |
| 345 | + for (var i=0; i < keys.length; ++i) { |
| 346 | + // each check is for validation so we negate the conditions and invalidate |
| 347 | + if (!( |
| 348 | + // check for an exact name match |
| 349 | + name.toLowerCase().indexOf(keys[i]) > -1 || |
| 350 | + // then an exact path match |
| 351 | + path.toLowerCase().indexOf(keys[i]) > -1 || |
| 352 | + // next if there is a parent, check for exact parent match |
| 353 | + (parent !== undefined && |
| 354 | + parent.name.toLowerCase().indexOf(keys[i]) > -1) || |
| 355 | + // lastly check to see if the name was a levenshtein match |
| 356 | + levenshtein(name.toLowerCase(), keys[i]) <= |
| 357 | + MAX_LEV_DISTANCE)) { |
| 358 | + return false; |
317 | 359 | }
|
318 | 360 | }
|
319 |
| - return validate; |
| 361 | + return true; |
320 | 362 | }
|
321 | 363 |
|
322 | 364 | function getQuery() {
|
|
496 | 538 |
|
497 | 539 | resultIndex = execQuery(query, 20000, index);
|
498 | 540 | len = resultIndex.length;
|
499 |
| - for (i = 0; i < len; i += 1) { |
| 541 | + for (i = 0; i < len; ++i) { |
500 | 542 | if (resultIndex[i].id > -1) {
|
501 | 543 | obj = searchIndex[resultIndex[i].id];
|
502 | 544 | filterdata.push([obj.name, obj.ty, obj.path, obj.desc]);
|
|
568 | 610 | // faster analysis operations
|
569 | 611 | var len = items.length;
|
570 | 612 | var lastPath = "";
|
571 |
| - for (var i = 0; i < len; i += 1) { |
| 613 | + for (var i = 0; i < len; ++i) { |
572 | 614 | var rawRow = items[i];
|
573 | 615 | var row = {crate: crate, ty: rawRow[0], name: rawRow[1],
|
574 | 616 | path: rawRow[2] || lastPath, desc: rawRow[3],
|
|
640 | 682 | crates.push(crate);
|
641 | 683 | }
|
642 | 684 | crates.sort();
|
643 |
| - for (var i = 0; i < crates.length; i++) { |
| 685 | + for (var i = 0; i < crates.length; ++i) { |
644 | 686 | var klass = 'crate';
|
645 | 687 | if (crates[i] == window.currentCrate) {
|
646 | 688 | klass += ' current';
|
|
657 | 699 | window.register_implementors = function(imp) {
|
658 | 700 | var list = $('#implementors-list');
|
659 | 701 | var libs = Object.getOwnPropertyNames(imp);
|
660 |
| - for (var i = 0; i < libs.length; i++) { |
| 702 | + for (var i = 0; i < libs.length; ++i) { |
661 | 703 | if (libs[i] == currentCrate) continue;
|
662 | 704 | var structs = imp[libs[i]];
|
663 |
| - for (var j = 0; j < structs.length; j++) { |
| 705 | + for (var j = 0; j < structs.length; ++j) { |
664 | 706 | var code = $('<code>').append(structs[j]);
|
665 | 707 | $.each(code.find('a'), function(idx, a) {
|
666 | 708 | var href = $(a).attr('href');
|
|
0 commit comments