Skip to content

Commit

Permalink
Add initial code
Browse files Browse the repository at this point in the history
  • Loading branch information
jednano committed Jan 25, 2014
1 parent 0cf3e18 commit 10cbe7d
Show file tree
Hide file tree
Showing 18 changed files with 434 additions and 3 deletions.
4 changes: 4 additions & 0 deletions .npmignore
@@ -0,0 +1,4 @@
test
.travis.yml
AUTHORS
Gruntfile.js
6 changes: 6 additions & 0 deletions .travis.yml
@@ -0,0 +1,6 @@
language: node_js
node_js:
- "0.8"
- "0.10"
before_script:
- npm install -g grunt-cli
5 changes: 5 additions & 0 deletions AUTHORS
@@ -0,0 +1,5 @@
"Cowboy" Ben Alman (http://benalman.com/)
Kyle Robinson Young (http://dontkry.com/)
Tyler Kellen (http://goingslowly.com)
Sindre Sorhus (http://sindresorhus.com)
Vlad Filippov (http://vladfilippov.com/)
56 changes: 56 additions & 0 deletions Gruntfile.js
@@ -0,0 +1,56 @@
/*
* grunt
* http://gruntjs.com/
*
* Copyright (c) 2013 "Cowboy" Ben Alman
* Licensed under the MIT license.
* https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT
*/

'use strict';

module.exports = function(grunt) {

// Project configuration.
grunt.initConfig({
nodeunit: {
all: ['test/*.js']
},
jshint: {
gruntfile_tasks: ['Gruntfile.js'],
libs_n_tests: ['lib/**/*.js', '<%= nodeunit.all %>'],
options: {
curly: true,
eqeqeq: true,
immed: true,
latedef: 'nofunc',
newcap: true,
noarg: true,
sub: true,
undef: true,
unused: true,
boss: true,
eqnull: true,
node: true,
}
},
watch: {
libs_n_tests: {
files: ['<%= jshint.libs_n_tests %>'],
tasks: ['jshint:libs_n_tests', 'nodeunit']
}
}
});

// These plugins provide necessary tasks.
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-nodeunit');
grunt.loadNpmTasks('grunt-contrib-watch');

// "npm test" runs these tasks
grunt.registerTask('test', ['jshint', 'nodeunit']);

// Default task.
grunt.registerTask('default', ['test']);

};
File renamed without changes.
79 changes: 76 additions & 3 deletions README.md
@@ -1,4 +1,77 @@
simple-glob
===========
# simple-glob

Simplified globbing, same as Grunt
> Simplified globbing, same as [Grunt][]
[![Build Status][]](http://travis-ci.org/jedmao/simple-glob)
[![Dependency Status][]](https://gemnasium.com/jedmao/simple-glob)
[![NPM version][]](http://badge.fury.io/js/simple-glob)
[![Views][]](https://sourcegraph.com/github.com/jedmao/simple-glob)

[![NPM][]](https://nodei.co/npm/simple-glob/)

The inspiration for this project was to simplify globbing patterns to work the same way many are familiar with (i.e., the globbing patterns in [Grunt][]). Instead of reinventing the wheel, I figured I'd just extract the code directly from [Grunt][]'s code base to get the exact same functionality that we know and love. Now, we can all enjoy the same globbing, even outside of [Grunt][]!

<i>Full disclaimer: The code contained in this project is 99% the original work of the Grunt.js team. I only renamed a couple things and moved things around a bit. I take no credit whatsoever and the original license is in tact, according to license conditions.</i>

<i>Note: The following documentation was taken mostly from [Grunt's Configuring Tasks][] page.</i>


## Globbing patterns

It is often impractical to specify all source filepaths individually, so simple-glob supports filename expansion (also know as globbing) via the built-in [node-glob][] and [minimatch][] libraries.

While this isn't a comprehensive tutorial on globbing patterns, know that in a filepath:

- `*` matches any number of characters, but not `/`
- `?` matches a single character, but not `/`
- `**` matches any number of characters, including `/`, as long as it's the only thing in a path part
- `{}` allows for a comma-separated list of "or" expressions
- `!` at the beginning of a pattern will negate the match

All most people need to know is that `foo/*.js` will match all files ending with `.js` in the `foo/` subdirectory, but `foo/**/*.js` will match all files ending with `.js` in the `foo/` subdirectory and all of its subdirectories.

Also, in order to simplify otherwise complicated globbing patterns, simple-glob allows arrays of file paths or globbing patterns to be specified. Patterns are processed in-order, with `!`-prefixed matches excluding matched files from the result set. The result set is uniqued.

For example:
```js
var glob = require('simple-glob');

// You can specify single files:
glob('foo/this.js');
// Or arrays of files:
glob(['foo/this.js', 'foo/that.js', 'foo/the-other.js']);
// Or you can generalize with a glob pattern:
glob('foo/th*.js');

// This single node-glob pattern:
glob('foo/{a,b}*.js');
// Could also be written like this:
glob(['foo/a*.js', 'foo/b*.js']);

// All .js files, in foo/, in alpha order:
glob(['foo/*.js']);
// Here, bar.js is first, followed by the remaining files, in alpha order:
glob(['foo/bar.js', 'foo/*.js']);

// All files except for bar.js, in alpha order:
glob(['foo/*.js', '!foo/bar.js']);
// All files in alpha order, but with bar.js at the end.
glob(['foo/*.js', '!foo/bar.js', 'foo/bar.js']);
```

For more on glob pattern syntax, see the [node-glob][] and [minimatch][] documentation.



[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/jedmao/simple-glob/trend.png)](https://bitdeli.com/free "Bitdeli Badge")


[Grunt]: http://gruntjs.com/
[Build Status]: https://secure.travis-ci.org/jedmao/simple-glob.png?branch=master
[Dependency Status]: https://gemnasium.com/jedmao/simple-glob.png
[NPM version]: https://badge.fury.io/js/simple-glob.png
[Views]: https://sourcegraph.com/api/repos/github.com/jedmao/simple-glob/counters/views-24h.png
[NPM]: https://nodei.co/npm/simple-glob.png?downloads=true
[Grunt's Configuring Tasks]: http://gruntjs.com/configuring-tasks
[node-glob]: https://github.com/isaacs/node-glob
[minimatch]: https://github.com/isaacs/minimatch
81 changes: 81 additions & 0 deletions lib/api.js
@@ -0,0 +1,81 @@
/*
* grunt
* http://gruntjs.com/
*
* Copyright (c) 2013 "Cowboy" Ben Alman
* Licensed under the MIT license.
* https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT
*/

'use strict';

var util = require('./util');

// Nodejs libs.
var fs = require('fs');
var path = require('path');

// External libs.
var _ = require('lodash');
var glob = require('glob');


// Process specified wildcard glob patterns or filenames against a
// callback, excluding and uniquing files in the result set.
var processPatterns = function(patterns, fn) {
// Filepaths to return.
var result = [];
// Iterate over flattened patterns array.
_.flatten(patterns).forEach(function(pattern) {
// If the first character is ! it should be omitted
var exclusion = pattern.indexOf('!') === 0;
// If the pattern is an exclusion, remove the !
if (exclusion) { pattern = pattern.slice(1); }
// Find all matching files for this pattern.
var matches = fn(pattern);
if (exclusion) {
// If an exclusion, remove matching files.
result = _.difference(result, matches);
} else {
// Otherwise add matching files.
result = _.union(result, matches);
}
});
return result;
};

// Return an array of all file paths that match the given wildcard patterns.
module.exports = function() {
var args = util.toArray(arguments);
// If the first argument is an options object, save those options to pass
// into the glob.sync method.
var options = util.kindOf(args[0]) === 'object' ? args.shift() : {};
// Use the first argument if it's an Array, otherwise convert the arguments
// object to an array and use that.
var patterns = Array.isArray(args[0]) ? args[0] : args;
// Return empty set if there are no patterns or filepaths.
if (patterns.length === 0) { return []; }
// Return all matching filepaths.
var matches = processPatterns(patterns, function(pattern) {
// Find all matching files for this pattern.
return glob.sync(pattern, options);
});
// Filter result set?
if (options.filter) {
matches = matches.filter(function(filepath) {
filepath = path.join(options.cwd || '', filepath);
try {
if (typeof options.filter === 'function') {
return options.filter(filepath);
} else {
// If the file is of the right type and exists, this should work.
return fs.statSync(filepath)[options.filter]();
}
} catch (e) {
// Otherwise, it's probably not the right type.
return false;
}
});
}
return matches;
};
30 changes: 30 additions & 0 deletions lib/util.js
@@ -0,0 +1,30 @@
/*
* grunt
* http://gruntjs.com/
*
* Copyright (c) 2013 "Cowboy" Ben Alman
* Licensed under the MIT license.
* https://github.com/gruntjs/grunt/blob/master/LICENSE-MIT
*/

'use strict';

// The module to be exported.
var util = module.exports = {};


// What "kind" is a value?
// I really need to rework https://github.com/cowboy/javascript-getclass
var kindsOf = {};
'Number String Boolean Function RegExp Array Date Error'.split(' ').forEach(function(k) {
kindsOf['[object ' + k + ']'] = k.toLowerCase();
});
util.kindOf = function(value) {
// Null or undefined.
if (value == null) { return String(value); }
// Everything else.
return kindsOf[kindsOf.toString.call(value)] || 'object';
};

// Coerce something to an Array.
util.toArray = Function.call.bind(Array.prototype.slice);
42 changes: 42 additions & 0 deletions package.json
@@ -0,0 +1,42 @@
{
"name": "simple-glob",
"description": "Simplified globbing, same as Grunt",
"version": "0.1.0",
"author": "\"Cowboy\" Ben Alman (http://benalman.com/)",
"homepage": "https://github.com/jedmao/simple-glob",
"repository": {
"type": "git",
"url": "https://github.com/jedmao/simple-glob.git"
},
"bugs": {
"url": "https://github.com/jedmao/simple-glob/issues"
},
"licenses": [
{
"type": "MIT",
"url": "http://github.com/jedmao/simple-glob/blob/master/LICENSE-MIT"
}
],
"main": "lib/api.js",
"scripts": {
"test": "grunt test"
},
"engines": {
"node": ">= 0.8.0"
},
"keywords": [
"glob",
"tool",
"grunt"
],
"dependencies": {
"glob": "~3.2.8",
"lodash": "~2.4.1",
"minimatch": "~0.2.14"
},
"devDependencies": {
"grunt-contrib-jshint": "~0.8.0",
"grunt-contrib-nodeunit": "~0.2.2",
"grunt-contrib-watch": "~0.5.3"
}
}

0 comments on commit 10cbe7d

Please sign in to comment.