diff --git a/package.json b/package.json index 69f1243..d70ccb3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "xeger", - "version": "1.2.0", + "version": "1.3.0", "description": "More verbose and readable regular expressions", "main": "xeger.js", "dependencies": {}, diff --git a/readme.md b/readme.md index a5b1c59..f39ebd7 100644 --- a/readme.md +++ b/readme.md @@ -132,6 +132,8 @@ Used to create the '-' inside *any* and *not* functions (see examples for *any* If you were to just do `x.any('A-Z')` the `-` would be escaped: `/[A\-Z]/` +See the "Chaining" section below for a different syntax that makes using `.to()` less clunky. + ### x.alphanumeric([options]) Matches any single alpha-numeric character (includes letters, numbers, and the underscore). @@ -212,7 +214,7 @@ xeger(function (x) { }); /* returns /(abc)(?:[123])/ */ ``` -### options +### Options You can pass in a few options to the above rule functions. @@ -231,3 +233,38 @@ xeger(function (x) { x.literal('$', { repeat: 5 }); }); /* returns /a?.*(?:123)+\!{2,3}\${5}/ */ ``` + +### Chaining, and `this` + +Xeger offers a few alternative ways to construct a regex. + +#### Chaining + +Each rule function returns a copy of Xeger object, allowing you to chain rule calls. + +```javascript +xeger(function (x) { + x.any(function () { + x.literal('A').to().literal('Z'); + }); +}); /* Returns /[A-Z]/ */ +``` + +If you call `xeger()` without giving it a callback function, it will return a fresh Xeger object, allowing you to chain calls. In this case, call `.regex()` at the end to get the final RegExp object out of it. + +```javascript +xeger().start().any(function () { + x.literal('A').to().literal('Z'); +}).regex(); /* Returns /[A-Z]/ */ +``` + +#### this and @ + +Instead of relying on the `x` parameter given to each rule callback, you can use the `this` object. This is handy if using CoffeeScript (which has the `@` shorthand to represent `this.`): + +```coffeescript +xeger -> + @any -> + @literal('a').to().literal('z') +# Returns /[a-z]/ +``` diff --git a/test.js b/test.js index 22dea1f..892c0f0 100644 --- a/test.js +++ b/test.js @@ -9,9 +9,10 @@ describe('xeger', function () { r.alphanumeric(); r.number(); r.newline(); + r.whitespace(); r.end(); }); - assert.equal(regex.toString(), '/^hello\\w\\d\\n$/'); + assert.equal(regex.toString(), '/^hello\\w\\d\\n\\s$/'); }); describe('flags', function () { @@ -107,6 +108,16 @@ describe('xeger', function () { }); }); + describe('chaining', function () { + var regex = xeger({ global: true }).start().literal('abc').any(function () { + this.literal('A').to().literal('Z'); + }).regex(); + + it('makes the expected regex', function () { + assert.equal(regex.toString(), '/^abc[A-Z]/g'); + }); + }); + it('parses a url', function () { var regex = xeger(function (r) { r.start(); diff --git a/xeger.js b/xeger.js index 3f8bab8..3d608ad 100644 --- a/xeger.js +++ b/xeger.js @@ -1,7 +1,14 @@ module.exports = function (cb, options) { + if (typeof cb !== 'function') { + options = cb; + } var r = new Xeger(cb, options); - return r.regex(); + if (typeof cb === 'function') { + return r.regex(); + } else { + return r; + } }; @@ -19,7 +26,9 @@ var Xeger = function (cb, options) { if (options.insensitive) { this.flags += 'i'; } - cb.call(this, this); + if (typeof cb === 'function') { + cb.call(this, this); + } }; /* Public */ @@ -37,38 +46,54 @@ Xeger.prototype.literal = function (str, options) { this.add(')'); } this.addOptions(options); + + return this; }; Xeger.prototype.alphanumeric = function (options) { this.add('\\w'); this.addOptions(options); + + return this; }; Xeger.prototype.number = function (options) { this.add('\\d'); this.addOptions(options); + + return this; }; Xeger.prototype.newline = function (options) { this.add('\\n'); this.addOptions(options); + + return this; }; Xeger.prototype.whitespace = function(options){ this.add('\\s'); this.addOptions(options); + + return this; }; Xeger.prototype.start = function () { this.add('^'); + + return this; }; Xeger.prototype.end = function () { this.add('$'); + + return this; }; Xeger.prototype.to = function () { this.add('-'); + + return this; }; Xeger.prototype.any = function (str, options) { @@ -84,6 +109,8 @@ Xeger.prototype.any = function (str, options) { this.add('.'); } this.addOptions(options); + + return this; }; Xeger.prototype.not = function (str, options) { @@ -96,6 +123,8 @@ Xeger.prototype.not = function (str, options) { this.add(']'); } this.addOptions(options); + + return this; }; Xeger.prototype.group = function (cb, options) { @@ -106,14 +135,16 @@ Xeger.prototype.group = function (cb, options) { cb.call(this, this); this.add(')'); this.addOptions(options); -}; -/* Private */ + return this; +}; Xeger.prototype.regex = function () { return new RegExp(this.regexStr, this.flags); }; +/* Private */ + Xeger.prototype.addOptions = function (options) { options = options || {};