coa 0.3.9 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
package/.npmignore CHANGED
@@ -1,5 +1,6 @@
1
1
  .idea
2
2
  *.iml
3
3
  node_modules/
4
+ !node_modules/coa*.js
4
5
  lib-cov/
5
6
  html-report/
package/.travis.yml CHANGED
@@ -1,10 +1,9 @@
1
1
  language: node_js
2
2
 
3
3
  node_js:
4
- - 0.6
5
- - 0.8
6
- - 0.9
4
+ - "0.10"
5
+ - "0.11"
7
6
 
8
7
  matrix:
9
8
  allow_failures:
10
- - node_js: 0.9
9
+ - node_js: 0.11
package/README.md CHANGED
@@ -227,6 +227,11 @@ Default value passed through validation function as ordinary value.<br>
227
227
  **@param** *Object* `_def`<br>
228
228
  **@returns** *COA.Opt* `this` instance (for chainability)
229
229
 
230
+ #### Opt.input
231
+ Make option value inputting stream.
232
+ It's add useful validation and shortcut for STDIN.
233
+ **@returns** *{COA.Opt}* `this` instance (for chainability)
234
+
230
235
  #### Opt.output
231
236
  Make option value outputing stream.<br>
232
237
  It's add useful validation and shortcut for STDOUT.<br>
@@ -303,7 +308,7 @@ Make argument value outputing stream.<br>
303
308
  It's add useful validation and shortcut for STDOUT.<br>
304
309
  **@returns** *COA.Arg* `this` instance (for chainability)
305
310
 
306
- #### Opt.comp
311
+ #### Arg.comp
307
312
  Set custom additional completion for current argument.<br>
308
313
  **@param** *Function* `fn` completion generation function,
309
314
  invoked in the context of command instance.
