aboutsummaryrefslogtreecommitdiff
path: root/node_modules/coa/src
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/coa/src')
-rw-r--r--node_modules/coa/src/arg.coffee130
-rw-r--r--node_modules/coa/src/cmd.coffee456
-rw-r--r--node_modules/coa/src/color.coffee25
-rw-r--r--node_modules/coa/src/completion.coffee156
-rw-r--r--node_modules/coa/src/index.coffee5
-rw-r--r--node_modules/coa/src/opt.coffee243
-rw-r--r--node_modules/coa/src/shell.coffee10
7 files changed, 1025 insertions, 0 deletions
diff --git a/node_modules/coa/src/arg.coffee b/node_modules/coa/src/arg.coffee
new file mode 100644
index 00000000..da57dff0
--- /dev/null
+++ b/node_modules/coa/src/arg.coffee
@@ -0,0 +1,130 @@
+Color = require('./color').Color
+Cmd = require('./cmd').Cmd
+Opt = require('./opt').Opt
+
+###*
+Argument
+
+Unnamed entity. From command line arguments passed as list of unnamed values.
+@namespace
+@class Presents argument
+###
+exports.Arg = class Arg
+
+ ###*
+ @constructs
+ @param {COA.Cmd} cmd parent command
+ ###
+ constructor: (@_cmd) -> @_cmd._args.push @
+
+ ###*
+ Set a canonical argument identifier to be used anywhere in text messages.
+ @param {String} _name argument name
+ @returns {COA.Arg} this instance (for chainability)
+ ###
+ name: Opt::name
+
+ ###*
+ Set a long description for argument to be used anywhere in text messages.
+ @param {String} _title argument title
+ @returns {COA.Arg} this instance (for chainability)
+ ###
+ title: Cmd::title
+
+ ###*
+ Makes an argument accepts multiple values.
+ Otherwise, the value will be used by the latter passed.
+ @returns {COA.Arg} this instance (for chainability)
+ ###
+ arr: Opt::arr
+
+ ###*
+ Makes an argument required.
+ @returns {COA.Arg} this instance (for chainability)
+ ###
+ req: Opt::req
+
+ ###*
+ Set a validation (or value) function for argument.
+ Value from command line passes through before becoming available from API.
+ Using for validation and convertion simple types to any values.
+ @param {Function} _val validating function,
+ invoked in the context of argument instance
+ and has one parameter with value from command line
+ @returns {COA.Arg} this instance (for chainability)
+ ###
+ val: Opt::val
+
+ ###*
+ Set a default value for argument.
+ Default value passed through validation function as ordinary value.
+ @param {Object} _def
+ @returns {COA.Arg} this instance (for chainability)
+ ###
+ def: Opt::def
+
+ ###*
+ Set custom additional completion for current argument.
+ @param {Function} completion generation function,
+ invoked in the context of argument instance.
+ Accepts parameters:
+ - {Object} opts completion options
+ It can return promise or any other value treated as result.
+ @returns {COA.Arg} this instance (for chainability)
+ ###
+ comp: Cmd::comp
+
+ ###*
+ Make argument value inputting stream.
+ It's add useful validation and shortcut for STDIN.
+ @returns {COA.Arg} this instance (for chainability)
+ ###
+ input: Opt::input
+
+ ###*
+ Make argument value outputing stream.
+ It's add useful validation and shortcut for STDOUT.
+ @returns {COA.Arg} this instance (for chainability)
+ ###
+ output: Opt::output
+
+ _parse: (arg, args) ->
+ @_saveVal(args, arg)
+
+ _saveVal: Opt::_saveVal
+
+ _checkParsed: (opts, args) -> not args.hasOwnProperty(@_name)
+
+ _usage: ->
+ res = []
+
+ res.push Color('lpurple', @_name.toUpperCase()), ' : ', @_title
+ if @_req then res.push ' ', Color('lred', '(required)')
+
+ res.join ''
+
+ _requiredText: -> 'Missing required argument:\n ' + @_usage()
+
+ ###*
+ Return rejected promise with error code.
+ Use in .val() for return with error.
+ @param {Object} reject reason
+ You can customize toString() method and exitCode property
+ of reason object.
+ @returns {Q.promise} rejected promise
+ ###
+ reject: Cmd::reject
+
+ ###*
+ Finish chain for current option and return parent command instance.
+ @returns {COA.Cmd} parent command
+ ###
+ end: Cmd::end
+
+ ###*
+ Apply function with arguments in context of arg instance.
+ @param {Function} fn
+ @param {Array} args
+ @returns {COA.Arg} this instance (for chainability)
+ ###
+ apply: Cmd::apply
diff --git a/node_modules/coa/src/cmd.coffee b/node_modules/coa/src/cmd.coffee
new file mode 100644
index 00000000..bde16248
--- /dev/null
+++ b/node_modules/coa/src/cmd.coffee
@@ -0,0 +1,456 @@
+UTIL = require 'util'
+PATH = require 'path'
+Color = require('./color').Color
+Q = require('q')
+
+#inspect = require('eyes').inspector { maxLength: 99999, stream: process.stderr }
+
+###*
+Command
+
+Top level entity. Commands may have options and arguments.
+@namespace
+@class Presents command
+###
+exports.Cmd = class Cmd
+
+ ###*
+ @constructs
+ @param {COA.Cmd} [cmd] parent command
+ ###
+ constructor: (cmd) ->
+ if this not instanceof Cmd
+ return new Cmd cmd
+
+ @_parent cmd
+
+ @_cmds = []
+ @_cmdsByName = {}
+
+ @_opts = []
+ @_optsByKey = {}
+
+ @_args = []
+
+ @_ext = false
+
+ @get: (propertyName, func) ->
+ Object.defineProperty @::, propertyName,
+ configurable: true
+ enumerable: true
+ get: func
+
+ ###*
+ Returns object containing all its subcommands as methods
+ to use from other programs.
+ @returns {Object}
+ ###
+ @get 'api', () ->
+ if not @_api
+ @_api = => @invoke.apply @, arguments
+ for c of @_cmdsByName
+ do (c) =>
+ @_api[c] = @_cmdsByName[c].api
+ @_api
+
+ _parent: (cmd) ->
+ @_cmd = cmd or this
+ if cmd
+ cmd._cmds.push @
+ if @_name then @_cmd._cmdsByName[@_name] = @
+ @
+
+ ###*
+ Set a canonical command identifier to be used anywhere in the API.
+ @param {String} _name command name
+ @returns {COA.Cmd} this instance (for chainability)
+ ###
+ name: (@_name) ->
+ if @_cmd isnt @ then @_cmd._cmdsByName[_name] = @
+ @
+
+ ###*
+ Set a long description for command to be used anywhere in text messages.
+ @param {String} _title command title
+ @returns {COA.Cmd} this instance (for chainability)
+ ###
+ title: (@_title) -> @
+
+ ###*
+ Create new or add existing subcommand for current command.
+ @param {COA.Cmd} [cmd] existing command instance
+ @returns {COA.Cmd} new subcommand instance
+ ###
+ cmd: (cmd) ->
+ if cmd then cmd._parent @
+ else new Cmd @
+
+ ###*
+ Create option for current command.
+ @returns {COA.Opt} new option instance
+ ###
+ opt: -> new (require('./opt').Opt) @
+
+ ###*
+ Create argument for current command.
+ @returns {COA.Opt} new argument instance
+ ###
+ arg: -> new (require('./arg').Arg) @
+
+ ###*
+ Add (or set) action for current command.
+ @param {Function} act action function,
+ invoked in the context of command instance
+ and has the parameters:
+ - {Object} opts parsed options
+ - {Array} args parsed arguments
+ - {Object} res actions result accumulator
+ It can return rejected promise by Cmd.reject (in case of error)
+ or any other value treated as result.
+ @param {Boolean} [force=false] flag for set action instead add to existings
+ @returns {COA.Cmd} this instance (for chainability)
+ ###
+ act: (act, force) ->
+ return @ unless act
+
+ if not force and @_act
+ @_act.push act
+ else
+ @_act = [act]
+
+ @
+
+ ###*
+ Set custom additional completion for current command.
+ @param {Function} completion generation function,
+ invoked in the context of command instance.
+ Accepts parameters:
+ - {Object} opts completion options
+ It can return promise or any other value treated as result.
+ @returns {COA.Cmd} this instance (for chainability)
+ ###
+ comp: (@_comp) -> @
+
+ ###*
+ Apply function with arguments in context of command instance.
+ @param {Function} fn
+ @param {Array} args
+ @returns {COA.Cmd} this instance (for chainability)
+ ###
+ apply: (fn, args...) ->
+ fn.apply this, args
+ @
+
+ ###*
+ Make command "helpful", i.e. add -h --help flags for print usage.
+ @returns {COA.Cmd} this instance (for chainability)
+ ###
+ helpful: ->
+ @opt()
+ .name('help').title('Help')
+ .short('h').long('help')
+ .flag()
+ .only()
+ .act ->
+ return @usage()
+ .end()
+
+ ###*
+ Adds shell completion to command, adds "completion" subcommand,
+ that makes all the magic.
+ Must be called only on root command.
+ @returns {COA.Cmd} this instance (for chainability)
+ ###
+ completable: ->
+ @cmd()
+ .name('completion')
+ .apply(require './completion')
+ .end()
+
+ ###*
+ Allow command to be extendable by external node.js modules.
+ @param {String} [pattern] Pattern of node.js module to find subcommands at.
+ @returns {COA.Cmd} this instance (for chainability)
+ ###
+ extendable: (pattern) ->
+ @_ext = pattern or true
+ @
+
+ _exit: (msg, code) ->
+ process.once 'exit', ->
+ if msg then console.error msg
+ process.exit code or 0
+
+ ###*
+ Build full usage text for current command instance.
+ @returns {String} usage text
+ ###
+ usage: ->
+ res = []
+
+ if @_title then res.push @_fullTitle()
+
+ res.push('', 'Usage:')
+
+ if @_cmds.length then res.push(['', '',
+ Color('lred', @_fullName()),
+ Color('lblue', 'COMMAND'),
+ Color('lgreen', '[OPTIONS]'),
+ Color('lpurple', '[ARGS]')].join ' ')
+
+ if @_opts.length + @_args.length then res.push(['', '',
+ Color('lred', @_fullName()),
+ Color('lgreen', '[OPTIONS]'),
+ Color('lpurple', '[ARGS]')].join ' ')
+
+ res.push(
+ @_usages(@_cmds, 'Commands'),
+ @_usages(@_opts, 'Options'),
+ @_usages(@_args, 'Arguments'))
+
+ res.join '\n'
+
+ _usage: ->
+ Color('lblue', @_name) + ' : ' + @_title
+
+ _usages: (os, title) ->
+ unless os.length then return
+ res = ['', title + ':']
+ for o in os
+ res.push ' ' + o._usage()
+ res.join '\n'
+
+ _fullTitle: ->
+ (if @_cmd is this then '' else @_cmd._fullTitle() + '\n') + @_title
+
+ _fullName: ->
+ (if this._cmd is this then '' else @_cmd._fullName() + ' ') + PATH.basename(@_name)
+
+ _ejectOpt: (opts, opt) ->
+ if (pos = opts.indexOf(opt)) >= 0
+ if opts[pos]._arr
+ opts[pos]
+ else
+ opts.splice(pos, 1)[0]
+
+ _checkRequired: (opts, args) ->
+ if not (@_opts.filter (o) -> o._only and o._name of opts).length
+ all = @_opts.concat @_args
+ while i = all.shift()
+ if i._req and i._checkParsed opts, args
+ return @reject i._requiredText()
+
+ _parseCmd: (argv, unparsed = []) ->
+ argv = argv.concat()
+ optSeen = false
+ while i = argv.shift()
+ if not i.indexOf '-'
+ optSeen = true
+ if not optSeen and /^\w[\w-_]*$/.test(i)
+ cmd = @_cmdsByName[i]
+
+ if not cmd and @_ext
+ # construct package name to require
+ if typeof @_ext is 'string'
+ if ~@_ext.indexOf('%s')
+ # use formatted string
+ pkg = UTIL.format(@_ext, i)
+ else
+ # just append subcommand name to the prefix
+ pkg = @_ext + i
+ else if @_ext is true
+ # use default scheme: <command>-<subcommand>-<subcommand> and so on
+ pkg = i
+ c = @
+ loop
+ pkg = c._name + '-' + pkg
+ if c._cmd is c then break
+ c = c._cmd
+
+ try
+ cmdDesc = require(pkg)
+ catch e
+
+ if cmdDesc
+ if typeof cmdDesc == 'function'
+ # set create subcommand, set its name and apply imported function
+ @cmd()
+ .name(i)
+ .apply(cmdDesc)
+ .end()
+ else if typeof cmdDesc == 'object'
+ # register subcommand
+ @cmd(cmdDesc)
+ # set command name
+ cmdDesc.name(i)
+ else
+ throw new Error 'Error: Unsupported command declaration type, ' +
+ 'should be function or COA.Cmd() object'
+ cmd = @_cmdsByName[i]
+ if cmd
+ return cmd._parseCmd argv, unparsed
+
+ unparsed.push i
+
+ { cmd: @, argv: unparsed }
+
+ _parseOptsAndArgs: (argv) ->
+ opts = {}
+ args = {}
+
+ nonParsedOpts = @_opts.concat()
+ nonParsedArgs = @_args.concat()
+
+ while i = argv.shift()
+ # opt
+ if i isnt '--' and not i.indexOf '-'
+
+ if m = i.match /^(--\w[\w-_]*)=(.*)$/
+ i = m[1]
+
+ # suppress 'unknown argument' error for flag options with values
+ if not @_optsByKey[i]._flag
+ argv.unshift m[2]
+
+ if opt = @_ejectOpt nonParsedOpts, @_optsByKey[i]
+ if Q.isRejected(res = opt._parse argv, opts)
+ return res
+ else
+ return @reject "Unknown option: #{ i }"
+
+ # arg
+ else
+ if i is '--'
+ i = argv.splice(0)
+
+ i = if Array.isArray(i) then i else [i]
+
+ while a = i.shift()
+ if arg = nonParsedArgs.shift()
+ if arg._arr then nonParsedArgs.unshift arg
+ if Q.isRejected(res = arg._parse a, args)
+ return res
+ else
+ return @reject "Unknown argument: #{ a }"
+
+ # set defaults
+ {
+ opts: @_setDefaults(opts, nonParsedOpts),
+ args: @_setDefaults(args, nonParsedArgs)
+ }
+
+ _setDefaults: (params, desc) ->
+ for i in desc
+ if i._name not of params and '_def' of i
+ i._saveVal params, i._def
+ params
+
+ _processParams: (params, desc) ->
+ notExists = []
+ for i in desc
+ n = i._name
+ if n not of params
+ notExists.push i
+ continue
+
+ vals = params[n]
+ delete params[n]
+ if not Array.isArray vals
+ vals = [vals]
+
+ for v in vals
+ if Q.isRejected(res = i._saveVal(params, v))
+ return res
+
+ # set defaults
+ @_setDefaults params, notExists
+
+ _parseArr: (argv) ->
+ Q.when @_parseCmd(argv), (p) ->
+ Q.when p.cmd._parseOptsAndArgs(p.argv), (r) ->
+ { cmd: p.cmd, opts: r.opts, args: r.args }
+
+ _do: (input) ->
+ Q.when input, (input) =>
+ cmd = input.cmd
+ [@_checkRequired].concat(cmd._act or []).reduce(
+ (res, act) ->
+ Q.when res, (res) ->
+ act.call(
+ cmd
+ input.opts
+ input.args
+ res)
+ undefined
+ )
+
+ ###*
+ Parse arguments from simple format like NodeJS process.argv
+ and run ahead current program, i.e. call process.exit when all actions done.
+ @param {Array} argv
+ @returns {COA.Cmd} this instance (for chainability)
+ ###
+ run: (argv = process.argv.slice(2)) ->
+ cb = (code) => (res) =>
+ if res
+ @_exit res.stack ? res.toString(), res.exitCode ? code
+ else
+ @_exit()
+ Q.when(@do(argv), cb(0), cb(1)).done()
+ @
+
+ ###*
+ Convenient function to run command from tests.
+ @param {Array} argv
+ @returns {Q.Promise}
+ ###
+ do: (argv) ->
+ @_do(@_parseArr argv || [])
+
+ ###*
+ Invoke specified (or current) command using provided
+ options and arguments.
+ @param {String|Array} cmds subcommand to invoke (optional)
+ @param {Object} opts command options (optional)
+ @param {Object} args command arguments (optional)
+ @returns {Q.Promise}
+ ###
+ invoke: (cmds = [], opts = {}, args = {}) ->
+ if typeof cmds == 'string'
+ cmds = cmds.split(' ')
+
+ if arguments.length < 3
+ if not Array.isArray cmds
+ args = opts
+ opts = cmds
+ cmds = []
+
+ Q.when @_parseCmd(cmds), (p) =>
+ if p.argv.length
+ return @reject "Unknown command: " + cmds.join ' '
+
+ Q.all([@_processParams(opts, @_opts), @_processParams(args, @_args)])
+ .spread (opts, args) =>
+ @_do({ cmd: p.cmd, opts: opts, args: args })
+ # catch fails from .only() options
+ .fail (res) =>
+ if res and res.exitCode is 0
+ res.toString()
+ else
+ @reject(res)
+
+ ###*
+ Return reject of actions results promise with error code.
+ Use in .act() for return with error.
+ @param {Object} reject reason
+ You can customize toString() method and exitCode property
+ of reason object.
+ @returns {Q.promise} rejected promise
+ ###
+ reject: (reason) -> Q.reject(reason)
+
+ ###*
+ Finish chain for current subcommand and return parent command instance.
+ @returns {COA.Cmd} parent command
+ ###
+ end: -> @_cmd
diff --git a/node_modules/coa/src/color.coffee b/node_modules/coa/src/color.coffee
new file mode 100644
index 00000000..f07a3a57
--- /dev/null
+++ b/node_modules/coa/src/color.coffee
@@ -0,0 +1,25 @@
+colors =
+ black: '30'
+ dgray: '1;30'
+ red: '31'
+ lred: '1;31'
+ green: '32'
+ lgreen: '1;32'
+ brown: '33'
+ yellow: '1;33'
+ blue: '34'
+ lblue: '1;34'
+ purple: '35'
+ lpurple: '1;35'
+ cyan: '36'
+ lcyan: '1;36'
+ lgray: '37'
+ white: '1;37'
+
+exports.Color = (c, str) ->
+ # Use \x1B instead of \033 because of CoffeeScript 1.3.x compilation error
+ [
+ '\x1B[', colors[c], 'm'
+ str
+ '\x1B[m'
+ ].join ''
diff --git a/node_modules/coa/src/completion.coffee b/node_modules/coa/src/completion.coffee
new file mode 100644
index 00000000..2c1e358d
--- /dev/null
+++ b/node_modules/coa/src/completion.coffee
@@ -0,0 +1,156 @@
+###*
+Most of the code adopted from the npm package shell completion code.
+See https://github.com/isaacs/npm/blob/master/lib/completion.js
+###
+
+Q = require 'q'
+escape = require('./shell').escape
+unescape = require('./shell').unescape
+
+module.exports = ->
+ @title('Shell completion')
+ .helpful()
+ .arg()
+ .name('raw')
+ .title('Completion words')
+ .arr()
+ .end()
+ .act (opts, args) ->
+ if process.platform == 'win32'
+ e = new Error 'shell completion not supported on windows'
+ e.code = 'ENOTSUP'
+ e.errno = require('constants').ENOTSUP
+ return @reject(e)
+
+ # if the COMP_* isn't in the env, then just dump the script
+ if !process.env.COMP_CWORD? or !process.env.COMP_LINE? or !process.env.COMP_POINT?
+ return dumpScript(@_cmd._name)
+
+ console.error 'COMP_LINE: %s', process.env.COMP_LINE
+ console.error 'COMP_CWORD: %s', process.env.COMP_CWORD
+ console.error 'COMP_POINT: %s', process.env.COMP_POINT
+ console.error 'args: %j', args.raw
+
+ # completion opts
+ opts = getOpts args.raw
+
+ # cmd
+ { cmd, argv } = @_cmd._parseCmd opts.partialWords
+ Q.when complete(cmd, opts), (compls) ->
+ console.error 'filtered: %j', compls
+ console.log compls.map(escape).join('\n')
+
+
+dumpScript = (name) ->
+ fs = require 'fs'
+ path = require 'path'
+ defer = Q.defer()
+
+ fs.readFile path.resolve(__dirname, 'completion.sh'), 'utf8', (err, d) ->
+ if err then return defer.reject err
+ d = d.replace(/{{cmd}}/g, path.basename name).replace(/^\#\!.*?\n/, '')
+
+ onError = (err) ->
+ # Darwin is a real dick sometimes.
+ #
+ # This is necessary because the "source" or "." program in
+ # bash on OS X closes its file argument before reading
+ # from it, meaning that you get exactly 1 write, which will
+ # work most of the time, and will always raise an EPIPE.
+ #
+ # Really, one should not be tossing away EPIPE errors, or any
+ # errors, so casually. But, without this, `. <(cmd completion)`
+ # can never ever work on OS X.
+ if err.errno == require('constants').EPIPE
+ process.stdout.removeListener 'error', onError
+ defer.resolve()
+ else
+ defer.reject(err)
+
+ process.stdout.on 'error', onError
+ process.stdout.write d, -> defer.resolve()
+
+ defer.promise
+
+
+getOpts = (argv) ->
+ # get the partial line and partial word, if the point isn't at the end
+ # ie, tabbing at: cmd foo b|ar
+ line = process.env.COMP_LINE
+ w = +process.env.COMP_CWORD
+ point = +process.env.COMP_POINT
+ words = argv.map unescape
+ word = words[w]
+ partialLine = line.substr 0, point
+ partialWords = words.slice 0, w
+
+ # figure out where in that last word the point is
+ partialWord = argv[w] or ''
+ i = partialWord.length
+ while partialWord.substr(0, i) isnt partialLine.substr(-1 * i) and i > 0
+ i--
+ partialWord = unescape partialWord.substr 0, i
+ if partialWord then partialWords.push partialWord
+
+ {
+ line: line
+ w: w
+ point: point
+ words: words
+ word: word
+ partialLine: partialLine
+ partialWords: partialWords
+ partialWord: partialWord
+ }
+
+
+complete = (cmd, opts) ->
+ compls = []
+
+ # complete on cmds
+ if opts.partialWord.indexOf('-')
+ compls = Object.keys(cmd._cmdsByName)
+ # Complete on required opts without '-' in last partial word
+ # (if required not already specified)
+ #
+ # Commented out because of uselessness:
+ # -b, --block suggest results in '-' on cmd line;
+ # next completion suggest all options, because of '-'
+ #.concat Object.keys(cmd._optsByKey).filter (v) -> cmd._optsByKey[v]._req
+ else
+ # complete on opt values: --opt=| case
+ if m = opts.partialWord.match /^(--\w[\w-_]*)=(.*)$/
+ optWord = m[1]
+ optPrefix = optWord + '='
+ else
+ # complete on opts
+ # don't complete on opts in case of --opt=val completion
+ # TODO: don't complete on opts in case of unknown arg after commands
+ # TODO: complete only on opts with arr() or not already used
+ # TODO: complete only on full opts?
+ compls = Object.keys cmd._optsByKey
+
+ # complete on opt values: next arg case
+ if not (o = opts.partialWords[opts.w - 1]).indexOf '-'
+ optWord = o
+
+ # complete on opt values: completion
+ if optWord and opt = cmd._optsByKey[optWord]
+ if not opt._flag and opt._comp
+ compls = Q.join compls, Q.when opt._comp(opts), (c, o) ->
+ c.concat o.map (v) -> (optPrefix or '') + v
+
+ # TODO: complete on args values (context aware, custom completion?)
+
+ # custom completion on cmds
+ if cmd._comp
+ compls = Q.join compls, Q.when(cmd._comp(opts)), (c, o) ->
+ c.concat o
+
+ # TODO: context aware custom completion on cmds, opts and args
+ # (can depend on already entered values, especially options)
+
+ Q.when compls, (compls) ->
+ console.error 'partialWord: %s', opts.partialWord
+ console.error 'compls: %j', compls
+ compls.filter (c) -> c.indexOf(opts.partialWord) is 0
diff --git a/node_modules/coa/src/index.coffee b/node_modules/coa/src/index.coffee
new file mode 100644
index 00000000..ae594be3
--- /dev/null
+++ b/node_modules/coa/src/index.coffee
@@ -0,0 +1,5 @@
+exports.Cmd = require('./cmd').Cmd
+exports.Opt = require('./cmd').Opt
+exports.Arg = require('./cmd').Arg
+exports.shell = require('./shell')
+exports.require = require;
diff --git a/node_modules/coa/src/opt.coffee b/node_modules/coa/src/opt.coffee
new file mode 100644
index 00000000..466383df
--- /dev/null
+++ b/node_modules/coa/src/opt.coffee
@@ -0,0 +1,243 @@
+fs = require 'fs'
+Q = require 'q'
+Color = require('./color').Color
+Cmd = require('./cmd').Cmd
+
+###*
+Option
+
+Named entity. Options may have short and long keys for use from command line.
+@namespace
+@class Presents option
+###
+exports.Opt = class Opt
+
+ ###*
+ @constructs
+ @param {COA.Cmd} cmd parent command
+ ###
+ constructor: (@_cmd) -> @_cmd._opts.push @
+
+ ###*
+ Set a canonical option identifier to be used anywhere in the API.
+ @param {String} _name option name
+ @returns {COA.Opt} this instance (for chainability)
+ ###
+ name: (@_name) -> @
+
+ ###*
+ Set a long description for option to be used anywhere in text messages.
+ @param {String} _title option title
+ @returns {COA.Opt} this instance (for chainability)
+ ###
+ title: Cmd::title
+
+ ###*
+ Set a short key for option to be used with one hyphen from command line.
+ @param {String} _short
+ @returns {COA.Opt} this instance (for chainability)
+ ###
+ short: (@_short) -> @_cmd._optsByKey['-' + _short] = @
+
+ ###*
+ Set a short key for option to be used with double hyphens from command line.
+ @param {String} _long
+ @returns {COA.Opt} this instance (for chainability)
+ ###
+ long: (@_long) -> @_cmd._optsByKey['--' + _long] = @
+
+ ###*
+ Make an option boolean, i.e. option without value.
+ @returns {COA.Opt} this instance (for chainability)
+ ###
+ flag: () ->
+ @_flag = true
+ @
+
+ ###*
+ Makes an option accepts multiple values.
+ Otherwise, the value will be used by the latter passed.
+ @returns {COA.Opt} this instance (for chainability)
+ ###
+ arr: ->
+ @_arr = true
+ @
+
+ ###*
+ Makes an option required.
+ @returns {COA.Opt} this instance (for chainability)
+ ###
+ req: ->
+ @_req = true
+ @
+
+ ###*
+ Makes an option to act as a command,
+ i.e. program will exit just after option action.
+ @returns {COA.Opt} this instance (for chainability)
+ ###
+ only: ->
+ @_only = true
+ @
+
+ ###*
+ Set a validation (or value) function for option.
+ Value from command line passes through before becoming available from API.
+ Using for validation and convertion simple types to any values.
+ @param {Function} _val validating function,
+ invoked in the context of option instance
+ and has one parameter with value from command line
+ @returns {COA.Opt} this instance (for chainability)
+ ###
+ val: (@_val) -> @
+
+ ###*
+ Set a default value for option.
+ Default value passed through validation function as ordinary value.
+ @param {Object} _def
+ @returns {COA.Opt} this instance (for chainability)
+ ###
+ def: (@_def) -> @
+
+ ###*
+ Make option value inputting stream.
+ It's add useful validation and shortcut for STDIN.
+ @returns {COA.Opt} this instance (for chainability)
+ ###
+ input: ->
+ # XXX: hack to workaround a bug in node 0.6.x,
+ # see https://github.com/joyent/node/issues/2130
+ process.stdin.pause();
+
+ @
+ .def(process.stdin)
+ .val (v) ->
+ if typeof v is 'string'
+ if v is '-'
+ process.stdin
+ else
+ s = fs.createReadStream v, { encoding: 'utf8' }
+ s.pause()
+ s
+ else v
+
+ ###*
+ Make option value outputing stream.
+ It's add useful validation and shortcut for STDOUT.
+ @returns {COA.Opt} this instance (for chainability)
+ ###
+ output: ->
+ @
+ .def(process.stdout)
+ .val (v) ->
+ if typeof v is 'string'
+ if v is '-'
+ process.stdout
+ else
+ fs.createWriteStream v, { encoding: 'utf8' }
+ else v
+
+ ###*
+ Add action for current option command.
+ This action is performed if the current option
+ is present in parsed options (with any value).
+ @param {Function} act action function,
+ invoked in the context of command instance
+ and has the parameters:
+ - {Object} opts parsed options
+ - {Array} args parsed arguments
+ - {Object} res actions result accumulator
+ It can return rejected promise by Cmd.reject (in case of error)
+ or any other value treated as result.
+ @returns {COA.Opt} this instance (for chainability)
+ ###
+ act: (act) ->
+ opt = @
+ name = @_name
+ @_cmd.act (opts) ->
+ if name of opts
+ res = act.apply @, arguments
+ if opt._only
+ Q.when res, (res) =>
+ @reject {
+ toString: -> res.toString()
+ exitCode: 0
+ }
+ else
+ res
+ @
+
+ ###*
+ Set custom additional completion for current option.
+ @param {Function} completion generation function,
+ invoked in the context of option instance.
+ Accepts parameters:
+ - {Object} opts completion options
+ It can return promise or any other value treated as result.
+ @returns {COA.Opt} this instance (for chainability)
+ ###
+ comp: Cmd::comp
+
+ _saveVal: (opts, val) ->
+ if @_val then val = @_val val
+ if @_arr
+ (opts[@_name] or= []).push val
+ else
+ opts[@_name] = val
+ val
+
+ _parse: (argv, opts) ->
+ @_saveVal(
+ opts,
+ if @_flag
+ true
+ else
+ argv.shift()
+ )
+
+ _checkParsed: (opts, args) -> not opts.hasOwnProperty @_name
+
+ _usage: ->
+ res = []
+ nameStr = @_name.toUpperCase()
+
+ if @_short
+ res.push '-', Color 'lgreen', @_short
+ unless @_flag then res.push ' ' + nameStr
+ res.push ', '
+
+ if @_long
+ res.push '--', Color 'green', @_long
+ unless @_flag then res.push '=' + nameStr
+
+ res.push ' : ', @_title
+
+ if @_req then res.push ' ', Color('lred', '(required)')
+
+ res.join ''
+
+ _requiredText: -> 'Missing required option:\n ' + @_usage()
+
+ ###*
+ Return rejected promise with error code.
+ Use in .val() for return with error.
+ @param {Object} reject reason
+ You can customize toString() method and exitCode property
+ of reason object.
+ @returns {Q.promise} rejected promise
+ ###
+ reject: Cmd::reject
+
+ ###*
+ Finish chain for current option and return parent command instance.
+ @returns {COA.Cmd} parent command
+ ###
+ end: Cmd::end
+
+ ###*
+ Apply function with arguments in context of option instance.
+ @param {Function} fn
+ @param {Array} args
+ @returns {COA.Opt} this instance (for chainability)
+ ###
+ apply: Cmd::apply
diff --git a/node_modules/coa/src/shell.coffee b/node_modules/coa/src/shell.coffee
new file mode 100644
index 00000000..efad108d
--- /dev/null
+++ b/node_modules/coa/src/shell.coffee
@@ -0,0 +1,10 @@
+exports.unescape = (w) ->
+ w = if w.charAt(0) is '"'
+ w.replace(/^"|([^\\])"$/g, '$1')
+ else
+ w.replace(/\\ /g, ' ')
+ w.replace(/\\("|'|\$|`|\\)/g, '$1')
+
+exports.escape = (w) ->
+ w = w.replace(/(["'$`\\])/g,'\\$1')
+ if w.match(/\s+/) then '"' + w + '"' else w