Skip to content

Commit

Permalink
Merge branch 'async'
Browse files Browse the repository at this point in the history
  • Loading branch information
mattyork committed Jan 3, 2015
2 parents c08e70a + 1da3cf2 commit bfbe805
Show file tree
Hide file tree
Showing 10 changed files with 90 additions and 60 deletions.
2 changes: 1 addition & 1 deletion .jshintrc
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@
"laxcomma": true,
"expr": true,
"strict": false,
"predef": ["describe", "it", "chai"]
"predef": ["describe", "it", "xit"]
}
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ all: fuzzy.js
fuzzy.js: lint test build

lint:
@./node_modules/jshint/bin/hint lib test examples \
@./node_modules/.bin/jshint lib test examples \
&& echo " ✔\033[32m passed jshint, yo! \033[0m"

test:
@./node_modules/mocha/bin/mocha
@./node_modules/.bin/mocha

build:
@./node_modules/uglify-js/bin/uglifyjs lib/fuzzy.js >fuzzy-min.js
@./node_modules/.bin/uglifyjs lib/fuzzy.js >fuzzy-min.js

clean:
rm fuzzy-min.js
Expand Down
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ Add unit tests for any new or changed functionality. Lint, test, and minify usin
v0.1.0 - July 25, 2012
## License
Copyright (c) 2012 Matt York
Copyright (c) 2015 Matt York
Licensed under the MIT license.
## TODO
Expand All @@ -107,3 +107,6 @@ Licensed under the MIT license.
a test already written, just need to implement it. Naive O(n^2) worst
case: find every match in the string, then select the highest scoring
match. Should benchmark this against current implementation once implemented
Also, "reactive rice" would be "<r><e>active r<i><c>e"
2. Async batch updates so the UI doesn't block for huge sets. Or maybe Web Workers?
3. Performance performance performance!
25 changes: 25 additions & 0 deletions bower.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"name": "fuzzy",
"version": "0.1.0",
"homepage": "https://github.com/mattyork/fuzzy",
"authors": [
"Matt York <york.matt@gmail.com>"
],
"description": "small, standalone fuzzy search / fuzzy filter like sublime text Cmd-P. browser or node.",
"main": "lib/fuzzy.js",
"keywords": [
"fuzzy",
"search",
"filter",
"sublime",
"sublime text"
],
"license": "MIT",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
]
}
17 changes: 9 additions & 8 deletions examples/directors.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,23 @@
// Each element in directors is an object, not a string. We can pass in a
// function that is called on each element in the array to extract the
// string to fuzzy search against. In this case, element.dir
, extract: function(element) {
return element.dir + '::' + element.movies;
, extract: function(entry) {
// return entry.dir + '::' + entry.movies;
return entry.dir;
}
}

// Filter!
var filtered = fuzzy.filter(search, directors, options);

// Map the results to the html we want generated
var results = filtered.slice(0,50).map(function(entry){
var items = entry.string.split('::');
var results = filtered.slice(0,50).map(function(result){
var items = result.string.split('::');
return listItemTemplate({
freebase: entry.original.fb
, director: items[0]
, movies: items[1]
, score: entry.score
freebase: result.original.fb
, director: result.string
, movies: result.original.movies
, score: result.score
});
});

Expand Down
2 changes: 1 addition & 1 deletion examples/disney.html
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@
listCharacters();

// Filter the characters on each change of the textbox
$('#search').on('keyup', listCharacters);
$('#search').on('keydown', listCharacters);
});
</script>
</head>
Expand Down
8 changes: 1 addition & 7 deletions fuzzy-min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

56 changes: 28 additions & 28 deletions lib/fuzzy.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ fuzzy.match = function(pattern, string, opts) {
pattern = opts.caseSensitive && pattern || pattern.toLowerCase();

// For each character in the string, either add it to the result
// or wrap in template if its the next string in the pattern
// or wrap in template if it's the next string in the pattern
for(var idx = 0; idx < len; idx++) {
ch = string[idx];
if(compareString[idx] === pattern[patternIdx]) {
Expand Down Expand Up @@ -95,40 +95,40 @@ fuzzy.match = function(pattern, string, opts) {
// // string to put after matching character
// , post: '</b>'
//
// // Optional function. Input is an element from the passed in
// // `arr`, output should be the string to test `pattern` against.
// // 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) {
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;
});
.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;
});
};


Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
"keywords": [
"fuzzy",
"search",
"filter"
"filter",
"sublime",
"sublime text"
]
}
25 changes: 15 additions & 10 deletions test/fuzzy.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,10 @@ describe('fuzzy', function(){
expect(fuzzy.match('ZEBRA!', 'ZaZbZ')).to.equal(null);
});
it('should return a greater score for consecutive matches of pattern', function(){
var consecutiveScore = fuzzy.match('abcd', 'abcd').score;
var consecutiveScore = fuzzy.match('abcd', 'zabcd').score;
var scatteredScore = fuzzy.match('abcd', 'azbcd').score;
expect(consecutiveScore).to.be.above(scatteredScore);
});
it('should return the same score for matches in the middle as matches at beginning', function(){
//TODO: Dont know how I feel about this. Sublime weights characters that
// appear toward the beginning of the string a bit higher
});
it('should be case insensitive by default', function(){
expect(fuzzy.filter('a', ['A'])[0].string).to.equal('A');
});
Expand All @@ -52,12 +48,21 @@ describe('fuzzy', function(){
opts.caseSensitive = false;
expect(fuzzy.match('AB', 'AB', opts)).to.not.equal(null);
});
xit('should return the same score for matches in the middle as matches at beginning', function(){
// TODO: Dont know how I feel about this. Sublime weights characters that
// appear toward the beginning of the string a bit higher
});
// TODO: implement this test
// it('should get the best match from a string, not just the first match', function(){
// var opts = {pre: '<', post: '>'};
// var result = fuzzy.match('bass', 'bodacious bass', opts).rendered;
// expect(result).to.equal('bodacious <b><a><s><s>');
// });
xit('should prefer consecutive characters even if they come after the first match', function(){
var opts = {pre: '<', post: '>'};
var result = fuzzy.match('bass', 'bodacious bass', opts).rendered;
expect(result).to.equal('bodacious <b><a><s><s>');
});
xit('should prefer consecutive characters in a match even if we need to break up into a substring', function(){
var opts = {pre: '<', post: '>'};
var result = fuzzy.match('reic', 'reactive rice', opts).rendered;
expect(result).to.equal('<r><e>active r<i><c>e');
});
});
describe('.filter', function(){
it('should return the index and matching array elements', function(){
Expand Down

0 comments on commit bfbe805

Please sign in to comment.