mirror of
				https://github.com/prometheus/prometheus.git
				synced 2025-10-31 16:31:03 +01:00 
			
		
		
		
	The fuzzy library didn't try to find a "best match", but settled on the first fuzzy match that exists. This patch includes a modified version of the fuzzy library, which recursivley tries on the rest of the search string to find a better match. If found, returns that one. Another small modification is that if a pattern fully matches, it skips the lookup entirley and returns the highest score possible for that match.
		
			
				
	
	
		
			183 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			183 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /*
 | |
|  * Fuzzy
 | |
|  * https://github.com/myork/fuzzy
 | |
|  *
 | |
|  * Copyright (c) 2012 Matt York
 | |
|  *
 | |
|  * Permission is hereby granted, free of charge, to any person
 | |
|  * obtaining a copy of this software and associated documentation
 | |
|  * files (the "Software"), to deal in the Software without
 | |
|  * restriction, including without limitation the rights to use,
 | |
|  * copy, modify, merge, publish, distribute, sublicense, and/or sell
 | |
|  * copies of the Software, and to permit persons to whom the
 | |
|  * Software is furnished to do so, subject to the following
 | |
|  * conditions:
 | |
|  *
 | |
|  * The above copyright notice and this permission notice shall be
 | |
|  * included in all copies or substantial portions of the Software.
 | |
|  *
 | |
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 | |
|  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 | |
|  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 | |
|  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 | |
|  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 | |
|  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 | |
|  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 | |
|  * OTHER DEALINGS IN THE SOFTWARE.
 | |
|  *
 | |
|  * A slightly modified version of https://github.com/mattyork/fuzzy/blob/3613086aa40c180ca722aeaf48cef575dc57eb5d/lib/fuzzy.js
 | |
|  */
 | |
| 
 | |
