pax_global_header00006660000000000000000000000064132716130200014505gustar00rootroot0000000000000052 comment=0daa3ed65a05fd73a9fd44714350e6c79c22f780 extglob-3.0.0/000077500000000000000000000000001327161302000131515ustar00rootroot00000000000000extglob-3.0.0/.editorconfig000066400000000000000000000004411327161302000156250ustar00rootroot00000000000000# http://editorconfig.org/ root = true [*] charset = utf-8 end_of_line = lf indent_size = 2 indent_style = space insert_final_newline = true trim_trailing_whitespace = true [{**/{actual,fixtures,expected,templates}/**,*.md}] trim_trailing_whitespace = false insert_final_newline = false extglob-3.0.0/.eslintrc.json000066400000000000000000000067751327161302000157640ustar00rootroot00000000000000{ "env": { "browser": false, "es6": true, "node": true, "mocha": true }, "globals": { "document": false, "navigator": false, "window": false }, "rules": { "accessor-pairs": 2, "arrow-spacing": [2, { "before": true, "after": true }], "block-spacing": [2, "always"], "brace-style": [2, "1tbs", { "allowSingleLine": true }], "comma-dangle": [2, "never"], "comma-spacing": [2, { "before": false, "after": true }], "comma-style": [2, "last"], "constructor-super": 2, "curly": [2, "multi-line"], "dot-location": [2, "property"], "eol-last": 2, "eqeqeq": [2, "allow-null"], "generator-star-spacing": [2, { "before": true, "after": true }], "handle-callback-err": [2, "^(err|error)$" ], "indent": [2, 2, { "SwitchCase": 1 }], "key-spacing": [2, { "beforeColon": false, "afterColon": true }], "keyword-spacing": [2, { "before": true, "after": true }], "new-cap": [2, { "newIsCap": true, "capIsNew": false }], "new-parens": 2, "no-array-constructor": 2, "no-caller": 2, "no-class-assign": 2, "no-cond-assign": 2, "no-const-assign": 2, "no-control-regex": 2, "no-debugger": 2, "no-delete-var": 2, "no-dupe-args": 2, "no-dupe-class-members": 2, "no-dupe-keys": 2, "no-duplicate-case": 2, "no-empty-character-class": 2, "no-eval": 2, "no-ex-assign": 2, "no-extend-native": 2, "no-extra-bind": 2, "no-extra-boolean-cast": 2, "no-extra-parens": [2, "functions"], "no-fallthrough": 2, "no-floating-decimal": 2, "no-func-assign": 2, "no-implied-eval": 2, "no-inner-declarations": [2, "functions"], "no-invalid-regexp": 2, "no-irregular-whitespace": 2, "no-iterator": 2, "no-label-var": 2, "no-labels": 2, "no-lone-blocks": 2, "no-mixed-spaces-and-tabs": 2, "no-multi-spaces": 2, "no-multi-str": 2, "no-multiple-empty-lines": [2, { "max": 1 }], "no-native-reassign": 0, "no-negated-in-lhs": 2, "no-new": 2, "no-new-func": 2, "no-new-object": 2, "no-new-require": 2, "no-new-wrappers": 2, "no-obj-calls": 2, "no-octal": 2, "no-octal-escape": 2, "no-proto": 0, "no-redeclare": 2, "no-regex-spaces": 2, "no-return-assign": 2, "no-self-compare": 2, "no-sequences": 2, "no-shadow-restricted-names": 2, "no-spaced-func": 2, "no-sparse-arrays": 2, "no-this-before-super": 2, "no-throw-literal": 2, "no-trailing-spaces": 0, "no-undef": 2, "no-undef-init": 2, "no-unexpected-multiline": 2, "no-unneeded-ternary": [2, { "defaultAssignment": false }], "no-unreachable": 2, "no-unused-vars": [2, { "vars": "all", "args": "none" }], "no-useless-call": 0, "no-with": 2, "one-var": [0, { "initialized": "never" }], "operator-linebreak": [0, "after", { "overrides": { "?": "before", ":": "before" } }], "padded-blocks": [0, "never"], "quotes": [2, "single", "avoid-escape"], "radix": 2, "semi": [2, "always"], "semi-spacing": [2, { "before": false, "after": true }], "space-before-blocks": [2, "always"], "space-before-function-paren": [2, "never"], "space-in-parens": [2, "never"], "space-infix-ops": 2, "space-unary-ops": [2, { "words": true, "nonwords": false }], "spaced-comment": [0, "always", { "markers": ["global", "globals", "eslint", "eslint-disable", "*package", "!", ","] }], "use-isnan": 2, "valid-typeof": 2, "wrap-iife": [2, "any"], "yoda": [2, "never"] } } extglob-3.0.0/.gitattributes000066400000000000000000000000171327161302000160420ustar00rootroot00000000000000*.* text eol=lfextglob-3.0.0/.gitignore000066400000000000000000000004561327161302000151460ustar00rootroot00000000000000# always ignore files *.DS_Store .idea .vscode *.sublime-* # test related, or directories generated by tests test/actual actual coverage .nyc* # npm node_modules npm-debug.log # yarn yarn.lock yarn-error.log # misc _gh_pages _draft _drafts bower_components vendor temp tmp TODO.md package-lock.jsonextglob-3.0.0/.travis.yml000066400000000000000000000001361327161302000152620ustar00rootroot00000000000000sudo: false os: - linux - osx language: node_js node_js: - '10' - '8' - '6' - '4' extglob-3.0.0/.verb.md000066400000000000000000000057431327161302000145200ustar00rootroot00000000000000- Convert an extglob string to a regex-compatible string. - More complete (and correct) support than [minimatch](https://github.com/isaacs/minimatch) (minimatch fails a large percentage of the extglob tests) - Handles [negation patterns](#extglob-patterns) - Handles [nested patterns](#extglob-patterns) - Organized code base, easy to maintain and make changes when edge cases arise - As you can see by the [benchmarks](#benchmarks), extglob doesn't pay with speed for it's completeness, accuracy and quality. **Heads up!**: This library only supports extglobs, to handle full glob patterns and other extended globbing features use [micromatch][] instead. ## Usage The main export is a function that takes a string and options, and returns an object with the parsed AST and the compiled `.output`, which is a regex-compatible string that can be used for matching. ```js var extglob = require('{%= name %}'); console.log(extglob('!(xyz)*.js')); ``` ## Extglob cheatsheet Extended globbing patterns can be defined as follows (as described by the [bash man page][bash]): | **pattern** | **regex equivalent** | **description** | | --- | --- | --- | | `?(pattern-list)` | `(...|...)?` | Matches zero or one occurrence of the given pattern(s) | | `*(pattern-list)` | `(...|...)*` | Matches zero or more occurrences of the given pattern(s) | | `+(pattern-list)` | `(...|...)+` | Matches one or more occurrences of the given pattern(s) | | `@(pattern-list)` | `(...|...)` [^1] | Matches one of the given pattern(s) | | `!(pattern-list)` | N/A | Matches anything except one of the given pattern(s) | [^1]: `@` isn't a RegEx character. ## API {%= apidocs("index.js") %} ## Options Available options are based on the options from Bash (and the option names used in bash). ### options.nullglob **Type**: `boolean` **Default**: `undefined` When enabled, the pattern itself will be returned when no matches are found. ### options.nonull Alias for [options.nullglob](#optionsnullglob), included for parity with minimatch. ### options.cache **Type**: `boolean` **Default**: `undefined` Functions are memoized based on the given glob patterns and options. Disable memoization by setting `options.cache` to false. ### options.failglob **Type**: `boolean` **Default**: `undefined` Throw an error is no matches are found. ## Benchmarks Last run on {%= date() %} ```sh {%= include("benchmark/stats.md") %} ``` ## Differences from Bash This library has complete parity with Bash 4.3 with only a couple of minor differences. - In some cases Bash returns true if the given string "contains" the pattern, whereas this library returns true if the string is an exact match for the pattern. You can relax this by setting `options.contains` to true. - This library is more accurate than Bash and thus does not fail some of the tests that Bash 4.3 still lists as failing in their unit tests [bash]: https://www.gnu.org/software/bash/manual/html_node/Pattern-Matching.html [micromatch]: https://github.com/jonschlinkert/micromatch extglob-3.0.0/LICENSE000066400000000000000000000021001327161302000141470ustar00rootroot00000000000000The MIT License (MIT) Copyright (c) 2015-2018, Jon Schlinkert. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. extglob-3.0.0/README.md000066400000000000000000000273461327161302000144440ustar00rootroot00000000000000# extglob [![NPM version](https://img.shields.io/npm/v/extglob.svg?style=flat)](https://www.npmjs.com/package/extglob) [![NPM monthly downloads](https://img.shields.io/npm/dm/extglob.svg?style=flat)](https://npmjs.org/package/extglob) [![NPM total downloads](https://img.shields.io/npm/dt/extglob.svg?style=flat)](https://npmjs.org/package/extglob) [![Linux Build Status](https://img.shields.io/travis/micromatch/extglob.svg?style=flat&label=Travis)](https://travis-ci.org/micromatch/extglob) [![Windows Build Status](https://img.shields.io/appveyor/ci/micromatch/extglob.svg?style=flat&label=AppVeyor)](https://ci.appveyor.com/project/micromatch/extglob) > Extended glob support for JavaScript. Adds (almost) the expressive power of regular expressions to glob patterns. ## Install Install with [npm](https://www.npmjs.com/): ```sh $ npm install --save extglob ``` Install with [yarn](https://yarnpkg.com): ```sh $ yarn add extglob ``` * Convert an extglob string to a regex-compatible string. * More complete (and correct) support than [minimatch](https://github.com/isaacs/minimatch) (minimatch fails a large percentage of the extglob tests) * Handles [negation patterns](#extglob-patterns) * Handles [nested patterns](#extglob-patterns) * Organized code base, easy to maintain and make changes when edge cases arise * As you can see by the [benchmarks](#benchmarks), extglob doesn't pay with speed for it's completeness, accuracy and quality. **Heads up!**: This library only supports extglobs, to handle full glob patterns and other extended globbing features use [micromatch](https://github.com/jonschlinkert/micromatch) instead. ## Usage The main export is a function that takes a string and options, and returns an object with the parsed AST and the compiled `.output`, which is a regex-compatible string that can be used for matching. ```js var extglob = require('extglob'); console.log(extglob('!(xyz)*.js')); ``` ## Extglob cheatsheet Extended globbing patterns can be defined as follows (as described by the [bash man page](https://www.gnu.org/software/bash/manual/html_node/Pattern-Matching.html)): | **pattern** | **regex equivalent** | **description** | | --- | --- | --- | | `?(pattern-list)` | `(...\|...)?` | Matches zero or one occurrence of the given pattern(s) | | `*(pattern-list)` | `(...\|...)*` | Matches zero or more occurrences of the given pattern(s) | | `+(pattern-list)` | `(...\|...)+` | Matches one or more occurrences of the given pattern(s) | | `@(pattern-list)` | `(...\|...)` [^1] | Matches one of the given pattern(s) | | `!(pattern-list)` | N/A | Matches anything except one of the given pattern(s) | ## API ### [extglob](index.js#L35) Convert the given `extglob` pattern into a regex-compatible string. Returns an object with the compiled result and the parsed AST. **Params** * `pattern` **{String}** * `options` **{Object}** * `returns` **{String}** **Example** ```js const extglob = require('extglob'); console.log(extglob('*.!(*a)')); //=> '(?!\\.)[^/]*?\\.(?!(?!\\.)[^/]*?a\\b).*?' ``` ### [.match](index.js#L55) Takes an array of strings and an extglob pattern and returns a new array that contains only the strings that match the pattern. **Params** * `list` **{Array}**: Array of strings to match * `pattern` **{String}**: Extglob pattern * `options` **{Object}** * `returns` **{Array}**: Returns an array of matches **Example** ```js const extglob = require('extglob'); console.log(extglob.match(['a.a', 'a.b', 'a.c'], '*.!(*a)')); //=> ['a.b', 'a.c'] ``` ### [.isMatch](index.js#L110) Returns true if the specified `string` matches the given extglob `pattern`. **Params** * `string` **{String}**: String to match * `pattern` **{String}**: Extglob pattern * `options` **{String}** * `returns` **{Boolean}** **Example** ```js const extglob = require('extglob'); console.log(extglob.isMatch('a.a', '*.!(*a)')); //=> false console.log(extglob.isMatch('a.b', '*.!(*a)')); //=> true ``` ### [.contains](index.js#L149) Returns true if the given `string` contains the given pattern. Similar to `.isMatch` but the pattern can match any part of the string. **Params** * `str` **{String}**: The string to match. * `pattern` **{String}**: Glob pattern to use for matching. * `options` **{Object}** * `returns` **{Boolean}**: Returns true if the patter matches any part of `str`. **Example** ```js const extglob = require('extglob'); console.log(extglob.contains('aa/bb/cc', '*b')); //=> true console.log(extglob.contains('aa/bb/cc', '*d')); //=> false ``` ### [.matcher](index.js#L183) Takes an extglob pattern and returns a matcher function. The returned function takes the string to match as its only argument. **Params** * `pattern` **{String}**: Extglob pattern * `options` **{String}** * `returns` **{Boolean}** **Example** ```js const extglob = require('extglob'); const isMatch = extglob.matcher('*.!(*a)'); console.log(isMatch('a.a')); //=> false console.log(isMatch('a.b')); //=> true ``` ### [.create](index.js#L213) Convert the given `extglob` pattern into a regex-compatible string. Returns an object with the compiled result and the parsed AST. **Params** * `str` **{String}** * `options` **{Object}** * `returns` **{String}** **Example** ```js const extglob = require('extglob'); console.log(extglob.create('*.!(*a)').output); //=> '(?!\\.)[^/]*?\\.(?!(?!\\.)[^/]*?a\\b).*?' ``` ### [.capture](index.js#L247) Returns an array of matches captured by `pattern` in `string`, or `null` if the pattern did not match. **Params** * `pattern` **{String}**: Glob pattern to use for matching. * `string` **{String}**: String to match * `options` **{Object}**: See available [options](#options) for changing how matches are performed * `returns` **{Boolean}**: Returns an array of captures if the string matches the glob pattern, otherwise `null`. **Example** ```js const extglob = require('extglob'); extglob.capture(pattern, string[, options]); console.log(extglob.capture('test/*.js', 'test/foo.js')); //=> ['foo'] console.log(extglob.capture('test/*.js', 'foo/bar.css')); //=> null ``` ### [.makeRe](index.js#L280) Create a regular expression from the given `pattern` and `options`. **Params** * `pattern` **{String}**: The pattern to convert to regex. * `options` **{Object}** * `returns` **{RegExp}** **Example** ```js const extglob = require('extglob'); const re = extglob.makeRe('*.!(*a)'); console.log(re); //=> /^[^\/]*?\.(?![^\/]*?a)[^\/]*?$/ ``` ## Options Available options are based on the options from Bash (and the option names used in bash). ### options.nullglob **Type**: `boolean` **Default**: `undefined` When enabled, the pattern itself will be returned when no matches are found. ### options.nonull Alias for [options.nullglob](#optionsnullglob), included for parity with minimatch. ### options.cache **Type**: `boolean` **Default**: `undefined` Functions are memoized based on the given glob patterns and options. Disable memoization by setting `options.cache` to false. ### options.failglob **Type**: `boolean` **Default**: `undefined` Throw an error is no matches are found. ## Benchmarks Last run on April 30, 2018 ```sh # negation-nested (49 bytes) extglob x 1,380,148 ops/sec ±3.35% (62 runs sampled) minimatch x 156,800 ops/sec ±4.13% (76 runs sampled) fastest is extglob (by 880% avg) # negation-simple (43 bytes) extglob x 1,821,746 ops/sec ±1.61% (76 runs sampled) minimatch x 365,618 ops/sec ±1.87% (84 runs sampled) fastest is extglob (by 498% avg) # range-false (57 bytes) extglob x 2,038,592 ops/sec ±3.39% (85 runs sampled) minimatch x 310,897 ops/sec ±12.62% (87 runs sampled) fastest is extglob (by 656% avg) # range-true (56 bytes) extglob x 2,105,081 ops/sec ±0.69% (91 runs sampled) minimatch x 332,188 ops/sec ±0.45% (91 runs sampled) fastest is extglob (by 634% avg) # star-simple (46 bytes) extglob x 2,154,184 ops/sec ±0.99% (89 runs sampled) minimatch x 452,812 ops/sec ±0.51% (88 runs sampled) fastest is extglob (by 476% avg) ``` ## Differences from Bash This library has complete parity with Bash 4.3 with only a couple of minor differences. * In some cases Bash returns true if the given string "contains" the pattern, whereas this library returns true if the string is an exact match for the pattern. You can relax this by setting `options.contains` to true. * This library is more accurate than Bash and thus does not fail some of the tests that Bash 4.3 still lists as failing in their unit tests ## About ### Related projects * [braces](https://www.npmjs.com/package/braces): Bash-like brace expansion, implemented in JavaScript. Safer than other brace expansion libs, with complete support… [more](https://github.com/micromatch/braces) | [homepage](https://github.com/micromatch/braces "Bash-like brace expansion, implemented in JavaScript. Safer than other brace expansion libs, with complete support for the Bash 4.3 braces specification, without sacrificing speed.") * [expand-brackets](https://www.npmjs.com/package/expand-brackets): Expand POSIX bracket expressions (character classes) in glob patterns. | [homepage](https://github.com/micromatch/expand-brackets "Expand POSIX bracket expressions (character classes) in glob patterns.") * [expand-range](https://www.npmjs.com/package/expand-range): Fast, bash-like range expansion. Expand a range of numbers or letters, uppercase or lowercase. Used… [more](https://github.com/jonschlinkert/expand-range) | [homepage](https://github.com/jonschlinkert/expand-range "Fast, bash-like range expansion. Expand a range of numbers or letters, uppercase or lowercase. Used by [micromatch].") * [fill-range](https://www.npmjs.com/package/fill-range): Fill in a range of numbers or letters, optionally passing an increment or `step` to… [more](https://github.com/jonschlinkert/fill-range) | [homepage](https://github.com/jonschlinkert/fill-range "Fill in a range of numbers or letters, optionally passing an increment or `step` to use, or create a regex-compatible range with `options.toRegex`") * [micromatch](https://www.npmjs.com/package/micromatch): Glob matching for javascript/node.js. A drop-in replacement and faster alternative to minimatch and multimatch. | [homepage](https://github.com/micromatch/micromatch "Glob matching for javascript/node.js. A drop-in replacement and faster alternative to minimatch and multimatch.") ### Contributing Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new). ### Contributors | **Commits** | **Contributor** | | --- | --- | | 54 | [jonschlinkert](https://github.com/jonschlinkert) | | 6 | [danez](https://github.com/danez) | | 2 | [isiahmeadows](https://github.com/isiahmeadows) | | 1 | [doowb](https://github.com/doowb) | | 1 | [devongovett](https://github.com/devongovett) | | 1 | [mjbvz](https://github.com/mjbvz) | | 1 | [shinnn](https://github.com/shinnn) | ### Building docs _(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_ To generate the readme, run the following command: ```sh $ npm install -g verbose/verb#dev verb-generate-readme && verb ``` ### Running tests Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command: ```sh $ npm install && npm test ``` ### Author **Jon Schlinkert** * [github/jonschlinkert](https://github.com/jonschlinkert) * [twitter/jonschlinkert](https://twitter.com/jonschlinkert) ### License Copyright © 2018, [Jon Schlinkert](https://github.com/jonschlinkert). Released under the [MIT License](LICENSE). *** _This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.6.0, on April 30, 2018._extglob-3.0.0/appveyor.yml000066400000000000000000000010641327161302000155420ustar00rootroot00000000000000# Test against this version of Node.js environment: matrix: # node.js - nodejs_version: "10.0" - nodejs_version: "8.0" - nodejs_version: "6.0" - nodejs_version: "4.0" # Install scripts. (runs after repo cloning) install: # Get the latest stable version of Node.js or io.js - ps: Install-Product node $env:nodejs_version # install modules - npm install # Post-install test scripts. test_script: # Output useful info for debugging. - node --version - npm --version # run tests - npm test # Don't actually build. build: off extglob-3.0.0/benchmark/000077500000000000000000000000001327161302000151035ustar00rootroot00000000000000extglob-3.0.0/benchmark/code/000077500000000000000000000000001327161302000160155ustar00rootroot00000000000000extglob-3.0.0/benchmark/code/extglob.js000066400000000000000000000001661327161302000200220ustar00rootroot00000000000000var extglob = require('../..'); module.exports = function(str, pattern) { return extglob.isMatch(str, pattern); }; extglob-3.0.0/benchmark/code/minimatch.js000066400000000000000000000001661327161302000203270ustar00rootroot00000000000000var minimatch = require('minimatch'); module.exports = function(str, pattern) { return minimatch(str, pattern); }; extglob-3.0.0/benchmark/fixtures/000077500000000000000000000000001327161302000167545ustar00rootroot00000000000000extglob-3.0.0/benchmark/fixtures/negation-nested.js000066400000000000000000000000611327161302000223730ustar00rootroot00000000000000module.exports = ['a.b', 'a.!(!(@(*b)))', true]; extglob-3.0.0/benchmark/fixtures/negation-simple.js000066400000000000000000000000531327161302000224030ustar00rootroot00000000000000module.exports = ['a.b', 'a.!(*a)', true]; extglob-3.0.0/benchmark/fixtures/range-false.js000066400000000000000000000000711327161302000214740ustar00rootroot00000000000000module.exports = ['para381', 'para?([345]|99)1', false]; extglob-3.0.0/benchmark/fixtures/range-true.js000066400000000000000000000000701327161302000213600ustar00rootroot00000000000000module.exports = ['para991', 'para?([345]|99)1', true]; extglob-3.0.0/benchmark/fixtures/star-simple.js000066400000000000000000000000561327161302000215530ustar00rootroot00000000000000module.exports = ['abef', 'ab*(e|f)*', true]; extglob-3.0.0/benchmark/index.js000066400000000000000000000004571327161302000165560ustar00rootroot00000000000000'use strict'; const path = require('path'); const suite = require('benchmarked'); const write = require('write'); suite.run({code: 'code/*.js', fixtures: 'fixtures/*.js'}) .then(function(stats) { return write(path.join(__dirname, 'stats.md'), suite.render(stats)); }) .catch(console.error); extglob-3.0.0/benchmark/package.json000066400000000000000000000002561327161302000173740ustar00rootroot00000000000000{ "name": "extglob-benchmarks", "version": "0.0.0", "private": true, "main": "index.js", "dependencies": { "benchmarked": "^2.0.0", "write": "^1.0.3" } } extglob-3.0.0/benchmark/stats.md000066400000000000000000000015551327161302000165710ustar00rootroot00000000000000# negation-nested (49 bytes) extglob x 1,380,148 ops/sec ±3.35% (62 runs sampled) minimatch x 156,800 ops/sec ±4.13% (76 runs sampled) fastest is extglob (by 880% avg) # negation-simple (43 bytes) extglob x 1,821,746 ops/sec ±1.61% (76 runs sampled) minimatch x 365,618 ops/sec ±1.87% (84 runs sampled) fastest is extglob (by 498% avg) # range-false (57 bytes) extglob x 2,038,592 ops/sec ±3.39% (85 runs sampled) minimatch x 310,897 ops/sec ±12.62% (87 runs sampled) fastest is extglob (by 656% avg) # range-true (56 bytes) extglob x 2,105,081 ops/sec ±0.69% (91 runs sampled) minimatch x 332,188 ops/sec ±0.45% (91 runs sampled) fastest is extglob (by 634% avg) # star-simple (46 bytes) extglob x 2,154,184 ops/sec ±0.99% (89 runs sampled) minimatch x 452,812 ops/sec ±0.51% (88 runs sampled) fastest is extglob (by 476% avg) extglob-3.0.0/changelog.md000066400000000000000000000014111327161302000154170ustar00rootroot00000000000000## Changelog ### v3.0.0 **Breaking changes** - Snapdragon was updated to 0.12. Other packages that integrate `extglob` need to also use snapdragon 0.12. - Minimum Node.JS version is now version 4. ### v2.0.0 **Added features** - Adds [.capture](readme.md#capture) method for capturing matches, thanks to [devongovett](https://github.com/devongovett) ### v1.0.0 **Breaking changes** - The main export now returns the compiled string, instead of the object returned from the compiler **Added features** - Adds a `.create` method to do what the main function did before v1.0.0 **Other changes** - adds `expand-brackets` parsers/compilers to handle nested brackets and extglobs - uses `to-regex` to build regex for `makeRe` method - improves coverage - optimizationsextglob-3.0.0/examples/000077500000000000000000000000001327161302000147675ustar00rootroot00000000000000extglob-3.0.0/examples/extglob.create.js000066400000000000000000000002051327161302000202300ustar00rootroot00000000000000'use strict'; var extglob = require('..'); console.log(extglob.create('*.!(*a)')); console.log(extglob.create('*(*(of*(a)x)z)')); extglob-3.0.0/examples/extglob.js000066400000000000000000000004061327161302000167710ustar00rootroot00000000000000'use strict'; var extglob = require('..'); console.log(extglob('!(xyz)*.js')); //=>'(?:(?!(?:xyz)).*?)(?!\.).*?\.js' console.log(extglob('*.!(*a)')); //=> '(?!\.).*?\.(?:(?!(?:(?!\.).*?a$)).*?)' console.log(extglob('+(*(of*(a)x)z)')); //=> '+((of(a)*x)*z)*' extglob-3.0.0/examples/makeRe.js000066400000000000000000000004511327161302000165310ustar00rootroot00000000000000// var mm = require('minimatch'); var extglob = require('./'); // var re = /^(?!a|b)[^/]*?\.md$/; var re = extglob.makeRe('!(?:(a|b)*).md'); // var re = mm.makeRe('!(a|b)*.md'); var arr = ['a.js', 'a.md', 'b.md', 'c.md'] .filter(function(ele) { return re.test(ele); }); console.log(arr); extglob-3.0.0/examples/parser.js000066400000000000000000000003511327161302000166200ustar00rootroot00000000000000'use strict'; var parsers = require('../lib/parsers'); var Extglob = require('../lib/extglob'); var extglob = new Extglob(); extglob.use(parsers); var pattern = '*(*(of*(a)x)z)'; var res = extglob.parse(pattern); console.log(res); extglob-3.0.0/examples/regex.js000066400000000000000000000002251327161302000164360ustar00rootroot00000000000000 var extglob = require('..'); var re = extglob.makeRe('*(a|b|c)'); console.log(re); console.log(re.test('bar')); console.log(re.test('bbbaaaccc')); extglob-3.0.0/examples/source-map.js000066400000000000000000000002541327161302000174010ustar00rootroot00000000000000'use strict'; var extglob = require('..'); var pattern = '*(*(of*(a)x)z)'; console.log(extglob.create(pattern)); console.log(extglob.create(pattern, {sourcemap: true})); extglob-3.0.0/gulpfile.js000066400000000000000000000015051327161302000153170ustar00rootroot00000000000000'use strict'; const gulp = require('gulp'); const mocha = require('gulp-mocha'); const unused = require('gulp-unused'); const istanbul = require('gulp-istanbul'); const eslint = require('gulp-eslint'); gulp.task('coverage', function() { return gulp.src(['index.js', 'lib/*.js']) .pipe(istanbul()) .pipe(istanbul.hookRequire()); }); gulp.task('test', ['coverage'], function() { return gulp.src('test/*.js') .pipe(mocha({reporter: 'spec'})) .pipe(istanbul.writeReports()); }); gulp.task('lint', function() { return gulp.src(['*.js', 'lib/*.js', 'test/{*,support/*}.js']) .pipe(eslint()) .pipe(eslint.format()); }); gulp.task('unused', function() { return gulp.src(['index.js', 'lib/*.js']) .pipe(unused({keys: Object.keys(require('./lib/utils.js'))})); }); gulp.task('default', ['test', 'lint']); extglob-3.0.0/index.js000066400000000000000000000200311327161302000146120ustar00rootroot00000000000000'use strict'; /** * Module dependencies */ const unique = require('array-unique'); const toRegex = require('to-regex'); /** * Local dependencies */ const compilers = require('./lib/compilers'); const parsers = require('./lib/parsers'); const Extglob = require('./lib/extglob'); const utils = require('./lib/utils'); const MAX_LENGTH = 1024 * 64; /** * Convert the given `extglob` pattern into a regex-compatible string. Returns * an object with the compiled result and the parsed AST. * * ```js * const extglob = require('extglob'); * console.log(extglob('*.!(*a)')); * //=> '(?!\\.)[^/]*?\\.(?!(?!\\.)[^/]*?a\\b).*?' * ``` * @param {String} `pattern` * @param {Object} `options` * @return {String} * @api public */ function extglob(pattern, options) { return extglob.create(pattern, options).output; } /** * Takes an array of strings and an extglob pattern and returns a new * array that contains only the strings that match the pattern. * * ```js * const extglob = require('extglob'); * console.log(extglob.match(['a.a', 'a.b', 'a.c'], '*.!(*a)')); * //=> ['a.b', 'a.c'] * ``` * @param {Array} `list` Array of strings to match * @param {String} `pattern` Extglob pattern * @param {Object} `options` * @return {Array} Returns an array of matches * @api public */ extglob.match = function(list, pattern, options) { if (typeof pattern !== 'string') { throw new TypeError('expected pattern to be a string'); } list = utils.arrayify(list); const isMatch = extglob.matcher(pattern, options); const len = list.length; let idx = -1; const matches = []; while (++idx < len) { const ele = list[idx]; if (isMatch(ele)) { matches.push(ele); } } // if no options were passed, uniquify results and return if (typeof options === 'undefined') { return unique(matches); } if (matches.length === 0) { if (options.failglob === true) { throw new Error('no matches found for "' + pattern + '"'); } if (options.nonull === true || options.nullglob === true) { return [pattern.split('\\').join('')]; } } return options.nodupes !== false ? unique(matches) : matches; }; /** * Returns true if the specified `string` matches the given * extglob `pattern`. * * ```js * const extglob = require('extglob'); * * console.log(extglob.isMatch('a.a', '*.!(*a)')); * //=> false * console.log(extglob.isMatch('a.b', '*.!(*a)')); * //=> true * ``` * @param {String} `string` String to match * @param {String} `pattern` Extglob pattern * @param {String} `options` * @return {Boolean} * @api public */ extglob.isMatch = function(str, pattern, options) { if (typeof pattern !== 'string') { throw new TypeError('expected pattern to be a string'); } if (typeof str !== 'string') { throw new TypeError('expected a string'); } if (pattern === str) { return true; } if (pattern === '' || pattern === ' ' || pattern === '.') { return pattern === str; } const isMatch = utils.memoize('isMatch', pattern, options, extglob.matcher); return isMatch(str); }; /** * Returns true if the given `string` contains the given pattern. Similar to `.isMatch` but * the pattern can match any part of the string. * * ```js * const extglob = require('extglob'); * console.log(extglob.contains('aa/bb/cc', '*b')); * //=> true * console.log(extglob.contains('aa/bb/cc', '*d')); * //=> false * ``` * @param {String} `str` The string to match. * @param {String} `pattern` Glob pattern to use for matching. * @param {Object} `options` * @return {Boolean} Returns true if the patter matches any part of `str`. * @api public */ extglob.contains = function(str, pattern, options) { if (typeof str !== 'string') { throw new TypeError('expected a string'); } if (pattern === '' || pattern === ' ' || pattern === '.') { return pattern === str; } const opts = Object.assign({}, options, {contains: true}); opts.strictClose = false; opts.strictOpen = false; return extglob.isMatch(str, pattern, opts); }; /** * Takes an extglob pattern and returns a matcher function. The returned * function takes the string to match as its only argument. * * ```js * const extglob = require('extglob'); * const isMatch = extglob.matcher('*.!(*a)'); * * console.log(isMatch('a.a')); * //=> false * console.log(isMatch('a.b')); * //=> true * ``` * @param {String} `pattern` Extglob pattern * @param {String} `options` * @return {Boolean} * @api public */ extglob.matcher = function(pattern, options) { if (typeof pattern !== 'string') { throw new TypeError('expected pattern to be a string'); } function matcher() { const re = extglob.makeRe(pattern, options); return function(str) { return re.test(str); }; } return utils.memoize('matcher', pattern, options, matcher); }; /** * Convert the given `extglob` pattern into a regex-compatible string. Returns * an object with the compiled result and the parsed AST. * * ```js * const extglob = require('extglob'); * console.log(extglob.create('*.!(*a)').output); * //=> '(?!\\.)[^/]*?\\.(?!(?!\\.)[^/]*?a\\b).*?' * ``` * @param {String} `str` * @param {Object} `options` * @return {String} * @api public */ extglob.create = function(pattern, options) { if (typeof pattern !== 'string') { throw new TypeError('expected pattern to be a string'); } function create() { const ext = new Extglob(options); const ast = ext.parse(pattern, options); return ext.compile(ast, options); } return utils.memoize('create', pattern, options, create); }; /** * Returns an array of matches captured by `pattern` in `string`, or `null` * if the pattern did not match. * * ```js * const extglob = require('extglob'); * extglob.capture(pattern, string[, options]); * * console.log(extglob.capture('test/*.js', 'test/foo.js')); * //=> ['foo'] * console.log(extglob.capture('test/*.js', 'foo/bar.css')); * //=> null * ``` * @param {String} `pattern` Glob pattern to use for matching. * @param {String} `string` String to match * @param {Object} `options` See available [options](#options) for changing how matches are performed * @return {Boolean} Returns an array of captures if the string matches the glob pattern, otherwise `null`. * @api public */ extglob.capture = function(pattern, str, options) { const re = extglob.makeRe(pattern, Object.assign({capture: true}, options)); function match() { return function(string) { const match = re.exec(string); if (!match) { return null; } return match.slice(1); }; } const capture = utils.memoize('capture', pattern, options, match); return capture(str); }; /** * Create a regular expression from the given `pattern` and `options`. * * ```js * const extglob = require('extglob'); * const re = extglob.makeRe('*.!(*a)'); * console.log(re); * //=> /^[^\/]*?\.(?![^\/]*?a)[^\/]*?$/ * ``` * @param {String} `pattern` The pattern to convert to regex. * @param {Object} `options` * @return {RegExp} * @api public */ extglob.makeRe = function(pattern, options) { if (pattern instanceof RegExp) { return pattern; } if (typeof pattern !== 'string') { throw new TypeError('expected pattern to be a string'); } if (pattern.length > MAX_LENGTH) { throw new Error('expected pattern to be less than ' + MAX_LENGTH + ' characters'); } function makeRe() { const opts = Object.assign({strictErrors: false}, options); if (opts.strictErrors === true) opts.strict = true; const res = extglob.create(pattern, opts); return toRegex(res.output, opts); } const regex = utils.memoize('makeRe', pattern, options, makeRe); if (regex.source.length > MAX_LENGTH) { throw new SyntaxError('potentially malicious regex detected'); } return regex; }; /** * Cache */ extglob.cache = utils.cache; extglob.clearCache = function() { extglob.cache.__data__ = {}; }; /** * Expose `Extglob` constructor, parsers and compilers */ extglob.Extglob = Extglob; extglob.compilers = compilers; extglob.parsers = parsers; /** * Expose `extglob` * @type {Function} */ module.exports = extglob; extglob-3.0.0/lib/000077500000000000000000000000001327161302000137175ustar00rootroot00000000000000extglob-3.0.0/lib/compilers.js000066400000000000000000000076501327161302000162620ustar00rootroot00000000000000'use strict'; const brackets = require('expand-brackets'); /** * Extglob compilers */ module.exports = function(extglob) { function star() { if (typeof extglob.options.star === 'function') { return extglob.options.star.apply(this, arguments); } if (typeof extglob.options.star === 'string') { return extglob.options.star; } return '.*?'; } /** * Use `expand-brackets` compilers */ extglob.use(brackets.compilers); extglob.compiler /** * Escaped: "\\*" */ .set('escape', function(node) { return this.emit(node.val, node); }) /** * Dot: "." */ .set('dot', function(node) { return this.emit('\\' + node.val, node); }) /** * Question mark: "?" */ .set('qmark', function(node) { let val = '[^\\\\/.]'; const prev = node.prev; if (node.parsed.slice(-1) === '(') { const ch = node.rest.charAt(0); if (ch !== '!' && ch !== '=' && ch !== ':') { return this.emit(val, node); } return this.emit(node.val, node); } if (prev.type === 'text' && prev.val) { return this.emit(val, node); } if (node.val.length > 1) { val += '{' + node.val.length + '}'; } return this.emit(val, node); }) /** * Plus: "+" */ .set('plus', function(node) { const prev = node.parsed.slice(-1); if (prev === ']' || prev === ')') { return this.emit(node.val, node); } const ch = this.output.slice(-1); if (!this.output || (/[?*+]/.test(ch) && node.parent.type !== 'bracket')) { return this.emit('\\+', node); } if (/\w/.test(ch) && !node.inside) { return this.emit('+\\+?', node); } return this.emit('+', node); }) /** * Star: "*" */ .set('star', function(node) { const prev = node.prev; const prefix = prev.type !== 'text' && prev.type !== 'escape' ? '(?!\\.)' : ''; return this.emit(prefix + star.call(this, node), node); }) /** * Parens */ .set('paren', function(node) { this.mapVisit(node); }) .set('paren.open', function(node) { const capture = this.options.capture ? '(' : ''; switch (node.parent.prefix) { case '!': case '^': return this.emit(capture + '(?:(?!(?:', node); case '*': case '+': case '?': case '@': return this.emit(capture + '(?:', node); default: { let val = node.val; if (this.options.bash === true) { val = '\\' + val; } else if (!this.options.capture && val === '(' && node.parent.rest[0] !== '?') { val += '?:'; } return this.emit(val, node); } } }) .set('paren.close', function(node) { const capture = this.options.capture ? ')' : ''; switch (node.prefix) { case '!': case '^': const prefix = /^(\)|$)/.test(node.rest) ? '$' : ''; let str = star.call(this, node); // if the extglob has a slash explicitly defined, we know the user wants // to match slashes, so we need to ensure the "star" regex allows for it if (node.parent.hasSlash && !this.options.star && this.options.slash !== false) { str = '.*?'; } return this.emit(prefix + ('))' + str + ')') + capture, node); case '*': case '+': case '?': return this.emit(')' + node.prefix + capture, node); case '@': return this.emit(')' + capture, node); default: { const val = (this.options.bash === true ? '\\' : '') + ')'; return this.emit(val, node); } } }) /** * Text */ .set('text', function(node) { const val = node.val.replace(/[\[\]]/g, '\\$&'); return this.emit(val, node); }); }; extglob-3.0.0/lib/extglob.js000066400000000000000000000034071327161302000157250ustar00rootroot00000000000000'use strict'; /** * Module dependencies */ const Snapdragon = require('snapdragon'); const capture = require('snapdragon-capture'); const define = require('define-property'); /** * Local dependencies */ const compilers = require('./compilers'); const parsers = require('./parsers'); /** * Customize Snapdragon parser and renderer */ function Extglob(options) { this.options = Object.assign({source: 'extglob'}, options); this.snapdragon = this.options.snapdragon || new Snapdragon(this.options); this.snapdragon.use(capture()); this.snapdragon.patterns = this.snapdragon.patterns || {}; this.compiler = this.snapdragon.compiler; this.parser = this.snapdragon.parser; compilers(this.snapdragon); parsers(this.snapdragon); /** * Override Snapdragon `.parse` method */ define(this.snapdragon, 'parse', function(str, options) { const parsed = Snapdragon.prototype.parse.apply(this, arguments); parsed.input = str; // escape unmatched brace/bracket/parens const last = this.parser.stack.pop(); if (last && this.options.strict !== true) { const node = last.nodes[0]; node.val = '\\' + node.val; const sibling = node.parent.nodes[1]; if (sibling.type === 'star') { sibling.loose = true; } } // add non-enumerable parser reference define(parsed, 'parser', this.parser); return parsed; }); /** * Decorate `.parse` method */ define(this, 'parse', function(ast, options) { return this.snapdragon.parse.apply(this.snapdragon, arguments); }); /** * Decorate `.compile` method */ define(this, 'compile', function(ast, options) { return this.snapdragon.compile.apply(this.snapdragon, arguments); }); } /** * Expose `Extglob` */ module.exports = Extglob; extglob-3.0.0/lib/parsers.js000066400000000000000000000055501327161302000157410ustar00rootroot00000000000000'use strict'; const brackets = require('expand-brackets'); const utils = require('./utils'); /** * Characters to use in text regex (we want to "not" match * characters that are matched by other parsers) */ const TEXT_REGEX = '([!@*?+]?\\(|\\)|[*?.+\\\\]|\\[:?(?=.*\\])|:?\\])+'; const not = utils.createRegex(TEXT_REGEX); /** * Extglob parsers */ function parsers(extglob) { extglob.state = extglob.state || {}; /** * Use `expand-brackets` parsers */ extglob.use(brackets.parsers); extglob.parser.sets.paren = extglob.parser.sets.paren || []; extglob.parser /** * Extglob open: "*(" */ .set('paren.open', function() { const pos = this.position(); const m = this.match(/^([!@*?+])?\(/); if (!m) return; const prev = this.prev(); const prefix = m[1]; const val = m[0]; const open = pos({ type: 'paren.open', val }); const node = pos({ type: 'paren', prefix, nodes: [] }); // if nested negation extglobs, just cancel them out to simplify if (prefix === '!' && prev.type === 'paren' && prev.prefix === '!') { prev.prefix = '@'; node.prefix = '@'; } this.pushNode(node, prev); this.pushNode(open, node); this.push('paren', node); }) /** * Extglob close: ")" */ .set('paren.close', function() { const parsed = this.parsed; const pos = this.position(); const m = this.match(/^\)/); if (!m) return; const parent = this.pop('paren'); const node = pos({ type: 'paren.close', rest: this.input, parsed, val: m[0] }); if (!this.isType(parent, 'paren')) { if (this.options.strict) { throw new Error('missing opening paren: "("'); } node.escaped = true; return node; } node.prefix = parent.prefix; this.pushNode(node, parent); }) /** * Escape: "\\." */ .set('escape', function() { const pos = this.position(); const m = this.match(/^\\(.)/); if (!m) return; return pos({ type: 'escape', val: m[0], ch: m[1] }); }) /** * Question marks: "?" */ .set('qmark', function() { const parsed = this.parsed; const pos = this.position(); const m = this.match(/^\?+(?!\()/); if (!m) return; extglob.state.metachar = true; return pos({ type: 'qmark', rest: this.input, parsed, val: m[0] }); }) /** * Character parsers */ .capture('star', /^\*(?!\()/) .capture('plus', /^\+(?!\()/) .capture('dot', /^\./) .capture('text', not); }; /** * Expose text regex string */ module.exports.TEXT_REGEX = TEXT_REGEX; /** * Extglob parsers */ module.exports = parsers; extglob-3.0.0/lib/utils.js000066400000000000000000000024121327161302000154140ustar00rootroot00000000000000'use strict'; const regex = require('regex-not'); const Cache = require('fragment-cache'); /** * Utils */ const utils = module.exports; const cache = utils.cache = new Cache(); /** * Cast `val` to an array * @return {Array} */ utils.arrayify = function(val) { if (!Array.isArray(val)) { return [val]; } return val; }; /** * Memoize a generated regex or function */ utils.memoize = function(type, pattern, options, fn) { const key = utils.createKey(type + pattern, options); if (cache.has(type, key)) { return cache.get(type, key); } const val = fn(pattern, options); if (options && options.cache === false) { return val; } cache.set(type, key, val); return val; }; /** * Create the key to use for memoization. The key is generated * by iterating over the options and concatenating key-value pairs * to the pattern string. */ utils.createKey = function(pattern, options) { let key = pattern; if (typeof options === 'undefined') { return key; } for (const prop in options) { key += ';' + prop + '=' + String(options[prop]); } return key; }; /** * Create the regex to use for matching text */ utils.createRegex = function(str) { const opts = {contains: true, strictClose: false}; return regex(str, opts); }; extglob-3.0.0/package.json000066400000000000000000000045741327161302000154510ustar00rootroot00000000000000{ "name": "extglob", "description": "Extended glob support for JavaScript. Adds (almost) the expressive power of regular expressions to glob patterns.", "version": "3.0.0", "homepage": "https://github.com/micromatch/extglob", "author": "Jon Schlinkert (https://github.com/jonschlinkert)", "contributors": [ "Brian Woodward (https://twitter.com/doowb)", "Devon Govett (http://badassjs.com)", "Isiah Meadows (https://www.isiahmeadows.com)", "Jon Schlinkert (http://twitter.com/jonschlinkert)", "Matt Bierner (http://mattbierner.com)", "Shinnosuke Watanabe (https://shinnn.github.io)", "Daniel Tschinder (https://github.com/danez)" ], "repository": "micromatch/extglob", "bugs": { "url": "https://github.com/micromatch/extglob/issues" }, "license": "MIT", "files": [ "index.js", "lib" ], "main": "index.js", "engines": { "node": ">=4.0.0" }, "scripts": { "test": "mocha" }, "dependencies": { "array-unique": "^0.3.2", "define-property": "^2.0.2", "expand-brackets": "^4.0.0", "fragment-cache": "^0.2.1", "regex-not": "^1.0.0", "snapdragon": "^0.12.0", "snapdragon-capture": "^0.2.0", "to-regex": "^3.0.1" }, "devDependencies": { "bash-match": "^1.0.2", "for-own": "^1.0.0", "gulp": "^3.9.1", "gulp-eslint": "^4.0.0", "gulp-format-md": "^1.0.0", "gulp-istanbul": "^1.1.2", "gulp-mocha": "^3.0.1", "gulp-unused": "^0.2.1", "helper-changelog": "^0.3.0", "is-windows": "^1.0.1", "micromatch": "^3.0.4", "minimatch": "^3.0.4", "minimist": "^1.2.0", "mocha": "^3.5.0", "multimatch": "^2.1.0" }, "keywords": [ "bash", "extended", "extglob", "glob", "globbing", "ksh", "match", "pattern", "patterns", "regex", "test", "wildcard" ], "lintDeps": { "devDependencies": { "files": { "options": { "ignore": [ "benchmark/**/*.js" ] } } } }, "verb": { "toc": false, "layout": "default", "tasks": [ "readme" ], "related": { "list": [ "braces", "expand-brackets", "expand-range", "fill-range", "micromatch" ] }, "helpers": [ "helper-changelog" ], "plugins": [ "gulp-format-md" ], "lint": { "reflinks": true } } } extglob-3.0.0/test/000077500000000000000000000000001327161302000141305ustar00rootroot00000000000000extglob-3.0.0/test/_negations.js000066400000000000000000000062061327161302000166200ustar00rootroot00000000000000'use strict'; /** * minimatch "tricky negations test" */ module.exports = { 'bar.min.js': { '*.!(js|css)': true, '!*.+(js|css)': false, '*.+(js|css)': true }, 'a-integration-test.js': { '*.!(j)': true, '*.!(js)': false, '!(*-integration-test.js)': false, '*-!(integration-)test.js': true, '*-!(integration)-test.js': false, '*!(-integration)-test.js': true, '*!(-integration-)test.js': true, '*!(integration)-test.js': true, '*!(integration-test).js': true, '*-!(integration-test).js': true, '*-!(integration-test.js)': true, '*-!(integra)tion-test.js': false, '*-integr!(ation)-test.js': false, '*-integr!(ation-t)est.js': false, '*-i!(ntegration-)test.js': false, '*i!(ntegration-)test.js': true, '*te!(gration-te)st.js': true, '*-!(integration)?test.js': false, '*?!(integration)?test.js': true }, 'foo-integration-test.js': { '@(foo-integration-test.js)': true, '@(*-integration-test.js)': true, '@(*-integration-test).js': true, 'foo-integration-test.js': true, '!(*-integration-test.js)': false }, 'foo.jszzz.js': { '*.!(js).js': true }, 'asd.jss': { '*.!(js)': true }, 'asd.jss.xyz': { '*.!(js)*.!(xy)': false, '*.!(js)*.!(xy)*': false, '*.!(js).!(xy)': false }, 'asd.jss.xy': { '*.!(js)*.!(xy)': false, '*.!(js)*.!(xy)*': false, '*.!(js).!(xy)': false, '*.!(js).!(xy)*': false }, 'asd.js.xyz': { '*.!(js)*.!(xy)': false, '*.!(js)*.!(xy)*': false, '*.!(js)*.!(xyz)': false, '*.!(js)*.!(xyz)*': false, '*.!(js).!(xy)': false, '*.!(js).!(xy)*': false, '*.!(js).!(xyz)': false, '*.!(js).!(xyz)*': false }, 'asd.js.xy': { '*.!(js).!(xy)': false }, 'asd.sjs.zxy': { '*.!(js).!(xy)': true }, 'asd..xyz': { '*.!(js).!(xy)': true }, 'asd..xy': { '*.!(js).!(xy)': false, '*.!(js|x).!(xy)': false }, 'foo.js.js': { '*!(js)': true, '*!(.js)': true, '*!(.js.js)': true, '*!(.js.js)*': true, '*(.js.js)': false, '**(.js.js)': true, '*(!(.js.js))': true, '*.!(js)*.!(js)': false, '*.!(js)+': false, '!(*(.js.js))': true, '*.!(js)': true, '*.!(js)*': false, // Bash 4.3 disagrees! '*.!(js)*.js': false // Bash 4.3 disagrees! }, 'a/foo.js.js': { '*/**(.*)': true, '*/**(.*.*)': true, 'a/**(.*.*)': true, '*/**(.js.js)': true, 'a/f*(!(.js.js))': true, 'a/!(*(.*))': true, 'a/!(+(.*))': true, 'a/!(*(.*.*))': true, '*/!(*(.*.*))': true, 'a/!(*(.js.js))': true }, 'testjson.json': { '*(*.json|!(*.js))': true, '+(*.json|!(*.js))': true, '@(*.json|!(*.js))': true, '?(*.json|!(*.js))': true }, 'foojs.js': { '*(*.json|!(*.js))': false, // Bash 4.3 disagrees! '*(*.json|!(*.js))*': true, '+(*.json|!(*.js))': false, // Bash 4.3 disagrees! '@(*.json|!(*.js))': false, '?(*.json|!(*.js))': false }, 'other.bar': { '*(*.json|!(*.js))': true, '*(*.json|!(*.js))*': true, '!(*(*.json|!(*.js)))*': false, '+(*.json|!(*.js))': true, '@(*.json|!(*.js))': true, '?(*.json|!(*.js))': true } }; extglob-3.0.0/test/bash.extglob.js000066400000000000000000000164161327161302000170560ustar00rootroot00000000000000'use strict'; require('mocha'); var match = require('./support/match'); var assert = require('assert'); // ported from http://www.bashcookbook.com/bashinfo/source/bash-4.3/tests/extglob.tests describe('bash tests derived from the pd-ksh test suite:', function() { var startLine = 11; var tests = [ [ '/dev/udp/129.22.8.102/45', '/dev/@(tcp|udp)/*/*', true ], '', 'valid numbers', [ '0', '0|[1-9]*([0-9])', true ], // Bash 4.3 disagrees [ '12', '0|[1-9]*([0-9])', true ], // Bash 4.3 disagrees [ '12abc', '0|[1-9]*([0-9])', false ], [ '1', '0|[1-9]*([0-9])', true ], // Bash 4.3 disagrees '', 'octal numbers', [ '07', '+([0-7])', true ], [ '0377', '+([0-7])', true ], [ '09', '+([0-7])', false ], '', 'stuff from korn\'s book', [ 'paragraph', 'para@(chute|graph)', true ], [ 'paramour', 'para@(chute|graph)', false ], [ 'para991', 'para?([345]|99)1', true ], [ 'para381', 'para?([345]|99)1', false ], [ 'paragraph', 'para*([0-9])', false ], [ 'para', 'para*([0-9])', true ], [ 'para13829383746592', 'para*([0-9])', true ], [ 'paragraph', 'para*([0-9])', false ], [ 'para', 'para+([0-9])', false ], [ 'para987346523', 'para+([0-9])', true ], [ 'paragraph', 'para!(*.[0-9])', true ], [ 'para.38', 'para!(*.[0-9])', true ], [ 'para.graph', 'para!(*.[0-9])', true ], [ 'para39', 'para!(*.[0-9])', true ], '', 'tests derived from those rosenblatt\'s korn shell book', [ '', '*(0|1|3|5|7|9)', true ], [ '""', '*(0|1|3|5|7|9)', false ], [ '137577991', '*(0|1|3|5|7|9)', true ], [ '2468', '*(0|1|3|5|7|9)', false ], [ 'file.c', '*.c?(c)', true ], [ 'file.C', '*.c?(c)', false ], [ 'file.cc', '*.c?(c)', true ], [ 'file.ccc', '*.c?(c)', false ], [ 'parse.y', '!(*.c|*.h|Makefile.in|config*|README)', true ], [ 'shell.c', '!(*.c|*.h|Makefile.in|config*|README)', false ], [ 'Makefile', '!(*.c|*.h|Makefile.in|config*|README)', true ], [ '"VMS.FILE;1"', '*\\;[1-9]*([0-9])', false ], [ '"VMS.FILE;0"', '*\\;[1-9]*([0-9])', false ], [ '"VMS.FILE;"', '*\\;[1-9]*([0-9])', false ], [ '"VMS.FILE;139"', '*\\;[1-9]*([0-9])', false ], [ '"VMS.FILE;139"', '*;[1-9]*([0-9])', false ], [ '"VMS.FILE;139"', '*;[1-9]*([0-9])*', true ], [ '"VMS.FILE;139"', '*;[1-9]**([0-9])*', true ], [ '"VMS.FILE;1N"', '*;[1-9]*([0-9])', false ], '', ['abcx', '!([*)*', true], ['abcx', '!(\\[*)*', true], ['abcz', '!([*)*', true], ['abcz', '!(\\[*)*', true], ['bbc', '!([*)*', true], ['bbc', '!(\\[*)*', true], ['abcx', '+(a|b[)*', true], ['abcx', '+(a|b\\[)*', true], ['abcz', '+(a|b[)*', true], ['abcz', '+(a|b\\[)*', true], ['bbc', '+(a|b[)*', false], ['abcx', '[a*(]*z', false], ['abcx', '[a*\\(]*z', false], ['abcz', '[a*(]*z', true], ['abcz', '[a*\\(]*z', true], ['bbc', '[a*(]*z', false], ['bbc', '[a*\\(]*z', false], '', ['abc', '+()c', false], ['abc', '+()x', false], ['abc', '+(*)c', true], ['abc', '+(*)x', false], ['abc', 'no-file+(a|b)stuff', false], ['abc', 'no-file+(a*(c)|b)stuff', false], '', ['abc', 'a+(b|c)d', false], ['abd', 'a+(b|c)d', true], ['acd', 'a+(b|c)d', true], '', ['abc', 'a!(@(b|B))d', false], ['abd', 'a!(@(b|B))d', false], ['acd', 'a!(@(b|B))d', true], '', ['abc', 'a[b*(foo|bar)]d', false], ['abd', 'a[b*(foo|bar)]d', true], ['acd', 'a[b*(foo|bar)]d', false], '', 'simple kleene star tests', ['foo', '*(a|b[)', false], ['foo', '*(a|b[)|f*', true], 'this doesn\'t work right yet (from bash notes, it does work in extglob)', ['*(a|b[)', '*(a|b[)', true], '', 'More tests derived from a bug report concerning extended glob patterns following a *', ['ab', 'ab*(e|f)', true], ['abcdef', 'ab*(e|f)', false], ['abcfef', 'ab*(e|f)', false], ['abcfefg', 'ab*(e|f)', false], ['abef', 'ab*(e|f)', true], '', ['ab', 'b?*(e|f)', false], ['abcdef', 'b?*(e|f)', false], ['abcfef', 'b?*(e|f)', false], ['abcfefg', 'b?*(e|f)', false], ['abef', 'b?*(e|f)', false], '', ['ab', 'ab*d+(e|f)', false], ['abcdef', 'ab*d+(e|f)', true], ['abcfef', 'ab*d+(e|f)', false], ['abcfefg', 'ab*d+(e|f)', false], ['abef', 'ab*d+(e|f)', false], '', ['ab', 'ab**(e|f)', true], ['abcdef', 'ab**(e|f)', true], ['abcfef', 'ab**(e|f)', true], ['abcfefg', 'ab**(e|f)', true], ['abef', 'ab**(e|f)', true], '', ['ab', 'ab*+(e|f)', false], ['abcdef', 'ab*+(e|f)', true], ['abcfef', 'ab*+(e|f)', true], ['abcfefg', 'ab*+(e|f)', false], ['abef', 'ab*+(e|f)', true], '', ['ab', 'ab**(e|f)', true], ['abcdef', 'ab**(e|f)', true], ['abcfef', 'ab**(e|f)', true], ['abcfefg', 'ab**(e|f)', true], ['abef', 'ab**(e|f)', true], '', ['ab', 'ab**(e|f)g', false], ['abcdef', 'ab**(e|f)g', false], ['abcfef', 'ab**(e|f)g', false], ['abcfefg', 'ab**(e|f)g', true], ['abef', 'ab**(e|f)g', false], '', ['ab', 'ab*+(e|f)', false], ['abcdef', 'ab*+(e|f)', true], ['abcfef', 'ab*+(e|f)', true], ['abcfefg', 'ab*+(e|f)', false], ['abef', 'ab*+(e|f)', true], '', ['ab', 'ab***ef', false], ['abcdef', 'ab***ef', true], ['abcfef', 'ab***ef', true], ['abcfefg', 'ab***ef', false], ['abef', 'ab***ef', true], '', ['ab', 'ab**', true], ['abcdef', 'ab**', true], ['abcfef', 'ab**', true], ['abcfefg', 'ab**', true], ['abef', 'ab**', true], '', 'bug in all versions up to and including bash-2.05b', ['123abc', '*?(a)bc', true], '', 'character classes', [['a.b', 'a,b', 'a:b', 'a-b', 'a;b', 'a b', 'a_b'], 'a[^[:alnum:]]b', ['a.b', 'a,b', 'a:b', 'a-b', 'a;b', 'a b', 'a_b']], [['a.b', 'a,b', 'a:b', 'a-b', 'a;b', 'a b', 'a_b'], 'a[-.,:; _]b', ['a.b', 'a,b', 'a:b', 'a-b', 'a;b', 'a b', 'a_b']], [['a.b', 'a,b', 'a:b', 'a-b', 'a;b', 'a b', 'a_b'], 'a@([^[:alnum:]])b', ['a.b', 'a,b', 'a:b', 'a-b', 'a;b', 'a b', 'a_b']], [['a.b', 'a,b', 'a:b', 'a-b', 'a;b', 'a b', 'a_b'], 'a@([-.,:; _])b', ['a.b', 'a,b', 'a:b', 'a-b', 'a;b', 'a b', 'a_b']], [['a.b', 'a,b', 'a:b', 'a-b', 'a;b', 'a b', 'a_b'], 'a@([.])b', ['a.b']], [['a.b', 'a,b', 'a:b', 'a-b', 'a;b', 'a b', 'a_b'], 'a@([^.])b', ['a,b', 'a:b', 'a-b', 'a;b', 'a b', 'a_b']], [['a.b', 'a,b', 'a:b', 'a-b', 'a;b', 'a b', 'a_b'], 'a@([^x])b', ['a,b', 'a:b', 'a-b', 'a;b', 'a b', 'a_b']], [['a.b', 'a,b', 'a:b', 'a-b', 'a;b', 'a b', 'a_b'], 'a+([^[:alnum:]])b', ['a.b', 'a,b', 'a:b', 'a-b', 'a;b', 'a b', 'a_b']], [['a.b', 'a,b', 'a:b', 'a-b', 'a;b', 'a b', 'a_b'], 'a@(.|[^[:alnum:]])b', ['a.b', 'a,b', 'a:b', 'a-b', 'a;b', 'a b', 'a_b']], '', ['a , b', '*([[:space:]]),*([[:space:]])', false], ['a , b', 'a*([[:space:]]),*([[:space:]])b', true] ]; tests.forEach(function(test, i) { if (!Array.isArray(test) || !test) return; var fixture = test[0]; var pattern = test[1]; // if (pattern !== 'a[-.,:\;\ _]b') return; var expected = test[2]; var msg = ') should ' + (expected ? '' : 'not ') + 'match ' + pattern; it((startLine + i) + msg, function() { if (Array.isArray(fixture)) { match(fixture, pattern, expected, msg); } else { assert.equal(match.isMatch(fixture, pattern), expected, msg); } }); }); }); extglob-3.0.0/test/bash.extglob1.js000066400000000000000000000022131327161302000171250ustar00rootroot00000000000000'use strict'; require('mocha'); var match = require('./support/match'); var assert = require('assert'); // ported from http://www.bashcookbook.com/bashinfo/source/bash-4.3/tests/extglob1.sub describe('bash extglob1 tests', function() { var startLine = 11; var tests = [ ['a.c', '+([[:alpha:].])', true], ['a.c', '+([[:alpha:].])+([[:alpha:].])', true], ['a.c', '*([[:alpha:].])', true], ['a.c', '*([[:alpha:].])*([[:alpha:].])', true], ['a.c', '?([[:alpha:].])?([[:alpha:].])?([[:alpha:].])', true], ['a.c', '@([[:alpha:].])@([[:alpha:].])@([[:alpha:].])', true], ['.', '!([[:alpha:].])', false], ['.', '?([[:alpha:].])', true], ['.', '@([[:alpha:].])', true], ['.', '*([[:alpha:].])', true], ['.', '+([[:alpha:].])', true] ]; tests.forEach(function(test, i) { if (!Array.isArray(test)) return; var fixture = test[0]; var pattern = test[1]; var expected = test[2]; var msg = '"' + fixture + '" should ' + (expected ? '' : 'not ') + 'match ' + pattern; it((startLine + i) + ' ' + msg, function() { assert.equal(match.isMatch(fixture, pattern), expected, msg); }); }); }); extglob-3.0.0/test/bash.extglob1a.js000066400000000000000000000021021327161302000172630ustar00rootroot00000000000000'use strict'; require('mocha'); var match = require('./support/match'); var assert = require('assert'); // ported from http://www.bashcookbook.com/bashinfo/source/bash-4.3/tests/extglob1a.sub describe('bash extglob1a tests', function() { var startLine = 11; var tests = [ ['a', 'a*!(x)', true], ['ab', 'a*!(x)', true], ['ba', 'a*!(x)', false], ['ax', 'a*!(x)', true], ['a', 'a!(x)', true], ['ab', 'a!(x)', true], ['ba', 'a!(x)', false], ['ax', 'a!(x)', false], ['a', 'a*?(x)', true], ['ab', 'a*?(x)', true], ['ba', 'a*?(x)', false], ['ax', 'a*?(x)', true], ['a', 'a?(x)', true], ['ab', 'a?(x)', false], ['ba', 'a?(x)', false], ['ax', 'a?(x)', true] ]; tests.forEach(function(test, i) { if (!Array.isArray(test)) return; var fixture = test[0]; var pattern = test[1]; var expected = test[2]; var msg = 'should ' + (expected ? '' : 'not ') + 'match ' + pattern; it((startLine + i) + ' ' + msg, function() { assert.equal(match.isMatch(fixture, pattern), expected, msg); }); }); }); extglob-3.0.0/test/bash.extglob2.js000066400000000000000000000072361327161302000171400ustar00rootroot00000000000000'use strict'; require('mocha'); var assert = require('assert'); var match = require('./support/match'); // tests ported from http://www.bashcookbook.com/bashinfo/source/bash-4.3/tests/extglob2.tests describe('bash extglob2 tests', function() { var startLine = 11; var tests = [ [ 'fofo', '*(f*(o))', true ], [ 'ffo', '*(f*(o))', true ], [ 'foooofo', '*(f*(o))', true ], [ 'foooofof', '*(f*(o))', true ], [ 'fooofoofofooo', '*(f*(o))', true ], [ 'foooofof', '*(f+(o))', false ], [ 'xfoooofof', '*(f*(o))', false ], [ 'foooofofx', '*(f*(o))', false ], [ 'ofxoofxo', '*(*(of*(o)x)o)', true ], [ 'ofooofoofofooo', '*(f*(o))', false ], [ 'foooxfooxfoxfooox', '*(f*(o)x)', true ], [ 'foooxfooxofoxfooox', '*(f*(o)x)', false ], [ 'foooxfooxfxfooox', '*(f*(o)x)', true ], [ 'ofxoofxo', '*(*(of*(o)x)o)', true ], [ 'ofoooxoofxo', '*(*(of*(o)x)o)', true ], [ 'ofoooxoofxoofoooxoofxo', '*(*(of*(o)x)o)', true ], [ 'ofoooxoofxoofoooxoofxoo', '*(*(of*(o)x)o)', true ], [ 'ofoooxoofxoofoooxoofxofo', '*(*(of*(o)x)o)', false ], [ 'ofoooxoofxoofoooxoofxooofxofxo', '*(*(of*(o)x)o)', true ], [ 'aac', '*(@(a))a@(c)', true ], [ 'ac', '*(@(a))a@(c)', true ], [ 'c', '*(@(a))a@(c)', false ], [ 'aaac', '*(@(a))a@(c)', true ], [ 'baaac', '*(@(a))a@(c)', false ], [ 'abcd', '?@(a|b)*@(c)d', true ], [ 'abcd', '@(ab|a*@(b))*(c)d', true ], [ 'acd', '@(ab|a*(b))*(c)d', true ], [ 'abbcd', '@(ab|a*(b))*(c)d', true ], [ 'effgz', '@(b+(c)d|e*(f)g?|?(h)i@(j|k))', true ], [ 'efgz', '@(b+(c)d|e*(f)g?|?(h)i@(j|k))', true ], [ 'egz', '@(b+(c)d|e*(f)g?|?(h)i@(j|k))', true ], [ 'egzefffgzbcdij', '*(b+(c)d|e*(f)g?|?(h)i@(j|k))', true ], [ 'egz', '@(b+(c)d|e+(f)g?|?(h)i@(j|k))', false ], [ 'ofoofo', '*(of+(o))', true ], [ 'oxfoxoxfox', '*(oxf+(ox))', true ], [ 'oxfoxfox', '*(oxf+(ox))', false ], [ 'ofoofo', '*(of+(o)|f)', true ], 'the following is supposed to match only as fo+ofo+ofo', [ 'foofoofo', '@(foo|f|fo)*(f|of+(o))', true ], [ 'oofooofo', '*(of|oof+(o))', true ], [ 'fffooofoooooffoofffooofff', '*(*(f)*(o))', true ], 'the following tests backtracking in alternation matches', [ 'fofoofoofofoo', '*(fo|foo)', true ], 'exclusion', [ 'foo', '!(x)', true ], [ 'foo', '!(x)*', true ], [ 'foo', '!(foo)', false ], [ 'foo', '!(foo)*', false ], // Bash 4.3 disagrees! [ 'foobar', '!(foo)', true ], [ 'foobar', '!(foo)*', false ], // Bash 4.3 disagrees! [ 'moo.cow', '!(*.*).!(*.*)', false ], // Bash 4.3 disagrees! [ 'mad.moo.cow', '!(*.*).!(*.*)', false ], [ 'mucca.pazza', 'mu!(*(c))?.pa!(*(z))?', false ], [ 'fff', '!(f)', true ], [ 'fff', '*(!(f))', true ], [ 'fff', '+(!(f))', true ], [ 'ooo', '!(f)', true ], [ 'ooo', '*(!(f))', true ], [ 'ooo', '+(!(f))', true ], [ 'foo', '!(f)', true ], [ 'foo', '*(!(f))', true ], [ 'foo', '+(!(f))', true ], [ 'f', '!(f)', false ], [ 'f', '*(!(f))', false ], [ 'f', '+(!(f))', false ], [ 'foot', '@(!(z*)|*x)', true ], [ 'zoot', '@(!(z*)|*x)', false ], [ 'foox', '@(!(z*)|*x)', true ], [ 'zoox', '@(!(z*)|*x)', true ], [ 'foo', '*(!(foo))', false ], // Bash 4.3 disagrees! [ 'foob', '!(foo)b*', false ], [ 'foobb', '!(foo)b*', false ] // Bash 4.3 disagrees! ]; tests.forEach(function(test, n) { if (!Array.isArray(test)) return; var fixture = test[0]; var pattern = test[1]; var expected = test[2]; var msg = 'should ' + (expected ? '' : 'not ') + 'match ' + pattern; it((startLine + n) + ' ' + msg, function() { assert.equal(match.isMatch(fixture, pattern), expected, msg); }); }); }); extglob-3.0.0/test/bash.extglob3.js000066400000000000000000000033361327161302000171360ustar00rootroot00000000000000'use strict'; require('mocha'); var match = require('./support/match'); var assert = require('assert'); // ported from http://www.bashcookbook.com/bashinfo/source/bash-4.3/tests/extglob3.tests describe('bash extglob3 tests', function() { var startLine = 11; var tests = [ [ 'ab/../', '@(ab|+([^/]))/..?(/)', true ], [ 'ab/../', '+([^/])/..?(/)', true ], [ 'ab/../', '@(ab|?b)/..?(/)', true ], [ 'ab/../', '+([^/])/../', true ], [ 'ab/../', '+([!/])/..?(/)', true ], [ 'ab/../', '@(ab|+([!/]))/..?(/)', true ], [ 'ab/../', '+([!/])/../', true ], [ 'ab/../', '+([!/])/..?(/)', true ], [ 'ab/../', '+([!/])/..@(/)', true ], [ 'ab/../', '+(ab)/..?(/)', true ], [ 'ab/../', '[!/][!/]/../', true ], [ 'ab/../', '@(ab|?b)/..?(/)', true ], [ 'ab/../', '[^/][^/]/../', true ], [ 'ab/../', '?b/..?(/)', true ], [ 'ab/../', '+(?b)/..?(/)', true ], [ 'ab/../', '+(?b|?b)/..?(/)', true ], [ 'ab/../', '@(?b|?b)/..?(/)', true ], [ 'ab/../', '@(a?|?b)/..?(/)', true ], [ 'ab/../', '?(ab)/..?(/)', true ], [ 'ab/../', '?(ab|??)/..?(/)', true ], [ 'ab/../', '@(??)/..?(/)', true ], [ 'ab/../', '@(??|a*)/..?(/)', true ], [ 'ab/../', '@(a*)/..?(/)', true ], [ 'ab/../', '+(??)/..?(/)', true ], [ 'ab/../', '+(??|a*)/..?(/)', true ], [ 'ab/../', '+(a*)/..?(/)', true ], [ 'x', '@(x)', true ] ]; tests.forEach(function(test, i) { if (!Array.isArray(test)) return; var fixture = test[0]; var pattern = test[1]; var expected = test[2]; var msg = 'should ' + (expected ? '' : 'not ') + 'match ' + pattern; it((startLine + i) + ' ' + msg, function() { assert.equal(match.isMatch(fixture, pattern), expected, msg); }); }); }); extglob-3.0.0/test/bash.js000066400000000000000000000234621327161302000154120ustar00rootroot00000000000000'use strict'; require('mocha'); var match = require('./support/match'); var assert = require('assert'); describe('running extglob against minimatch tests', function() { var tests = [ ['*(a|b[)', '*(a|b\\[)', false], ['123abc', 'ab*d+(e|f)', false], ['123abc', 'ab?*(e|f)', false], ['a', '!(a)', false], ['a', '(b)', false], ['a', '??', false], ['a', 'a??b', false], ['a', 'b?(a|b)', false], ['a.', '*.+(b|d)', false], ['a', '!(*.a|*.b|*.c)', true], ['a.a', '!(*.[a-b]*)', false], ['a.a', '!(*.a|*.b|*.c)', false], ['a.a', '!(*[a-b].[a-b]*)', false], ['a.a', '!*.(a|b)', false], ['a.a', '!*.(a|b)*', false], ['a.a', '*.!(a)', false], ['a.a', '*.+(b|d)', false], ['a.a.a', '!(*.[a-b]*)', false], ['a.a.a', '!(*[a-b].[a-b]*)', false], ['a.a.a', '!*.(a|b)', false], ['a.a.a', '!*.(a|b)*', false], ['a.a.a', '*.+(b|d)', false], ['a.abcd', '!(*.a|*.b|*.c)', false], ['a.abcd', '!(*.a|*.b|*.c)*', false], ['a.abcd', '*.!(a|b|c)', false], ['a.abcd', '*.!(a|b|c)*', false], ['a.b', '!(*.*)', false], ['a.b', '!(*.[a-b]*)', false], ['a.b', '!(*[a-b].[a-b]*)', false], ['a.b', '!*.(a|b)', false], ['a.b', '!*.(a|b)*', false], ['a.bb', '!(*.[a-b]*)', false], ['a.bb', '!(*[a-b].[a-b]*)', false], ['a.bb', '!*.(a|b)', false], ['a.bb', '!*.(a|b)*', false], ['a.ccc', '!*.(a|b)', false], ['a.ccc', '!*.(a|b)*', false], ['a.ccc', '*.+(b|d)', false], ['a.js', '!(*.js)', false], ['a.js', '*.!(js)', false], ['a.js.js', '!(*.js)', false], ['aa', '?', false], ['aa', '@(a)b', false], ['aa', 'a??b', false], ['aab', '?', false], ['aab', '??', false], ['aab', '@(c)b', false], ['ab', 'a!(@(b|B))', false], ['aB', 'a!(@(b|B))', false], ['ab', 'a(*b', false], ['ab', 'ab**(e|f)g', false], ['ab', 'ab*+(e|f)', false], ['ab', 'ab*d+(e|f)', false], ['ab', 'ab?*(e|f)', false], ['abcdef', '(a+|b)+', false], ['abcdef', 'ab**(e|f)g', false], ['abcdef', 'ab?*(e|f)', false], ['abcfef', '(a+|b)+', false], ['abcfef', 'ab**(e|f)g', false], ['abcfef', 'ab*d+(e|f)', false], ['abcfefg', '(a+|b)+', false], ['abcfefg', 'ab*d+(e|f)', false], ['abcfefg', 'ab?*(e|f)', false], ['abd', '(a+|b)+', false], ['abd', 'a!(@(b|B))d', false], ['abd', 'ab*d+(e|f)', false], ['abef', '(a+|b)+', false], ['abef', '*(a+|b)', false], ['abef', 'ab**(e|f)g', false], ['abef', 'ab*d+(e|f)', false], ['acd', '(a+|b)+', false], ['acd', 'ab*d+(e|f)', false], ['acd', 'ab?*(e|f)', false], ['ax', 'a?(b*)', false], ['b/a', '!(b/a)', false], ['baaac', '*(@(a))a@(c)', false], ['bb', 'a?(a|b)', false], ['c', '*(@(a))a@(c)', false], ['c.a', '!(*.[a-b]*)', false], ['c.a', '!*.(a|b)', false], ['c.a', '!*.(a|b)*', false], ['c.a', '*.!(a)', false], ['c.a', '*.+(b|d)', false], ['c.js', '!(*.js)', false], ['c.js', '*.!(js)', false], ['cow', '.!(*.*)', false], ['d.a.d', '!*.(a|b)', false], ['d.a.d', '!*.(a|b)*', false], ['egz', '@(b+(c)d|e+(f)g?|?(h)i@(j|k))', false], ['f', '!(f)', false], ['f', '*(!(f))', false], ['f', '+(!(f))', false], ['f.a', '!(*.a|*.b|*.c)', false], ['f.a', '*.!(a|b|c)', false], ['foo', '!(foo)', false], ['foo', '!(foo)*', false], // bash 4.3 disagrees ['foo', '!(foo)+', false], ['foo', '!(foo)b*', false], ['foo', '*(!(foo))', false], ['foo.js.js', '*.!(js)*', false], ['foo.js.js', '*.!(js)*.!(js)', false], ['foo.js.js', '*.!(js)+', false], ['foob', '!(foo)b*', false], ['foobar', '!(foo)*', false], // bash 4.3 disagrees ['foobar', '!(foo)b*', false], ['foobb', '!(foo)b*', false], ['foooofof', '*(f+(o))', false], ['foooofofx', '*(f*(o))', false], ['foooxfooxofoxfooox', '*(f*(o)x)', false], ['mad.moo.cow', '!(*.*).!(*.*)', false], ['mad.moo.cow', '.!(*.*)', false], ['Makefile.in', '!(*.c|*.h|Makefile.in|config*|README)', false], ['moo', '.!(*.*)', false], ['moo.cow', '!(*.*).!(*.*)', false], // bash 4.3 disagrees ['moo.cow', '.!(*.*)', false], ['mucca.pazza', 'mu!(*(c))?.pa!(*(z))?', false], ['ofooofoofofooo', '*(f*(o))', false], ['ofoooxoofxoofoooxoofxofo', '*(*(of*(o)x)o)', false], ['oxfoxfox', '*(oxf+(ox))', false], ['shell.c', '!(*.c|*.h|Makefile.in|config*|README)', false], ['xfoooofof', '*(f*(o))', false], ['zoot', '@(!(z*)|*x)', false], ['zz', '(a+|b)*', false], ['a', '(a)', true], ['a', '*(a)', true], ['a', '+(a)', true], ['a', '?', true], ['a', '?(a|b)', true], ['a', 'a?(a|b)', true], ['a', 'a?(x)', true], ['a((((b', 'a(*b', true], ['a((b', 'a(*b', true], ['a(b', 'a(*b', true], ['a.', '!(*.a|*.b|*.c)', true], ['a.', '*!(.a|.b|.c)', true], ['a.', '*.!(a)', true], ['a.', '*.!(a|b|c)', true], ['a.a', '(a|d).(a|b)*', true], ['a.a', '*!(.a|.b|.c)', true], ['a.a.a', '*.!(a)', true], ['a.abcd', '*!(*.a|*.b|*.c)*', true], ['a.abcd', '*!(.a|.b|.c)', true], ['a.b', '(a|d).(a|b)*', true], ['a.b', '*!(.a|.b|.c)', true], ['a.b', '*.!(a)', true], ['a.b', '*.+(b|d)', true], ['a.bb', '(a|d).(a|b)*', true], ['a.bb', '*.+(b|d)', true], ['a.c', '*!(.a|.b|.c)', true], ['a.c.d', '!(*.a|*.b|*.c)', true], ['a.c.d', '*!(.a|.b|.c)', true], ['a.c.d', '*.!(a|b|c)', true], ['a.ccc', '!(*.[a-b]*)', true], ['a.ccc', '!(*[a-b].[a-b]*)', true], ['a.js', '*!(.js)', true], ['a.js.js', '*!(.js)', true], ['a.js.js', '*.!(js)', true], ['a.md', '!(*.js)', true], ['a.md', '*!(.js)', true], ['a.md', '*.!(js)', true], ['aa', '!(a)', true], ['aaac', '*(@(a))a@(c)', true], ['aab', 'a??b', true], ['aac', '*(@(a))a@(c)', true], ['ab', '!(*.*)', true], ['ab', '(a+|b)+', true], ['ab', 'ab**(e|f)', true], ['ab]', 'a!(@(b|B))', true], ['abab', 'ab**(e|f)', true], ['abb', '!(*.*)', true], ['abbcd', '@(ab|a*(b))*(c)d', true], ['aBc', 'a!(@(b|B))', true], ['abcd', '?@(a|b)*@(c)d', true], ['abcd', '@(ab|a*@(b))*(c)d', true], ['abcdef', '(a+|b)*', true], ['abcdef', 'ab**(e|f)', true], ['abcdef', 'ab*+(e|f)', true], ['abcdef', 'ab*d+(e|f)', true], ['abcfef', '(a+|b)*', true], ['abcfef', 'ab**(e|f)', true], ['abcfef', 'ab*+(e|f)', true], ['abcfef', 'ab?*(e|f)', true], ['abcfefg', '(a+|b)*', true], ['abcfefg', 'ab**(e|f)', true], ['abd', '(a+|b)*', true], ['abd', 'a!(@(b|B))', true], ['abd', 'ab**(e|f)', true], ['abd', 'ab?*(e|f)', true], ['abef', '(a+|b)*', true], ['abef', 'ab**(e|f)', true], ['abef', 'ab*+(e|f)', true], ['abef', 'ab?*(e|f)', true], ['ac', '*(@(a))a@(c)', true], ['ac', 'a!(@(b|B))', true], ['acd', '(a+|b)*', true], ['acd', '@(ab|a*(b))*(c)d', true], ['acd', 'a!(@(b|B))', true], ['acd', 'a!(@(b|B))d', true], ['ax', '?(a*|b)', true], ['b', '(a+|b)*', true], ['b/b', '!(b/a)', true], ['b/c', '!(b/a)', true], ['ba', 'b?(a|b)', true], ['bar', '!(foo)*', true], ['bar', '!(foo)b*', true], ['baz', '!(foo)*', true], ['baz', '!(foo)b*', true], ['c.a', '!(*[a-b].[a-b]*)', true], ['c.c', '*!(.a|.b|.c)', true], ['c.ccc', '!(*.[a-b]*)', true], ['c.ccc', '!(*[a-b].[a-b]*)', true], ['c.js', '*!(.js)', true], ['d.a.d', '!(*.[a-b]*)', true], ['d.a.d', '!(*[a-b].[a-b]*)', true], ['d.a.d', '*.!(a)', true], ['d.a.d', '*.+(b|d)', true], ['d.d', '!(*.a|*.b|*.c)', true], ['d.d', '*!(.a|.b|.c)', true], ['d.d', '*.!(a|b|c)', true], ['d.js.d', '!(*.js)', true], ['d.js.d', '*!(.js)', true], ['d.js.d', '*.!(js)', true], ['e.e', '!(*.a|*.b|*.c)', true], ['e.e', '*!(.a|.b|.c)', true], ['e.e', '*.!(a|b|c)', true], ['effgz', '@(b+(c)d|e*(f)g?|?(h)i@(j|k))', true], ['efgz', '@(b+(c)d|e*(f)g?|?(h)i@(j|k))', true], ['egz', '@(b+(c)d|e*(f)g?|?(h)i@(j|k))', true], ['egzefffgzbcdij', '*(b+(c)d|e*(f)g?|?(h)i@(j|k))', true], ['f.a', '*!(.a|.b|.c)', true], ['f.f', '!(*.a|*.b|*.c)', true], ['f.f', '*!(.a|.b|.c)', true], ['f.f', '*.!(a|b|c)', true], ['fff', '!(f)', true], ['fff', '*(!(f))', true], ['fff', '+(!(f))', true], ['fffooofoooooffoofffooofff', '*(*(f)*(o))', true], ['ffo', '*(f*(o))', true], ['fofo', '*(f*(o))', true], ['fofoofoofofoo', '*(fo|foo)', true], ['foo', '!(f)', true], ['foo', '!(x)', true], ['foo', '!(x)*', true], ['foo', '*(!(f))', true], ['foo', '+(!(f))', true], ['foo.js.js', '*.!(js)', true], ['foobar', '!(foo)', true], ['foofoofo', '@(foo|f|fo)*(f|of+(o))', true], ['fooofoofofooo', '*(f*(o))', true], ['foooofo', '*(f*(o))', true], ['foooofof', '*(f*(o))', true], ['foooxfooxfoxfooox', '*(f*(o)x)', true], ['foooxfooxfxfooox', '*(f*(o)x)', true], ['foot', '@(!(z*)|*x)', true], ['foox', '@(!(z*)|*x)', true], ['Makefile', '!(*.c|*.h|Makefile.in|config*|README)', true], ['ofoofo', '*(of+(o))', true], ['ofoofo', '*(of+(o)|f)', true], ['ofoooxoofxo', '*(*(of*(o)x)o)', true], ['ofoooxoofxoofoooxoofxo', '*(*(of*(o)x)o)', true], ['ofoooxoofxoofoooxoofxoo', '*(*(of*(o)x)o)', true], ['ofoooxoofxoofoooxoofxooofxofxo', '*(*(of*(o)x)o)', true], ['ofxoofxo', '*(*(of*(o)x)o)', true], ['oofooofo', '*(of|oof+(o))', true], ['ooo', '!(f)', true], ['ooo', '*(!(f))', true], ['ooo', '+(!(f))', true], ['oxfoxoxfox', '*(oxf+(ox))', true], ['parse.y', '!(*.c|*.h|Makefile.in|config*|README)', true], ['zoox', '@(!(z*)|*x)', true] ]; tests.forEach(function(test) { var fixture = test[0]; var pattern = test[1]; var expected = test[2]; var msg = '"' + fixture + '" should ' + (expected ? '' : 'not ') + 'match ' + pattern; it(msg, function() { assert.equal(match.isMatch(fixture, pattern), expected, msg); }); }); }); extglob-3.0.0/test/capture.js000066400000000000000000000034511327161302000161340ustar00rootroot00000000000000'use strict'; var capture = require('../').capture; var assert = require('assert'); describe('.capture()', function() { it('should return null if no match', function() { assert.equal(capture('test/(a|b)', 'hi/123'), null); }); it('should capture paren groups', function() { assert.deepEqual(capture('test/(a|b)/x.js', 'test/a/x.js'), ['a']); assert.deepEqual(capture('test/(a|b)/x.js', 'test/b/x.js'), ['b']); }); it('should capture star groups', function() { assert.deepEqual(capture('test/a*(a|b)/x.js', 'test/a/x.js'), ['']); assert.deepEqual(capture('test/a*(a|b)/x.js', 'test/aa/x.js'), ['a']); assert.deepEqual(capture('test/a*(a|b)/x.js', 'test/ab/x.js'), ['b']); assert.deepEqual(capture('test/a*(a|b)/x.js', 'test/aba/x.js'), ['ba']); }); it('should capture plus groups', function() { assert.deepEqual(capture('test/+(a|b)/x.js', 'test/a/x.js'), ['a']); assert.deepEqual(capture('test/+(a|b)/x.js', 'test/b/x.js'), ['b']); assert.deepEqual(capture('test/+(a|b)/x.js', 'test/ab/x.js'), ['ab']); assert.deepEqual(capture('test/+(a|b)/x.js', 'test/aba/x.js'), ['aba']); }); it('should capture optional groups', function() { assert.deepEqual(capture('test/a?(a|b)/x.js', 'test/a/x.js'), ['']); assert.deepEqual(capture('test/a?(a|b)/x.js', 'test/ab/x.js'), ['b']); assert.deepEqual(capture('test/a?(a|b)/x.js', 'test/aa/x.js'), ['a']); }); it('should capture @ groups', function() { assert.deepEqual(capture('test/@(a|b)/x.js', 'test/a/x.js'), ['a']); assert.deepEqual(capture('test/@(a|b)/x.js', 'test/b/x.js'), ['b']); }); it('should capture negated groups', function() { assert.deepEqual(capture('test/!(a|b)/x.js', 'test/x/x.js'), ['x']); assert.deepEqual(capture('test/!(a|b)/x.js', 'test/y/x.js'), ['y']); }); }); extglob-3.0.0/test/errors.js000066400000000000000000000034521327161302000160060ustar00rootroot00000000000000'use strict'; var assert = require('assert'); var extglob = require('..'); describe('errors', function() { it('should throw an error when extglob() receives an invalid pattern', function(cb) { try { assert(extglob()); cb(new Error('expected an error')); } catch (err) { assert.equal(err.message, 'expected pattern to be a string'); } cb(); }); it('should throw an error when extglob.isMatch() receives an invalid pattern', function(cb) { try { assert(extglob.isMatch()); cb(new Error('expected an error')); } catch (err) { assert.equal(err.message, 'expected pattern to be a string'); } cb(); }); it('should throw an error when extglob.makeRe() receives an invalid pattern', function(cb) { try { assert(extglob.makeRe()); cb(new Error('expected an error')); } catch (err) { assert.equal(err.message, 'expected pattern to be a string'); } cb(); }); it('should throw an error when extglob.create() receives an invalid pattern', function(cb) { try { assert(extglob.create()); cb(new Error('expected an error')); } catch (err) { assert.equal(err.message, 'expected pattern to be a string'); } cb(); }); it('should throw an error when extglob.isMatch() receives an invalid string', function(cb) { try { assert(extglob.isMatch(null, '*')); cb(new Error('expected an error')); } catch (err) { assert.equal(err.message, 'expected a string'); } cb(); }); it('should throw an error when extglob.match() receives an invalid pattern', function(cb) { try { assert(extglob.match()); cb(new Error('expected an error')); } catch (err) { assert.equal(err.message, 'expected pattern to be a string'); } cb(); }); }); extglob-3.0.0/test/fixtures/000077500000000000000000000000001327161302000160015ustar00rootroot00000000000000extglob-3.0.0/test/fixtures/posix.txt000066400000000000000000000072461327161302000177150ustar00rootroot00000000000000# A test suite for the POSIX.2 (BRE) pattern matching code LC_ALL=C LANG=C # First, test POSIX.2 character classes case e in [[:xdigit:]]) echo ok 1;; esac case a in [[:alpha:]123]) echo ok 2;; esac case 1 in [[:alpha:]123]) echo ok 3;; esac case 9 in [![:alpha:]]) echo ok 4;; esac # invalid character class expressions are just characters to be matched case a in [:al:]) echo ok 5;; esac case a in [[:al:]) echo ok 6;; esac case '!' in [abc[:punct:][0-9]) echo ok 7;; esac # let's try to match the start of a valid sh identifier case 'PATH' in [_[:alpha:]]*) echo ok 8;; esac # let's try to match the first two characters of a valid sh identifier case PATH in [_[:alpha:]][_[:alnum:]]*) echo ok 9;; esac # is ^C a cntrl character? case $'\003' in [[:cntrl:]]) echo ok 10;; esac # how about A? case A in [[:cntrl:]]) echo oops -- cntrl ;; *) echo ok 11;; esac case 9 in [[:digit:]]) echo ok 12;; esac case X in [[:digit:]]) echo oops -- digit;; *) echo ok 13;; esac case $'\033' in [[:graph:]]) echo oops -- graph;; *) echo ok 14;; esac case $'\040' in [[:graph:]]) echo oops -- graph 2;; *) echo ok 15;; esac case ' ' in [[:graph:]]) echo oops -- graph 3;; *) echo ok 16;; esac case 'aB' in [[:lower:]][[:upper:]]) echo ok 17;; esac case $'\040' in [[:print:]]) echo ok 18;; *) echo oops -- print;; esac case PS3 in [_[:alpha:]][_[:alnum:]][_[:alnum:]]*) echo ok 19;; esac case a in [[:alpha:][:digit:]]) echo ok 20;; *) echo oops - skip brackpat ;; esac case a in [[:alpha:]\]) echo oops -- dangling backslash in brackpat ;; *) echo ok 21 ;; esac # what's a newline? is it a blank? a space? case $'\n' in [[:blank:]]) echo ok -- blank ;; [[:space:]]) echo ok -- space ;; *) echo oops newline ;; esac # OK, what's a tab? is it a blank? a space? case $'\t' in [[:blank:]]) echo ok -- blank ;; [[:space:]]) echo ok -- space ;; *) echo oops newline ;; esac # let's check out characters in the ASCII range case $'\377' in [[:ascii:]]) echo oops -- ascii\?;; esac case 9 in [1[:alpha:]123]) echo oops 1;; esac # however, an unterminated brace expression containing a valid char class # that matches had better fail case a in [[:alpha:]) echo oops 2;; esac case $'\b' in [[:graph:]]) echo oops 3;; esac case $'\b' in [[:print:]]) echo oops 4;; esac case $' ' in [[:punct:]]) echo oops 5;; esac # Next, test POSIX.2 collating symbols case 'a' in [[.a.]]) echo ok 1;; esac case '-' in [[.hyphen.]-9]) echo ok 2;; esac case 'p' in [[.a.]-[.z.]]) echo ok 3;; esac case '-' in [[.-.]]) echo ok 4;; esac case ' ' in [[.space.]]) echo ok 5;; esac case ' ' in [[.grave-accent.]]) echo oops - grave;; *) echo ok 6;; esac case '4' in [[.-.]-9]) echo ok 7;; esac # an invalid collating symbol cannot be the first part of a range case 'c' in [[.yyz.]-[.z.]]) echo oops - yyz;; *) echo ok 8;; esac case 'c' in [[.yyz.][.a.]-z]) echo ok 9;; esac # but when not part of a range is not an error case 'c' in [[.yyz.][.a.]-[.z.]]) echo ok 10 ;; esac case 'p' in [[.a.]-[.Z.]]) echo oops -- bad range ;; *) echo ok 11;; esac case p in [[.a.]-[.zz.]p]) echo ok 12;; *) echo oops -- bad range 2;; esac case p in [[.aa.]-[.z.]p]) echo ok 13;; *) echo oops -- bad range 3;; esac case c in [[.yyz.]cde]) echo ok 14;; esac case abc in [[.cb.]a-Za]*) echo ok 15;; esac case $'\t' in [[.space.][.tab.][.newline.]]) echo ok 16;; esac # and finally, test POSIX.2 equivalence classes case "abc" in [[:alpha:]][[=b=]][[:ascii:]]) echo ok 1;; esac case "abc" in [[:alpha:]][[=B=]][[:ascii:]]) echo oops -- =B=;; *) echo ok 2 ;; esac case a in [[=b=]) echo oops;; # an incomplete equiv class is just a string *) echo ok 3;; esac extglob-3.0.0/test/options.js000066400000000000000000000023661327161302000161700ustar00rootroot00000000000000'use strict'; var assert = require('assert'); var matcher = require('./support/match'); var extglob = require('..'); describe('options', function() { describe('options.nonull', function() { it('should return the pattern when no matches are found', function() { matcher.match(['ax'], 'a?(b*)', []); matcher.match(['ax'], 'a?(b*)', ['a?(b*)'], {nonull: true}); matcher.match(['az'], 'a?(b*)', ['a?(b*)'], {nonull: true}); matcher.match(['ag'], 'a?(b*)', ['a?(b*)'], {nonull: true}); }); }); describe('options.failglob', function() { it('should throw an error when no matches are found', function(cb) { try { extglob.match(['ax'], 'a?(b*)', {failglob: true}); return cb(new Error('expected an error')); } catch (err) { assert(/no matches/.test(err.message)); } cb(); }); }); describe('options.strict', function() { it('should throw an error when an opening brace is missing', function(cb) { assert(!extglob.isMatch('foo', 'a)')); try { assert(!extglob.isMatch('foo', 'a)', {strict: true})); return cb(new Error('expected an error')); } catch (err) { assert(/missing/.test(err.message)); } cb(); }); }); }); extglob-3.0.0/test/reference.js000066400000000000000000000013711327161302000164260ustar00rootroot00000000000000'use strict'; require('mocha'); var assert = require('assert'); var forOwn = require('for-own'); var matcher = require('./support/matcher'); var negations = require('./_negations'); describe('running extglob against minimatch tests', function() { forOwn(negations, function(val, fixture) { if (fixture !== 'asd.jss.xyz') return; describe('"' + fixture + '"', function() { forOwn(val, function(expected, pattern) { var exp = expected === false ? ' not' : ''; it('should' + exp + ' match "' + pattern + '"', function() { var actual = matcher.isMatch(fixture, pattern); if (actual === null) return; assert.equal(actual, expected, fixture + ' => ' + pattern); }); }); }); }); }); extglob-3.0.0/test/support/000077500000000000000000000000001327161302000156445ustar00rootroot00000000000000extglob-3.0.0/test/support/compare.js000066400000000000000000000001701327161302000176260ustar00rootroot00000000000000module.exports = function(a, b) { a = a.toLowerCase(); b = b.toLowerCase(); return a > b ? 1 : a < b ? -1 : 0; }; extglob-3.0.0/test/support/match.js000066400000000000000000000026501327161302000173010ustar00rootroot00000000000000'use strict'; var assert = require('assert'); var matcher = require('./matcher'); var compare = require('./compare'); var utils = require('./utils'); module.exports = function(fixtures, pattern, expected, options, msg) { if (!Array.isArray(expected)) { var tmp = expected; expected = options; options = tmp; } if (typeof options === 'string') { msg = options; options = {}; } msg = msg ? (pattern + ' ' + msg) : pattern; var actual = matcher.match(utils.arrayify(fixtures), pattern, options); expected.sort(compare); actual.sort(compare); assert.deepEqual(actual, expected, msg); }; module.exports.match = function(fixtures, pattern, expected, options, msg) { if (!Array.isArray(expected)) { var tmp = expected; expected = options; options = tmp; } if (typeof options === 'string') { msg = options; options = {}; } msg = msg ? (pattern + ' ' + msg) : pattern; var actual = matcher.match(utils.arrayify(fixtures), pattern, options); expected.sort(compare); actual.sort(compare); assert.deepEqual(actual, expected, msg); }; module.exports.isMatch = function(fixture, pattern, options) { return matcher.isMatch.apply(null, arguments); }; module.exports.contains = function(fixture, pattern, options) { return matcher.contains.apply(null, arguments); }; module.exports.makeRe = function(pattern, options) { return matcher.makeRe.apply(null, arguments); }; extglob-3.0.0/test/support/matcher.js000066400000000000000000000033051327161302000176260ustar00rootroot00000000000000'use strict'; var argv = require('minimist')(process.argv.slice(2)); var mm = require('multimatch'); var minimatch = require('minimatch'); var bash = require('./try-bash'); var utils = require('./utils'); var extglob = require('../..'); // use multimatch for the array/array scenario function mi() { return mm.apply(null, arguments); } // label for debugging mm.multimatch = true; mi.minimatch = true; extglob.extglob = true; bash.bash = true; /** * Decorate methods onto multimatch for parity with nanomatch */ mm.isMatch = function(files, patterns, options) { return mm(utils.arrayify(files), patterns, options).length > 0; }; mm.contains = function(files, patterns, options) { return mm.isMatch(files, patterns, options); }; mm.match = function(files, patterns, options) { return mm(utils.arrayify(files), patterns, options); }; mm.makeRe = function(pattern, options) { return mi.makeRe(pattern, options); }; /** * Decorate methods onto minimatch for parity with nanomatch */ mi.isMatch = function(file, pattern, options) { return minimatch(file, pattern, options); }; mi.contains = function(files, patterns, options) { return mi.isMatch(files, patterns, options); }; mi.match = function(files, pattern, options) { return minimatch.match(utils.arrayify(files), pattern, options); }; mi.makeRe = function(pattern, options) { return minimatch.makeRe(pattern, options); }; /** * Detect matcher based on argv, with nanomatch as default */ var matcher = argv.mm ? mm : (argv.mi ? mi : extglob); if (argv.bash) { matcher = bash; } /** * Expose matcher */ module.exports = matcher; module.exports.bash = bash; module.exports.extglob = extglob; module.exports.mm = mm; module.exports.mi = mi; extglob-3.0.0/test/support/parse.js000066400000000000000000000021221327161302000173110ustar00rootroot00000000000000'use strict'; var fs = require('fs'); var path = require('path'); var mm = require('micromatch'); function parseFiles(pattern, options) { var opts = Object.assign({cwd: path.join(__dirname, '../fixtures')}, options); var cwd = opts.cwd; var files = mm(fs.readdirSync(cwd), pattern); var tests = {}; for (var i = 0; i < files.length; i++) { var file = files[i]; var name = path.basename(file, path.extname(file)); tests[name] = parse(path.join(cwd, file)); } return tests; } function parse(fp) { var str = fs.readFileSync(fp, 'utf8'); var lines = str.split('\n'); var len = lines.length; var idx = -1; var tests = []; while (++idx < len) { var line = lines[idx].trim(); if (!line) continue; if (/^#\s\w/.test(line)) { tests.push(line.replace(/^[#\s]+/, '').toLowerCase()); continue; } if (!/^[tf] /.test(line)) continue; var segs = line.split(/\s+/).filter(Boolean); if (segs.length !== 3) continue; tests.push([segs[1], segs[2], segs[0] === 't']); } return tests.filter(Boolean); } module.exports = parseFiles; extglob-3.0.0/test/support/try-bash.js000066400000000000000000000010571327161302000177360ustar00rootroot00000000000000'use strict'; var bash = require('bash-match'); var isWindows = require('is-windows'); function matcher() { if (isWindows()) return; return bash.apply(null, arguments); } matcher.match = function(fixtures, pattern) { if (isWindows()) return; try { return bash.match(fixtures, pattern); } catch (err) {} return null; }; matcher.isMatch = function(fixtures, pattern) { if (isWindows()) return; try { return bash.isMatch(fixtures, pattern); } catch (err) {} return null; }; /** * Expose `matcher` */ module.exports = matcher; extglob-3.0.0/test/support/utils.js000066400000000000000000000003511327161302000173410ustar00rootroot00000000000000'use strict'; exports.arrayify = function(val) { return val ? (Array.isArray(val) ? val : [val]) : []; }; exports.alphaSort = function(a, b) { a = a.toLowerCase(); b = b.toLowerCase(); return a > b ? 1 : a < b ? -1 : 0; }; extglob-3.0.0/test/test.js000066400000000000000000000656071327161302000154630ustar00rootroot00000000000000'use strict'; var assert = require('assert'); var match = require('./support/match'); var extglob = require('..'); /** * Most of these tests were converted directly from * bash 4.3 and 4.4 unit tests. */ describe('extglobs', function() { it('should export a function', function() { assert.equal(typeof extglob, 'function'); }); it.skip('failing unit tests from bash', function() { match(['moo.cow'], '!(*.*).!(*.*)', ['moo.cow']); match(['foo.js.js'], '*.!(js)*', ['foo.js.js']); }); it('should throw on imbalanced sets when `options.strictErrors` is true', function() { assert.throws(function() { match.isMatch('a((b', 'a(b', {strictErrors: true}); }, 'row:1 col:2 missing opening parens: "a(b"'); assert.throws(function() { match.isMatch('a((b', 'a(*b', {strictErrors: true}); }, 'row:1 col:2 missing opening parens: "a(*b"'); }); // from minimatch tests it('should match extglobs ending with statechar', function() { assert(!match.isMatch('ax', 'a?(b*)')); assert(match.isMatch('ax', '?(a*|b)')); }); it('should not choke on non-extglobs', function() { match(['c/z/v'], 'c/z/v', ['c/z/v']); }); it('should work with file extensions', function() { match(['.md', 'a.js', 'a.md', 'b.md', 'c.md'], '@(a|b).md', ['a.md', 'b.md']); match(['.md', 'a.js', 'a.md', 'aa.md', 'ab.md', 'b.md', 'bb.md', 'c.md'], '+(a|b).md', ['a.md', 'aa.md', 'ab.md', 'b.md', 'bb.md']); match(['.md', 'a.js', 'a.md', 'aa.md', 'ab.md', 'b.md', 'bb.md', 'c.md'], '*(a|b).md', ['.md', 'a.md', 'aa.md', 'ab.md', 'b.md', 'bb.md']); }); it('should support star (`*`) extglobs', function() { match(['cz', 'abz', 'az'], 'a*(z)', ['az']); match(['cz', 'abz', 'az'], 'a**(z)', ['az', 'abz']); match(['c/z/v', 'z', 'zf', 'fz'], '*(z)', ['z']); match(['c/z/v', 'c/a/v'], 'c/*(z)/v', ['c/z/v']); match(['a.js.js', 'a.md.js'], '*.*(js).js', ['a.js.js']); }); it('should support negation (`!`) extglobs', function() { match(['moo.cow'], '!(!(moo)).!(!(cow))', ['moo.cow']); match(['c/z/v', 'c/a/v'], 'c/!(z)/v', ['c/a/v']); match(['c/z/v', 'c/a/v'], 'c/!(z)/v', ['c/a/v']); match(['cz', 'abz', 'az'], 'a!(z)', ['abz']); match(['cz', 'abz', 'az'], 'a*!(z)', ['az', 'abz']); match(['c/a/v'], 'c/!(z)/v', ['c/a/v']); match(['a/z', 'a/b'], 'a/!(z)', ['a/b']); var f1 = ['a/a', 'a/b', 'a/c', 'b/a', 'b/b', 'b/c']; match(f1, '*(b/a)', ['b/a']); match(f1, '!(b/a)', [], {star: '[^/]*?'}); match(f1, '!((b/a))', [], {star: '[^/]*?'}); match(f1, '!((?:b/a))', [], {star: '[^/]*?'}); match(f1, '!(b/(a))', [], {star: '[^/]*?'}); match(f1, '!(b/a)', ['a/a', 'a/b', 'a/c', 'b/b', 'b/c']); match(f1, '!((b/a))', ['a/a', 'a/b', 'a/c', 'b/b', 'b/c']); match(f1, '!((?:b/a))', ['a/a', 'a/b', 'a/c', 'b/b', 'b/c']); match(f1, '!(b/(a))', ['a/a', 'a/b', 'a/c', 'b/b', 'b/c']); match(['b', 'b ', 'b ', 'c '], '@(!(a) {1,2})*', ['b ', 'b ', 'c ']); match(['b', 'b ', 'bb', 'ccc'], '@(!(a) {1,2})*', ['b ']); match(['b', 'a ', 'b ', 'bb', 'ccc'], '@(!(a){1,2} )*', ['b ']); var f2 = ['a', 'b', 'aa', 'ab', 'bb', 'ac', 'aaa', 'aab', 'abb', 'ccc']; match(f2, '!(a)', ['aa', 'aaa', 'aab', 'ab', 'abb', 'ac', 'b', 'bb', 'ccc']); match(f2, '!(a*)', ['b', 'bb', 'ccc']); match(f2, '!(*a*)', ['b', 'bb', 'ccc']); match(f2, '!(*a)', ['aab', 'ab', 'abb', 'ac', 'b', 'bb', 'ccc']); match(f2, '!(a)*', ['b', 'bb', 'ccc']); match(f2, '!(*a)*', ['b', 'bb', 'ccc']); match(f2, 'a!(b)*', ['a', 'aa', 'aaa', 'aab', 'ac']); match(['aajs', 'bajs', 'aamd', 'abmd'], 'a!(a)md', ['abmd']); match(['aajs', 'bajs', 'aamd', 'abmd'], 'a!(.)md', ['aamd', 'abmd']); match(['a.js', 'a.md', 'b.md', 'c.md'], '!(a|b).md', ['c.md']); match(['a.js', 'a.md', 'b.md', 'c.md'], '!(a|c).md', ['b.md']); match(['a.js', 'a.md', 'b.md', 'b.js', 'c.md'], '!(a|c).@(md|js)', ['b.md', 'b.js']); }); it('should support plus (`+`) extglobs', function() { match(['cz', 'abz', 'az'], 'a+(z)', ['az']); match(['c/z/v', 'z', 'zf', 'fz'], '+(z)', ['z']); match(['c/z/v', 'c/a/v'], 'c/+(z)/v', ['c/z/v']); match(['az', 'bz', 'axz'], 'a+(z)', ['az']); }); it('should support qmark (`?`) extglobs', function() { match(['c/z/v', 'z', 'zf', 'fz'], '?(z)', ['z']); match(['cz', 'abz', 'az'], 'a?(z)', ['az']); }); it('should support ampersand (`@`) extglobs', function() { match(['c/z/v', 'c/a/v'], 'c/@(z)/v', ['c/z/v']); match(['cz', 'abz', 'az'], 'a*@(z)', ['az', 'abz']); match(['cz', 'abz', 'az'], 'a@(z)', ['az']); }); it('should support qmark matching', function() { var arr = ['a', 'aa', 'ab', 'aaa', 'abcdefg']; match(arr, '?', ['a']); match(arr, '??', ['aa', 'ab']); match(arr, '???', ['aaa']); }); it('should match exactly one of the given pattern:', function() { var arr = ['aa.aa', 'a.bb', 'a.aa.a', 'cc.a', 'a.a', 'c.a', 'dd.aa.d', 'b.a']; match(arr, '(b|a).(a)', ['a.a', 'b.a']); match(arr, '@(b|a).@(a)', ['a.a', 'b.a']); }); it('stuff from korn\'s book', function() { assert(!match.isMatch('para', 'para+([0-9])')); assert(!match.isMatch('para381', 'para?([345]|99)1')); assert(!match.isMatch('paragraph', 'para*([0-9])')); assert(!match.isMatch('paragraph', 'para*([0-9])')); assert(!match.isMatch('paramour', 'para@(chute|graph)')); assert(match.isMatch('para', 'para*([0-9])')); assert(match.isMatch('para.38', 'para!(*.[00-09])')); assert(match.isMatch('para.graph', 'para!(*.[0-9])')); assert(match.isMatch('para13829383746592', 'para*([0-9])')); assert(match.isMatch('para39', 'para!(*.[0-9])')); assert(match.isMatch('para987346523', 'para+([0-9])')); assert(match.isMatch('para991', 'para?([345]|99)1')); assert(match.isMatch('paragraph', 'para!(*.[0-9])')); assert(match.isMatch('paragraph', 'para@(chute|graph)')); }); it('tests derived from those in rosenblatt\'s korn shell book', function() { match(['', '137577991', '2468'], '*(0|1|3|5|7|9)', ['', '137577991']); match(['file.c', 'file.C', 'file.cc', 'file.ccc'], '*.c?(c)', ['file.c', 'file.cc']); match(['parse.y', 'shell.c', 'Makefile', 'Makefile.in'], '!(*.c|*.h|Makefile.in|config*|README)', ['parse.y', 'Makefile']); match(['VMS.FILE;', 'VMS.FILE;0', 'VMS.FILE;1', 'VMS.FILE;139', 'VMS.FILE;1N'], '*\\;[1-9]*([0-9])', ['VMS.FILE;1', 'VMS.FILE;139']); }); it('tests derived from the pd-ksh test suite', function() { match(['abcx', 'abcz', 'bbc'], '!([[*])*', ['abcx', 'abcz', 'bbc']); match(['abcx', 'abcz', 'bbc'], '+(a|b\\[)*', ['abcx', 'abcz']); match(['abd', 'acd'], 'a+(b|c)d', ['abd', 'acd']); match(['abd', 'acd', 'ac', 'ab'], 'a!(@(b|B))', ['acd', 'abd', 'ac']); match(['abd', 'acd'], 'a!(@(b|B))d', ['acd']); match(['abd', 'acd'], 'a[b*(foo|bar)]d', ['abd']); match(['abcx', 'abcz', 'bbc', 'aaz', 'aaaz'], '[a*(]*z', ['aaz', 'aaaz', 'abcz']); }); it('simple kleene star tests', function() { assert(!match.isMatch('foo', '*(a|b\\[)')); assert(match.isMatch('foo', '*(a|b\\[)|f*')); }); it('this doesn\'t work in bash either (per bash extglob.tests notes)', function() { assert(!match.isMatch('*(a|b[)', '*(a|b\\[)')); assert(match.isMatch('*(a|b[)', '\\*\\(a\\|b\\[\\)')); }); it('should support multiple extglobs:', function() { var arr = ['a.a', 'a.b', 'a.c', 'a.c.d', 'c.c', 'a.', 'd.d', 'e.e', 'f.f', 'a.abcd']; match(arr, '*.(a|b|@(ab|a*@(b))*(c)d)', ['a.a', 'a.b', 'a.abcd']); match(arr, '!(*.a|*.b|*.c)', ['a.', 'a.c.d', 'd.d', 'e.e', 'f.f']); match(arr, '!(*.[^a-c])', ['a.a', 'a.b', 'a.c', 'c.c', 'a.', 'a.abcd']); match(arr, '!(*.[a-c])', ['a.', 'a.c.d', 'a.abcd', 'd.d', 'e.e', 'f.f']); match(arr, '!(*.[a-c]*)', ['a.', 'a.c.d', 'd.d', 'e.e', 'f.f']); match(arr, '!(*.[a-c])*', ['a.', 'd.d', 'e.e', 'f.f']); match(arr, '*!(.a|.b|.c)', arr); match(arr, '*!(.a|.b|.c)*', arr); match(arr, '*.!(a|b|c)', ['a.c.d', 'a.', 'd.d', 'e.e', 'f.f']); match(arr, '*.!(a|b|c)*', ['a.c.d', 'a.', 'd.d', 'e.e', 'f.f']); }); it('should correctly match empty parens', function() { match(['def', 'ef'], '()ef', ['ef']); }); it('should match escaped parens', function() { var arr = ['a(b', 'a\\(b', 'a((b', 'a((((b', 'ab']; match(arr, 'a(b', ['a(b']); match(arr, 'a\\(b', ['a(b']); match(arr, 'a(*b', ['a(b', 'a((b', 'a((((b']); }); it('should match escaped backslashes', function() { match(['a(b', 'a\\(b', 'a((b', 'a((((b', 'ab'], 'a\\\\(b', ['a\\(b']); match(['a\\b', 'a/b', 'ab'], 'a\\\\b', ['a\\b']); }); // these are not extglobs, and do not need to pass, but they are included // to test integration with expand-brackets it('should match common regex patterns', function() { var fixtures = ['a c', 'a1c', 'a123c', 'a.c', 'a.xy.zc', 'a.zc', 'abbbbc', 'abbbc', 'abbc', 'abc', 'abq', 'axy zc', 'axy', 'axy.zc', 'axyzc']; match(['a\\b', 'a/b', 'ab'], 'a/b', ['a/b']); match(fixtures, 'ab?bc', ['abbbc']); match(fixtures, 'ab*c', ['abbbbc', 'abbbc', 'abbc', 'abc']); match(fixtures, 'ab+bc', ['abbbbc', 'abbbc', 'abbc']); match(fixtures, '^abc$', ['abc']); match(fixtures, 'a.c', ['a.c']); match(fixtures, 'a.*c', ['a.c', 'a.xy.zc', 'a.zc']); match(fixtures, 'a*c', ['a c', 'a.c', 'a1c', 'a123c', 'abbbbc', 'abbbc', 'abbc', 'abc', 'axyzc', 'axy zc', 'axy.zc', 'a.xy.zc', 'a.zc']); match(fixtures, 'a\\w+c', ['a1c', 'a123c', 'abbbbc', 'abbbc', 'abbc', 'abc', 'axyzc'], 'Should match word characters'); match(fixtures, 'a\\W+c', ['a.c', 'a c'], 'Should match non-word characters'); match(fixtures, 'a\\d+c', ['a1c', 'a123c'], 'Should match numbers'); match(['foo@#$%123ASD #$$%^&', 'foo!@#$asdfl;', '123'], '\\d+', ['123']); match(['a123c', 'abbbc'], 'a\\D+c', ['abbbc'], 'Should match non-numbers'); match(['foo', ' foo '], '(f|o)+\\b', ['foo'], 'Should match word boundaries'); }); }); describe('bash unit tests', function() { var fixtures = ['ffffffo', 'fffooofoooooffoofffooofff', 'ffo', 'fofo', 'fofoofoofofoo', 'foo', 'foob', 'foobb', 'foofoofo', 'fooofoofofooo', 'foooofo', 'foooofof', 'foooofofx', 'foooxfooxfoxfooox', 'foooxfooxfxfooox', 'foooxfooxofoxfooox', 'foot', 'foox', 'ofoofo', 'ofooofoofofooo', 'ofoooxoofxo', 'ofoooxoofxoofoooxoofxo', 'ofoooxoofxoofoooxoofxofo', 'ofoooxoofxoofoooxoofxoo', 'ofoooxoofxoofoooxoofxooofxofxo', 'ofxoofxo', 'oofooofo', 'ooo', 'oxfoxfox', 'oxfoxoxfox', 'xfoooofof']; it('should match extended globs from the bash spec:', function() { var f2 = ['bar', 'f', 'fa', 'fb', 'ff', 'fff', 'fo', 'foo', 'foo/bar', 'foobar', 'foot', 'foox', 'o', 'of', 'ooo', 'ox', 'x', 'xx']; match(f2, '!(foo)', ['bar', 'f', 'fa', 'fb', 'ff', 'fff', 'fo', 'foo/bar', 'foobar', 'foot', 'foox', 'o', 'of', 'ooo', 'ox', 'x', 'xx']); match(f2, '!(!(foo))', ['foo']); match(f2, '!(!(!(foo)))', ['bar', 'f', 'fa', 'fb', 'ff', 'fff', 'fo', 'foo/bar', 'foobar', 'foot', 'foox', 'o', 'of', 'ooo', 'ox', 'x', 'xx']); match(f2, '!(!(!(!(foo))))', ['foo']); match(f2, '!(!(foo))*', ['foo', 'foo/bar', 'foobar', 'foot', 'foox']); match(f2, '!(f!(o))', ['fo']); match(f2, '!(f(o))', ['bar', 'f', 'fa', 'fb', 'ff', 'fff', 'foo', 'foobar', 'foo/bar', 'foot', 'foox', 'o', 'of', 'ooo', 'ox', 'x', 'xx']); match(f2, '!(f)', ['bar', 'fa', 'fb', 'ff', 'fff', 'fo', 'foo', 'foobar', 'foo/bar', 'foot', 'foox', 'o', 'of', 'ooo', 'ox', 'x', 'xx']); match(f2, '!(f)', ['bar', 'fa', 'fb', 'ff', 'fff', 'fo', 'foo', 'foobar', 'foo/bar', 'foot', 'foox', 'o', 'of', 'ooo', 'ox', 'x', 'xx']); match(f2, '!(foo)', ['bar', 'f', 'fa', 'fb', 'ff', 'fff', 'fo', 'foobar', 'foo/bar', 'foot', 'foox', 'o', 'of', 'ooo', 'ox', 'x', 'xx']); match(f2, '!(foo)*', ['bar', 'f', 'fa', 'fb', 'ff', 'fff', 'fo', 'o', 'of', 'ooo', 'ox', 'x', 'xx']); match(f2, '!(x)', ['bar', 'f', 'fa', 'fb', 'ff', 'fff', 'fo', 'foo', 'foobar', 'foo/bar', 'foot', 'foox', 'o', 'of', 'ooo', 'ox', 'xx']); match(f2, '!(x)*', ['bar', 'f', 'fa', 'fb', 'ff', 'fff', 'fo', 'foo', 'foobar', 'foo/bar', 'foot', 'foox', 'o', 'of', 'ooo', 'ox']); match(f2, '*(!(f))', ['bar', 'fa', 'fb', 'ff', 'fff', 'fo', 'foo', 'foobar', 'foo/bar', 'foot', 'foox', 'o', 'of', 'ooo', 'ox', 'x', 'xx']); match(f2, '*((foo))', ['foo']); match(f2, '+(!(f))', ['bar', 'fa', 'fb', 'ff', 'fff', 'fo', 'foo', 'foobar', 'foo/bar', 'foot', 'foox', 'o', 'of', 'ooo', 'ox', 'x', 'xx']); match(f2, '@(!(z*)|*x)', ['bar', 'f', 'fa', 'fb', 'ff', 'fff', 'fo', 'foo', 'foobar', 'foo/bar', 'foot', 'foox', 'o', 'of', 'ooo', 'ox', 'x', 'xx']); match(f2, 'foo/!(foo)', ['foo/bar']); match(fixtures, '(foo)bb', ['foobb']); match(fixtures, '*(*(f)*(o))', [ 'ffffffo', 'fffooofoooooffoofffooofff', 'ffo', 'fofo', 'fofoofoofofoo', 'foo', 'foofoofo', 'fooofoofofooo', 'foooofo', 'foooofof', 'ofoofo', 'ofooofoofofooo', 'oofooofo', 'ooo']); match(fixtures, '*(*(of*(o)x)o)', [ 'ofoooxoofxo', 'ofoooxoofxoofoooxoofxo', 'ofoooxoofxoofoooxoofxoo', 'ofoooxoofxoofoooxoofxooofxofxo', 'ofxoofxo', 'ooo']); match(fixtures, '*(f*(o))', ['ffffffo', 'fffooofoooooffoofffooofff', 'ffo', 'fofo', 'fofoofoofofoo', 'foo', 'foofoofo', 'fooofoofofooo', 'foooofo', 'foooofof']); match(fixtures, '*(f*(o)x)', ['foooxfooxfoxfooox', 'foooxfooxfxfooox', 'foox']); match(fixtures, '*(f+(o))', ['fofo', 'fofoofoofofoo', 'foo', 'foofoofo', 'fooofoofofooo', 'foooofo']); match(fixtures, '*(of+(o))', ['ofoofo']); match(fixtures, '*(of+(o)|f)', ['fofo', 'fofoofoofofoo', 'ofoofo', 'ofooofoofofooo']); match(fixtures, '*(of|oof+(o))', ['ofoofo', 'oofooofo']); match(fixtures, '*(oxf+(ox))', ['oxfoxoxfox']); match(fixtures, '@(!(z*)|*x)', ['ffffffo', 'fffooofoooooffoofffooofff', 'ffo', 'fofo', 'fofoofoofofoo', 'foo', 'foob', 'foobb', 'foofoofo', 'fooofoofofooo', 'foooofo', 'foooofof', 'foooofofx', 'foooxfooxfoxfooox', 'foooxfooxfxfooox', 'foooxfooxofoxfooox', 'foot', 'foox', 'ofoofo', 'ofooofoofofooo', 'ofoooxoofxo', 'ofoooxoofxoofoooxoofxo', 'ofoooxoofxoofoooxoofxofo', 'ofoooxoofxoofoooxoofxoo', 'ofoooxoofxoofoooxoofxooofxofxo', 'ofxoofxo', 'oofooofo', 'ooo', 'oxfoxfox', 'oxfoxoxfox', 'xfoooofof']); match(fixtures, '@(foo|f|fo)*(f|of+(o))', ['fofo', 'fofoofoofofoo', 'foo', 'foofoofo', 'fooofoofofooo']); var arr = ['aaac', 'aac', 'ac', 'abbcd', 'abcd', 'acd', 'baaac', 'c', 'foo']; match(arr, '*(@(a))a@(c)', ['aaac', 'aac', 'ac']); match(arr, '@(ab|a*(b))*(c)d', ['abbcd', 'abcd', 'acd']); match(arr, '?@(a|b)*@(c)d', ['abbcd', 'abcd']); match(arr, '@(ab|a*@(b))*(c)d', ['abbcd', 'abcd']); match(['aac'], '*(@(a))b@(c)', []); }); it('should backtrack in alternation matches', function() { match(fixtures, '*(fo|foo)', ['fofo', 'fofoofoofofoo', 'foo', 'foofoofo']); }); it('should support exclusions', function() { match(['foob', 'foobb', 'foo', 'bar', 'baz', 'foobar'], '!(foo)b*', ['bar', 'baz']); match(['foo', 'bar', 'baz', 'foobar'], '*(!(foo))', ['bar', 'baz', 'foobar']); // Bash 4.3 says this should match `foo` and `foobar` too match(['foo', 'bar', 'baz', 'foobar'], '!(foo)*', ['bar', 'baz']); match(['moo.cow', 'moo', 'cow'], '!(*.*)', ['moo', 'cow']); match(['mad.moo.cow'], '!(*.*).!(*.*)', []); match(['moo.cow', 'moo', 'cow'], '!(*.*).', []); match(['moo.cow', 'moo', 'cow'], '.!(*.*)', []); match(['mucca.pazza'], 'mu!(*(c))?.pa!(*(z))?', []); match(['effgz'], '@(b+(c)d|e*(f)g?|?(h)i@(j|k))', ['effgz']); match(['efgz'], '@(b+(c)d|e*(f)g?|?(h)i@(j|k))', ['efgz']); match(['egz'], '@(b+(c)d|e*(f)g?|?(h)i@(j|k))', ['egz']); match(['egz'], '@(b+(c)d|e+(f)g?|?(h)i@(j|k))', []); match(['egzefffgzbcdij'], '*(b+(c)d|e*(f)g?|?(h)i@(j|k))', ['egzefffgzbcdij']); }); it('valid numbers', function() { assert(match.isMatch('/dev/udp/129.22.8.102/45', '/dev/@(tcp|udp)/*/*')); match(['0', '12', '1', '12abc', '555'], '[1-6]([0-9])', ['12']); match(['0', '12', '1', '12abc', '555'], '[1-6]*([0-9])', ['1', '12', '555']); match(['0', '12', '1', '12abc', '555'], '[1-5]*([6-9])', ['1']); match(['0', '12', '1', '12abc', '555'], '0|[1-6]*([0-9])', ['0', '1', '12', '555']); match(['07', '0377', '09'], '+([0-7])', ['0377', '07']); }); it('stuff from korn\'s book', function() { assert(!match.isMatch('para', 'para+([0-9])')); assert(!match.isMatch('para381', 'para?([345]|99)1')); assert(!match.isMatch('paragraph', 'para*([0-9])')); assert(!match.isMatch('paragraph', 'para*([0-9])')); assert(!match.isMatch('paramour', 'para@(chute|graph)')); assert(match.isMatch('para', 'para*([0-9])')); assert(match.isMatch('para.38', 'para!(*.[0-9])')); assert(match.isMatch('para.graph', 'para!(*.[0-9])')); assert(match.isMatch('para13829383746592', 'para*([0-9])')); assert(match.isMatch('para39', 'para!(*.[0-9])')); assert(match.isMatch('para987346523', 'para+([0-9])')); assert(match.isMatch('para991', 'para?([345]|99)1')); assert(match.isMatch('paragraph', 'para!(*.[0-9])')); assert(match.isMatch('paragraph', 'para@(chute|graph)')); }); it('tests derived from those in rosenblatt\'s korn shell book', function() { assert(match.isMatch('', '*(0|1|3|5|7|9)')); assert(match.isMatch('137577991', '*(0|1|3|5|7|9)')); assert(!match.isMatch('2468', '*(0|1|3|5|7|9)')); assert(!match.isMatch('file.C', '*.c?(c)')); assert(!match.isMatch('file.ccc', '*.c?(c)')); assert(match.isMatch('file.c', '*.c?(c)')); assert(match.isMatch('file.cc', '*.c?(c)')); assert(match.isMatch('parse.y', '!(*.c|*.h|Makefile.in|config*|README)')); assert(match.isMatch('Makefile', '!(*.c|*.h|Makefile.in|config*|README)')); assert(!match.isMatch('shell.c', '!(*.c|*.h|Makefile.in|config*|README)')); assert(!match.isMatch('VMS.FILE;', '*\\;[1-9]*([0-9])')); assert(!match.isMatch('VMS.FILE;0', '*\\;[1-9]*([0-9])')); assert(!match.isMatch('VMS.FILE;1N', '*\\;[1-9]*([0-9])')); assert(match.isMatch('VMS.FILE;1', '*\\;[1-9]*([0-9])')); assert(match.isMatch('VMS.FILE;139', '*\\;[1-9]*([0-9])')); }); it('tests derived from the pd-ksh test suite', function() { match(['abcx', 'abcz', 'bbc'], '!([*)*', ['abcx', 'abcz', 'bbc']); match(['abcx', 'abcz', 'bbc'], '+(a|b[)*', ['abcx', 'abcz']); match(['abcx', 'abcz', 'bbc'], '[a*(]*)z', []); match(['abc'], '+()c', []); match(['abc'], '+()x', []); match(['abc'], '+(*)c', ['abc']); match(['abc'], '+(*)x', []); match(['abc'], 'no-file+(a|b)stuff', []); match(['abc'], 'no-file+(a*(c)|b)stuff', []); match(['abd', 'acd'], 'a+(b|c)d', ['abd', 'acd']); match(['abc'], 'a+(b|c)d', []); match(['acd'], 'a!(@(b|B))d', ['acd']); match(['abc', 'abd'], 'a!(@(b|B))d', []); match(['abd'], 'a[b*(foo|bar)]d', ['abd']); match(['abc', 'acd'], 'a[b*(foo|bar)]d', []); }); it('simple kleene star tests', function() { assert(!match.isMatch('foo', '*(a|b[)')); assert(!match.isMatch('(', '*(a|b[)')); assert(!match.isMatch(')', '*(a|b[)')); assert(!match.isMatch('|', '*(a|b[)')); assert(match.isMatch('a', '*(a|b)')); assert(match.isMatch('b', '*(a|b)')); assert(match.isMatch('b[', '*(a|b\\[)')); assert(match.isMatch('ab[', '+(a|b\\[)')); assert(!match.isMatch('ab[cde', '+(a|b\\[)')); assert(match.isMatch('ab[cde', '+(a|b\\[)*')); }); it('check extended globbing in pattern removal', function() { match(['a', 'abc'], '+(a|abc)', ['a', 'abc']); match(['abcd', 'abcde', 'abcedf'], '+(a|abc)', []); match(['f'], '+(def|f)', ['f']); match(['def'], '+(f|def)', ['def']); match(['cdef', 'bcdef', 'abcedf'], '+(f|def)', []); match(['abcd'], '*(a|b)cd', ['abcd']); match(['a', 'ab', 'abc'], '*(a|b)cd', []); match(['a', 'ab', 'abc', 'abcde', 'abcdef'], '"*(a|b)cd"', []); }); it('More tests derived from a bug report (in bash) concerning extended glob patterns following a *', function() { var fixtures = ['123abc', 'ab', 'abab', 'abcdef', 'accdef', 'abcfefg', 'abef', 'abcfef', 'abd', 'acd']; match(['/dev/udp/129.22.8.102/45'], '/dev\\/@(tcp|udp)\\/*\\/*', ['/dev/udp/129.22.8.102/45']); match(fixtures, '(a+|b)*', ['ab', 'abab', 'accdef', 'abcdef', 'abcfefg', 'abef', 'abcfef', 'abd', 'acd']); match(fixtures, '(a+|b)+', ['ab', 'abab']); match(fixtures, 'a(b*(foo|bar))d', ['abd']); match(fixtures, 'ab*(e|f)', ['ab', 'abef']); match(fixtures, 'ab**(e|f)', ['ab', 'abab', 'abcdef', 'abcfef', 'abd', 'abef', 'abcfefg']); match(fixtures, 'ab**(e|f)g', ['abcfefg']); match(fixtures, 'ab***ef', ['abcdef', 'abcfef', 'abef']); match(fixtures, 'ab*+(e|f)', ['abcdef', 'abcfef', 'abef']); match(fixtures, 'ab*d*(e|f)', ['abcdef', 'abd']); match(fixtures, 'ab*d+(e|f)', ['abcdef']); match(fixtures, 'ab?*(e|f)', ['abcfef', 'abd', 'abef']); }); it('bug in all versions up to and including bash-2.05b', function() { assert(match.isMatch('123abc', '*?(a)bc')); }); it('should work with character classes', function() { var fixtures = ['a.b', 'a,b', 'a:b', 'a-b', 'a;b', 'a b', 'a_b']; match(fixtures, 'a[^[:alnum:]]b', fixtures); match(fixtures, 'a[-.,:\\;\\ _]b', fixtures); match(fixtures, 'a@([^[:alnum:]])b', fixtures); match(fixtures, 'a@([-.,:; _])b', fixtures); match(fixtures, 'a@([.])b', ['a.b']); match(fixtures, 'a@([^.])b', ['a,b', 'a:b', 'a-b', 'a;b', 'a b', 'a_b']); match(fixtures, 'a@([^x])b', ['a,b', 'a:b', 'a-b', 'a;b', 'a b', 'a_b']); match(fixtures, 'a+([^[:alnum:]])b', fixtures); match(fixtures, 'a@(.|[^[:alnum:]])b', fixtures); }); it('should support POSIX character classes in extglobs', function() { assert(match.isMatch('a.c', '+([[:alpha:].])')); assert(match.isMatch('a.c', '+([[:alpha:].])+([[:alpha:].])')); assert(match.isMatch('a.c', '*([[:alpha:].])')); assert(match.isMatch('a.c', '*([[:alpha:].])*([[:alpha:].])')); assert(match.isMatch('a.c', '?([[:alpha:].])?([[:alpha:].])?([[:alpha:].])')); assert(match.isMatch('a.c', '@([[:alpha:].])@([[:alpha:].])@([[:alpha:].])')); assert(!match.isMatch('.', '!(\\.)')); assert(!match.isMatch('.', '!([[:alpha:].])')); assert(match.isMatch('.', '?([[:alpha:].])')); assert(match.isMatch('.', '@([[:alpha:].])')); }); // ported from http://www.bashcookbook.com/bashinfo/source/bash-4.3/tests/extglob2.tests it('should pass extglob2 tests', function() { assert(!match.isMatch('baaac', '*(@(a))a@(c)')); assert(!match.isMatch('c', '*(@(a))a@(c)')); assert(!match.isMatch('egz', '@(b+(c)d|e+(f)g?|?(h)i@(j|k))')); assert(!match.isMatch('foooofof', '*(f+(o))')); assert(!match.isMatch('foooofofx', '*(f*(o))')); assert(!match.isMatch('foooxfooxofoxfooox', '*(f*(o)x)')); assert(!match.isMatch('ofooofoofofooo', '*(f*(o))')); assert(!match.isMatch('ofoooxoofxoofoooxoofxofo', '*(*(of*(o)x)o)')); assert(!match.isMatch('oxfoxfox', '*(oxf+(ox))')); assert(!match.isMatch('xfoooofof', '*(f*(o))')); assert(match.isMatch('aaac', '*(@(a))a@(c)')); assert(match.isMatch('aac', '*(@(a))a@(c)')); assert(match.isMatch('abbcd', '@(ab|a*(b))*(c)d')); assert(match.isMatch('abcd', '?@(a|b)*@(c)d')); assert(match.isMatch('abcd', '@(ab|a*@(b))*(c)d')); assert(match.isMatch('ac', '*(@(a))a@(c)')); assert(match.isMatch('acd', '@(ab|a*(b))*(c)d')); assert(match.isMatch('effgz', '@(b+(c)d|e*(f)g?|?(h)i@(j|k))')); assert(match.isMatch('efgz', '@(b+(c)d|e*(f)g?|?(h)i@(j|k))')); assert(match.isMatch('egz', '@(b+(c)d|e*(f)g?|?(h)i@(j|k))')); assert(match.isMatch('egzefffgzbcdij', '*(b+(c)d|e*(f)g?|?(h)i@(j|k))')); assert(match.isMatch('fffooofoooooffoofffooofff', '*(*(f)*(o))')); assert(match.isMatch('ffo', '*(f*(o))')); assert(match.isMatch('fofo', '*(f*(o))')); assert(match.isMatch('foofoofo', '@(foo|f|fo)*(f|of+(o))')); assert(match.isMatch('fooofoofofooo', '*(f*(o))')); assert(match.isMatch('foooofo', '*(f*(o))')); assert(match.isMatch('foooofof', '*(f*(o))')); assert(match.isMatch('foooxfooxfoxfooox', '*(f*(o)x)')); assert(match.isMatch('foooxfooxfxfooox', '*(f*(o)x)')); assert(match.isMatch('ofoofo', '*(of+(o))')); assert(match.isMatch('ofoofo', '*(of+(o)|f)')); assert(match.isMatch('ofoooxoofxo', '*(*(of*(o)x)o)')); assert(match.isMatch('ofoooxoofxoofoooxoofxo', '*(*(of*(o)x)o)')); assert(match.isMatch('ofoooxoofxoofoooxoofxoo', '*(*(of*(o)x)o)')); assert(match.isMatch('ofoooxoofxoofoooxoofxooofxofxo', '*(*(of*(o)x)o)')); assert(match.isMatch('ofxoofxo', '*(*(of*(o)x)o)')); assert(match.isMatch('oofooofo', '*(of|oof+(o))')); assert(match.isMatch('oxfoxoxfox', '*(oxf+(ox))')); }); it('should support backtracking in alternation matches', function() { assert(match.isMatch('fofoofoofofoo', '*(fo|foo)')); }); it('should support exclusions', function() { assert(!match.isMatch('f', '!(f)')); assert(!match.isMatch('f', '*(!(f))')); assert(!match.isMatch('f', '+(!(f))')); assert(!match.isMatch('foo', '!(foo)')); assert(!match.isMatch('foob', '!(foo)b*')); assert(!match.isMatch('mad.moo.cow', '!(*.*).!(*.*)')); assert(!match.isMatch('mucca.pazza', 'mu!(*(c))?.pa!(*(z))?')); assert(!match.isMatch('zoot', '@(!(z*)|*x)')); assert(match.isMatch('fff', '!(f)')); assert(match.isMatch('fff', '*(!(f))')); assert(match.isMatch('fff', '+(!(f))')); assert(match.isMatch('foo', '!(f)')); assert(match.isMatch('foo', '!(x)')); assert(match.isMatch('foo', '!(x)*')); assert(match.isMatch('foo', '*(!(f))')); assert(match.isMatch('foo', '+(!(f))')); assert(match.isMatch('foobar', '!(foo)')); assert(match.isMatch('foot', '@(!(z*)|*x)')); assert(match.isMatch('foox', '@(!(z*)|*x)')); assert(match.isMatch('ooo', '!(f)')); assert(match.isMatch('ooo', '*(!(f))')); assert(match.isMatch('ooo', '+(!(f))')); assert(match.isMatch('zoox', '@(!(z*)|*x)')); }); it('should pass extglob3 tests', function() { assert(match.isMatch('ab/../', '+(??)/..?(/)')); assert(match.isMatch('ab/../', '+(??|a*)/..?(/)')); assert(match.isMatch('ab/../', '+(?b)/..?(/)')); assert(match.isMatch('ab/../', '+(?b|?b)/..?(/)')); assert(match.isMatch('ab/../', '+([!/])/../')); assert(match.isMatch('ab/../', '+([!/])/..?(/)')); assert(match.isMatch('ab/../', '+([!/])/..@(/)')); assert(match.isMatch('ab/../', '+([^/])/../')); assert(match.isMatch('ab/../', '+([^/])/..?(/)')); assert(match.isMatch('ab/../', '+(a*)/..?(/)')); assert(match.isMatch('ab/../', '+(ab)/..?(/)')); assert(match.isMatch('ab/../', '?(ab)/..?(/)')); assert(match.isMatch('ab/../', '?(ab|??)/..?(/)')); assert(match.isMatch('ab/../', '?b/..?(/)')); assert(match.isMatch('ab/../', '@(??)/..?(/)')); assert(match.isMatch('ab/../', '@(??|a*)/..?(/)')); assert(match.isMatch('ab/../', '@(?b|?b)/..?(/)')); assert(match.isMatch('ab/../', '@(a*)/..?(/)')); assert(match.isMatch('ab/../', '@(a?|?b)/..?(/)')); assert(match.isMatch('ab/../', '@(ab|+([!/]))/..?(/)')); assert(match.isMatch('ab/../', '@(ab|+([^/]))/..?(/)')); assert(match.isMatch('ab/../', '@(ab|?b)/..?(/)')); assert(match.isMatch('ab/../', '[!/][!/]/../')); assert(match.isMatch('ab/../', '[^/][^/]/../')); assert(match.isMatch('x', '@(x)')); }); });