commit cfb8cba10c69711f19f68a4b082bde50664544a2 Author: brettlangdon Date: Tue May 27 10:44:11 2014 -0400 commit initial version diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/README.md b/README.md new file mode 100644 index 0000000..64921e7 --- /dev/null +++ b/README.md @@ -0,0 +1,50 @@ +tend +==== + +Quick and easy cli command to watch a directory for file changes and run a +provided command when any files have been changed, removed or added. + +## Installation + +```bash +npm install -g tend +``` + +## Usage +``` +Usage: + tend (--help | --version) + tend [--restart] [--ignoreHidden] [] + +Options: + -h --help Show this help text + -v --version Show tend version information + -r --restart If is still running when there is a change, stop and re-run it + -i --ignoreHidden Ignore changes to files which start with "." +``` + +```bash +tend --restart --ignoreHidden ./ "node server.js" +``` + +## License +``` +The MIT License (MIT) Copyright (c) 2014 Brett Langdon (http://brett.is) + +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. +``` diff --git a/bin/tend b/bin/tend new file mode 100755 index 0000000..a985a08 --- /dev/null +++ b/bin/tend @@ -0,0 +1,28 @@ +#!/usr/bin/env node + +var docopt = require('docopt'); +var tend = require('../'); + +var doc = [ + 'Usage:', + ' tend (--help | --version)', + ' tend [--restart] [--ignoreHidden] []', + '', + 'Options:', + ' -h --help Show this help text', + ' -v --version Show tend version information', + ' -r --restart If is still running when there is a change, stop and re-run it', + ' -i --ignoreHidden Ignore changes to files which start with "."', +].join('\r\n'); + +var args = docopt.docopt(doc, { + help: true, + version: 'tend ' + require('../package.json').version, +}); + +var options = { + pattern: args[''], + ignoreHidden: args['--ignoreHidden'], + restart: args['--restart'], +}; +tend.tend(args[''], args[''], options); diff --git a/lib/index.js b/lib/index.js new file mode 100644 index 0000000..aa40d56 --- /dev/null +++ b/lib/index.js @@ -0,0 +1,73 @@ +var colors = require('colors'); +var path = require('path'); +var spawn = require('child_process').spawn; +var watch = require('watch'); + +module.exports.tend = function(dir, rawCommand, options) { + options = options || {}; + var pattern = options.pattern || '.'; + var filter = new RegExp(pattern, 'i'); + + var ignoreHidden = options.ignoreHidden === true; + var restart = options.restart === true; + + var args = rawCommand.split(' '); + var command = args.shift(); + var executor = null; + var timeout = null; + + var startCommand = function() { + console.log(('Running Command: ' + rawCommand).green); + executor = spawn(command, args); + executor.stdout.on('data', function(chunk) { + console.log(chunk.toString()); + }); + executor.stderr.on('data', function(chunk) { + console.error(chunk.toString().red); + }); + executor.on('error', function(error) { + console.error('Error Running Command'.red); + }); + executor.on('close', function(code, signal) { + if (code === 0) { + console.log('Command Exited Successfully'.green); + } else if (signal) { + console.warn(('Command Killed With Signal: ' + signal).yellow); + } else { + console.error(('Command Exited With Status: ' + code).red); + } + executor = null; + }); + console.log(('Process ' + executor.pid + ' Started').green); + }.bind(this); + + watch.watchTree(dir, function(f, curr, prev) { + if (curr === null && prev === null) { + return; + } + if (ignoreHidden) { + var basename = path.basename(f); + if (basename.indexOf('.') === 0) { + return; + } + } + if (!filter.test(f)) { + return; + } + + if (executor && restart) { + console.warn(('Killing Process: ' + executor.pid).yellow); + executor.on('close', function(code, signal) { + startCommand(); + }); + executor.kill(); + return; + } else if (executor) { + console.warn(('Process ' + executor.pid + ' Still Running').yellow); + return; + } + + clearTimeout(timeout); + timeout = setTimeout(startCommand, 300); + }); +}; diff --git a/package.json b/package.json new file mode 100644 index 0000000..741bb74 --- /dev/null +++ b/package.json @@ -0,0 +1,34 @@ +{ + "name": "tend", + "version": "0.1.0", + "description": "CLI Tool to run a command when a file changes", + "main": "lib/index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git://github.com/brettlangdon/tend.git" + }, + "keywords": [ + "tend", + "watch", + "cli", + "file", + "command" + ], + "author": "Brett Langdon (http://brett.is)", + "license": "MIT", + "bugs": { + "url": "https://github.com/brettlangdon/tend/issues" + }, + "homepage": "https://github.com/brettlangdon/tend", + "dependencies": { + "watch": "~0.10.0", + "docopt": "~0.4.0", + "colors": "~0.6.2" + }, + "bin": { + "tend": "bin/tend" + } +}