| (function() {
 | |
| 
 | |
| var root = this;
 | |
| 
 | |
| var fuzzy = {};
 | |
| 
 | |
| // Use in node or in browser
 | |
| if (typeof exports !== 'undefined') {
 | |
|   module.exports = fuzzy;
 | |
| } else {
 | |
|   root.fuzzy = fuzzy;
 | |
| }
 | |
| 
 | |
| // Return all elements of `array` that have a fuzzy
 | |
| // match against `pattern`.
 | |
| fuzzy.simpleFilter = function(pattern, array) {
 | |
|   return array.filter(function(str) {
 | |
|     return fuzzy.test(pattern, str);
 | |
|   });
 | |
| };
 | |
| 
 | |
| // Does `pattern` fuzzy match `str`?
 | |
| fuzzy.test = function(pattern, str) {
 | |
|   return fuzzy.match(pattern, str) !== null;
 | |
| };
 | |
| 
 | |
| // If `pattern` matches `str`, wrap each matching character
 | |
| // in `opts.pre` and `opts.post`. If no match, return null
 | |
| fuzzy.match = function(pattern, str, opts, _fromIndex) {
 | |
|   opts = opts || {};
 | |
|   var patternIdx = 0
 | |
|     , result = []
 | |
|     , len = str.length
 | |
|     , fromIndex = _fromIndex || 0
 | |
|     , totalScore = 0
 | |
|     , currScore = 0
 | |
|     // prefix
 | |
|     , pre = opts.pre || ''
 | |
|     // suffix
 | |
|     , post = opts.post || ''
 | |
|     // String to compare against. This might be a lowercase version of the
 | |
|     // raw string
 | |
|     , compareString =  opts.caseSensitive && str || str.toLowerCase()
 | |
|     , ch;
 | |
| 
 | |
|   pattern = opts.caseSensitive && pattern || pattern.toLowerCase();
 | |
| 
 | |
|   // If there's an exact match, add pre/post, max out score and skip the lookup
 | |
|   if (compareString === pattern) {
 | |
|     return {
 | |
|       rendered: pre + compareString.split('').join(post+pre) + post,
 | |
|       score: Infinity
 | |
|     };
 | |
|   }
 | |
| 
 | |
|   // For each character in the string, either add it to the result
 | |
|   // or wrap in template if it's the next string in the pattern
 | |
|   for(var idx = 0; idx < len; idx++) {
 | |
|     ch = str[idx];
 | |
|     if(idx >= fromIndex && compareString[idx] === pattern[patternIdx]) {
 | |
|       ch = pre + ch + post;
 | |
|       patternIdx += 1;
 | |
| 
 | |
|       // consecutive characters should increase the score more than linearly
 | |
|       currScore += 1 + currScore;
 | |
|     } else {
 | |
|       currScore = 0;
 | |
|     }
 | |
|     totalScore += currScore;
 | |
|     result[result.length] = ch;
 | |
|   }
 | |
| 
 | |
|   // return rendered string if we have a match for every char
 | |
|   if(patternIdx === pattern.length) {
 | |
|     var nextPossible = str.indexOf(pattern[0], str.indexOf(pattern[0], fromIndex) + 1)
 | |
|       , candidate;
 | |
| 
 | |
|     // If possible, try to find a better match at the rest of the string
 | |
|     if (nextPossible > -1 && str.length - nextPossible >= pattern.length) {
 | |
|       var candidate = fuzzy.match(pattern, str, opts, nextPossible);
 | |
|     }
 | |
| 
 | |
|     return candidate && candidate.score > totalScore ? candidate : {
 | |
|       rendered: result.join(''), score: totalScore
 | |
|     };
 | |
|   }
 | |
| 
 | |
|   return null;
 | |
| };
 | |
| 
 | |
| // The normal entry point. Filters `arr` for matches against `pattern`.
 | |
| // It returns an array with matching values of the type:
 | |
| //
 | |
| //     [{
 | |
| //         string:   '<b>lah' // The rendered string
 | |
| //       , index:    2        // The index of the element in `arr`
 | |
| //       , original: 'blah'   // The original element in `arr`
 | |
| //     }]
 | |
| //
 | |
| // `opts` is an optional argument bag. Details:
 | |
| //
 | |
| //    opts = {
 | |
| //        // string to put before a matching character
 | |
| //        pre:     '<b>'
 | |
| //
 | |
| //        // string to put after matching character
 | |
| //      , post:    '</b>'
 | |
| //
 | |
| //        // Optional function. Input is an entry in the given arr`,
 | |
| //        // output should be the string to test `pattern` against.
 | |
| //        // In this example, if `arr = [{crying: 'koala'}]` we would return
 | |
| //        // 'koala'.
 | |
| //      , extract: function(arg) { return arg.crying; }
 | |
| //    }
 | |
| fuzzy.filter = function(pattern, arr, opts) {
 | |
|   if(!arr || arr.length === 0) {
 | |
|     return [];
 | |
|   }
 | |
|   if (typeof pattern !== 'string' || pattern === '') {
 | |
|     return arr;
 | |
|   }
 | |
|   opts = opts || {};
 | |
|   return arr
 | |
|     .reduce(function(prev, element, idx, arr) {
 | |
|       var str = element;
 | |
|       if(opts.extract) {
 | |
|         str = opts.extract(element);
 | |
|       }
 | |
|       var rendered = fuzzy.match(pattern, str, opts);
 | |
|       if(rendered != null) {
 | |
|         prev[prev.length] = {
 | |
|             string: rendered.rendered
 | |
|           , score: rendered.score
 | |
|           , index: idx
 | |
|           , original: element
 | |
|         };
 | |
|       }
 | |
|       return prev;
 | |
|     }, [])
 | |
| 
 | |
|     // Sort by score. Browsers are inconsistent wrt stable/unstable
 | |
|     // sorting, so force stable by using the index in the case of tie.
 | |
|     // See http://ofb.net/~sethml/is-sort-stable.html
 | |
|     .sort(function(a,b) {
 | |
|       var compare = b.score - a.score;
 | |
|       if(compare) return compare;
 | |
|       return a.index - b.index;
 | |
|     });
 | |
| };
 | |
| 
 | |
| 
 | |
| }());
 |