Skip to content

Commit

Permalink
fix(matcher): allow ignoring {} by using $, ie ${a} should match with…
Browse files Browse the repository at this point in the history
… {a}

there is a refactor too, trying to separate braceExpand logic in a utility function

fix #37
  • Loading branch information
roggervalf committed Dec 6, 2020
1 parent faaa075 commit 470f07d
Show file tree
Hide file tree
Showing 8 changed files with 202 additions and 91 deletions.
81 changes: 53 additions & 28 deletions dist/main.es.js

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

2 changes: 1 addition & 1 deletion dist/main.es.js.map

Large diffs are not rendered by default.

81 changes: 53 additions & 28 deletions dist/main.js

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

2 changes: 1 addition & 1 deletion dist/main.js.map

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions src/Matcher.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ describe('Matcher Class', () => {

it('returns true', () => {
expect(new Matcher('*').match('secrets::999/image')).toBe(true);
expect(new Matcher('number{125}').match('number125')).toBe(true);
expect(new Matcher('number${125}').match('number{125}')).toBe(true);
expect(new Matcher('{125,126}').match('125')).toBe(true);
expect(new Matcher('secrets:123').match('secrets:123')).toBe(true);
expect(
Expand Down
35 changes: 2 additions & 33 deletions src/Matcher.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { decomposeString } from './utils/decomposeString';
import { braceExpand } from './utils/braceExpand';

export class Matcher {
private readonly pattern: string;
Expand All @@ -12,7 +12,7 @@ export class Matcher {
this.maxLength = maxLength;
this.empty = !this.pattern ? true : false;

const set = this.braceExpand();
const set = braceExpand(pattern);
this.set = set.map((val) => this.parse(val));
this.set = this.set.filter((s) => {
return Boolean(s);
Expand All @@ -25,15 +25,6 @@ export class Matcher {
return this.set.some((pattern) => this.matchOne(str, pattern));
}

private braceExpand(): string[] {
const pattern = this.pattern;
if (!pattern.match(/{.*}/)) {
return [pattern];
}

return this.expand(pattern, true);
}

private parse(pattern: string): string | RegExp {
if (pattern.length > this.maxLength) {
throw new TypeError('Pattern is too long');
Expand Down Expand Up @@ -65,28 +56,6 @@ export class Matcher {
return regExp;
}

private expand(str: string, isTop?: boolean): string[] {
const expansions = [] as string[];
const balance = decomposeString('{', '}', str);
if (balance.start < 0 || /\$$/.test(balance.pre)) return [str];

const parts = balance.body.split(',');
// no need to expand pre, since it is guaranteed to be free of brace-sets
const pre = balance.pre;
const postParts = balance.post.length
? this.expand(balance.post, false)
: [''];

parts.forEach((part: string) => {
postParts.forEach((postPart) => {
const expansion = pre + part + postPart;
if (!isTop || expansion) expansions.push(expansion);
});
});

return expansions;
}

private matchOne(str: string, pattern: string | RegExp): boolean {
if (typeof pattern === 'string') {
return str === pattern;
Expand Down
33 changes: 33 additions & 0 deletions src/utils/braceExpand.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { braceExpand } from './braceExpand';

describe('braceExpand', () => {
it('expands with same order', () => {
expect(braceExpand('a{b,f,m}p')).toMatchObject(['abp', 'afp', 'amp']);
});

describe('when ${ is present', () => {
it('ignores {}', () => {
expect(braceExpand('${13}')).toMatchObject(['{13}']);
expect(braceExpand('${13}$${ab}')).toMatchObject(['{13}${ab}']);
expect(braceExpand('${13}a$b${ab}')).toMatchObject(['{13}a$b{ab}']);
expect(braceExpand('${a,b}${c,d}')).toMatchObject(['{a,b}{c,d}']);
expect(braceExpand('x${a,b}x${c,d}x')).toMatchObject(['x{a,b}x{c,d}x']);
expect(braceExpand('x${a,b}x{y,w}${c,d}x')).toMatchObject([
'x{a,b}xy{c,d}x',
'x{a,b}xw{c,d}x'
]);
});
});

describe('when there is an empty option', () => {
it('expands as many times as empty spaces', () => {
expect(braceExpand('-v{,,,,}')).toMatchObject([
'-v',
'-v',
'-v',
'-v',
'-v'
]);
});
});
});
57 changes: 57 additions & 0 deletions src/utils/braceExpand.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { decomposeString } from './decomposeString';

/**
* Generate an array of string depending on {} blocks.
*
* @param {string} pattern Pattern string that can contains {} blocks.
* @returns {string[]} Returns an array of string with all the combinations.
* @example
* ```javascript
* braceExpand('${13}')
* // => ['{13}']
*
* braceExpand('a{b,f,m}p')
* // => ['abp','afp','amp']
*
* braceExpand('-v{,,}')
* // => ['-v','-v','-v']
* ```
*/
const braceExpand = (pattern: string): string[] => {
if (!pattern.match(/{.*}/)) {
return [pattern];
}

return expand(pattern, true);
};

const expand = (str: string, isTop?: boolean): string[] => {
const expansions = [] as string[];
const balance = decomposeString('{', '}', str);
if (balance.start < 0) return [str];

const parts = balance.body.split(',');
// no need to expand pre, since it is guaranteed to be free of brace-sets
const pre = balance.pre;
const postParts = balance.post.length ? expand(balance.post, false) : [''];

if (/\$$/.test(balance.pre)) {
postParts.forEach((postPart) => {
const expansion = `${balance.pre.slice(0, -1)}{${
balance.body
}}${postPart}`;
expansions.push(expansion);
});
} else {
parts.forEach((part: string) => {
postParts.forEach((postPart) => {
const expansion = pre + part + postPart;
if (!isTop || expansion) expansions.push(expansion);
});
});
}

return expansions;
};

export { braceExpand };

0 comments on commit 470f07d

Please sign in to comment.