coa 1.0.3 → 1.0.4

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.
Files changed (49) hide show
  1. package/.npmignore +6 -0
  2. package/.nyc_output/1f2a0db5a6d6559149db56d397f47cfc.json +1 -0
  3. package/.nyc_output/75b82d38f2186df930141082076e11c6.json +1 -0
  4. package/.travis.yml +9 -0
  5. package/GNUmakefile +34 -0
  6. package/README.md +1 -19
  7. package/coverage/base.css +212 -0
  8. package/coverage/coa/index.html +93 -0
  9. package/coverage/coa/index.js.html +68 -0
  10. package/coverage/coa/lib/arg.js.html +239 -0
  11. package/coverage/coa/lib/cmd.js.html +1556 -0
  12. package/coverage/coa/lib/coaobject.js.html +365 -0
  13. package/coverage/coa/lib/coaparam.js.html +440 -0
  14. package/coverage/coa/lib/color.js.html +131 -0
  15. package/coverage/coa/lib/completion.js.html +593 -0
  16. package/coverage/coa/lib/index.html +197 -0
  17. package/coverage/coa/lib/index.js.html +107 -0
  18. package/coverage/coa/lib/opt.js.html +524 -0
  19. package/coverage/coa/lib/shell.js.html +107 -0
  20. package/coverage/index.html +106 -0
  21. package/coverage/prettify.css +1 -0
  22. package/coverage/prettify.js +1 -0
  23. package/coverage/sort-arrow-sprite.png +0 -0
  24. package/coverage/sorter.js +158 -0
  25. package/index.js +1 -1
  26. package/lib/arg.js +161 -44
  27. package/lib/cmd.js +547 -434
  28. package/lib/color.js +22 -19
  29. package/lib/completion.js +119 -161
  30. package/lib/index.js +10 -14
  31. package/lib/opt.js +313 -130
  32. package/lib/shell.js +13 -13
  33. package/package.json +14 -19
  34. package/qq.js +17 -0
  35. package/src/arg.coffee +130 -0
  36. package/src/cmd.coffee +456 -0
  37. package/src/color.coffee +25 -0
  38. package/src/completion.coffee +156 -0
  39. package/src/index.coffee +5 -0
  40. package/src/opt.coffee +243 -0
  41. package/src/shell.coffee +10 -0
  42. package/test/coa.js +496 -0
  43. package/test/mocha.opts +2 -0
  44. package/test/shell-test.js +60 -0
  45. package/tests/api-h.js +9 -0
  46. package/tests/h.js +6 -0
  47. package/LICENSE +0 -21
  48. package/lib/coaobject.js +0 -100
  49. package/lib/coaparam.js +0 -125
