coa 0.4.1 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +28 -33
- package/README.ru.md +316 -0
- package/index.js +1 -1
- package/lib/arg.js +44 -161
- package/lib/cmd.js +434 -547
- package/lib/coaobject.js +100 -0
- package/lib/coaparam.js +125 -0
- package/lib/color.js +19 -22
- package/lib/completion.js +161 -119
- package/lib/index.js +14 -10
- package/lib/opt.js +130 -313
- package/lib/shell.js +13 -13
- package/package.json +21 -17
- package/.npmignore +0 -6
- package/.travis.yml +0 -11
- package/GNUmakefile +0 -34
- package/src/arg.coffee +0 -130
- package/src/cmd.coffee +0 -456
- package/src/color.coffee +0 -25
- package/src/completion.coffee +0 -158
- package/src/index.coffee +0 -5
- package/src/opt.coffee +0 -243
- package/src/shell.coffee +0 -10
- package/test/coa.js +0 -496
- package/test/common.js +0 -1
- package/test/mocha.opts +0 -3
- package/test/shell-test.js +0 -60
- package/tests/api-h.js +0 -9
- package/tests/h.js +0 -6
package/lib/coaobject.js
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
const Q = require('q');
|
4
|
+
|
5
|
+
/**
|
6
|
+
* COA Object
|
7
|
+
*
|
8
|
+
* Base class for all COA-related objects
|
9
|
+
*
|
10
|
+
* --------|-----|-----|-----
|
11
|
+
* | Cmd | Opt | Arg
|
12
|
+
* --------|-----|-----|-----
|
13
|
+
* name | ✓ | ✓ | ✓
|
14
|
+
* title | ✓ | ✓ | ✓
|
15
|
+
* comp | ✓ | ✓ | ✓
|
16
|
+
* reject | ✓ | ✓ | ✓
|
17
|
+
* end | ✓ | ✓ | ✓
|
18
|
+
* apply | ✓ | ✓ | ✓
|
19
|
+
*
|
20
|
+
* @class CoaObject
|
21
|
+
*/
|
22
|
+
module.exports = class CoaObject {
|
23
|
+
constructor(cmd) {
|
24
|
+
this._cmd = cmd;
|
25
|
+
this._name = null;
|
26
|
+
this._title = null;
|
27
|
+
this._comp = null;
|
28
|
+
}
|
29
|
+
|
30
|
+
/**
|
31
|
+
* Set a canonical identifier to be used anywhere in the API.
|
32
|
+
*
|
33
|
+
* @param {String} name - command, option or argument name
|
34
|
+
* @returns {COA.CoaObject} - this instance (for chainability)
|
35
|
+
*/
|
36
|
+
name(name) {
|
37
|
+
this._name = name;
|
38
|
+
return this;
|
39
|
+
}
|
40
|
+
|
41
|
+
/**
|
42
|
+
* Set a long description to be used anywhere in text messages.
|
43
|
+
* @param {String} title - human readable entity title
|
44
|
+
* @returns {COA.CoaObject} - this instance (for chainability)
|
45
|
+
*/
|
46
|
+
title(title) {
|
47
|
+
this._title = title;
|
48
|
+
return this;
|
49
|
+
}
|
50
|
+
|
51
|
+
/**
|
52
|
+
* Set custom additional completion for current object.
|
53
|
+
*
|
54
|
+
* @param {Function} comp - completion generation function,
|
55
|
+
* invoked in the context of object instance.
|
56
|
+
* Accepts parameters:
|
57
|
+
* - {Object} opts - completion options
|
58
|
+
* It can return promise or any other value threated as a result.
|
59
|
+
* @returns {COA.CoaObject} - this instance (for chainability)
|
60
|
+
*/
|
61
|
+
comp(comp) {
|
62
|
+
this._comp = comp;
|
63
|
+
return this;
|
64
|
+
}
|
65
|
+
|
66
|
+
/**
|
67
|
+
* Apply function with arguments in a context of object instance.
|
68
|
+
*
|
69
|
+
* @param {Function} fn - body
|
70
|
+
* @param {Array.<*>} args... - arguments
|
71
|
+
* @returns {COA.CoaObject} - this instance (for chainability)
|
72
|
+
*/
|
73
|
+
apply(fn) {
|
74
|
+
arguments.length > 1?
|
75
|
+
fn.apply(this, [].slice.call(arguments, 1))
|
76
|
+
: fn.call(this);
|
77
|
+
|
78
|
+
return this;
|
79
|
+
}
|
80
|
+
|
81
|
+
/**
|
82
|
+
* Return reject of actions results promise with error code.
|
83
|
+
* Use in .act() for return with error.
|
84
|
+
* @param {Object} reason - reject reason
|
85
|
+
* You can customize toString() method and exitCode property
|
86
|
+
* of reason object.
|
87
|
+
* @returns {Q.promise} rejected promise
|
88
|
+
*/
|
89
|
+
reject(reason) {
|
90
|
+
return Q.reject(reason);
|
91
|
+
}
|
92
|
+
|
93
|
+
/**
|
94
|
+
* Finish chain for current subcommand and return parent command instance.
|
95
|
+
* @returns {COA.Cmd} parent command
|
96
|
+
*/
|
97
|
+
end() {
|
98
|
+
return this._cmd;
|
99
|
+
}
|
100
|
+
};
|
package/lib/coaparam.js
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
const fs = require('fs');
|
4
|
+
|
5
|
+
const CoaObject = require('./coaobject');
|
6
|
+
|
7
|
+
/**
|
8
|
+
* COA Parameter
|
9
|
+
*
|
10
|
+
* Base class for options and arguments
|
11
|
+
*
|
12
|
+
* --------|-----|-----|-----
|
13
|
+
* | Cmd | Opt | Arg
|
14
|
+
* --------|-----|-----|-----
|
15
|
+
* arr | | ✓ | ✓
|
16
|
+
* req | | ✓ | ✓
|
17
|
+
* val | | ✓ | ✓
|
18
|
+
* def | | ✓ | ✓
|
19
|
+
* input | | ✓ | ✓
|
20
|
+
* output | | ✓ | ✓
|
21
|
+
*
|
22
|
+
* @class CoaParam
|
23
|
+
* @extends CoaObject
|
24
|
+
*/
|
25
|
+
module.exports = class CoaParam extends CoaObject {
|
26
|
+
constructor(cmd) {
|
27
|
+
super(cmd);
|
28
|
+
|
29
|
+
this._arr = false;
|
30
|
+
this._req = false;
|
31
|
+
this._val = undefined;
|
32
|
+
this._def = undefined;
|
33
|
+
}
|
34
|
+
|
35
|
+
/**
|
36
|
+
* Makes a param accepts multiple values.
|
37
|
+
* Otherwise, the value will be used by the latter passed.
|
38
|
+
*
|
39
|
+
* @returns {COA.CoaParam} - this instance (for chainability)
|
40
|
+
*/
|
41
|
+
arr() {
|
42
|
+
this._arr = true;
|
43
|
+
return this;
|
44
|
+
}
|
45
|
+
|
46
|
+
/**
|
47
|
+
* Makes a param required.
|
48
|
+
*
|
49
|
+
* @returns {COA.CoaParam} - this instance (for chainability)
|
50
|
+
*/
|
51
|
+
req() {
|
52
|
+
this._req = true;
|
53
|
+
return this;
|
54
|
+
}
|
55
|
+
|
56
|
+
/**
|
57
|
+
* Set a validation (or value) function for param.
|
58
|
+
* Value from command line passes through before becoming available from API.
|
59
|
+
* Using for validation and convertion simple types to any values.
|
60
|
+
*
|
61
|
+
* @param {Function} val - validating function,
|
62
|
+
* invoked in the context of option instance
|
63
|
+
* and has one parameter with value from command line.
|
64
|
+
* @returns {COA.CoaParam} - this instance (for chainability)
|
65
|
+
*/
|
66
|
+
val(val) {
|
67
|
+
this._val = val;
|
68
|
+
return this;
|
69
|
+
}
|
70
|
+
|
71
|
+
/**
|
72
|
+
* Set a default value for param.
|
73
|
+
* Default value passed through validation function as ordinary value.
|
74
|
+
*
|
75
|
+
* @param {*} def - default value of function generator
|
76
|
+
* @returns {COA.CoaParam} - this instance (for chainability)
|
77
|
+
*/
|
78
|
+
def(def) {
|
79
|
+
this._def = def;
|
80
|
+
return this;
|
81
|
+
}
|
82
|
+
|
83
|
+
/**
|
84
|
+
* Make option value inputting stream.
|
85
|
+
* It's add useful validation and shortcut for STDIN.
|
86
|
+
*
|
87
|
+
* @returns {COA.CoaParam} - this instance (for chainability)
|
88
|
+
*/
|
89
|
+
input() {
|
90
|
+
process.stdin.pause();
|
91
|
+
return this
|
92
|
+
.def(process.stdin)
|
93
|
+
.val(function(v) {
|
94
|
+
if(typeof v !== 'string')
|
95
|
+
return v;
|
96
|
+
|
97
|
+
if(v === '-')
|
98
|
+
return process.stdin;
|
99
|
+
|
100
|
+
const s = fs.createReadStream(v, { encoding : 'utf8' });
|
101
|
+
s.pause();
|
102
|
+
return s;
|
103
|
+
});
|
104
|
+
}
|
105
|
+
|
106
|
+
/**
|
107
|
+
* Make option value outputing stream.
|
108
|
+
* It's add useful validation and shortcut for STDOUT.
|
109
|
+
*
|
110
|
+
* @returns {COA.CoaParam} - this instance (for chainability)
|
111
|
+
*/
|
112
|
+
output() {
|
113
|
+
return this
|
114
|
+
.def(process.stdout)
|
115
|
+
.val(function(v) {
|
116
|
+
if(typeof v !== 'string')
|
117
|
+
return v;
|
118
|
+
|
119
|
+
if(v === '-')
|
120
|
+
return process.stdout;
|
121
|
+
|
122
|
+
return fs.createWriteStream(v, { encoding : 'utf8' });
|
123
|
+
});
|
124
|
+
}
|
125
|
+
};
|
package/lib/color.js
CHANGED
@@ -1,25 +1,22 @@
|
|
1
|
-
|
2
|
-
var colors;
|
1
|
+
'use strict';
|
3
2
|
|
4
|
-
colors = {
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
3
|
+
const colors = {
|
4
|
+
black : '30',
|
5
|
+
dgray : '1;30',
|
6
|
+
red : '31',
|
7
|
+
lred : '1;31',
|
8
|
+
green : '32',
|
9
|
+
lgreen : '1;32',
|
10
|
+
brown : '33',
|
11
|
+
yellow : '1;33',
|
12
|
+
blue : '34',
|
13
|
+
lblue : '1;34',
|
14
|
+
purple : '35',
|
15
|
+
lpurple : '1;35',
|
16
|
+
cyan : '36',
|
17
|
+
lcyan : '1;36',
|
18
|
+
lgray : '37',
|
19
|
+
white : '1;37'
|
21
20
|
};
|
22
21
|
|
23
|
-
exports
|
24
|
-
return ['\x1B[', colors[c], 'm', str, '\x1B[m'].join('');
|
25
|
-
};
|
22
|
+
module.exports = (c, str) => `\x1B[${colors[c]}m${str}\x1B[m`;
|
package/lib/completion.js
CHANGED
@@ -1,134 +1,176 @@
|
|
1
|
-
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
const constants = require('constants');
|
4
|
+
const fs = require('fs');
|
5
|
+
const path = require('path');
|
6
|
+
|
7
|
+
const Q = require('q');
|
8
|
+
|
9
|
+
const shell = require('./shell');
|
10
|
+
const escape = shell.escape;
|
11
|
+
const unescape = shell.unescape;
|
12
|
+
|
2
13
|
/**
|
3
|
-
Most of the code adopted from the npm package shell completion code.
|
4
|
-
See https://github.com/isaacs/npm/blob/master/lib/completion.js
|
5
|
-
|
14
|
+
* Most of the code adopted from the npm package shell completion code.
|
15
|
+
* See https://github.com/isaacs/npm/blob/master/lib/completion.js
|
16
|
+
*
|
17
|
+
* @returns {COA.CoaObject}
|
18
|
+
*/
|
19
|
+
module.exports = function completion() {
|
20
|
+
return this
|
21
|
+
.title('Shell completion')
|
22
|
+
.helpful()
|
23
|
+
.arg()
|
24
|
+
.name('raw')
|
25
|
+
.title('Completion words')
|
26
|
+
.arr()
|
27
|
+
.end()
|
28
|
+
.act((opts, args) => {
|
29
|
+
if(process.platform === 'win32') {
|
30
|
+
const e = new Error('shell completion not supported on windows');
|
31
|
+
e.code = 'ENOTSUP';
|
32
|
+
e.errno = constants.ENOTSUP;
|
33
|
+
return this.reject(e);
|
34
|
+
}
|
6
35
|
|
7
|
-
|
36
|
+
// if the COMP_* isn't in the env, then just dump the script
|
37
|
+
if((process.env.COMP_CWORD == null)
|
38
|
+
|| (process.env.COMP_LINE == null)
|
39
|
+
|| (process.env.COMP_POINT == null)) {
|
40
|
+
return dumpScript(this._cmd._name);
|
41
|
+
}
|
8
42
|
|
9
|
-
|
43
|
+
console.error('COMP_LINE: %s', process.env.COMP_LINE);
|
44
|
+
console.error('COMP_CWORD: %s', process.env.COMP_CWORD);
|
45
|
+
console.error('COMP_POINT: %s', process.env.COMP_POINT);
|
46
|
+
console.error('args: %j', args.raw);
|
10
47
|
|
11
|
-
|
48
|
+
// completion opts
|
49
|
+
opts = getOpts(args.raw);
|
12
50
|
|
13
|
-
|
51
|
+
// cmd
|
52
|
+
const parsed = this._cmd._parseCmd(opts.partialWords);
|
53
|
+
return Q.when(complete(parsed.cmd, parsed.opts), compls => {
|
54
|
+
console.error('filtered: %j', compls);
|
55
|
+
return console.log(compls.map(escape).join('\n'));
|
56
|
+
});
|
57
|
+
});
|
58
|
+
};
|
14
59
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
if ((process.env.COMP_CWORD == null) || (process.env.COMP_LINE == null) || (process.env.COMP_POINT == null)) {
|
25
|
-
return dumpScript(this._cmd._name);
|
26
|
-
}
|
27
|
-
console.error('COMP_LINE: %s', process.env.COMP_LINE);
|
28
|
-
console.error('COMP_CWORD: %s', process.env.COMP_CWORD);
|
29
|
-
console.error('COMP_POINT: %s', process.env.COMP_POINT);
|
30
|
-
console.error('args: %j', args.raw);
|
31
|
-
opts = getOpts(args.raw);
|
32
|
-
_ref = this._cmd._parseCmd(opts.partialWords), cmd = _ref.cmd, argv = _ref.argv;
|
33
|
-
return Q.when(complete(cmd, opts), function(compls) {
|
34
|
-
console.error('filtered: %j', compls);
|
35
|
-
return console.log(compls.map(escape).join('\n'));
|
60
|
+
function dumpScript(name) {
|
61
|
+
const defer = Q.defer();
|
62
|
+
|
63
|
+
fs.readFile(path.resolve(__dirname, 'completion.sh'), 'utf8', function(err, d) {
|
64
|
+
if(err) return defer.reject(err);
|
65
|
+
d = d.replace(/{{cmd}}/g, path.basename(name)).replace(/^\#\!.*?\n/, '');
|
66
|
+
|
67
|
+
process.stdout.on('error', onError);
|
68
|
+
process.stdout.write(d, () => defer.resolve());
|
36
69
|
});
|
37
|
-
});
|
38
|
-
};
|
39
70
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
71
|
+
return defer.promise;
|
72
|
+
|
73
|
+
function onError(err) {
|
74
|
+
// Darwin is a real dick sometimes.
|
75
|
+
//
|
76
|
+
// This is necessary because the "source" or "." program in
|
77
|
+
// bash on OS X closes its file argument before reading
|
78
|
+
// from it, meaning that you get exactly 1 write, which will
|
79
|
+
// work most of the time, and will always raise an EPIPE.
|
80
|
+
//
|
81
|
+
// Really, one should not be tossing away EPIPE errors, or any
|
82
|
+
// errors, so casually. But, without this, `. <(cmd completion)`
|
83
|
+
// can never ever work on OS X.
|
84
|
+
if(err.errno !== constants.EPIPE) return defer.reject(err);
|
53
85
|
process.stdout.removeListener('error', onError);
|
54
86
|
return defer.resolve();
|
55
|
-
|
56
|
-
|
57
|
-
|
87
|
+
}
|
88
|
+
}
|
89
|
+
|
90
|
+
function getOpts(argv) {
|
91
|
+
// get the partial line and partial word, if the point isn't at the end
|
92
|
+
// ie, tabbing at: cmd foo b|ar
|
93
|
+
const line = process.env.COMP_LINE;
|
94
|
+
const w = +process.env.COMP_CWORD;
|
95
|
+
const point = +process.env.COMP_POINT;
|
96
|
+
const words = argv.map(unescape);
|
97
|
+
const word = words[w];
|
98
|
+
const partialLine = line.substr(0, point);
|
99
|
+
const partialWords = words.slice(0, w);
|
100
|
+
|
101
|
+
// figure out where in that last word the point is
|
102
|
+
let partialWord = argv[w] || '';
|
103
|
+
let i = partialWord.length;
|
104
|
+
while(partialWord.substr(0, i) !== partialLine.substr(-1 * i) && i > 0) i--;
|
105
|
+
|
106
|
+
partialWord = unescape(partialWord.substr(0, i));
|
107
|
+
partialWord && partialWords.push(partialWord);
|
108
|
+
|
109
|
+
return {
|
110
|
+
line,
|
111
|
+
w,
|
112
|
+
point,
|
113
|
+
words,
|
114
|
+
word,
|
115
|
+
partialLine,
|
116
|
+
partialWords,
|
117
|
+
partialWord
|
58
118
|
};
|
59
|
-
|
60
|
-
return process.stdout.write(d, function() {
|
61
|
-
return defer.resolve();
|
62
|
-
});
|
63
|
-
});
|
64
|
-
return defer.promise;
|
65
|
-
};
|
119
|
+
}
|
66
120
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
w = +process.env.COMP_CWORD;
|
71
|
-
point = +process.env.COMP_POINT;
|
72
|
-
words = argv.map(unescape);
|
73
|
-
word = words[w];
|
74
|
-
partialLine = line.substr(0, point);
|
75
|
-
partialWords = words.slice(0, w);
|
76
|
-
partialWord = argv[w] || '';
|
77
|
-
i = partialWord.length;
|
78
|
-
while (partialWord.substr(0, i) !== partialLine.substr(-1 * i) && i > 0) {
|
79
|
-
i--;
|
80
|
-
}
|
81
|
-
partialWord = unescape(partialWord.substr(0, i));
|
82
|
-
if (partialWord) {
|
83
|
-
partialWords.push(partialWord);
|
84
|
-
}
|
85
|
-
return {
|
86
|
-
line: line,
|
87
|
-
w: w,
|
88
|
-
point: point,
|
89
|
-
words: words,
|
90
|
-
word: word,
|
91
|
-
partialLine: partialLine,
|
92
|
-
partialWords: partialWords,
|
93
|
-
partialWord: partialWord
|
94
|
-
};
|
95
|
-
};
|
121
|
+
function complete(cmd, opts) {
|
122
|
+
let optWord, optPrefix,
|
123
|
+
compls = [];
|
96
124
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
125
|
+
// Complete on cmds
|
126
|
+
if(opts.partialWord.indexOf('-'))
|
127
|
+
compls = Object.keys(cmd._cmdsByName);
|
128
|
+
// Complete on required opts without '-' in last partial word
|
129
|
+
// (if required not already specified)
|
130
|
+
//
|
131
|
+
// Commented out because of uselessness:
|
132
|
+
// -b, --block suggest results in '-' on cmd line;
|
133
|
+
// next completion suggest all options, because of '-'
|
134
|
+
//.concat Object.keys(cmd._optsByKey).filter (v) -> cmd._optsByKey[v]._req
|
135
|
+
else {
|
136
|
+
// complete on opt values: --opt=| case
|
137
|
+
const m = opts.partialWord.match(/^(--\w[\w-_]*)=(.*)$/);
|
138
|
+
if(m) {
|
139
|
+
optWord = m[1];
|
140
|
+
optPrefix = optWord + '=';
|
141
|
+
} else
|
142
|
+
// complete on opts
|
143
|
+
// don't complete on opts in case of --opt=val completion
|
144
|
+
// TODO: don't complete on opts in case of unknown arg after commands
|
145
|
+
// TODO: complete only on opts with arr() or not already used
|
146
|
+
// TODO: complete only on full opts?
|
147
|
+
compls = Object.keys(cmd._optsByKey);
|
120
148
|
}
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
149
|
+
|
150
|
+
// complete on opt values: next arg case
|
151
|
+
opts.partialWords[opts.w - 1].indexOf('-') || (optWord = opts.partialWords[opts.w - 1]);
|
152
|
+
|
153
|
+
// complete on opt values: completion
|
154
|
+
let opt;
|
155
|
+
optWord
|
156
|
+
&& (opt = cmd._optsByKey[optWord])
|
157
|
+
&& !opt._flag
|
158
|
+
&& opt._comp
|
159
|
+
&& (compls = Q.join(compls,
|
160
|
+
Q.when(opt._comp(opts),
|
161
|
+
(c, o) => c.concat(o.map(v => (optPrefix || '') + v)))));
|
162
|
+
|
163
|
+
// TODO: complete on args values (context aware, custom completion?)
|
164
|
+
|
165
|
+
// custom completion on cmds
|
166
|
+
cmd._comp && (compls = Q.join(compls, Q.when(cmd._comp(opts)), (c, o) => c.concat(o)));
|
167
|
+
|
168
|
+
// TODO: context aware custom completion on cmds, opts and args
|
169
|
+
// (can depend on already entered values, especially options)
|
170
|
+
|
171
|
+
return Q.when(compls, complitions => {
|
172
|
+
console.error('partialWord: %s', opts.partialWord);
|
173
|
+
console.error('compls: %j', complitions);
|
174
|
+
return compls.filter(c => c.indexOf(opts.partialWord) === 0);
|
132
175
|
});
|
133
|
-
|
134
|
-
};
|
176
|
+
}
|
package/lib/index.js
CHANGED
@@ -1,10 +1,14 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
1
|
+
const
|
2
|
+
Cmd = require('./cmd'),
|
3
|
+
Opt = require('./opt'),
|
4
|
+
Arg = require('./arg'),
|
5
|
+
shell = require('./shell');
|
6
|
+
|
7
|
+
module.exports = {
|
8
|
+
Cmd : Cmd.create,
|
9
|
+
Opt : Opt.create,
|
10
|
+
Arg : Arg.create,
|
11
|
+
classes : { Cmd, Opt, Arg },
|
12
|
+
shell,
|
13
|
+
require
|
14
|
+
};
|