Skip to content
This repository has been archived by the owner on Feb 2, 2023. It is now read-only.

Commit

Permalink
add custom matcher callback, resolves #3
Browse files Browse the repository at this point in the history
  • Loading branch information
adamrenklint committed Mar 23, 2015
1 parent 31b8f7c commit 5ab5ce7
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 0 deletions.
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,20 @@ expect(expanded[3][0]).to.equal('2.4.01');
- ```even```
- ```odd```

## Custom matchers

It is possible to add a custom *matcher callback*, a function which gets executed for each possible position within the range.

The stack of matchers will continue to execute until a position has been accepted or until the stack ends.

```js
expr.addMatcher(function (position, fragments) {
if (position === '1.1.45') return true;
if (fragments[0] === 1 && fragments[2] === 96) return true;
return false;
});
```

## Develop

- ```make test```
Expand All @@ -51,6 +65,7 @@ expect(expanded[3][0]).to.equal('2.4.01');
- CHANGED: *events* are now called *notes* [dilla/8](https://github.com/adamrenklint/dilla/issues/8)
- **1.1.0**
- CHANGED: expects options object instead of barsPerLoop and beatsPerBar separately [#4](https://github.com/adamrenklint/dilla-expressions/issues/4)
- NEW: possible to add custom matcher callback [#3](https://github.com/adamrenklint/dilla-expressions/issues/3)

## License

Expand Down
19 changes: 19 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ function getFragments (position) {
});
}

var matchers = [];

function addMatcher (matcher) {
if (!matcher || typeof matcher !== 'function') throw new Error('Invalid argument: matcher is not a function');
matchers.push(matcher);
}

function makeExpressionFunction (expression) {
var exprFragments = getFragments(expression);
return function expressionFn (position) {
Expand All @@ -36,13 +43,24 @@ function makeExpressionFunction (expression) {
if (exprFragment === 'even' && positionFragments[index] % 2 === 0) return;
if (exprFragment === 'odd' && positionFragments[index] % 2 === 1) return;
if (exprFragment === '*') return;

// if (typeof exprFragment === 'string' && exprFragment.indexOf('%') >= 0) {
// console.log('deal with modulus', exprFragment, positionFragments[index])
// }
// position is invalid, break out early
// console.log('>', position, positionFragments);
valid = false;
return true;
});

var _matchers = matchers.slice();
var matcher;
while (!valid && _matchers.length) {
matcher = _matchers.shift();
if (matcher(position, positionFragments)) {
valid = true;
}
}
return valid;
};
}
Expand Down Expand Up @@ -75,4 +93,5 @@ function expressions (notes, options) {
});
}

expressions.addMatcher = addMatcher;
module.exports = expressions;
111 changes: 111 additions & 0 deletions test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -368,3 +368,114 @@ describe('when using mixed expression', function () {
// expect(result[7][0]).to.equal('1.2.91');
// });
});

describe('addMatcher (matcher)', function () {
describe('when matcher is not a function', function () {
it('should throw an error', function () {
expect(function () {
expr.addMatcher();
}).to.throw(Error);
expect(function () {
expr.addMatcher('foo');
}).to.throw(Error);
expect(function () {
expr.addMatcher(1323);
}).to.throw(Error);
expect(function () {
expr.addMatcher({'pos': '1.1.01' });
}).to.throw(Error);
expect(function () {
expr.addMatcher(['1.1.1.1.1']);
}).to.throw(Error);
});
});

describe('when matcher is a function', function () {
it('should execute the matcher for each possible note', function () {
var count = 0;
var last = null;
expr.addMatcher(function (position, fragments) {
count++;
last = position;
});
expr([
['1.1.*']
], standardOptions);
expect(count).to.equal(672);
expect(last).to.equal('2.4.96');
});
describe('when matcher returns false', function () {
describe('when another rule matches', function () {
it('should include the note', function () {
expr.addMatcher(function (position, fragments) {
if (position === '1.1.03') return false;
});
var result = expr([
['1.1.odd']
], standardOptions);
var found = result.filter(function (res) {
return res[0] === '1.1.03';
});
expect(found.length).to.equal(1);
});
});
describe('when no other rule matches', function () {
it('should not include the note', function () {
expr.addMatcher(function (position, fragments) {
if (position === '1.1.02') return false;
});
var result = expr([
['1.1.odd']
], standardOptions);
var found = result.filter(function (res) {
return res[0] === '1.1.02';
});
expect(found.length).to.equal(0);
});
});
});
describe('when matcher returns true', function () {
describe('when a previous rule matches', function () {
it('should include the note', function () {
expr.addMatcher(function (position, fragments) {
if (position === '1.1.05') return true;
});
var result = expr([
['1.1.odd']
], standardOptions);
var found = result.filter(function (res) {
return res[0] === '1.1.05';
});
expect(found.length).to.equal(1);
});
it('should not execute matcher', function () {
var count = 0;
expr.addMatcher(function (position, fragments) {
return true;
});
expr.addMatcher(function (position, fragments) {
count++;
});
var result = expr([
['1.1.*']
], standardOptions);
expect(count).to.equal(0);
});
});
describe('when no other rule matches', function () {
it('should include the note', function () {
expr.addMatcher(function (position, fragments) {
if (position === '1.1.04') return true;
});
var result = expr([
['1.1.odd']
], standardOptions);
var found = result.filter(function (res) {
return res[0] === '1.1.04';
});
expect(found.length).to.equal(1);
});
});
});
});
});

0 comments on commit 5ab5ce7

Please sign in to comment.