package/test/coa.js ADDED
@@ -0,0 +1,496 @@
1
+ var assert = require('chai').assert,
2
+ COA = require('..');
3
+
4
+ /**
5
+ * Mocha BDD interface.
6
+ */
7
+ /** @name describe @function */
8
+ /** @name it @function */
9
+ /** @name before @function */
10
+ /** @name after @function */
11
+ /** @name beforeEach @function */
12
+ /** @name afterEach @function */
13
+
14
+ describe('Opt', function() {
15
+
16
+ describe('Unknown option', function() {
17
+
18
+ var cmd = COA.Cmd();
19
+
20
+ it('should fail', function() {
21
+ return cmd.do(['-a'])
22
+ .then(assert.fail, emptyFn);
23
+ });
24
+
25
+ });
26
+
27
+ describe('Short options', function() {
28
+
29
+ var cmd = COA.Cmd()
30
+ .opt()
31
+ .name('a')
32
+ .short('a')
33
+ .end()
34
+ .opt()
35
+ .name('b')
36
+ .short('b')
37
+ .end()
38
+ .act(function(opts) {
39
+ return opts;
40
+ });
41
+
42
+ it('should return passed values', function() {
43
+ return cmd.do(['-a', 'a', '-b', 'b'])
44
+ .then(function(res) {
45
+ assert.deepEqual(res, { a: 'a', b: 'b' });
46
+ });
47
+ });
48
+
49
+ });
50
+
51
+ describe('Long options', function() {
52
+
53
+ var cmd = COA.Cmd()
54
+ .opt()
55
+ .name('long1')
56
+ .long('long1')
57
+ .end()
58
+ .opt()
59
+ .name('long2')
60
+ .long('long2')
61
+ .end()
62
+ .act(function(opts) {
63
+ return opts;
64
+ });
65
+
66
+ it('should return passed values', function() {
67
+ return cmd.do(['--long1', 'long value', '--long2=another long value'])
68
+ .then(function(res) {
69
+ assert.deepEqual(res, { long1: 'long value', long2: 'another long value' });
70
+ });
71
+ });
72
+
73
+ });
74
+
75
+ describe('Array option', function() {
76
+
77
+ var cmd = COA.Cmd()
78
+ .opt()
79
+ .name('a')
80
+ .short('a')
81
+ .arr()
82
+ .end()
83
+ .act(function(opts) {
84
+ return opts;
85
+ });
86
+
87
+ it('should return array of passed values', function() {
88
+ return cmd.do(['-a', '1', '-a', '2'])
89
+ .then(function(res) {
90
+ assert.deepEqual(res, { a: ['1', '2'] });
91
+ });
92
+ });
93
+
94
+ });
95
+
96
+ describe('Required option', function() {
97
+
98
+ var cmd = COA.Cmd()
99
+ .opt()
100
+ .name('a')
101
+ .short('a')
102
+ .req()
103
+ .end()
104
+ .act(function(opts) {
105
+ return opts;
106
+ });
107
+
108
+ it('should fail if not specified', function() {
109
+ return cmd.do()
110
+ .then(assert.fail, emptyFn);
111
+ });
112
+
113
+ it('should return passed value if specified', function() {
114
+ return cmd.do(['-a', 'test'])
115
+ .then(function(opts) {
116
+ assert.equal(opts.a, 'test');
117
+ });
118
+ });
119
+
120
+ });
121
+
122
+ describe('Option with default value', function() {
123
+
124
+ var cmd = COA.Cmd()
125
+ .opt()
126
+ .name('a')
127
+ .short('a')
128
+ .def('aaa')
129
+ .end()
130
+ .act(function(opts) {
131
+ return opts;
132
+ });
133
+
134
+ it('should return default value if not specified', function() {
135
+ return cmd.do()
136
+ .then(function(opts) {
137
+ assert.equal(opts.a, 'aaa');
138
+ });
139
+ });
140
+
141
+ it('should return passed value if specified', function() {
142
+ return cmd.do(['-a', 'test'])
143
+ .then(function(opts) {
144
+ assert.equal(opts.a, 'test');
145
+ });
146
+ });
147
+
148
+ });
149
+
150
+ describe('Validated / transformed option', function() {
151
+
152
+ var cmd = COA.Cmd()
153
+ .opt()
154
+ .name('a')
155
+ .short('a')
156
+ .val(function(v) {
157
+ if (v === 'invalid') return this.reject('fail');
158
+ return { value: v };
159
+ })
160
+ .end()
161
+ .act(function(opts) {
162
+ return opts;
163
+ });
164
+
165
+ it('should fail if custom checks suppose to do so', function() {
166
+ return cmd.do(['-a', 'invalid'])
167
+ .then(assert.fail, emptyFn);
168
+ });
169
+
170
+ it('should return transformed value', function() {
171
+ return cmd.do(['-a', 'test'])
172
+ .then(function(opts) {
173
+ assert.deepEqual(opts.a, { value: 'test' });
174
+ });
175
+ });
176
+
177
+ });
178
+
179
+ describe('Only option (--version case)', function() {
180
+
181
+ var ver = require('../package.json').version,
182
+ cmd = COA.Cmd()
183
+ .opt()
184
+ .name('version')
185
+ .long('version')
186
+ .flag()
187
+ .only()
188
+ .act(function() {
189
+ return ver;
190
+ })
191
+ .end()
192
+ .opt()
193
+ .name('req')
194
+ .short('r')
195
+ .req()
196
+ .end();
197
+
198
+ it('should process the only() option', function() {
199
+ return cmd.do(['--version'])
200
+ .then(assert.fail, function(res) {
201
+ assert.equal(res, ver);
202
+ });
203
+ });
204
+
205
+ });
206
+
207
+ it('input()');
208
+ it('output()');
209
+
210
+ });
211
+
212
+ describe('Arg', function() {
213
+
214
+ describe('Unknown arg', function() {
215
+
216
+ var cmd = COA.Cmd();
217
+
218
+ it('should fail', function() {
219
+ return cmd.do(['test'])
220
+ .then(assert.fail, emptyFn);
221
+ });
222
+
223
+ });
224
+
225
+ describe('Unknown arg after known', function() {
226
+
227
+ var cmd = COA.Cmd()
228
+ .arg()
229
+ .name('a')
230
+ .end();
231
+
232
+ it('should fail', function() {
233
+ return cmd.do(['test', 'unknown'])
234
+ .then(assert.fail, emptyFn);
235
+ });
236
+
237
+ });
238
+
239
+ describe('Array arg', function() {
240
+
241
+ var cmd = COA.Cmd()
242
+ .arg()
243
+ .name('a')
244
+ .arr()
245
+ .end()
246
+ .act(function(opts, args) {
247
+ return args;
248
+ });
249
+
250
+ it('should return array of passed values', function() {
251
+ return cmd.do(['value 1', 'value 2'])
252
+ .then(function(args) {
253
+ assert.deepEqual(args, { a: ['value 1', 'value 2'] });
254
+ });
255
+ });
256
+
257
+ });
258
+
259
+ describe('Required arg', function() {
260
+
261
+ var cmd = COA.Cmd()
262
+ .arg()
263
+ .name('a')
264
+ .req()
265
+ .end()
266
+ .act(function(opts, args) {
267
+ return args;
268
+ });
269
+
270
+ it('should fail if not specified', function() {
271
+ return cmd.do()
272
+ .then(assert.fail, emptyFn);
273
+ });
274
+
275
+ it('should return passed value if specified', function() {
276
+ return cmd.do(['value'])
277
+ .then(function(args) {
278
+ assert.equal(args.a, 'value');
279
+ });
280
+ });
281
+
282
+ });
283
+
284
+ describe('Args after options', function() {
285
+
286
+ var cmd = COA.Cmd()
287
+ .opt()
288
+ .name('opt')
289
+ .long('opt')
290
+ .end()
291
+ .arg()
292
+ .name('arg1')
293
+ .end()
294
+ .arg()
295
+ .name('arg2')
296
+ .arr()
297
+ .end()
298
+ .act(function(opts, args) {
299
+ return { opts: opts, args: args };
300
+ });
301
+
302
+ it('should return passed values', function() {
303
+ return cmd.do(['--opt', 'value', 'value', 'value 1', 'value 2'])
304
+ .then(function(o) {
305
+ assert.deepEqual(o, {
306
+ opts: { opt: 'value' },
307
+ args: {
308
+ arg1: 'value',
309
+ arg2: ['value 1', 'value 2']
310
+ }
311
+ });
312
+ });
313
+ });
314
+
315
+ });
316
+
317
+ describe('Raw args', function() {
318
+
319
+ var cmd = COA.Cmd()
320
+ .arg()
321
+ .name('raw')
322
+ .arr()
323
+ .end()
324
+ .act(function(opts, args) {
325
+ return args;
326
+ });
327
+
328
+ it('should return passed arg values', function() {
329
+ return cmd.do(['--', 'raw', 'arg', 'values'])
330
+ .then(function(args) {
331
+ assert.deepEqual(args, { raw: ['raw', 'arg', 'values'] });
332
+ });
333
+ });
334
+
335
+ });
336
+
337
+ });
338
+
339
+ describe('Cmd', function() {
340
+
341
+ var doTest = function(o) {
342
+ assert.deepEqual(o, {
343
+ opts: { opt: 'value' },
344
+ args: {
345
+ arg1: 'value',
346
+ arg2: ['value 1', 'value 2']
347
+ }
348
+ });
349
+ },
350
+
351
+ invokeOpts = { opt: 'value' },
352
+ invokeArgs = {
353
+ arg1: 'value',
354
+ arg2: ['value 1', 'value 2']
355
+ };
356
+
357
+ describe('Subcommand', function() {
358
+
359
+ var cmd = COA.Cmd()
360
+ .cmd()
361
+ .name('command')
362
+ .opt()
363
+ .name('opt')
364
+ .long('opt')
365
+ .end()
366
+ .arg()
367
+ .name('arg1')
368
+ .end()
369
+ .arg()
370
+ .name('arg2')
371
+ .arr()
372
+ .end()
373
+ .act(function(opts, args) {
374
+ return { opts: opts, args: args };
375
+ })
376
+ .end();
377
+
378
+ describe('when specified on command line', function() {
379
+
380
+ it('should be invoked and accept passed opts and args', function() {
381
+ return cmd.do(['command', '--opt', 'value', 'value', 'value 1', 'value 2'])
382
+ .then(doTest);
383
+ });
384
+
385
+ });
386
+
387
+ describe('when invoked using api', function() {
388
+
389
+ it('should be invoked and accept passed opts and args', function() {
390
+ return cmd.api.command(invokeOpts, invokeArgs)
391
+ .then(doTest);
392
+ });
393
+
394
+ });
395
+
396
+ describe('when invoked using invoke()', function() {
397
+
398
+ it('should be invoked and accept passed opts and args', function() {
399
+ return cmd.invoke('command', invokeOpts, invokeArgs)
400
+ .then(doTest);
401
+ });
402
+
403
+ });
404
+
405
+ describe('when unexisting command invoked using invoke()', function() {
406
+
407
+ it('should fail', function() {
408
+ return cmd.invoke('unexistent')
409
+ .then(assert.fail, emptyFn);
410
+ });
411
+
412
+ });
413
+
414
+ });
415
+
416
+ describe('External subcommand', function() {
417
+
418
+ describe('default scheme: cmd.extendable()', function() {
419
+
420
+ describe('when described as a function', function() {
421
+ var cmd = COA.Cmd()
422
+ .name('coa')
423
+ .extendable();
424
+
425
+ it('should be invoked and accept passed opts and args', function() {
426
+ return cmd.do(['test', '--opt', 'value', 'value', 'value 1', 'value 2'])
427
+ .then(doTest);
428
+ });
429
+ });
430
+
431
+ describe('when described as an COA.Cmd() object', function() {
432
+ var cmd = COA.Cmd()
433
+ .name('coa')
434
+ .extendable();
435
+
436
+ it('should be invoked and accept passed opts and args', function() {
437
+ return cmd.do(['test-obj', '--opt', 'value', 'value', 'value 1', 'value 2'])
438
+ .then(doTest);
439
+ });
440
+ });
441
+
442
+ describe('2nd level subcommand', function() {
443
+ var cmd = COA.Cmd()
444
+ .name('coa')
445
+ .cmd()
446
+ .name('test')
447
+ .extendable()
448
+ .end();
449
+
450
+ it('should be invoked and accept passed opts and args', function() {
451
+ return cmd.do(['test', 'obj', '--opt', 'value', 'value', 'value 1', 'value 2'])
452
+ .then(doTest);
453
+ });
454
+ });
455
+
456
+ });
457
+
458
+ describe("common prefix: cmd.extendable('coa-')", function() {
459
+
460
+ describe('when described as a function', function() {
461
+ var cmd = COA.Cmd()
462
+ .name('coa')
463
+ .extendable('coa-');
464
+
465
+ it('should be invoked and accept passed opts and args', function() {
466
+ return cmd.do(['test', '--opt', 'value', 'value', 'value 1', 'value 2'])
467
+ .then(doTest);
468
+ });
469
+ });
470
+
471
+ });
472
+
473
+ describe("format string: cmd.extendable('coa-%s')", function() {
474
+
475
+ describe('when described as a function', function() {
476
+ var cmd = COA.Cmd()
477
+ .name('coa')
478
+ .extendable('coa-%s');
479
+
480
+ it('should be invoked and accept passed opts and args', function() {
481
+ return cmd.do(['test', '--opt', 'value', 'value', 'value 1', 'value 2'])
482
+ .then(doTest);
483
+ });
484
+ });
485
+
486
+ });
487
+
488
+ });
489
+
490
+ it('helpful(), name(), title()');
491
+
492
+ });
493
+
494
+ function emptyFn() {
495
+ // empty function
496
+ }
@@ -0,0 +1,2 @@
1
+ --reporter spec
2
+ --timeout 20
@@ -0,0 +1,60 @@
1
+ var assert = require('chai').assert,
2
+ shell = require('..').shell;
3
+
4
+ /**
5
+ * Mocha BDD interface.
6
+ */
7
+ /** @name describe @function */
8
+ /** @name it @function */
9
+ /** @name before @function */
10
+ /** @name after @function */
11
+ /** @name beforeEach @function */
12
+ /** @name afterEach @function */
13
+
14
+ describe('shell', function() {
15
+
16
+ describe('escape()', function() {
17
+
18
+ var escape = shell.escape;
19
+
20
+ it('Should wrap values with spaces in double quotes', function() {
21
+ assert.equal(escape('asd abc'), '"asd abc"');
22
+ });
23
+
24
+ it('Should escape double quote "', function() {
25
+ assert.equal(escape('"asd'), '\\"asd');
26
+ });
27
+
28
+ it("Should escape single quote '", function() {
29
+ assert.equal(escape("'asd"), "\\'asd");
30
+ });
31
+
32
+ it('Should escape backslash \\', function() {
33
+ assert.equal(escape('\\asd'), '\\\\asd');
34
+ });
35
+
36
+ it('Should escape dollar $', function() {
37
+ assert.equal(escape('$asd'), '\\$asd');
38
+ });
39
+
40
+ it('Should escape backtick `', function() {
41
+ assert.equal(escape('`asd'), '\\`asd');
42
+ });
43
+
44
+ });
45
+
46
+ describe('unescape()', function() {
47
+
48
+ var unescape = shell.unescape;
49
+
50
+ it('Should strip double quotes at the both ends', function() {
51
+ assert.equal(unescape('"asd"'), 'asd');
52
+ });
53
+
54
+ it('Should not strip escaped double quotes at the both ends', function() {
55
+ assert.equal(unescape('\\"asd\\"'), '"asd"');
56
+ });
57
+
58
+ });
59
+
60
+ });
package/tests/api-h.js ADDED
@@ -0,0 +1,9 @@
1
+ require('..').Cmd()
2
+ .name('bla')
3
+ .title('Bla bla bla')
4
+ .helpful()
5
+ .invoke({ help: true })
6
+ .then(function(res) {
7
+ console.log(res);
8
+ })
9
+ .done(); // Q.done()
package/tests/h.js ADDED
@@ -0,0 +1,6 @@
1
+ var argv = process.argv.slice(2);
2
+ require('..').Cmd()
3
+ .name('bla')
4
+ .title('Bla bla bla')
5
+ .helpful()
6
+ .run(argv.length? argv : ['-h']);
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- The MIT License (MIT)
2
-
3
- Copyright (c) 2015-present Sergey Berezhnoy <veged@ya.ru>
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
package/lib/coaobject.js DELETED
@@ -1,100 +0,0 @@
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
- };