package/README.ru.md ADDED
@@ -0,0 +1,316 @@
1
+ # Command-Option-Argument
2
+ [![build status](https://secure.travis-ci.org/veged/coa.png)](http://travis-ci.org/veged/coa)
3
+
4
+ ## Что это?
5
+
6
+ COA — парсер параметров командной строки, позволяющий извлечь максимум пользы от формального API вашей программы.
7
+ Как только вы опишете определение в терминах команд, параметров и аргументов, вы автоматически получите:
8
+
9
+ * Справку для командной строки
10
+ * API для использования программы как модуля в COA-совместимых программах
11
+ * Автодополнение для командной строки
12
+
13
+ ### Прочие возможности
14
+
15
+ * Широкий выбор настроек для параметров и аргументов, включая множественные значения, логические значения и обязательность параметров
16
+ * Возможность асинхронного исполнения команд, используя промисы (используется библиотека [Q](https://github.com/kriskowal/q))
17
+ * Простота использования существующих команд как подмодулей для новых команд
18
+ * Комбинированная валидация и анализ сложных значений
19
+
20
+ ## Примеры
21
+
22
+ ````javascript
23
+ require('coa').Cmd() // декларация команды верхнего уровня
24
+ .name(process.argv[1]) // имя команды верхнего уровня, берем из имени программы
25
+ .title('Жутко полезная утилита для командной строки') // название для использования в справке и сообщениях
26
+ .helpful() // добавляем поддержку справки командной строки (-h, --help)
27
+ .opt() // добавляем параметр
28
+ .name('version') // имя параметра для использования в API
29
+ .title('Version') // текст для вывода в сообщениях
30
+ .short('v') // короткое имя параметра: -v
31
+ .long('version') // длинное имя параметра: --version
32
+ .flag() // параметр не требует ввода значения
33
+ .act(function(opts) { // действия при вызове аргумента
34
+ // результатом является вывод текстового сообщения
35
+ return JSON.parse(require('fs').readFileSync(__dirname + '/package.json'))
36
+ .version;
37
+ })
38
+ .end() // завершаем определение параметра и возвращаемся к определению верхнего уровня
39
+ .cmd().name('subcommand').apply(require('./subcommand').COA).end() // загрузка подкоманды из модуля
40
+ .cmd() // добавляем еще одну подкоманду
41
+ .name('othercommand').title('Еще одна полезная подпрограмма').helpful()
42
+ .opt()
43
+ .name('input').title('input file, required')
44
+ .short('i').long('input')
45
+ .val(function(v) { // функция-валидатор, также может использоваться для трансформации значений параметров
46
+ return require('fs').createReadStream(v) })
47
+ .req() // параметр является обязательным
48
+ .end() // завершаем определение параметра и возвращаемся к определению команды
49
+ .end() // завершаем определение подкоманды и возвращаемся к определению команды верхнего уровня
50
+ .run(process.argv.slice(2)); // разбираем process.argv и запускаем
51
+ ````
52
+
53
+ ````javascript
54
+ // subcommand.js
55
+ exports.COA = function() {
56
+ this
57
+ .title('Полезная подпрограмма').helpful()
58
+ .opt()
59
+ .name('output').title('output file')
60
+ .short('o').long('output')
61
+ .output() // использовать стандартную настройку для параметра вывода
62
+ .end()
63
+ };
64
+ ````
65
+
66
+ ## API
67
+
68
+ ### Cmd
69
+ Команда — сущность верхнего уровня. У команды могут быть определены параметры и аргументы.
70
+
71
+ #### Cmd.api
72
+ Возвращает объект, который можно использовать в других программах. Подкоманды являются методами этого объекта.<br>
73
+ **@returns** *{Object}*
74
+
75
+ #### Cmd.name
76
+ Определяет канонический идентификатор команды, используемый в вызовах API.<br>
77
+ **@param** *String* `_name` имя команды<br>
78
+ **@returns** *COA.Cmd* `this` экземпляр команды (для поддержки цепочки методов)
79
+
80
+ #### Cmd.title
81
+ Определяет название команды, используемый в текстовых сообщениях.<br>
82
+ **@param** *String* `_title` название команды<br>
83
+ **@returns** *COA.Cmd* `this` экземпляр команды (для поддержки цепочки методов)
84
+
85
+ #### Cmd.cmd
86
+ Создает новую подкоманду или добавляет ранее определенную подкоманду к текущей команде.<br>
87
+ **@param** *COA.Cmd* `[cmd]` экземпляр ранее определенной подкоманды<br>
88
+ **@returns** *COA.Cmd* экземпляр новой или ранее определенной подкоманды
89
+
90
+ #### Cmd.opt
91
+ Создает параметр для текущей команды.<br>
92
+ **@returns** *COA.Opt* `new` экземпляр параметра
93
+
94
+ #### Cmd.arg
95
+ Создает аргумент для текущей команды.<br>
96
+ **@returns** *COA.Opt* `new` экземпляр аргумента
97
+
98
+ #### Cmd.act
99
+ Добавляет (или создает) действие для текущей команды.<br>
100
+ **@param** *Function* `act` функция,
101
+ выполняемая в контексте экземпляра текущей команды
102
+ и принимающая следующие параметры:<br>
103
+ - *Object* `opts` параметры команды<br>
104
+ - *Array* `args` аргументы команды<br>
105
+ - *Object* `res` объект-аккумулятор результатов<br>
106
+ Функция может вернуть проваленный промис из Cmd.reject (в случае ошибки)
107
+ или любое другое значение, рассматриваемое как результат.<br>
108
+ **@param** *{Boolean}* [force=false] флаг, назначающий немедленное исполнение вместо добавления к списку существующих действий<br>
109
+ **@returns** *COA.Cmd* `this` экземпляр команды (для поддержки цепочки методов)
110
+
111
+ #### Cmd.apply
112
+ Исполняет функцию с переданными аргументами в контексте экземпляра текущей команды.<br>
113
+ **@param** *Function* `fn`<br>
114
+ **@param** *Array* `args`<br>
115
+ **@returns** *COA.Cmd* `this` экземпляр команды (для поддержки цепочки методов)
116
+
117
+ #### Cmd.comp
118
+ Назначает кастомную функцию автодополнения для текущей команды.<br>
119
+ **@param** *Function* `fn` функция-генератор автодополнения,
120
+ исполняемая в контексте текущей команды.
121
+ Принимает параметры:<br>
122
+ - *Object* `opts` параметры<br>
123
+ Может возвращать промис или любое другое значение, рассматриваемое как результат исполнения команды.<br>
124
+ **@returns** *COA.Cmd* `this` экземпляр команды (для поддержки цепочки методов)
125
+
126
+ #### Cmd.helpful
127
+ Ставит флаг поддержки справки командной строки, т.е. вызов команды с параметрами -h --help выводит справку по работе с командой.<br>
128
+ **@returns** *COA.Cmd* `this` экземпляр команды (для поддержки цепочки методов)
129
+
130
+ #### Cmd.completable
131
+ Добавляет поддержку автодополнения командной строки. Добавляется подкоманда "completion", которая выполняет все необходимые действия.<br>
132
+ Может быть добавлен только для главной команды.<br>
133
+ **@returns** *COA.Cmd* `this` экземпляр команды (для поддержки цепочки методов)
134
+
135
+ #### Cmd.usage
136
+ Возвращает текст справки по использованию команды для текущего экземпляра.<br>
137
+ **@returns** *String* `usage` Текст справки по использованию
138
+
139
+ #### Cmd.run
140
+ Разбирает аргументы из значения, возвращаемого NodeJS process.argv,
141
+ и запускает текущую программу, т.е. вызывает process.exit после завершения
142
+ всех действий.<br>
143
+ **@param** *Array* `argv`<br>
144
+ **@returns** *COA.Cmd* `this` экземпляр команды (для поддержки цепочки методов)
145
+
146
+ #### Cmd.invoke
147
+ Исполняет переданную (или текущую) команду с указанными параметрами и аргументами.<br>
148
+ **@param** *String|Array* `cmds` подкоманда для исполнения (необязательно)<br>
149
+ **@param** *Object* `opts` параметры, передаваемые команде (необязательно)<br>
150
+ **@param** *Object* `args` аргументы, передаваемые команде (необязательно)<br>
151
+ **@returns** *Q.Promise*
152
+
153
+ #### Cmd.reject
154
+ Проваливает промисы, возращенные в действиях.<br>
155
+ Используется в .act() для возврата с ошибкой.<br>
156
+ **@param** *Object* `reason` причина провала<br>
157
+ Вы можете определить метод toString() и свойство toString()
158
+ объекта причины провала.<br>
159
+ **@returns** *Q.promise* проваленный промис
160
+
161
+ #### Cmd.end
162
+ Завершает цепочку методов текущей подкоманды и возвращает экземпляр родительской команды.<br>
163
+ **@returns** *COA.Cmd* `parent` родительская команда
164
+
165
+ ### Opt
166
+ Параметр — именованная сущность. У параметра может быть определено короткое или длинное имя для использования из командной строки.<br>
167
+ **@namespace**<br>
168
+ **@class** Переданный параметр
169
+
170
+ #### Opt.name
171
+ Определяет канонический идентификатор параметра, используемый в вызовах API.<br>
172
+ **@param** *String* `_name` имя параметра<br>
173
+ **@returns** *COA.Opt* `this` экземпляр параметра (для поддержки цепочки методов)
174
+
175
+ #### Opt.title
176
+ Определяет описание для параметра, используемое в текстовых сообщениях.<br>
177
+ **@param** *String* `_title` название параметра<br>
178
+ **@returns** *COA.Opt* `this` экземпляр параметра (для поддержки цепочки методов)
179
+
180
+ #### Opt.short
181
+ Назначает ключ для короткого имени параметра, передаваемого из командной строки с одинарным дефисом (например, `-v`).<br>
182
+ **@param** *String* `_short`<br>
183
+ **@returns** *COA.Opt* `this` экземпляр параметра (для поддержки цепочки методов)
184
+
185
+ #### Opt.long
186
+ Назначает ключ для длинного имени параметра, передаваемого из командной строки с двойным дефисом (например, `--version`).<br>
187
+ **@param** *String* `_long`<br>
188
+ **@returns** *COA.Opt* `this` экземпляр параметра (для поддержки цепочки методов)
189
+
190
+ #### Opt.flag
191
+ Помечает параметр как логический, т.е. параметр не имеющий значения.<br>
192
+ **@returns** *COA.Opt* `this` экземпляр параметра (для поддержки цепочки методов)
193
+
194
+ #### Opt.arr
195
+ Помечает параметр как принимающий множественные значения.<br>
196
+ Иначе будет использовано последнее переданное значение параметра.<br>
197
+ **@returns** *COA.Opt* `this` экземпляр параметра (для поддержки цепочки методов)
198
+
199
+ #### Opt.req
200
+ Помечает параметр как обязательный.<br>
201
+ **@returns** *COA.Opt* `this` экземпляр параметра (для поддержки цепочки методов)
202
+
203
+ #### Opt.only
204
+ Интерпретирует параметр как команду,
205
+ т.е. программа будет завершена сразу после выполнения параметра.<br>
206
+ **@returns** *COA.Opt* `this` экземпляр параметра (для поддержки цепочки методов)
207
+
208
+ #### Opt.val
209
+ Назначает функцию валидации (или трансформации значения) для значения параметра.<br>
210
+ Значение, полученное из командной строки, передается в функцию-валидатор прежде чем оно станет доступно из API.<br>
211
+ Используется для валидации и трансформации введенных данных.<br>
212
+ **@param** *Function* `_val` функция валидации,
213
+ исполняемая в контексте экземпляра параметра
214
+ и принимающая в качестве единственного параметра значение, полученное
215
+ из командной строки<br>
216
+ **@returns** *COA.Opt* `this` экземпляр параметра (для поддержки цепочки методов)
217
+
218
+ #### Opt.def
219
+ Назначает значение параметра по умолчанию. Это значение также передается
220
+ в функцию валидации как обычное значение.<br>
221
+ **@param** *Object* `_def`<br>
222
+ **@returns** *COA.Opt* `this` экземпляр параметра (для поддержки цепочки методов)
223
+
224
+ #### Opt.input
225
+ Помечает параметр как принимающий ввод пользователя. <br>
226
+ Позволяет использовать валидацию для STDIN.<br>
227
+ **@returns** *{COA.Opt}* `this` экземпляр параметра (для поддержки цепочки методов)
228
+
229
+ #### Opt.output
230
+ Помечает параметр как вывод.<br>
231
+ Позволяет использовать валидацию для STDOUT.<br>
232
+ **@returns** *COA.Opt* `this` экземпляр параметра (для поддержки цепочки методов)
233
+
234
+ #### Opt.act
235
+ Добавляет (или создает) действие для текущего параметра команды.
236
+ Это действие будет выполнено, если текущий параметр есть
237
+ в списке полученных параметров (с любым значением).<br>
238
+ **@param** *Function* `act` функция, выполняемая в контексте
239
+ экземпляра текущей команды и принимающая следующие параметры:<br>
240
+ - *Object* `opts` параметры команды<br>
241
+ - *Array* `args` аргументы команды<br>
242
+ - *Object* `res` объект-аккумулятор результатов<br>
243
+ Функция может вернуть проваленный промис из Cmd.reject (в случае ошибки)
244
+ или любое другое значение, рассматриваемое как результат.<br>
245
+ **@returns** *COA.Opt* `this` экземпляр параметра (для поддержки цепочки методов)
246
+
247
+ #### Opt.comp
248
+ Назначает кастомную функцию автодополнения для текущей команды.<br>
249
+ **@param** *Function* `fn` функция-генератор автодоплнения, исполняемая в
250
+ контексте экземпляра команды.
251
+ Принимает параметры:<br>
252
+ - *Object* `opts` параметры автодополнения<br>
253
+ Может возвращать промис или любое другое значение, рассматриваемое как результат исполнения команды.<br>
254
+ **@returns** *COA.Opt* `this` экземпляр параметра (для поддержки цепочки методов)
255
+
256
+ #### Opt.end
257
+ Завершает цепочку методов текущего параметра и возвращает экземпляр родительской команды.<br>
258
+ **@returns** *COA.Cmd* `parent` родительская команда
259
+
260
+
261
+ ### Arg
262
+ Аргумент — неименованная сущность.<br>
263
+ Аргументы передаются из командной строки как список неименованных значений.
264
+
265
+ #### Arg.name
266
+ Определяет канонический идентификатор аргумента, используемый в вызовах API.<br>
267
+ **@param** *String* `_name` имя аргумента<br>
268
+ **@returns** *COA.Arg* `this` экземпляр аргумента (для поддержки цепочки методов)
269
+
270
+ #### Arg.title
271
+ Определяет описание для аргумента, используемое в текстовых сообщениях.<br>
272
+ **@param** *String* `_title` описание аргумента<br>
273
+ **@returns** *COA.Arg* `this` экземпляр аргумента (для поддержки цепочки методов)
274
+
275
+ #### Arg.arr
276
+ Помечает аргумент как принимающий множественные значения.<br>
277
+ Иначе будет использовано последнее переданное значение аргумента.<br>
278
+ **@returns** *COA.Arg* `this` экземпляр аргумента (для поддержки цепочки методов)
279
+
280
+ #### Arg.req
281
+ Помечает аргумент как обязательный.<br>
282
+ **@returns** *COA.Arg* `this` экземпляр аргумента (для поддержки цепочки методов)
283
+
284
+ #### Arg.val
285
+ Назначает функцию валидации (или трансформации значения) для аргумента.<br>
286
+ Значение, полученное из командной строки, передается в функцию-валидатор прежде чем оно станет доступно из API.<br>
287
+ Используется для валидации и трансформации введенных данных.<br>
288
+ **@param** *Function* `_val` функция валидации,
289
+ исполняемая в контексте экземпляра аргумента
290
+ и принимающая в качестве единственного параметра значение, полученное
291
+ из командной строки<br>
292
+ **@returns** *COA.Opt* `this` экземпляр аргумента (для поддержки цепочки методов)
293
+
294
+ #### Arg.def
295
+ Назначает дефолтное значение для аргумента. Дефолтное значение передается
296
+ в функцию валидации как обычное значение.<br>
297
+ **@param** *Object* `_def`<br>
298
+ **@returns** *COA.Arg* `this` экземпляр аргумента (для поддержки цепочки методов)
299
+
300
+ #### Arg.output
301
+ Помечает параметр как вывод.<br>
302
+ Позволяет назначить валидацию для STDOUT.<br>
303
+ **@returns** *COA.Arg* `this` экземпляр аргумента (для поддержки цепочки методов)
304
+
305
+ #### Arg.comp
306
+ Назначает кастомную функцию автодополнения для текущего аргумента.<br>
307
+ **@param** *Function* `fn` функция-генератор автодоплнения,
308
+ исполняемая в контексте текущей команды.
309
+ Принимает параметры:<br>
310
+ - *Object* `opts` параметры
311
+ Может возвращать промис или любое другое значение, рассматриваемое как результат исполнения команды.<br>
312
+ **@returns** *COA.Arg* `this` экземпляр аргумента (для поддержки цепочки методов)
313
+
314
+ #### Arg.end
315
+ Завершает цепочку методов текущего аргумента и возвращает экземпляр родительской команды.<br>
316
+ **@returns** *COA.Cmd* `parent` родительская команда
package/lib/arg.js CHANGED
@@ -1,4 +1,4 @@
1
- // Generated by CoffeeScript 1.4.0
1
+ // Generated by CoffeeScript 1.6.3
2
2
  var Arg, Cmd, Color, Opt;
3
3
 
4
4
  Color = require('./color').Color;
package/lib/cmd.js CHANGED
@@ -1,4 +1,4 @@
1
- // Generated by CoffeeScript 1.4.0
1
+ // Generated by CoffeeScript 1.6.3
2
2
  var Cmd, Color, PATH, Q, UTIL,
3
3
  __slice = [].slice;
4
4
 
@@ -35,6 +35,7 @@ exports.Cmd = Cmd = (function() {
35
35
  this._opts = [];
36
36
  this._optsByKey = {};
37
37
  this._args = [];
38
+ this._ext = false;
38
39
  }
39
40
 
40
41
  Cmd.get = function(propertyName, func) {
@@ -70,10 +71,13 @@ exports.Cmd = Cmd = (function() {
70
71
  });
71
72
 
72
73
  Cmd.prototype._parent = function(cmd) {
74
+ this._cmd = cmd || this;
73
75
  if (cmd) {
74
76
  cmd._cmds.push(this);
77
+ if (this._name) {
78
+ this._cmd._cmdsByName[this._name] = this;
79
+ }
75
80
  }
76
- this._cmd = cmd || this;
77
81
  return this;
78
82
  };
79
83
 
@@ -221,10 +225,22 @@ exports.Cmd = Cmd = (function() {
221
225
  return this.cmd().name('completion').apply(require('./completion')).end();
222
226
  };
223
227
 
228
+ /**
229
+ Allow command to be extendable by external node.js modules.
230
+ @param {String} [pattern] Pattern of node.js module to find subcommands at.
231
+ @returns {COA.Cmd} this instance (for chainability)
232
+ */
233
+
234
+
235
+ Cmd.prototype.extendable = function(pattern) {
236
+ this._ext = pattern || true;
237
+ return this;
238
+ };
239
+
224
240
  Cmd.prototype._exit = function(msg, code) {
225
241
  return process.once('exit', function() {
226
242
  if (msg) {
227
- UTIL.error(msg);
243
+ console.error(msg);
228
244
  }
229
245
  return process.exit(code || 0);
230
246
  });
@@ -304,7 +320,7 @@ exports.Cmd = Cmd = (function() {
304
320
  };
305
321
 
306
322
  Cmd.prototype._parseCmd = function(argv, unparsed) {
307
- var cmd, i, optSeen;
323
+ var c, cmd, cmdDesc, e, i, optSeen, pkg;
308
324
  if (unparsed == null) {
309
325
  unparsed = [];
310
326
  }
@@ -314,8 +330,46 @@ exports.Cmd = Cmd = (function() {
314
330
  if (!i.indexOf('-')) {
315
331
  optSeen = true;
316
332
  }
317
- if (!optSeen && /^\w[\w-_]*$/.test(i) && (cmd = this._cmdsByName[i])) {
318
- return cmd._parseCmd(argv, unparsed);
333
+ if (!optSeen && /^\w[\w-_]*$/.test(i)) {
334
+ cmd = this._cmdsByName[i];
335
+ if (!cmd && this._ext) {
336
+ if (typeof this._ext === 'string') {
337
+ if (~this._ext.indexOf('%s')) {
338
+ pkg = UTIL.format(this._ext, i);
339
+ } else {
340
+ pkg = this._ext + i;
341
+ }
342
+ } else if (this._ext === true) {
343
+ pkg = i;
344
+ c = this;
345
+ while (true) {
346
+ pkg = c._name + '-' + pkg;
347
+ if (c._cmd === c) {
348
+ break;
349
+ }
350
+ c = c._cmd;
351
+ }
352
+ }
353
+ try {
354
+ cmdDesc = require(pkg);
355
+ } catch (_error) {
356
+ e = _error;
357
+ }
358
+ if (cmdDesc) {
359
+ if (typeof cmdDesc === 'function') {
360
+ this.cmd().name(i).apply(cmdDesc).end();
361
+ } else if (typeof cmdDesc === 'object') {
362
+ this.cmd(cmdDesc);
363
+ cmdDesc.name(i);
364
+ } else {
365
+ throw new Error('Error: Unsupported command declaration type, ' + 'should be function or COA.Cmd() object');
366
+ }
367
+ cmd = this._cmdsByName[i];
368
+ }
369
+ }
370
+ if (cmd) {
371
+ return cmd._parseCmd(argv, unparsed);
372
+ }
319
373
  }
320
374
  unparsed.push(i);
321
375
  }
package/lib/color.js CHANGED
@@ -1,4 +1,4 @@
1
- // Generated by CoffeeScript 1.4.0
1
+ // Generated by CoffeeScript 1.6.3
2
2
  var colors;
3
3
 
4
4
  colors = {
package/lib/completion.js CHANGED
@@ -1,4 +1,4 @@
1
- // Generated by CoffeeScript 1.4.0
1
+ // Generated by CoffeeScript 1.6.3
2
2
  /**
3
3
  Most of the code adopted from the npm package shell completion code.
4
4
  See https://github.com/isaacs/npm/blob/master/lib/completion.js
@@ -21,7 +21,7 @@ module.exports = function() {
21
21
  e.errno = require('constants').ENOTSUP;
22
22
  return this.reject(e);
23
23
  }
24
- if (!(process.env.COMP_CWORD != null) || !(process.env.COMP_LINE != null) || !(process.env.COMP_POINT != null)) {
24
+ if ((process.env.COMP_CWORD == null) || (process.env.COMP_LINE == null) || (process.env.COMP_POINT == null)) {
25
25
  return dumpScript(this._cmd._name);
26
26
  }
27
27
  console.error('COMP_LINE: %s', process.env.COMP_LINE);
package/lib/index.js CHANGED
@@ -1,7 +1,10 @@
1
- // Generated by CoffeeScript 1.4.0
2
-
1
+ // Generated by CoffeeScript 1.6.3
3
2
  exports.Cmd = require('./cmd').Cmd;
4
3
 
4
+ exports.Opt = require('./cmd').Opt;
5
+
6
+ exports.Arg = require('./cmd').Arg;
7
+
5
8
  exports.shell = require('./shell');
6
9
 
7
10
  exports.require = require;
package/lib/opt.js CHANGED
@@ -1,4 +1,4 @@
1
- // Generated by CoffeeScript 1.4.0
1
+ // Generated by CoffeeScript 1.6.3
2
2
  var Cmd, Color, Opt, Q, fs;
3
3
 
4
4
  fs = require('fs');
package/lib/shell.js CHANGED
@@ -1,5 +1,4 @@
1
- // Generated by CoffeeScript 1.4.0
2
-
1
+ // Generated by CoffeeScript 1.6.3
3
2
  exports.unescape = function(w) {
4
3
  w = w.charAt(0) === '"' ? w.replace(/^"|([^\\])"$/g, '$1') : w.replace(/\\ /g, ' ');
5
4
  return w.replace(/\\("|'|\$|`|\\)/g, '$1');
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "coa",
3
3
  "description": "Command-Option-Argument: Yet another parser for command line options.",
4
- "version": "0.3.9",
4
+ "version": "1.0.1",
5
5
  "homepage": "http://github.com/veged/coa",
6
6
  "author": "Sergey Berezhnoy <veged@ya.ru> (http://github.com/veged)",
7
7
  "maintainers": [
@@ -19,22 +19,21 @@
19
19
  "lib": "./lib"
20
20
  },
21
21
  "dependencies": {
22
- "q": "~0.8.10"
22
+ "q": "^1.1.2"
23
23
  },
24
24
  "devDependencies": {
25
- "coffee-script": "~1.4.0",
26
- "istanbul": "~0.1.11",
27
- "mocha-as-promised": "*",
25
+ "coffee-script": "~1.6.3",
26
+ "istanbul": "~0.1.40",
28
27
  "mocha-istanbul": "*",
29
- "mocha": "~1.6.0",
30
- "chai": "~1.3.0"
28
+ "mocha": "~1.21.4",
29
+ "chai": "~1.7.2"
31
30
  },
32
31
  "scripts": {
33
32
  "test": "make test",
34
33
  "coverage": "make coverage"
35
34
  },
36
35
  "engines": {
37
- "node": ">= 0.6.0"
36
+ "node": ">= 0.8.0"
38
37
  },
39
38
  "licenses": [
40
39
  {
package/src/cmd.coffee CHANGED
@@ -32,6 +32,8 @@ exports.Cmd = class Cmd
32
32
 
33
33
  @_args = []
34
34
 
35
+ @_ext = false
36
+
35
37
  @get: (propertyName, func) ->
36
38
  Object.defineProperty @::, propertyName,
37
39
  configurable: true
@@ -52,8 +54,10 @@ exports.Cmd = class Cmd
52
54
  @_api
53
55
 
54
56
  _parent: (cmd) ->
55
- if cmd then cmd._cmds.push @
56
57
  @_cmd = cmd or this
58
+ if cmd
59
+ cmd._cmds.push @
60
+ if @_name then @_cmd._cmdsByName[@_name] = @
57
61
  @
58
62
 
59
63
  ###*
@@ -163,9 +167,18 @@ exports.Cmd = class Cmd
163
167
  .apply(require './completion')
164
168
  .end()
165
169
 
170
+ ###*
171
+ Allow command to be extendable by external node.js modules.
172
+ @param {String} [pattern] Pattern of node.js module to find subcommands at.
173
+ @returns {COA.Cmd} this instance (for chainability)
174
+ ###
175
+ extendable: (pattern) ->
176
+ @_ext = pattern or true
177
+ @
178
+
166
179
  _exit: (msg, code) ->
167
180
  process.once 'exit', ->
168
- if msg then UTIL.error msg
181
+ if msg then console.error msg
169
182
  process.exit code or 0
170
183
 
171
184
  ###*
@@ -233,8 +246,49 @@ exports.Cmd = class Cmd
233
246
  while i = argv.shift()
234
247
  if not i.indexOf '-'
235
248
  optSeen = true
236
- if not optSeen and /^\w[\w-_]*$/.test(i) and cmd = @_cmdsByName[i]
237
- return cmd._parseCmd argv, unparsed
249
+ if not optSeen and /^\w[\w-_]*$/.test(i)
250
+ cmd = @_cmdsByName[i]
251
+
252
+ if not cmd and @_ext
253
+ # construct package name to require
254
+ if typeof @_ext is 'string'
255
+ if ~@_ext.indexOf('%s')
256
+ # use formatted string
257
+ pkg = UTIL.format(@_ext, i)
258
+ else
259
+ # just append subcommand name to the prefix
260
+ pkg = @_ext + i
261
+ else if @_ext is true
262
+ # use default scheme: <command>-<subcommand>-<subcommand> and so on
263
+ pkg = i
264
+ c = @
265
+ loop
266
+ pkg = c._name + '-' + pkg
267
+ if c._cmd is c then break
268
+ c = c._cmd
269
+
270
+ try
271
+ cmdDesc = require(pkg)
272
+ catch e
273
+
274
+ if cmdDesc
275
+ if typeof cmdDesc == 'function'
276
+ # set create subcommand, set its name and apply imported function
277
+ @cmd()
278
+ .name(i)
279
+ .apply(cmdDesc)
280
+ .end()
281
+ else if typeof cmdDesc == 'object'
282
+ # register subcommand
283
+ @cmd(cmdDesc)
284
+ # set command name
285
+ cmdDesc.name(i)
286
+ else
287
+ throw new Error 'Error: Unsupported command declaration type, ' +
288
+ 'should be function or COA.Cmd() object'
289
+ cmd = @_cmdsByName[i]
290
+ if cmd
291
+ return cmd._parseCmd argv, unparsed
238
292
 
239
293
  unparsed.push i
240
294
 
package/src/index.coffee CHANGED
@@ -1,3 +1,5 @@
1
1
  exports.Cmd = require('./cmd').Cmd
2
+ exports.Opt = require('./cmd').Opt
3
+ exports.Arg = require('./cmd').Arg
2
4
  exports.shell = require('./shell')
3
5
  exports.require = require;
package/test/coa.js CHANGED
@@ -338,6 +338,22 @@ describe('Arg', function() {
338
338
 
339
339
  describe('Cmd', function() {
340
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
+
341
357
  describe('Subcommand', function() {
342
358
 
343
359
  var cmd = COA.Cmd()
@@ -357,23 +373,7 @@ describe('Cmd', function() {
357
373
  .act(function(opts, args) {
358
374
  return { opts: opts, args: args };
359
375
  })
360
- .end(),
361
-
362
- doTest = function(o) {
363
- assert.deepEqual(o, {
364
- opts: { opt: 'value' },
365
- args: {
366
- arg1: 'value',
367
- arg2: ['value 1', 'value 2']
368
- }
369
- });
370
- },
371
-
372
- invokeOpts = { opt: 'value' },
373
- invokeArgs = {
374
- arg1: 'value',
375
- arg2: ['value 1', 'value 2']
376
- };
376
+ .end();
377
377
 
378
378
  describe('when specified on command line', function() {
379
379
 
@@ -413,6 +413,80 @@ describe('Cmd', function() {
413
413
 
414
414
  });
415
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
+
416
490
  it('helpful(), name(), title()');
417
491
 
418
492
  });
package/test/mocha.opts CHANGED
@@ -1,4 +1,2 @@
1
1
  --reporter spec
2
- --ignore-leaks
3
- --timeout 0
4
- --require test/common.js
2
+ --timeout 20
package/tests/api-h.js CHANGED
@@ -6,4 +6,4 @@ require('..').Cmd()
6
6
  .then(function(res) {
7
7
  console.log(res);
8
8
  })
9
- .end(); // Q.end()
9
+ .done(); // Q.done()
package/test/common.js DELETED
@@ -1 +0,0 @@
1
- require('mocha-as-promised')(require('mocha'));