Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

add XRegExp.match, remove XRegExp.matchAll. closes #32

  • Loading branch information...
commit 684c1095cddfcc2dc23b32466b5de1ddc4befeed 1 parent 400eda0
@slevithan authored
View
8 README.md
@@ -191,7 +191,7 @@ XRegExp.matchRecursive(str, '<', '>', 'gy');
`XRegExp.matchRecursive` throws an error if it sees an unbalanced delimiter in the target string.
-### XRegExp Prototype Methods
+### XRegExp Prototypes
In browsers, first include the script:
@@ -200,7 +200,7 @@ In browsers, first include the script:
<script src="addons/prototypes.js"></script>
~~~
-New XRegExp regexes then gain a collection of useful methods: `apply`, `call`, `forEach`, `globalize`, `xexec`, and `xtest`.
+New XRegExp regexes then gain a collection of useful methods: `apply`, `call`, `forEach`, `globalize`, `match`, `xexec`, and `xtest`.
~~~ js
// To demonstrate the call method, let's first create the function we'll be using...
@@ -274,9 +274,9 @@ If XRegExp was not installed using npm, just open `tests/index.html` in your bro
XRegExp and addons copyright 2007-2012 by [Steven Levithan](http://stevenlevithan.com/).
-Tools: Unicode range generators by [Mathias Bynens](http://mathiasbynens.be/), and adapted from his [unicode-data](https://github.com/mathiasbynens/unicode-data) project. Source file concatenator by [Bjarke Walling](http://twitter.com/walling).
+Tools: Unicode range generators created by [Mathias Bynens](http://mathiasbynens.be/), and adapted from his [unicode-data](https://github.com/mathiasbynens/unicode-data) project. Source file concatenator by [Bjarke Walling](http://twitter.com/walling).
-Prior art: `XRegExp.build` inspired by [Lea Verou](http://lea.verou.me/)'s [RegExp.create](http://lea.verou.me/2011/03/create-complex-regexps-more-easily/). `XRegExp.union` inspired by [Ruby](http://www.ruby-lang.org/). XRegExp's syntax extensions come from Perl, .NET, etc.
+Prior art: `XRegExp.build` inspired by [Lea Verou](http://lea.verou.me/)'s [RegExp.create](http://lea.verou.me/2011/03/create-complex-regexps-more-easily/). `XRegExp.union` inspired by [Ruby](http://www.ruby-lang.org/). XRegExp's syntax extensions and flags come from Perl, .NET, etc.
All code released under the [MIT License](http://mit-license.org/).
View
12 src/addons/prototypes.js
@@ -1,5 +1,5 @@
/*!
- * XRegExp Prototype Methods 1.1.0-beta
+ * XRegExp Prototypes 1.1.0-dev
* (c) 2012 Steven Levithan <http://xregexp.com/>
* MIT License
*/
@@ -13,7 +13,7 @@
* XRegExp.globalize(/[a-z]/i).xexec('abc');
*/
(function (XRegExp) {
- "use strict";
+ 'use strict';
// Shortcut
var proto = XRegExp.prototype;
@@ -73,15 +73,15 @@
};
/**
- * Implicitly calls {@link #XRegExp.matchAll}.
+ * Implicitly calls {@link #XRegExp.match}.
* @memberOf XRegExp.prototype
* @example
*
- * XRegExp.matchAll('<1><2><3>', /\d/);
+ * XRegExp('\\d').match('1a23', 'all');
* // -> ['1', '2', '3']
*/
- proto.matchAll = function (str) {
- return XRegExp.matchAll(str, this);
+ proto.match = function (str, scope) {
+ return XRegExp.match(str, this, scope);
};
/**
View
42 src/xregexp.js
@@ -532,7 +532,7 @@ var XRegExp = (function (undefined) {
cacheFlags += "y";
}
regex.xregexp = regex.xregexp || getNativeProps();
- // Shares cached copies with `XRegExp.matchAll`/`replace`
+ // Shares cached copies with `XRegExp.match`/`replace`
r2 = regex.xregexp[cacheFlags] || (
regex.xregexp[cacheFlags] = copy(regex, {
add: cacheFlags,
@@ -667,34 +667,48 @@ var XRegExp = (function (undefined) {
};
/**
- * Returns an array containing all matches. Flag g has no effect on the result. Also fixes browser
- * bugs compared to the native `String.prototype.match` with flag g.
+ * Returns the first matched string, or in global mode, an array containing all matched strings.
+ * This is essentially a more convenient re-implementation of `String.prototype.match` that gives
+ * the result types you actually want (string instead of `exec`-style array in match-first mode,
+ * and an empty array instead of `null` when no matches are found in match-all mode). It also lets
+ * you override flag `g` and ignore `lastIndex`, and fixes browser bugs.
* @memberOf XRegExp
* @param {String} str String to search.
* @param {RegExp} regex Regex to search with.
- * @returns {Array} Array with all matched strings, or an empty array.
+ * @param {String} [scope='one'] Use 'one' to return the first match as a string, or null. Use
+ * 'all' to return an array of all matched strings, or an empty array. If not explicitly
+ * specified and using a regex with flag `g`, `scope` is 'all'.
+ * @returns {String|Array} First match as a string, or an array of all matched strings.
* @example
*
- * XRegExp.matchAll('<1><2><3>', /\d/);
- * // -> ['1', '2', '3']
+ * // Match first
+ * XRegExp.match('abc', /\w/); // -> 'a'
+ * XRegExp.match('abc', /\w/g, 'one'); // -> 'a'
+ * XRegExp.match('abc', /x/g, 'one'); // -> null
*
- * XRegExp.matchAll('<1><2><3>', /a/);
- * // -> []
+ * // Match all
+ * XRegExp.match('abc', /\w/g); // -> ['a', 'b', 'c']
+ * XRegExp.match('abc', /\w/, 'all'); // -> ['a', 'b', 'c']
+ * XRegExp.match('abc', /x/, 'all'); // -> []
*/
- self.matchAll = function (str, regex) {
- var cacheFlags = 'g' + (regex.sticky ? 'y' : ''),
+ self.match = function (str, regex, scope) {
+ var global = (regex.global && scope !== 'one') || scope === 'all',
+ cacheFlags = (global ? 'g' : '') + (regex.sticky ? 'y' : ''),
result,
r2;
regex.xregexp = regex.xregexp || getNativeProps();
// Shares cached copies with `XRegExp.exec`/`replace`
- r2 = regex.xregexp[cacheFlags] || (
- regex.xregexp[cacheFlags] = copy(regex, {add: cacheFlags})
+ r2 = regex.xregexp[cacheFlags || 'noGY'] || (
+ regex.xregexp[cacheFlags || 'noGY'] = copy(regex, {
+ add: cacheFlags,
+ remove: scope === 'one' ? 'g' : ''
+ })
);
result = nativ.match.call(str, r2);
if (regex.global) {
regex.lastIndex = 0;
}
- return result || [];
+ return global ? (result || []) : (result && result[0]);
};
/**
@@ -795,7 +809,7 @@ var XRegExp = (function (undefined) {
result;
if (isRegex) {
search.xregexp = search.xregexp || getNativeProps();
- // Shares cached copies with `XRegExp.exec`/`matchAll`. Since a copy is used,
+ // Shares cached copies with `XRegExp.exec`/`match`. Since a copy is used,
// `search`'s `lastIndex` isn't updated *during* replacement iterations
s2 = search.xregexp[cacheFlags || "noGY"] || (
search.xregexp[cacheFlags || "noGY"] = copy(search, {
View
32 tests/tests.js
@@ -24,7 +24,7 @@ test("Basic availability", function () {
ok(XRegExp.install, "XRegExp.install exists");
ok(XRegExp.isInstalled, "XRegExp.isInstalled exists");
ok(XRegExp.isRegExp, "XRegExp.isRegExp exists");
- ok(XRegExp.matchAll, "XRegExp.matchAll exists");
+ ok(XRegExp.match, "XRegExp.match exists");
ok(XRegExp.matchChain, "XRegExp.matchChain exists");
ok(XRegExp.replace, "XRegExp.replace exists");
ok(XRegExp.replaceEach, "XRegExp.replaceEach exists");
@@ -270,19 +270,31 @@ test("XRegExp.isRegExp", function () {
}
});
-test("XRegExp.matchAll", function () {
+test("XRegExp.match", function () {
var nonglobal = /\d/,
global = /\d/g,
str = "1 2 3 z";
nonglobal.lastIndex = global.lastIndex = 2;
- deepEqual(XRegExp.matchAll(str, nonglobal), ["1", "2", "3"], "Regex without flag g matches all");
+ deepEqual(XRegExp.match(str, nonglobal, "all"), ["1", "2", "3"], "Regex without flag g matches all");
equal(nonglobal.lastIndex, 2, "lastIndex of nonglobal regex unmodified after search");
- deepEqual(XRegExp.matchAll(str, global), ["1", "2", "3"], "Regex with flag g matches all");
+ deepEqual(XRegExp.match(str, global), ["1", "2", "3"], "Regex with flag g matches all");
equal(global.lastIndex, 0, "lastIndex of global regex reset after search");
- deepEqual(XRegExp.matchAll(str, /!/), [], "Empty array returned if no matches");
- raises(function () {XRegExp.matchAll(str, "1");}, TypeError, "String search throws error");
- raises(function () {XRegExp.matchAll(str, new String("1"));}, TypeError, "String object search throws error");
+ raises(function () {XRegExp.match(str, "1");}, TypeError, "String search throws error");
+ raises(function () {XRegExp.match(str, new String("1"));}, TypeError, "String object search throws error");
+
+ deepEqual(XRegExp.match("a bc", /\w/), "a");
+ deepEqual(XRegExp.match("a bc", /\w/, "one"), "a");
+ deepEqual(XRegExp.match("a bc", /\w/g, "one"), "a");
+ deepEqual(XRegExp.match("a bc", /x/), null);
+ deepEqual(XRegExp.match("a bc", /x/, "one"), null);
+ deepEqual(XRegExp.match("a bc", /x/g, "one"), null);
+ deepEqual(XRegExp.match("a bc", /\w/g), ["a", "b", "c"]);
+ deepEqual(XRegExp.match("a bc", /\w/g, "all"), ["a", "b", "c"]);
+ deepEqual(XRegExp.match("a bc", /\w/, "all"), ["a", "b", "c"]);
+ deepEqual(XRegExp.match("a bc", /x/g), []);
+ deepEqual(XRegExp.match("a bc", /x/g, "all"), []);
+ deepEqual(XRegExp.match("a bc", /x/, "all"), []);
});
test("XRegExp.matchChain", function () {
@@ -1020,9 +1032,9 @@ test("Prototype Methods", function () {
ok(regex.globalize, "globalize exists for XRegExp instance");
deepEqual(regex.globalize(), XRegExp.globalize(regex), "globalize method works like XRegExp.globalize");
- ok(XRegExp.prototype.matchAll, "XRegExp.prototype.matchAll exists");
- ok(regex.matchAll, "matchAll exists for XRegExp instance");
- deepEqual(regex.matchAll("x x"), XRegExp.matchAll("x x", regex), "matchAll method works like XRegExp.matchAll");
+ ok(XRegExp.prototype.match, "XRegExp.prototype.match exists");
+ ok(regex.match, "match exists for XRegExp instance");
+ deepEqual(regex.match("x x", "all"), XRegExp.match("x x", regex, "all"), "match method works like XRegExp.match");
ok(XRegExp.prototype.xexec, "XRegExp.prototype.xexec exists");
ok(regex.xexec, "xexec exists for XRegExp instance");
View
56 xregexp-all.js
@@ -536,7 +536,7 @@ var XRegExp = (function (undefined) {
cacheFlags += "y";
}
regex.xregexp = regex.xregexp || getNativeProps();
- // Shares cached copies with `XRegExp.matchAll`/`replace`
+ // Shares cached copies with `XRegExp.match`/`replace`
r2 = regex.xregexp[cacheFlags] || (
regex.xregexp[cacheFlags] = copy(regex, {
add: cacheFlags,
@@ -671,34 +671,48 @@ var XRegExp = (function (undefined) {
};
/**
- * Returns an array containing all matches. Flag g has no effect on the result. Also fixes browser
- * bugs compared to the native `String.prototype.match` with flag g.
+ * Returns the first matched string, or in global mode, an array containing all matched strings.
+ * This is essentially a more convenient re-implementation of `String.prototype.match` that gives
+ * the result types you actually want (string instead of `exec`-style array in match-first mode,
+ * and an empty array instead of `null` when no matches are found in match-all mode). It also lets
+ * you override flag `g` and ignore `lastIndex`, and fixes browser bugs.
* @memberOf XRegExp
* @param {String} str String to search.
* @param {RegExp} regex Regex to search with.
- * @returns {Array} Array with all matched strings, or an empty array.
+ * @param {String} [scope='one'] Use 'one' to return the first match as a string, or null. Use
+ * 'all' to return an array of all matched strings, or an empty array. If not explicitly
+ * specified and using a regex with flag `g`, `scope` is 'all'.
+ * @returns {String|Array} First match as a string, or an array of all matched strings.
* @example
*
- * XRegExp.matchAll('<1><2><3>', /\d/);
- * // -> ['1', '2', '3']
+ * // Match first
+ * XRegExp.match('abc', /\w/); // -> 'a'
+ * XRegExp.match('abc', /\w/g, 'one'); // -> 'a'
+ * XRegExp.match('abc', /x/g, 'one'); // -> null
*
- * XRegExp.matchAll('<1><2><3>', /a/);
- * // -> []
- */
- self.matchAll = function (str, regex) {
- var cacheFlags = 'g' + (regex.sticky ? 'y' : ''),
+ * // Match all
+ * XRegExp.match('abc', /\w/g); // -> ['a', 'b', 'c']
+ * XRegExp.match('abc', /\w/, 'all'); // -> ['a', 'b', 'c']
+ * XRegExp.match('abc', /x/, 'all'); // -> []
+ */
+ self.match = function (str, regex, scope) {
+ var global = (regex.global && scope !== 'one') || scope === 'all',
+ cacheFlags = (global ? 'g' : '') + (regex.sticky ? 'y' : ''),
result,
r2;
regex.xregexp = regex.xregexp || getNativeProps();
// Shares cached copies with `XRegExp.exec`/`replace`
- r2 = regex.xregexp[cacheFlags] || (
- regex.xregexp[cacheFlags] = copy(regex, {add: cacheFlags})
+ r2 = regex.xregexp[cacheFlags || 'noGY'] || (
+ regex.xregexp[cacheFlags || 'noGY'] = copy(regex, {
+ add: cacheFlags,
+ remove: scope === 'one' ? 'g' : ''
+ })
);
result = nativ.match.call(str, r2);
if (regex.global) {
regex.lastIndex = 0;
}
- return result || [];
+ return global ? (result || []) : (result && result[0]);
};
/**
@@ -799,7 +813,7 @@ var XRegExp = (function (undefined) {
result;
if (isRegex) {
search.xregexp = search.xregexp || getNativeProps();
- // Shares cached copies with `XRegExp.exec`/`matchAll`. Since a copy is used,
+ // Shares cached copies with `XRegExp.exec`/`match`. Since a copy is used,
// `search`'s `lastIndex` isn't updated *during* replacement iterations
s2 = search.xregexp[cacheFlags || "noGY"] || (
search.xregexp[cacheFlags || "noGY"] = copy(search, {
@@ -3579,7 +3593,7 @@ var XRegExp = (function (undefined) {
/*---- prototypes.js ----*/
/*!
- * XRegExp Prototype Methods 1.1.0-beta
+ * XRegExp Prototypes 1.1.0-dev
* (c) 2012 Steven Levithan <http://xregexp.com/>
* MIT License
*/
@@ -3593,7 +3607,7 @@ var XRegExp = (function (undefined) {
* XRegExp.globalize(/[a-z]/i).xexec('abc');
*/
(function (XRegExp) {
- "use strict";
+ 'use strict';
// Shortcut
var proto = XRegExp.prototype;
@@ -3653,15 +3667,15 @@ var XRegExp = (function (undefined) {
};
/**
- * Implicitly calls {@link #XRegExp.matchAll}.
+ * Implicitly calls {@link #XRegExp.match}.
* @memberOf XRegExp.prototype
* @example
*
- * XRegExp.matchAll('<1><2><3>', /\d/);
+ * XRegExp('\\d').match('1a23', 'all');
* // -> ['1', '2', '3']
*/
- proto.matchAll = function (str) {
- return XRegExp.matchAll(str, this);
+ proto.match = function (str, scope) {
+ return XRegExp.match(str, this, scope);
};
/**
Please sign in to comment.
Something went wrong with that request. Please try again.